Note : This page has been superseded, please use this new guide.
Heart beat sensors now seem to be cheap and plentiful (around 2 USD, a little less than 2 GBP and around 1.80 Euros). Here we’ll hook one up with an OLED display to show the results. Let’s Go…
The heart beat sensor I bought is shown below:
They should NOT be used as a medical device (XTroncial official disclaimer!), if you have any concerns about any part of your health – see a Doctor, not a web page about hooking up cheap heart rate sensors to cheap micro-controllers! But…. having said that, for fun I’ve found it very accurate in its readings, combined with some sort of graphical plot on a display its a really neat easy project.
Video Guide
If you want something more visual a video guide is available here:
How they work
As can be seen there are only three wires to these devices. One is power, the other ground and the final one is the analogue signal. So, these are not digital devices like the temperature sensor or the many other sensors available. This device outputs a voltage from 0V to VDD (supply voltage) depending on what they “sense”. They work by emitting an Infra-Red signal from an IR-Diode onto your skin. Just underneath your skin are capillaries carrying blood. Every time your heart pumps there is an small increase in blood flow/pressure. This swells the capillaries slightly, this slightly more filled capillary reflects more infra-red than at times when the heart is not giving your blood a “push”. An Infra-detector on the device senses the different reflected IR levels. Some simple comparator circuitry converts this into a voltage signal which we can read with the Arduino’s analogue inputs.
Connecting it up
Any micro-controller with an analogue input should work as the device operates from 3 -6V range (maybe even higher). Just connect the signal line (labelled “S” on my device) to an analogue input pin. The value you read from the pin will be in the range of zero to whatever the top value is on your particular micro-controller. For the normal default Arduino the range is from 0-1023 (1024 values). Here is the connection diagram showing just the Heart Beat connections.
This shows :
Pulse Sensor “+” to +5v on Arduino
Pulse Sensor “-” to Gnd on Arduino
Pulse Sensor “S” to A0 on Arduino
To show your heart beat graphically you can use the Arduino IDE in-built serial monitor plotter. Load up the code below into your IDE, then upload to your Arduino. Then select “Tools->Serial Plotter”
1 2 3 4 5 6 7 8 9 10 |
void setup() { Serial.begin(9600); } void loop() { Serial.println(analogRead(0)); delay(20); } |
Here’s my screen shot showing you what to expect. The Arduino Serial Plotter plots a value sent to it on a graph against time.
Using your own display
The in built plotter is great for a quick play but it doesn’t show you your heart rate in BPM (Beats Per Minute) at the same time. So for this project we’re adding in our own OLED display. These are readily available and the set up has been discussed in this article before, so we’ll just add it in here without further discussion. Wiring diagram below:
Here’s the code that will run this display, showing your “ECG” trace and your BPM. It was quite quickly “knocked up”, so apologies for any inefficiency.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#include <Adafruit_SSD1306.h> #define OLED_Address 0x3C Adafruit_SSD1306 oled(1); int x=0; int lastx=0; int lasty=0; int LastTime=0; bool BPMTiming=false; bool BeatComplete=false; int BPM=0; #define UpperThreshold 550 #define LowerThreshold 500 void setup() { oled.begin(SSD1306_SWITCHCAPVCC, OLED_Address); oled.clearDisplay(); oled.setTextSize(2); } void loop() { if(x>127) { oled.clearDisplay(); x=0; lastx=x; } int value=analogRead(0); oled.setTextColor(WHITE); int y=60-(value/16); oled.writeLine(lastx,lasty,x,y,WHITE); lasty=y; lastx=x; // calc bpm if(value>UpperThreshold) { if(BeatComplete) { BPM=millis()-LastTime; BPM=int(60/(float(BPM)/1000)); BPMTiming=false; BeatComplete=false; } if(BPMTiming==false) { LastTime=millis(); BPMTiming=true; } } if((value<LowerThreshold)&(BPMTiming)) BeatComplete=true; // display bpm oled.writeFillRect(0,50,128,16,BLACK); oled.setCursor(0,50); oled.print(BPM); oled.print(" BPM"); oled.display(); x++; } |
The output of this can be seen in the picture at the start of this article.
Use and limitations
As mentioned these are cheap but remarkable sensors but don’t expect to strap one to your finger and go jogging. They are very sensitive to movement and moving your hand about will cause massive swings of values – even if taped on. Also, tape them on too tightly and it reduces sensitivity dramatically. They can only be used if your hand is still, having said that you could still measure your Heart Beat at resting and just after exercise to compare. If you have any tips for monitoring with these devices whilst exercising please leave a comment.
Extending the project
A piezo sounder or speaker would be a nice addition, to give the “beep” sound effect, why not post your design if you implement this! New : See later after “Addendum”, this has now been added.
Addendum
A request was made for the BPM to be output as a raw value to the serial monitor (not plotter). Although not tested the code below should accomplish this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
bool BPMTiming=false; bool BeatComplete=false; int LastTime=0; int BPM=0; #define UpperThreshold 550 #define LowerThreshold 500 void setup() { Serial.begin(9600); } void loop() { int value=analogRead(0); // calc bpm if(value>UpperThreshold) { if(BeatComplete) { BPM=millis()-LastTime; BPM=int(60/(float(BPM)/1000)); BPMTiming=false; BeatComplete=false; } if(BPMTiming==false) { LastTime=millis(); BPMTiming=true; } } if((value<LowerThreshold)&(BPMTiming)) BeatComplete=true; // output bpm to serial monitor Serial.print(BPM); Serial.println(" BPM"); delay(1000); } |
Adding a Piezo Buzzer
To make this a little more “realistic” you could add a sound output. So the addition of a Piezo buzzer has been added. Simply connect it to pin D8 and GND, load up the code below and you’ll be good to go. This code beeps every heart-beat. it does not sound a “flat-line” single tone if limited activity. This is because it was not always very reliable due to the nature of the sensor which detects spurious pulses. In the real world a heart-beat monitor has several sensors monitoring actual heart activity. The photo shows my speaker addition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#include <Adafruit_SSD1306.h> #define OLED_Address 0x3C Adafruit_SSD1306 oled(1); int x=0; int lastx=0; int lasty=0; int LastTime=0; int ThisTime; bool BPMTiming=false; bool BeatComplete=false; int BPM=0; #define UpperThreshold 560 #define LowerThreshold 500 void setup() { oled.begin(SSD1306_SWITCHCAPVCC, OLED_Address); oled.clearDisplay(); oled.setTextSize(2); } void loop() { if(x>127) { oled.clearDisplay(); x=0; lastx=x; } ThisTime=millis(); int value=analogRead(0); oled.setTextColor(WHITE); int y=60-(value/16); oled.writeLine(lastx,lasty,x,y,WHITE); lasty=y; lastx=x; // calc bpm if(value>UpperThreshold) { if(BeatComplete) { BPM=ThisTime-LastTime; BPM=int(60/(float(BPM)/1000)); BPMTiming=false; BeatComplete=false; tone(8,1000,250); } if(BPMTiming==false) { LastTime=millis(); BPMTiming=true; } } if((value<LowerThreshold)&(BPMTiming)) BeatComplete=true; // display bpm oled.writeFillRect(0,50,128,16,BLACK); oled.setCursor(0,50); oled.print(BPM); oled.print(" BPM"); oled.display(); x++; } |
A video is available showing this addition