PulseAnalyzer is a pure non-blocking heart rate and IBI (Inter-Beat Interval) detection library designed for complex interactive installations.
Traditional heart rate libraries often hijack hardware timers, causing fatal system conflicts and pin failures when simultaneously driving stepper motor arrays, WS2812 LED strips, or pneumatic solenoids. This library utilizes a pure millis() polling architecture combined with a Dynamic Threshold Peak Detection algorithm, providing ultra-high precision pulse wave recognition while perfectly compatible with multi-task concurrency.
- 🚫 Zero Blocking: Completely abandons
delay()and hardware interrupts. Perfectly compatible with timing-critical libraries likeAccelStepperandFastLED. - 📈 Dynamic Adaptive Threshold: The algorithm tracks the peaks and troughs of the PPG waveform in real-time, automatically calculating the amplitude and setting the next trigger threshold at 50%, ensuring extreme interference resistance.
- 🔌 Cross-Platform Compatibility: Flawlessly supports 10-bit ADC Arduino boards (Uno/Mega2560) and 12-bit ADC ESP32/ESP8266.
- 💡 Auto Visual Feedback: Built-in non-blocking LED breathing/blinking logic without managing pin states in your main loop.
- 📊 Raw Waveform Output: Supports extracting raw ADC data, which can be directly fed into the Arduino IDE "Serial Plotter" for visual debugging.
- Click Code -> Download ZIP in the top right corner of this repository.
- Open Arduino IDE.
- Navigate to Sketch -> Include Library -> Add .ZIP Library.
- Select the downloaded ZIP file.
| Pulse Sensor | Arduino Mega 2560 | ESP32 (Note: MUST use ADC1) |
|---|---|---|
| S (Signal) | A0 (or any analog pin) |
GPIO 34 (or 32, 33, 35, 36, 39) |
| + (VCC) | 5V |
3.3V ( |
| - (GND) | GND |
GND |
Here is a basic example. Note the difference in initial threshold initialization.
#include <PulseAnalyzer.h>
// Instantiate object
// Syntax: PulseAnalyzer(SensorPin, InitialThreshold, [Optional]LED_Pin)
// 👉 For Arduino Mega/Uno (10-bit ADC, 0-1023):
PulseAnalyzer myPulse(A0, 512, 13);
// 👉 For ESP32 (12-bit ADC, 0-4095):
// PulseAnalyzer myPulse(34, 2048, 2);
void setup() {
Serial.begin(115200);
myPulse.begin();
Serial.println("PulseAnalyzer Ready!");
}
void loop() {
// 1. Call update() at high speed without blocking
// Returns true ONLY at the exact moment a heartbeat pulse is detected
if (myPulse.update()) {
int currentBPM = myPulse.getBPM();
int currentIBI = myPulse.getIBI();
Serial.print("❤️ Thump! IBI: ");
Serial.print(currentIBI);
Serial.print(" ms | BPM: ");
Serial.println(currentBPM);
// Trigger your pneumatic valves, lights, or motor animations here...
}
// 2. Run your other complex logic freely here
// stepper.run();
// FastLED.show();
}Constructor.
pin: Analog input pin connected to the pulse sensor.initialThresh: Initial baseline. Since the PPG signal is usually around half of VCC,512is recommended for 10-bit ADCs, and2048for 12-bit ADCs.blinkPin(optional): Digital pin connected to an LED. If configured, the pin will automatically light up for 50ms upon detecting a heartbeat. Leave blank or enter-1to disable.
Clears the internal IBI moving average array and prepares to receive data. Must be called in setup().
[CORE METHOD] The engine of the algorithm. MUST be called in loop() as fast as possible (recommended total loop execution time < 2ms).
- Returns:
trueif and only if the waveform crosses the dynamic threshold (heartbeat occurs). Otherwisefalse.
Returns the most recently calculated BPM (Beats Per Minute). Automatically resets to 0 if no heartbeat is detected for 2.5 seconds.
Returns the time interval between the last two heartbeats in milliseconds.
Returns the raw ADC value from the most recent sampling. (💡 Pro Tip: Put this in your loop and Serial.println(myPulse.getRawSignal());, then open the Arduino IDE Serial Plotter to observe your real-time ECG waveform!)
The extreme accuracy of this library relies on the update() method being called at high frequency (underlying sampling interval is 2ms). Absolutely AVOID using delay() or long-running while loops in your main loop(). If the main loop is blocked for more than 10ms, peaks will be missed, and BPM calculations will be severely distorted.
This project is licensed under the MIT License. Feel free to use, modify, and integrate it into your wild kinetic installations!