Skip to content

Commit 204df93

Browse files
authored
Merge pull request #182 from WorldFamousElectronics/joel-m-branch-1
Support for Arduino DUE
2 parents caf8a3d + 28307b3 commit 204df93

File tree

4 files changed

+184
-32
lines changed

4 files changed

+184
-32
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
Code to detect pulses from the PulseSensor,
3+
using an interrupt service routine.
4+
5+
Here is a link to the tutorial\
6+
https://pulsesensor.com/pages/getting-advanced
7+
8+
Copyright World Famous Electronics LLC - see LICENSE
9+
Contributors:
10+
Joel Murphy, https://pulsesensor.com
11+
Yury Gitman, https://pulsesensor.com
12+
Bradford Needham, @bneedhamia, https://bluepapertech.com
13+
14+
Licensed under the MIT License, a copy of which
15+
should have been included with this software.
16+
17+
This software is not intended for medical use.
18+
*/
19+
20+
/*
21+
Include the DueTimer library. If you don't have it, use library manager to get it.
22+
You can also find it at https://github.com/ivanseidel/DueTimer
23+
If you use the Servo library, probably want to include that before this inlude. Just sayin'...
24+
This will grab the next available timer and call it sampleTimer for use throughout the code
25+
*/
26+
#include <DueTimer.h>
27+
DueTimer sampleTimer = Timer.getAvailable();
28+
29+
/*
30+
Every Sketch that uses the PulseSensor Playground must
31+
define USE_ARDUINO_INTERRUPTS before including PulseSensorPlayground.h.
32+
Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use
33+
interrupts to automatically read and process PulseSensor data.
34+
35+
See PulseSensor_BPM_Alternative.ino for an example of not using interrupts.
36+
*/
37+
#define USE_ARDUINO_INTERRUPTS true
38+
#include <PulseSensorPlayground.h>
39+
40+
/*
41+
* Declare the interrupt service routine
42+
* This will be used in setup as the interrupt callback in attachInterrupt
43+
*/
44+
void sampleTimer_ISR(){
45+
PulseSensorPlayground::OurThis->onSampleTime();
46+
}
47+
48+
/*
49+
The format of our output.
50+
51+
Set this to PROCESSING_VISUALIZER if you're going to run
52+
the Processing Visualizer Sketch.
53+
See https://github.com/WorldFamousElectronics/PulseSensor_Amped_Processing_Visualizer
54+
55+
Set this to SERIAL_PLOTTER if you're going to run
56+
the Arduino IDE's Serial Plotter.
57+
*/
58+
const int OUTPUT_TYPE = SERIAL_PLOTTER;
59+
60+
/*
61+
Pinout:
62+
PULSE_INPUT = Analog Input. Connected to the pulse sensor
63+
purple (signal) wire.
64+
PULSE_BLINK = digital Output. Connected to an LED (and 1K series resistor)
65+
that will flash on each detected pulse.
66+
PULSE_FADE = digital Output. PWM pin onnected to an LED (and 1K series resistor)
67+
that will smoothly fade with each pulse.
68+
NOTE: PULSE_FADE must be a pin that supports PWM. Do not use
69+
pin 9 or 10, because those pins' PWM interferes with the sample timer.
70+
THRESHOLD should be set higher than the PulseSensor signal idles
71+
at when there is nothing touching it. The expected idle value
72+
should be 512, which is 1/2 of the ADC range. To check the idle value
73+
open a serial monitor and make note of the PulseSensor signal values
74+
with nothing touching the sensor. THRESHOLD should be a value higher
75+
than the range of idle noise by 25 to 50 or so. When the library
76+
is finding heartbeats, the value is adjusted based on the pulse signal
77+
waveform. THRESHOLD sets the default when there is no pulse present.
78+
Adjust as neccesary.
79+
*/
80+
const int PULSE_INPUT = A0;
81+
const int PULSE_BLINK = LED_BUILTIN;
82+
const int PULSE_FADE = 5;
83+
const int THRESHOLD = 550; // Adjust this number to avoid noise when idle
84+
85+
/*
86+
All the PulseSensor Playground functions.
87+
*/
88+
PulseSensorPlayground pulseSensor;
89+
90+
void setup() {
91+
/*
92+
Use 115200 baud because that's what the Processing Sketch expects to read,
93+
and because that speed provides about 11 bytes per millisecond.
94+
95+
If we used a slower baud rate, we'd likely write bytes faster than
96+
they can be transmitted, which would mess up the timing
97+
of readSensor() calls, which would make the pulse measurement
98+
not work properly.
99+
*/
100+
Serial.begin(115200);
101+
102+
// Configure the PulseSensor manager.
103+
104+
pulseSensor.analogInput(PULSE_INPUT);
105+
pulseSensor.blinkOnPulse(PULSE_BLINK);
106+
pulseSensor.fadeOnPulse(PULSE_FADE);
107+
108+
pulseSensor.setSerial(Serial);
109+
pulseSensor.setOutputType(OUTPUT_TYPE);
110+
pulseSensor.setThreshold(THRESHOLD);
111+
112+
// Now that everything is ready, start reading the PulseSensor signal.
113+
if (!pulseSensor.begin()) {
114+
/*
115+
PulseSensor initialization failed,
116+
likely because our particular Arduino platform interrupts
117+
aren't supported yet.
118+
119+
If your Sketch hangs here, try PulseSensor_BPM_Alternative.ino,
120+
which doesn't use interrupts.
121+
*/
122+
for(;;) {
123+
// Flash the led to show things didn't work.
124+
digitalWrite(PULSE_BLINK, LOW);
125+
delay(50); Serial.println('!');
126+
digitalWrite(PULSE_BLINK, HIGH);
127+
delay(50);
128+
}
129+
}
130+
131+
/* This starts the sample timer interrupt. Do this last in the setup() routine.
132+
* We are using Timer6 to avoid potential conflict with the servo library
133+
* This timer selection could be better...
134+
* Use pause() and resume() to start and stop sampling on the fly
135+
* Check Resources folder in the library for more tools
136+
*/
137+
sampleTimer.attachInterrupt(sampleTimer_ISR);
138+
sampleTimer.start(2000); // Calls every period microseconds
139+
140+
}
141+
142+
void loop() {
143+
/*
144+
Wait a bit.
145+
We don't output every sample, because our baud rate
146+
won't support that much I/O.
147+
*/
148+
delay(20);
149+
150+
// write the latest sample to Serial.
151+
pulseSensor.outputSample();
152+
153+
/*
154+
If a beat has happened since we last checked,
155+
write the per-beat information to Serial.
156+
*/
157+
if (pulseSensor.sawStartOfBeat()) {
158+
pulseSensor.outputBeat();
159+
}
160+
}

src/PulseSensorPlayground.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ boolean PulseSensorPlayground::PulseSensorPlayground::begin() {
5151
for (;;);
5252
#endif // PULSE_SENSOR_MEMORY_USAGE
5353

54+
// #if defined (ARDUINO_ARCH_SAM)
55+
// void sampleTimer(){
56+
// onSampleTime(); // PulseSensorPlayground::OurThis->onSampleTime();
57+
// }
58+
// #endif
59+
5460
// Lastly, set up and turn on the interrupts.
5561
if (UsingInterrupts) {
5662
if (!PulseSensorPlaygroundSetupInterrupt()) {

src/PulseSensorPlayground.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,6 @@
133133
#if defined(ARDUINO_ARCH_NRF52)
134134
#include "Adafruit_TinyUSB.h"
135135
#endif
136-
// #if defined(ARDUINO_ARCH_RENESAS)
137-
// #include "FspTimer.h"
138-
// FspTimer sampleTimer
139-
// #endif
140136
#include <Arduino.h>
141137
#include "utility/PulseSensor.h"
142138
#if USE_SERIAL

src/utility/Interrupts.h

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,7 @@
7373
#define DISABLE_PULSE_SENSOR_INTERRUPTS cli()
7474
#define ENABLE_PULSE_SENSOR_INTERRUPTS sei()
7575
#endif
76-
77-
// #if defined (ARDUINO_ARCH_NRF52840)
78-
// #define TIMER1_INTERVAL_US 2000 // critical fine tuning here!
79-
// NRF52Timer nRF52_Timer(NRF_TIMER_3);
80-
// #endif
81-
76+
8277
// SAVED FOR FUTURE SUPPORT OF TEENSY INTERRUPTS
8378
#if defined(__MK66FX1M0__)||(__MK64FX512__)||(__MK20DX256__)||(__MK20DX128__)
8479
// #include <FlexiTimer2.h>
@@ -115,7 +110,7 @@ boolean PulseSensorPlaygroundEnableInterrupt();
115110
*/
116111
boolean PulseSensorPlayground::UsingInterrupts = USE_ARDUINO_INTERRUPTS;
117112

118-
boolean PulseSensorPlaygroundSetupInterrupt() {
113+
boolean PulseSensorPlaygroundSetupInterrupt(){
119114
boolean result = false;
120115

121116
#if !USE_ARDUINO_INTERRUPTS
@@ -239,8 +234,8 @@ boolean PulseSensorPlaygroundSetupInterrupt() {
239234
#endif
240235

241236
#if defined(__arc__)||(ARDUINO_SAMD_MKR1000)||(ARDUINO_SAMD_MKRZERO)||(ARDUINO_SAMD_ZERO)\
242-
||(ARDUINO_ARCH_SAMD)||(ARDUINO_ARCH_STM32)||(ARDUINO_STM32_STAR_OTTO)||(ARDUINO_NANO33BLE)\
243-
||(ARDUINO_ARCH_SAM)
237+
||(ARDUINO_ARCH_SAMD)||(ARDUINO_ARCH_STM32)||(ARDUINO_STM32_STAR_OTTO)||(ARDUINO_NANO33BLE)
238+
244239

245240
#error "Unsupported Board Selected! Try Using the example: PulseSensor_BPM_Alternative.ino"
246241
result = false; // unknown or unsupported platform.
@@ -249,15 +244,11 @@ boolean PulseSensorPlaygroundSetupInterrupt() {
249244
#if defined(__arc__)||(ARDUINO_SAMD_MKR1000)||(ARDUINO_SAMD_MKRZERO)||(ARDUINO_SAMD_ZERO)\
250245
||(ARDUINO_ARCH_SAMD)||(ARDUINO_ARCH_STM32)||(ARDUINO_STM32_STAR_OTTO)||(ARDUINO_ARCH_NRF52)\
251246
||(ARDUINO_NANO33BLE)||(ARDUINO_ARCH_RP2040)||(ARDUINO_ARCH_ESP32)||(ARDUINO_ARCH_MBED_NANO)\
252-
||(ARDUINO_ARCH_NRF52840)||(ARDUINO_ARCH_SAM)
247+
||(ARDUINO_ARCH_NRF52840)||(ARDUINO_ARCH_RENESAS)||(ARDUINO_ARCH_SAM)
253248

254249
result = true;
255250
#endif
256251

257-
#if defined(ARDUINO_ARCH_RENESAS)
258-
result = true;
259-
#endif
260-
261252
#endif // USE_ARDUINO_INTERRUPTS
262253

263254
return result;
@@ -326,6 +317,12 @@ boolean PulseSensorPlaygroundDisableInterrupt(){
326317

327318
#if defined(ARDUINO_ARCH_RENESAS)
328319
sampleTimer.stop();
320+
result = true;
321+
#endif
322+
323+
#if defined(ARDUINO_ARCH_SAM)
324+
sampleTimer.stop();
325+
result = true;
329326
#endif
330327

331328
#endif
@@ -400,6 +397,12 @@ boolean PulseSensorPlaygroundEnableInterrupt(){
400397

401398
#if defined(ARDUINO_ARCH_RENESAS)
402399
sampleTimer.start();
400+
result = true;
401+
#endif
402+
403+
#if defined(ARDUINO_ARCH_SAM)
404+
sampleTimer.start(2000);
405+
result = true;
403406
#endif
404407

405408
#endif
@@ -474,25 +477,12 @@ return result; // unknown or unsupported platform.
474477
#endif
475478
#endif
476479

477-
// #if defined (ARDUINO_ARCH_NRF52840)
478-
// void Timer3_ISR(){
479-
// // thisSample = micros();
480-
// // isrCounter++;
481-
// PulseSensorPlayground::OurThis->onSampleTime();
482-
// }
483-
// #endif
480+
484481

485482
#if defined(__MK66FX1M0__)||(__MK64FX512__)||(__MK20DX256__)||(__MK20DX128__)
486483
// Interrupts not supported yet for Teensy
487484
#endif
488485

489-
// #if defined(ARDUINO_ARCH_RENESAS)
490-
// void sampleTimerISR(timer_callback_args_t __attribute((unused)) *p_args)
491-
// {
492-
// PulseSensorPlayground::OurThis->onSampleTime();
493-
// }
494-
// #endif
495-
496486

497487
#endif // USE_ARDUINO_INTERRUPTS
498488

0 commit comments

Comments
 (0)