diff --git a/examples/PulseSensor_ATtiny85_Serial/PulseSensor_ATtiny85_Serial.ino b/examples/PulseSensor_ATtiny85_Serial/PulseSensor_ATtiny85_Serial.ino index 374ab21..54a4d9f 100644 --- a/examples/PulseSensor_ATtiny85_Serial/PulseSensor_ATtiny85_Serial.ino +++ b/examples/PulseSensor_ATtiny85_Serial/PulseSensor_ATtiny85_Serial.ino @@ -23,7 +23,7 @@ Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_ATtiny85_noSerial/PulseSensor_ATtiny85_noSerial.ino b/examples/PulseSensor_ATtiny85_noSerial/PulseSensor_ATtiny85_noSerial.ino index de1b83a..5edd069 100644 --- a/examples/PulseSensor_ATtiny85_noSerial/PulseSensor_ATtiny85_noSerial.ino +++ b/examples/PulseSensor_ATtiny85_noSerial/PulseSensor_ATtiny85_noSerial.ino @@ -23,7 +23,7 @@ Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_BPM/PulseSensor_BPM.ino b/examples/PulseSensor_BPM/PulseSensor_BPM.ino index 4c641dd..96264f1 100644 --- a/examples/PulseSensor_BPM/PulseSensor_BPM.ino +++ b/examples/PulseSensor_BPM/PulseSensor_BPM.ino @@ -23,7 +23,7 @@ Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_BPM_UNO_R4/PulseSensor_BPM_UNO_R4.ino b/examples/PulseSensor_BPM_UNO_R4/PulseSensor_BPM_UNO_R4.ino new file mode 100644 index 0000000..143a969 --- /dev/null +++ b/examples/PulseSensor_BPM_UNO_R4/PulseSensor_BPM_UNO_R4.ino @@ -0,0 +1,174 @@ +/* + Code to detect pulses from the PulseSensor, + using an interrupt service routine. + +>>>> This example targest the Arduino UNO R4. +>>>> It has been tested on the Minima and the WiFi board variants. + + 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. +*/ + +/* + We use the FspTimer to setup a timer interrupt for sample acquisition + FspTimer is part of the hardware core files for this chip +*/ +#include "FspTimer.h" +FspTimer sampleTimer; + + +/* + 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 PulseSensorBPM_Alternative.ino for an example of not using interrupts. +*/ +#define USE_ARDUINO_INTERRUPTS true +#include + +/* + This is the timer interrupt service routine where we acquire and process samples +*/ +void sampleTimerISR(timer_callback_args_t __attribute((unused)) *p_args){ + 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); + } + } + +/* + We have to get control of a timer on the R4. First, we try and see if there are any free timers available. + If there are no free timers available, we will just take control of one from some other purpose. + We shouldn't have to force things, but if you use alot of timers, beware of this force use code! +*/ + uint8_t timer_type = GPT_TIMER; + int8_t tindex = FspTimer::get_available_timer(timer_type); + if(tindex == 0){ + FspTimer::force_use_of_pwm_reserved_timer(); + tindex = FspTimer::get_available_timer(timer_type); + } + +/* + Begin sets up the timer that we just got control of as a periodic timer with 500Hz frequency. + It also passes the interrupt service routine that we made above. +*/ + sampleTimer.begin(TIMER_MODE_PERIODIC, timer_type, tindex, SAMPLE_RATE_500HZ, 0.0f, sampleTimerISR); + sampleTimer.setup_overflow_irq(); + sampleTimer.open(); + sampleTimer.start(); +} + +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(); + } + +} + diff --git a/examples/PulseSensor_RP2040/PulseSensor_RP2040.ino b/examples/PulseSensor_RP2040/PulseSensor_RP2040.ino index 52246ea..d621a38 100644 --- a/examples/PulseSensor_RP2040/PulseSensor_RP2040.ino +++ b/examples/PulseSensor_RP2040/PulseSensor_RP2040.ino @@ -41,7 +41,7 @@ RPI_PICO_Timer sampleTimer(0); // the paramater may need to change, depending? Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_Servo/PulseSensor_Servo.ino b/examples/PulseSensor_Servo/PulseSensor_Servo.ino index d630fd4..de61271 100644 --- a/examples/PulseSensor_Servo/PulseSensor_Servo.ino +++ b/examples/PulseSensor_Servo/PulseSensor_Servo.ino @@ -29,7 +29,7 @@ Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_Speaker/PulseSensor_Speaker.ino b/examples/PulseSensor_Speaker/PulseSensor_Speaker.ino index 7d9bf94..f2a7c99 100644 --- a/examples/PulseSensor_Speaker/PulseSensor_Speaker.ino +++ b/examples/PulseSensor_Speaker/PulseSensor_Speaker.ino @@ -26,7 +26,7 @@ Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_nRF52/PulseSensor_nRF52.ino b/examples/PulseSensor_nRF52/PulseSensor_nRF52.ino index aff22ad..1f167ac 100644 --- a/examples/PulseSensor_nRF52/PulseSensor_nRF52.ino +++ b/examples/PulseSensor_nRF52/PulseSensor_nRF52.ino @@ -59,7 +59,7 @@ NRF52Timer sampleTimer(NRF_TIMER_3); Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/examples/PulseSensor_nRF52840_Feather_Express/PulseSensor_nRF52840_Feather_Express.ino b/examples/PulseSensor_nRF52840_Feather_Express/PulseSensor_nRF52840_Feather_Express.ino index 7300193..4c614b2 100644 --- a/examples/PulseSensor_nRF52840_Feather_Express/PulseSensor_nRF52840_Feather_Express.ino +++ b/examples/PulseSensor_nRF52840_Feather_Express/PulseSensor_nRF52840_Feather_Express.ino @@ -78,7 +78,7 @@ BLEDis bledis; Here, #define USE_ARDUINO_INTERRUPTS true tells the library to use interrupts to automatically read and process PulseSensor data. - See ProcessEverySample.ino for an example of not using interrupts. + See PulseSensor_BPM_Alternative.ino for an example of not using interrupts. */ #define USE_ARDUINO_INTERRUPTS true #include diff --git a/library.properties b/library.properties index bb5d225..920182d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PulseSensor Playground -version=1.8.2 +version=1.9.0 author=Joel Murphy, Yury Gitman, Brad Needham maintainer=Joel Murphy, Yury Gitman sentence=Support at PulseSensor.com diff --git a/src/PulseSensorPlayground.h b/src/PulseSensorPlayground.h index 4a664e1..edf1a52 100644 --- a/src/PulseSensorPlayground.h +++ b/src/PulseSensorPlayground.h @@ -133,6 +133,10 @@ #if defined(ARDUINO_ARCH_NRF52) #include "Adafruit_TinyUSB.h" #endif +// #if defined(ARDUINO_ARCH_RENESAS) +// #include "FspTimer.h" +// FspTimer sampleTimer +// #endif #include #include "utility/PulseSensor.h" #if USE_SERIAL @@ -140,6 +144,8 @@ #endif #include "utility/PulseSensorTimingStatistics.h" +#define SAMPLE_RATE_500HZ 500 + class PulseSensorPlayground { public: /* @@ -464,6 +470,12 @@ class PulseSensorPlayground { #if PULSE_SENSOR_TIMING_ANALYSIS // Don't use ram and flash we don't need. PulseSensorTimingStatistics *pTiming; #endif // PULSE_SENSOR_TIMING_ANALYSIS + +#if defined(ARDUINO_ARCH_RENESAS) + uint8_t timer_type; + int8_t tindex; +#endif + }; /* diff --git a/src/utility/Interrupts.h b/src/utility/Interrupts.h index 0adadc7..b05ae4d 100644 --- a/src/utility/Interrupts.h +++ b/src/utility/Interrupts.h @@ -65,7 +65,7 @@ #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_SAM)||(ARDUINO_ARCH_RENESAS) #define DISABLE_PULSE_SENSOR_INTERRUPTS #define ENABLE_PULSE_SENSOR_INTERRUPTS @@ -254,6 +254,10 @@ boolean PulseSensorPlaygroundSetupInterrupt() { result = true; #endif + #if defined(ARDUINO_ARCH_RENESAS) + result = true; + #endif + #endif // USE_ARDUINO_INTERRUPTS return result; @@ -320,8 +324,14 @@ boolean PulseSensorPlaygroundDisableInterrupt(){ result = true; #endif + #if defined(ARDUINO_ARCH_RENESAS) + sampleTimer.stop(); + #endif + #endif + + return result; // unknown or unsupported platform. } // PulseSensorPlaygroundDisableInterrupt @@ -388,6 +398,10 @@ boolean PulseSensorPlaygroundEnableInterrupt(){ result = true; #endif + #if defined(ARDUINO_ARCH_RENESAS) + sampleTimer.start(); + #endif + #endif return result; // unknown or unsupported platform. @@ -472,7 +486,12 @@ return result; // unknown or unsupported platform. // 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