Measure your heart rate with the heartbeat sensor

Put your fingertip on the heartbeat sensor and watch your pulse appear as a wave on the Serial Plotter. The UNO finds every beat in the wave and works out your heart rate in beats per minute, just like the...
  • Level:Intermediate
  • Duration: 50 min
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Measure your heart rate with the heartbeat sensor – EEMENTOR STEM™ lesson

When you visit a doctor or a hospital, a nurse often clips a small sensor on your finger. A red light shines through your fingertip, and the sensor measures how much light gets through. Every time your heart beats, a little more blood is pushed into your finger, and a little less light gets through. In this lesson you do the same with the heartbeat sensor from the sensor kit and the UNO. You will see your own pulse as a wave on the Serial Plotter, and the UNO will find every beat and work out your heart rate in beats per minute (BPM). Then you can find out how fast your heart beats after ten jumping jacks, or when you hold your breath.

What you'll learn

  • How a pulse sensor "sees" blood with infrared light (photoplethysmography, PPG)
  • How to clean up a weak, noisy signal with two moving averages
  • How to find beats with a threshold that adapts to the signal
  • How to turn the time between beats into beats per minute

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Heartbeat sensor module (45-in-1 Sensor Kit)
  • A dark cloth or a small box to keep room light away from the sensor
  • Breadboard and jumper wires (UNO R3 Starter Kit)

This is a science project, not a medical device. It is great for learning how pulse sensors work, but it is not accurate enough to check anyone's health. If you ever feel unwell, dizzy or your heart races for no reason, tell an adult or a doctor, and never use this project instead of a real medical check.

Wiring

Breadboard wiring diagram: Measure your heart rate with the heartbeat sensor
Breadboard view. Check each connection against the wiring table below.

Build it step by step

Plug in all the parts first, then add the wires in this order. In each picture the new wires are bright and the ones from earlier steps are faded. Click a picture to see it larger.

Step 1 of 2: Power rails: 5V and GND from the UNO
Step 1. Power rails: 5V and GND from the UNO
Step 2 of 2: Heartbeat sensor (fingertip here): S → A0
Step 2. Heartbeat sensor (fingertip here): S → A0
From To
Heartbeat sensor S (signal) UNO A0
Heartbeat sensor + (middle pin) 5V
Heartbeat sensor − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

The module has an infrared LED on one side and a light sensor (a phototransistor) on the other. Bend the LED a little so it points towards the sensor, with a gap just wide enough for your fingertip.

The sketch

const int SENSOR_PIN = A0, LED_PIN = 13;
const unsigned long SAMPLE_MS = 20;   // 50 readings a second
const bool PLOTTER = true;            // true: a wave for the Serial Plotter, false: one line per beat

float smooth = 0, baseline = 0, envelope = 2;
bool high = false;
unsigned long lastSample = 0, lastBeat = 0;
unsigned long gaps[4];                // the last four times between beats
int count = 0, next = 0, bpm = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  smooth = baseline = analogRead(SENSOR_PIN);
  if (!PLOTTER) Serial.println("Put your fingertip on the sensor and keep still");
}

void beat(unsigned long now) {
  unsigned long gap = now - lastBeat;
  lastBeat = now;
  if (gap > 2000) return;             // the first beat after a pause: nothing to measure yet
  gaps[next] = gap;
  next = (next + 1) % 4;
  if (count < 4) count++;
  unsigned long sum = 0;
  for (int i = 0; i < count; i++) sum += gaps[i];
  bpm = 60000UL * count / sum;        // 60,000 ms in a minute
  if (!PLOTTER) {
    Serial.print("Beat! ");
    Serial.print(bpm);
    Serial.println(" BPM");
  }
}

void loop() {
  unsigned long now = millis();
  if (now - lastSample < SAMPLE_MS) return;
  lastSample = now;

  int reading = analogRead(SENSOR_PIN);
  smooth = smooth * 0.7 + reading * 0.3;          // removes fast flicker
  baseline = baseline * 0.97 + smooth * 0.03;     // follows slow changes, like pressing harder
  float pulse = smooth - baseline;                // what is left is the heartbeat wave

  envelope = max(envelope * 0.995, fabs(pulse));  // how big the recent waves are
  float threshold = max(envelope * 0.5, 0.8);     // half way up, but never tiny noise

  if (!high && pulse > threshold && now - lastBeat > 300) {   // at most 200 beats a minute
    high = true;
    digitalWrite(LED_PIN, HIGH);
    beat(now);
  }
  if (high && pulse < 0) {            // the wave has gone back down: ready for the next beat
    high = false;
    digitalWrite(LED_PIN, LOW);
  }
  if (now - lastBeat > 3000 && count > 0) {       // no beat for 3 s: finger gone?
    count = 0;                        // start a fresh average
    next = 0;
    bpm = 0;
    if (!PLOTTER) Serial.println("No pulse found. Keep your finger still on the sensor");
  }

  if (PLOTTER) {
    Serial.print("pulse:");
    Serial.print(pulse, 1);
    Serial.print(",threshold:");
    Serial.println(threshold, 1);
  }
}

Try it

  1. Upload the sketch and open Tools → Serial Plotter at 9600 baud.
  2. Rest your fingertip gently between the LED and the sensor. Don't press hard: squeezing pushes the blood out of your fingertip. Cover your hand and the sensor with a dark cloth, because lamps flicker and disturb the light sensor.
  3. Keep completely still for 10 seconds. A wave appears: one bump for every heartbeat. The built-in LED "L" blinks with each beat.
  4. Change PLOTTER to false, upload again and open the Serial Monitor. Now you see your heart rate: Beat! 72 BPM.
  5. Do ten jumping jacks, sit down and measure again. How long does it take until your heart rate is back to where it started?

A resting heart rate is usually between about 70 and 110 BPM for children and 60 to 100 for adults. Athletes can be lower. Moving your finger, talking or laughing makes big bumps that the sketch may count as extra beats, so keep still while you measure.

What you should see

Serial Plotter at 9600 baud with a red pulse wave and a blue threshold line, the LED blinking on each beat, and the Serial Monitor showing lines like Beat! 72 BPM.

How it works

Infrared light shining through a fingertip to a light sensor, then the sketch's smooth, baseline and pulse steps and the maths 60,000 × 4 ÷ 3,200 = 75 BPM.

Light goes through your fingertip quite easily, but blood absorbs some of it. Each heartbeat pushes a small wave of blood into the tiny blood vessels of your finger, so for a moment less infrared light reaches the sensor. Measuring blood with light like this is called photoplethysmography, or PPG. Pulse oximeters in hospitals, smartwatches and fitness bands all use it.

The change is tiny: often only a few steps out of 1023. So the sketch cleans the signal in two steps. smooth takes 30 % of each new reading and removes fast flicker. baseline takes only 3 % and moves so slowly that it ignores the heartbeat but follows slow changes, for example when you press a little harder. smooth - baseline leaves just the heartbeat wave, going up and down around zero.

Every person's wave has a different size, so a fixed threshold would not work. The envelope remembers how big the recent waves were and shrinks slowly; the threshold is half of it. A beat counts when the wave rises above the threshold, and the next beat can only count after the wave has gone back below zero and at least 300 ms have passed. The sketch keeps the times between the last four beats: if they add up to 3,200 ms, the heart rate is 60,000 × 4 ÷ 3,200 = 75 BPM.

Try this next

  • Add the passive buzzer on pin 8 and play a short tone() on every beat, like a hospital heart monitor.
  • Show the heart rate on the 1602 LCD, with a heart symbol that blinks on each beat.
  • Measure your heart rate lying down, sitting and standing. In which position is it lowest, and why?
  • Try your earlobe instead of your finger: clip the sensor gently with a clothes peg.

Troubleshooting

  • The wave is flat: check S on A0 and that the LED points at the sensor. Try another finger, and make sure your hands are warm: cold fingers have less blood flow.
  • The wave is huge and jumpy, or the BPM is far too high: you are moving, pressing too hard or room light is getting in. Rest your hand on the table, touch lightly and cover the sensor.
  • Nothing changes at all, even without a finger: the + and − pins may be the other way round on your module. Check the labels and the wiring.
  • The Serial Plotter shows text instead of a graph: close it, set PLOTTER back to true and upload again.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit