Skip to content

Commit

Permalink
Merge pull request #182 from WorldFamousElectronics/joel-m-branch-1
Browse files Browse the repository at this point in the history
Support for Arduino DUE
  • Loading branch information
biomurph authored Oct 30, 2023
2 parents caf8a3d + 28307b3 commit 204df93
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 32 deletions.
160 changes: 160 additions & 0 deletions examples/PulseSensor_DUE/PulseSensor_DUE.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
Code to detect pulses from the PulseSensor,
using an interrupt service routine.

Here is a link to the tutorial\
https://pulsesensor.com/pages/getting-advanced

Copyright World Famous Electronics LLC - see LICENSE
Contributors:
Joel Murphy, https://pulsesensor.com
Yury Gitman, https://pulsesensor.com
Bradford Needham, @bneedhamia, https://bluepapertech.com

Licensed under the MIT License, a copy of which
should have been included with this software.

This software is not intended for medical use.
*/

/*
Include the DueTimer library. If you don't have it, use library manager to get it.
You can also find it at https://github.com/ivanseidel/DueTimer
If you use the Servo library, probably want to include that before this inlude. Just sayin'...
This will grab the next available timer and call it sampleTimer for use throughout the code
*/
#include <DueTimer.h>
DueTimer sampleTimer = Timer.getAvailable();

/*
Every Sketch that uses the PulseSensor Playground must
define USE_ARDUINO_INTERRUPTS before including PulseSensorPlayground.h.
Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use
interrupts to automatically read and process PulseSensor data.

See PulseSensor_BPM_Alternative.ino for an example of not using interrupts.
*/
#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>

/*
* Declare the interrupt service routine
* This will be used in setup as the interrupt callback in attachInterrupt
*/
void sampleTimer_ISR(){
PulseSensorPlayground::OurThis->onSampleTime();
}

/*
The format of our output.

Set this to PROCESSING_VISUALIZER if you're going to run
the Processing Visualizer Sketch.
See https://github.com/WorldFamousElectronics/PulseSensor_Amped_Processing_Visualizer

Set this to SERIAL_PLOTTER if you're going to run
the Arduino IDE's Serial Plotter.
*/
const int OUTPUT_TYPE = SERIAL_PLOTTER;

/*
Pinout:
PULSE_INPUT = Analog Input. Connected to the pulse sensor
purple (signal) wire.
PULSE_BLINK = digital Output. Connected to an LED (and 1K series resistor)
that will flash on each detected pulse.
PULSE_FADE = digital Output. PWM pin onnected to an LED (and 1K series resistor)
that will smoothly fade with each pulse.
NOTE: PULSE_FADE must be a pin that supports PWM. Do not use
pin 9 or 10, because those pins' PWM interferes with the sample timer.
THRESHOLD should be set higher than the PulseSensor signal idles
at when there is nothing touching it. The expected idle value
should be 512, which is 1/2 of the ADC range. To check the idle value
open a serial monitor and make note of the PulseSensor signal values
with nothing touching the sensor. THRESHOLD should be a value higher
than the range of idle noise by 25 to 50 or so. When the library
is finding heartbeats, the value is adjusted based on the pulse signal
waveform. THRESHOLD sets the default when there is no pulse present.
Adjust as neccesary.
*/
const int PULSE_INPUT = A0;
const int PULSE_BLINK = LED_BUILTIN;
const int PULSE_FADE = 5;
const int THRESHOLD = 550; // Adjust this number to avoid noise when idle

/*
All the PulseSensor Playground functions.
*/
PulseSensorPlayground pulseSensor;

void setup() {
/*
Use 115200 baud because that's what the Processing Sketch expects to read,
and because that speed provides about 11 bytes per millisecond.

If we used a slower baud rate, we'd likely write bytes faster than
they can be transmitted, which would mess up the timing
of readSensor() calls, which would make the pulse measurement
not work properly.
*/
Serial.begin(115200);

// Configure the PulseSensor manager.

pulseSensor.analogInput(PULSE_INPUT);
pulseSensor.blinkOnPulse(PULSE_BLINK);
pulseSensor.fadeOnPulse(PULSE_FADE);

pulseSensor.setSerial(Serial);
pulseSensor.setOutputType(OUTPUT_TYPE);
pulseSensor.setThreshold(THRESHOLD);

// Now that everything is ready, start reading the PulseSensor signal.
if (!pulseSensor.begin()) {
/*
PulseSensor initialization failed,
likely because our particular Arduino platform interrupts
aren't supported yet.

If your Sketch hangs here, try PulseSensor_BPM_Alternative.ino,
which doesn't use interrupts.
*/
for(;;) {
// Flash the led to show things didn't work.
digitalWrite(PULSE_BLINK, LOW);
delay(50); Serial.println('!');
digitalWrite(PULSE_BLINK, HIGH);
delay(50);
}
}

/* This starts the sample timer interrupt. Do this last in the setup() routine.
* We are using Timer6 to avoid potential conflict with the servo library
* This timer selection could be better...
* Use pause() and resume() to start and stop sampling on the fly
* Check Resources folder in the library for more tools
*/
sampleTimer.attachInterrupt(sampleTimer_ISR);
sampleTimer.start(2000); // Calls every period microseconds

}

void loop() {
/*
Wait a bit.
We don't output every sample, because our baud rate
won't support that much I/O.
*/
delay(20);

// write the latest sample to Serial.
pulseSensor.outputSample();

/*
If a beat has happened since we last checked,
write the per-beat information to Serial.
*/
if (pulseSensor.sawStartOfBeat()) {
pulseSensor.outputBeat();
}
}
6 changes: 6 additions & 0 deletions src/PulseSensorPlayground.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ boolean PulseSensorPlayground::PulseSensorPlayground::begin() {
for (;;);
#endif // PULSE_SENSOR_MEMORY_USAGE

// #if defined (ARDUINO_ARCH_SAM)
// void sampleTimer(){
// onSampleTime(); // PulseSensorPlayground::OurThis->onSampleTime();
// }
// #endif

// Lastly, set up and turn on the interrupts.
if (UsingInterrupts) {
if (!PulseSensorPlaygroundSetupInterrupt()) {
Expand Down
4 changes: 0 additions & 4 deletions src/PulseSensorPlayground.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@
#if defined(ARDUINO_ARCH_NRF52)
#include "Adafruit_TinyUSB.h"
#endif
// #if defined(ARDUINO_ARCH_RENESAS)
// #include "FspTimer.h"
// FspTimer sampleTimer
// #endif
#include <Arduino.h>
#include "utility/PulseSensor.h"
#if USE_SERIAL
Expand Down
46 changes: 18 additions & 28 deletions src/utility/Interrupts.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,7 @@
#define DISABLE_PULSE_SENSOR_INTERRUPTS cli()
#define ENABLE_PULSE_SENSOR_INTERRUPTS sei()
#endif

// #if defined (ARDUINO_ARCH_NRF52840)
// #define TIMER1_INTERVAL_US 2000 // critical fine tuning here!
// NRF52Timer nRF52_Timer(NRF_TIMER_3);
// #endif


// SAVED FOR FUTURE SUPPORT OF TEENSY INTERRUPTS
#if defined(__MK66FX1M0__)||(__MK64FX512__)||(__MK20DX256__)||(__MK20DX128__)
// #include <FlexiTimer2.h>
Expand Down Expand Up @@ -115,7 +110,7 @@ boolean PulseSensorPlaygroundEnableInterrupt();
*/
boolean PulseSensorPlayground::UsingInterrupts = USE_ARDUINO_INTERRUPTS;

boolean PulseSensorPlaygroundSetupInterrupt() {
boolean PulseSensorPlaygroundSetupInterrupt(){
boolean result = false;

#if !USE_ARDUINO_INTERRUPTS
Expand Down Expand Up @@ -239,8 +234,8 @@ boolean PulseSensorPlaygroundSetupInterrupt() {
#endif

#if defined(__arc__)||(ARDUINO_SAMD_MKR1000)||(ARDUINO_SAMD_MKRZERO)||(ARDUINO_SAMD_ZERO)\
||(ARDUINO_ARCH_SAMD)||(ARDUINO_ARCH_STM32)||(ARDUINO_STM32_STAR_OTTO)||(ARDUINO_NANO33BLE)\
||(ARDUINO_ARCH_SAM)
||(ARDUINO_ARCH_SAMD)||(ARDUINO_ARCH_STM32)||(ARDUINO_STM32_STAR_OTTO)||(ARDUINO_NANO33BLE)


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

result = true;
#endif

#if defined(ARDUINO_ARCH_RENESAS)
result = true;
#endif

#endif // USE_ARDUINO_INTERRUPTS

return result;
Expand Down Expand Up @@ -326,6 +317,12 @@ boolean PulseSensorPlaygroundDisableInterrupt(){

#if defined(ARDUINO_ARCH_RENESAS)
sampleTimer.stop();
result = true;
#endif

#if defined(ARDUINO_ARCH_SAM)
sampleTimer.stop();
result = true;
#endif

#endif
Expand Down Expand Up @@ -400,6 +397,12 @@ boolean PulseSensorPlaygroundEnableInterrupt(){

#if defined(ARDUINO_ARCH_RENESAS)
sampleTimer.start();
result = true;
#endif

#if defined(ARDUINO_ARCH_SAM)
sampleTimer.start(2000);
result = true;
#endif

#endif
Expand Down Expand Up @@ -474,25 +477,12 @@ return result; // unknown or unsupported platform.
#endif
#endif

// #if defined (ARDUINO_ARCH_NRF52840)
// void Timer3_ISR(){
// // thisSample = micros();
// // isrCounter++;
// PulseSensorPlayground::OurThis->onSampleTime();
// }
// #endif


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

// #if defined(ARDUINO_ARCH_RENESAS)
// void sampleTimerISR(timer_callback_args_t __attribute((unused)) *p_args)
// {
// PulseSensorPlayground::OurThis->onSampleTime();
// }
// #endif


#endif // USE_ARDUINO_INTERRUPTS

Expand Down

0 comments on commit 204df93

Please sign in to comment.