heart rate — ESP32 simulation

ESP32 reads a pulse wave from a custom Synthetic Heartbeat chip on GPIO 32 and computes BPM, flashing an RGB LED and beeping the buzzer on each beat.

An interactive ESP32 circuit simulation you can run free in your browser on Velxio, by 2023beec071.

Components

Sketch code

// ============================================================
// HEARTBEAT - BPM detector fed by a Synthetic Heartbeat chip
// The custom chip (custom chip "Synthetic Heartbeat") drives a
//   pulse wave on GPIO 32 (one pulse per beat, tunable via its
//   "bpm" attribute: 30-200).
// We detect RISING EDGES and compute BPM from the IBI.
// Feedback: RGB LED flashes + buzzer beeps on every beat.
// ============================================================

#define SENSOR_PIN  32
#define LED_RED     26
#define LED_GREEN   25
#define BUZZER      27

// Sanity window: real resting heart beats are 40-200 BPM
#define MIN_IBI_MS  300   // 300ms  -> 200 BPM
#define MAX_IBI_MS  1500  // 1500ms ->  40 BPM

unsigned long lastBeat = 0;
bool lastState = LOW;

void setup()
{
  Serial.begin(115200);

  pinMode(SENSOR_PIN, INPUT_PULLDOWN);   // watch the pulse wave
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(BUZZER, OUTPUT);

  digitalWrite(LED_GREEN, HIGH);         // green = armed / off beat
  digitalWrite(LED_RED, LOW);
  delay(100);

  Serial.println("Heartbeat detector armed (Synthetic Heartbeat chip on pin 32).");
}

void loop()
{
  bool state = digitalRead(SENSOR_PIN);

  // rising edge of the pulse wave
  if (state == HIGH && lastState == LOW)
  {
    unsigned long now = millis();
    if (lastBeat > 0)
    {
      unsigned long ibi = now - lastBeat;
      if (ibi >= MIN_IBI_MS && ibi <= MAX_IBI_MS)
      {
        int bpm = 60000UL / ibi;
        Serial.print("Beat!  IBI = ");
        Serial.print(ibi);
        Serial.print(" ms   BPM = ");
        Serial.println(bpm);

        digitalWrite(LED_GREEN, LOW);
        digitalWrite(LED_RED, HIGH);
        tone(BUZZER, 1000, 60);
      }
    }
    lastBeat = now;
  }

  if (state == LOW && lastState == HIGH)
  {
    digitalWrite(LED_GREEN, HIGH);
    digitalWrite(LED_RED, LOW);
  }

  lastState = state;
  delay(2);   // keep loop() responsive for the input
}

More projects by 2023beec071