This biomedical monitoring project utilizes an ESP32 processing core to capture blood volume changes caused by arterial tissue contraction pulse waves. By scanning the analog telemetry stream outputted by a specialized Pulse Sensor module, a threshold-driven heartbeat detection algorithm measures precise time intervals between beats to extract stabilized real-time Beats Per Minute (BPM). Visual telemetry arrays are simultaneously routed down active serial pipes and onto a sleek 0.96-inch SSD1306 OLED interface monitor.
Watch the full demonstration, calibration configuration walkthrough, and biotelemetry testing live below:
Procure the following components to execute the core prototyping phase layout configurations:
| Target Component Label | Structural Allocation Quantity | Functional Deployment Purpose |
|---|---|---|
| ESP32 Development Board | 1 Unit | Central processing execution core and telemetry clock loop. |
| Pulse Sensor Transducer Module | 1 Unit | Real-time peripheral blood volume change sensory capture. |
| 0.96" SSD1306 OLED Display (I2C) | 1 Unit | High-contrast visual interface for real-time telemetry metrics tracking. |
| Prototyping Breadboard & Wires | 1 Set | Solderless hardware interface routing connection matrix. |
Wire the physical subsystem communication buses in accordance with the following structured reference maps:
| Sensor Transducer Node Pin | ESP32 Host Mapping Node Pin |
|---|---|
| VCC (Module Power) | 3.3V Power Output Rail |
| GND (Ground Return Plane) | GND Common Reference Ground |
| Signal (Analog Data Output) | GPIO 13 Analog Intercept Node |
| Character Display I2C Board Node | ESP32 Master Mapping Pin Interface |
|---|---|
| VCC (Module Power) | 3.3V Shared Positive Voltage Rail |
| GND (Module Ground) | GND Shared Reference Ground Plane |
| SDA (I2C Serial Data Line) | GPIO 21 Dedicated Communication Node |
| SCL (I2C Serial Clock Line) | GPIO 20 Dedicated Communication Node |
Copy and integrate this production-ready code directly into your local desktop Arduino IDE environment:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
// Pins matching your circuit image
#define PULSE_PIN 13
#define SDA_PIN 21
#define SCL_PIN 20
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// BPM Tracking Variables
unsigned long lastBeatTime = 0;
unsigned long currentBeatTime = 0;
// Adjusted for 16-bit scale (0-65535). Midpoint is roughly 35000 at 3.3V
int threshold = 35000;
bool anyBeat = false;
int bpm = 0;
void setup()
{
Serial.begin(115200);
// REMOVED: pinMode(PULSE_PIN, INPUT) as it glitches ESP32 analog reads.
// Initialize I2C with your exact pins: SDA=21, SCL=20
Wire.begin(SDA_PIN, SCL_PIN);
// Initialize OLED Display
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.setTextColor(SSD1306_WHITE);
display.clearDisplay();
display.display();
Serial.println("Heart Rate Monitor Started");
}
void loop()
{
// Read the analog signal from the Pulse Sensor
int signalValue = analogRead(PULSE_PIN);
// Heartbeat detection logic
if (signalValue > threshold && anyBeat == false)
{
anyBeat = true;
currentBeatTime = millis();
unsigned long beatDuration = currentBeatTime - lastBeatTime;
// Debounce: Human heart standard range
if (beatDuration > 300 && beatDuration < 2000)
{
bpm = 60000 / beatDuration;
}
lastBeatTime = currentBeatTime;
}
// Reset the beat flag when the signal drops back below the threshold
if (signalValue < (threshold - 2000))
{
anyBeat = false;
}
// Print to Serial Monitor
Serial.print("Signal:");
Serial.print(signalValue);
Serial.print(",");
Serial.print("BPM:");
Serial.println(bpm);
// Draw everything to the OLED Screen
display.clearDisplay();
display.setTextSize(1);
display.setCursor(15, 0);
display.println("HEART RATE MONITOR");
display.drawFastHLine(0, 12, 128, SSD1306_WHITE);
display.setCursor(0, 22);
display.print("Signal: ");
display.print(signalValue);
display.setCursor(100, 22);
if(anyBeat) {
display.print("<3");
} else {
display.print(" ");
}
display.setTextSize(2);
display.setCursor(0, 42);
display.print("BPM: ");
if (bpm > 30 && bpm < 200) {
display.print(bpm);
} else {
display.print("---");
}
display.display();
delay(20);
}

0 Comments