Skip to content

zjp007/PulseAnalyzer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PulseAnalyzer 💓

Version Platform License

中文 | English

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.

✨ Features

  • 🚫 Zero Blocking: Completely abandons delay() and hardware interrupts. Perfectly compatible with timing-critical libraries like AccelStepper and FastLED.
  • 📈 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.

🛠️ Installation

  1. Click Code -> Download ZIP in the top right corner of this repository.
  2. Open Arduino IDE.
  3. Navigate to Sketch -> Include Library -> Add .ZIP Library.
  4. Select the downloaded ZIP file.

🔌 Wiring

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 (⚠️ CRITICAL: 5V will fry the ESP32 pin)
- (GND) GND GND

🚀 Quick Start

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();
}

📚 API Reference

PulseAnalyzer(int pin, int initialThresh, int blinkPin = -1)

Constructor.

  • pin: Analog input pin connected to the pulse sensor.
  • initialThresh: Initial baseline. Since the PPG signal is usually around half of VCC, 512 is recommended for 10-bit ADCs, and 2048 for 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 -1 to disable.

void begin()

Clears the internal IBI moving average array and prepares to receive data. Must be called in setup().

bool update()

[CORE METHOD] The engine of the algorithm. MUST be called in loop() as fast as possible (recommended total loop execution time < 2ms).

  • Returns: true if and only if the waveform crosses the dynamic threshold (heartbeat occurs). Otherwise false.

int getBPM()

Returns the most recently calculated BPM (Beats Per Minute). Automatically resets to 0 if no heartbeat is detected for 2.5 seconds.

int getIBI()

Returns the time interval between the last two heartbeats in milliseconds.

int getRawSignal()

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!)


⚠️ Performance Warning

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.


📄 License

This project is licensed under the MIT License. Feel free to use, modify, and integrate it into your wild kinetic installations!

About

A non-blocking, dynamic-threshold heart rate detection library for ESP32 and AVR board.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages