Pages

24 April 2015

Arduino Heart Rate Monitor

Project Description

Heart Rate Monitors are very popular at the moment.
There is something very appealing about watching the pattern of your own heart beat.
And once you see it, there is an unstoppable urge to try and control it.
This simple project will allow you to visualize your heart beat, and will calculate
your heart rate. Keep reading to learn how to create your very own heart rate monitor.

Grove Base Shield to Module Connections

/* ================================================================================================= Project: Arduino Heart rate monitor Author: Scott C Created: 21st April 2015 Arduino IDE: 1.6.2 Website: http://arduinobasics.blogspot.com/p/arduino-basics-projects-page.html Description: This is a simple sketch that uses a Grove Ear-clip Heart Rate sensor attached to an Arduino UNO, which sends heart rate data to the computer via Serial communication. You can see the raw data using the Serial monitor on the Arduino IDE, however, this sketch was specifically designed to interface with the matching Processing sketch for a much nicer graphical display. NO LIBRARIES REQUIRED.=================================================================================================== */
#define Heart 2 //Attach the Grove Ear-clip sensor to digital pin 2.
#define LED 4 //Attach an LED to digital pin 4boolean beat = false; /* This "beat" variable is used to control the timing of the Serial communication so that data is only sent when there is a "change" in digital readings. *///==SETUP==========================================================================================voidsetup() {
Serial.begin(9600); //Initialise serial communicationpinMode(Heart, INPUT); //Set digital pin 2 (heart rate sensor pin) as an INPUTpinMode(LED, OUTPUT); //Set digital pin 4 (LED) to an OUTPUT
}
//==LOOP============================================================================================voidloop() {
if(digitalRead(Heart)>0){ //The heart rate sensor will trigger HIGH when there is a heart beatif(!beat){ //Only send data when it first discovers a heart beat - otherwise it will send a high value multiple times
beat=true; //By changing the beat variable to true, it stops further transmissions of the high signaldigitalWrite(LED, HIGH); //Turn the LED on Serial.println(1023); //Send the high value to the computer via Serial communication.
}
} else { //If the reading is LOW, if(beat){ //and if this has just changed from HIGH to LOW (first low reading)
beat=false; //change the beat variable to false (to stop multiple transmissions)digitalWrite(LED, LOW); //Turn the LED off.Serial.println(0); //then send a low value to the computer via Serial communication.
}
}
}

/* ================================================================================================= Project: Arduino Heart rate monitor Author: Scott C Created: 21st April 2015Processing IDE: 2.2.1 Website: http://arduinobasics.blogspot.com/p/arduino-basics-projects-page.html Description: A Grove Ear-clip heart rate sensor allows an Arduino UNO to sense your pulse. The data obtained by the Arduino can then be sent to the computer via Serial communication which is then displayed graphically using this Processing sketch.=================================================================================================== */import processing.serial.*; // Import the serial library to allow Serial communication with the Arduinoint numOfRecs = 45; // numOfRecs: The number of rectangles to display across the screen
Rectangle[] myRecs = new Rectangle[numOfRecs]; // myRecs[]: Is the array of Rectangles. Rectangle is a custom class (programmed within this sketch)
Serial myPort;
String comPortString="0"; //comPortString: Is used to hold the string received from the Arduinofloat arduinoValue = 0; //arduinoValue: Is the float variable converted from comPortStringboolean beat = false; // beat: Used to control for multiple high/low signals coming from the Arduinoint totalTime = 0; // totalTime: Is the variable used to identify the total time between beatsint lastTime = 0; // lastTime: Is the variable used to remember when the last beat took placeint beatCounter = 0; // beatCounter: Is used to keep track of the number of beats (in order to calculate the average BPM)int totalBeats = 10; // totalBeats: Tells the computer that we want to calculate the average BPM using 10 beats.int[] BPM = newint[totalBeats]; // BPM[]: Is the Beat Per Minute (BPM) array - to hold 10 BPM calculationsint sumBPM = 0; // sumBPM: Is used to sum the BPM[] array values, and is then used to calculate the average BPM.int avgBPM = 0; // avgBPM: Is the variable used to hold the average BPM calculated value.PFont f, f2; // f & f2 : Are font related variables. Used to store font properties. //==SETUP==============================================================================================voidsetup(){
size(displayWidth,displayHeight); // Set the size of the display to match the monitor width and heightsmooth(); // Draw all shapes with smooth edges.
f = createFont("Arial",24); // Initialise the "f" font variable - used for the "calibrating" text displayed at the beginning
f2 = createFont("Arial",96); // Initialise the "f2" font variable - used for the avgBPM display on screenfor(int i=0; i<numOfRecs; i++){ // Initialise the array of rectangles
myRecs[i] = new Rectangle(i, numOfRecs);
}
for(int i=0; i<totalBeats; i++){ // Initialise the BPM array
BPM[i] = 0;
}
myPort = new Serial(this, Serial.list()[0], 9600); // Start Serial communication with the Arduino using a baud rate of 9600
myPort.bufferUntil('\n'); // Trigger a SerialEvent on new line
}
//==DRAW==============================================================================================voiddraw(){
background(0); // Set the background to BLACK (this clears the screen each time)
drawRecs(); // Method call to draw the rectangles on the screen
drawBPM(); // Method call to draw the avgBPM value to the top right of the screen
}
//==drawRecs==========================================================================================void drawRecs(){ // This custom method will draw the rectangles on the screen
myRecs[0].setSize(arduinoValue); // Set the first rectangle to match arduinoValue; any positive value will start the animation.for(int i=numOfRecs-1; i>0; i--){ // The loop counts backwards for coding efficiency - and is used to draw all of the rectangles to screen
myRecs[i].setMult(i); // setMulti creates the specific curve pattern.
myRecs[i].setRed(avgBPM); // The rectangles become more "Red" with higher avgBPM values
myRecs[i].setSize(myRecs[i-1].getH()); // The current rectangle size is determined by the height of the rectangle immediately to it's leftfill(myRecs[i].getR(),myRecs[i].getG(), myRecs[i].getB()); // Set the colour of this rectanglerect(myRecs[i].getX(), myRecs[i].getY(), myRecs[i].getW(), myRecs[i].getH()); // Draw this rectangle
}
}
//==drawBPM===========================================================================================void drawBPM(){ // This custom method is used to calculate the avgBPM and draw it to screen.
sumBPM = 0; // Reset the sumBPM variable
avgBPM = 0; // Reset the avgBPM variableboolean calibrating = false; // calibrating: this boolean variable is used to control when the avgBPM is displayed to screenfor(int i=1; i<totalBeats; i++){
sumBPM = sumBPM + BPM[i-1]; // Sum all of the BPM values in the BPM array.if(BPM[i-1]<1){ // If any BPM values are equal to 0, then set the calibrating variable to true.
calibrating = true; // This will be used later to display "calibrating" on the screen.
}
}
avgBPM = sumBPM/(totalBeats-1); // Calculate the average BPM from all BPM valuesfill(255); // The text will be displayed as WHITE textif(calibrating){
textFont(f);
text("Calibrating", (4*width)/5, (height/5)); // If the calibrating variable is TRUE, then display the word "Calibrating" on screenfill(0); // Change the fill and stroke to black (0) so that other text is "hidden" while calibrating variable is TRUEstroke(0);
} else {
textFont(f2);
text(avgBPM, (4*width)/5, (height/5)); // If the calibrating variable is FALSE, then display the avgBPM variable on screenstroke(255); // Change the stroke to white (255) to show the white line underlying the word BPM.
}
textFont(f);
text("BPM", (82*width)/100, (height/11)); // This will display the underlined word "BPM" when calibrating variable is FALSE.line((80*width)/100, (height/10),(88*width)/100, (height/10));
stroke(0);
}
//==serialEvent===========================================================================================void serialEvent(Serial cPort){ // This will be triggered every time a "new line" of data is received from the Arduino
comPortString = cPort.readStringUntil('\n'); // Read this data into the comPortString variable.if(comPortString != null) { // If the comPortString variable is not NULL then
comPortString=trim(comPortString); // trim any white space around the text.int i = int(map(Integer.parseInt(comPortString),1,1023,1,height)); // convert the string to an integer, and map the value so that the rectangle will fit within the screen.
arduinoValue = float(i); // Convert the integer into a float value.if (!beat){
if(arduinoValue>0){ // When a beat is detected, the "trigger" method is called.
trigger(millis()); // millis() creates a timeStamp of when the beat occured.
beat=true; // The beat variable is changed to TRUE to register that a beat has been detected.
}
}
if (arduinoValue<1){ // When the Arduino value returns back to zero, we will need to change the beat status to FALSE.
beat = false;
}
}
}
//==trigger===========================================================================================void trigger(int time){ // This method is used to calculate the Beats per Minute (BPM) and to store the last 10 BPMs into the BPM[] array.
totalTime = time - lastTime; // totalTime = the current beat time minus the last time there was a beat.
lastTime = time; // Set the lastTime variable to the current "time" for the next round of calculations.
BPM[beatCounter] = 60000/totalTime; // Calculate BPM from the totalTime. 60000 = 1 minute.
beatCounter++; // Increment the beatCounter if (beatCounter>totalBeats-1){ // Reset the beatCounter when the total number of BPMs have been stored into the BPM[] array.
beatCounter=0; // This allows us to keep the last 10 BPM calculations at all times.
}
}
//==sketchFullScreen==========================================================================================boolean sketchFullScreen() { // This puts Processing into Full Screen Modereturntrue;
}
//==Rectangle CLASS==================================================================================*********class Rectangle{
float xPos, defaultY, yPos, myWidth, myHeight, myMultiplier; // Variables used for drawing rectanglesint blueVal, greenVal, redVal; // Variables used for the rectangle colour
Rectangle(int recNum, int nRecs){ // The rectangles are constructed using two variables. The total number of rectangles to be displayed, and the identification of this rectangle (recNum)
myWidth = displayWidth/nRecs; // The width of the rectangle is determined by the screen width and the total number of rectangles.
xPos = recNum * myWidth; // The x Position of this rectangle is determined by the width of the rectangles (all same) and the rectangle identifier.
defaultY=displayHeight/2; // The default Y position of the rectangle is half way down the screen.
yPos = defaultY; // yPos is used to adjust the position of the rectangle as the size changes.
myHeight = 1; // The height of the rectangle starts at 1 pixel
myMultiplier = 1; // The myMultiplier variable will be used to create the funnel shaped path for the rectangles.
redVal = 0; // The red Value starts off being 0 - but changes with avgBPM. Higher avgBPM means higher redValif (recNum>0){ // The blue Value progressively increases with every rectangle (moving to the right of the screen)
blueVal = (recNum*255)/nRecs;
} else {
blueVal = 0;
}
greenVal = 255-blueVal; // Initially, the green value is at the opposite end of the spectrum to the blue value.
}
void setSize(float newSize){ // This is used to set the new size of each rectangle
myHeight=newSize*myMultiplier;
yPos=defaultY-(newSize/2);
}
void setMult(int i){ // The multiplier is a function of COS, which means that it varies from 1 to 0.
myMultiplier = cos(radians(i)); // You can try other functions to experience different effects.
}
void setRed(int r){
redVal = int(constrain(map(float(r), 60, 100, 0, 255),0,255)); // setRed is used to change the redValue based on the "normal" value for resting BPM (60-100).
greenVal = 255 - redVal; // When the avgBPM > 100, redVal will equal 255, and the greenVal will equal 0.
} // When the avgBPM < 60, redVal will equal 0, and greenVal will equal 255.float getX(){ // get the x Position of the rectanglereturn xPos;
}
float getY(){ // get the y Position of the rectanglereturn yPos;
}
float getW(){ // get the width of the rectanglereturn myWidth;
}
float getH(){ // get the height of the rectanglereturn myHeight;
}
float getM(){ // get the Multiplier of the rectanglereturn myMultiplier;
}
int getB(){ // get the "blue" component of the rectangle colourreturn blueVal;
}
int getR(){ // get the "red" component of the rectangle colourreturn redVal;
}
int getG(){ // get the "green" component of the rectangle colourreturn greenVal;
}
}

Processing Code Discussion:

The Rectangle class was created to store relevant information about each rectangle.
By using a custom class, we were able to design our rectangles any way we wanted.
These rectangles have properties and methods which allow us to easily control their
position, size and colour. By adding some smart functionality to each rectangle, we were able to get the rectangle to automatically
position and colour itself based on key values.

The Serial library is used to allow communication with the Arduino. In this Processing sketch, the values obtained from the Arduino
were converted to floats to allow easy calulations of the beats per minute (BPM).
I am aware that I have over-engineered the serialEvent method somewhat, because the Arduino
is only really sending two values. I didn't really need to convert the String. But I am happy with
the end result, and it does the job I needed it to...

This project is quite simple. I designed it so that you could omit the Processing code if you wanted to.
In that scenario, you would only be left with a blinking LED that blinks in time with your pulse.
The Processing code takes this project to the next level. It provides a nice animation and calculates
the beats per minute (BPM).

I hope you liked this tutorial. Please feel free to share it, comment or give it a plus one.
If you didn't like it, I would still appreciate your constructive feedback.

If you like this page, please do me a favour and show your appreciation :

83 comments:

I want to get a strip of LEDs (such as these: https://www.sparkfun.com/products/12023) to pulse to my heartbeat. Could you suggest how that would be done? I´m a novice with electronics so would really appreciate your help.

Hi Ali - please go to the forum post that I mentioned in my last reply.I have posted a link to my instagram account which perhaps shows what you are trying to do.Let me know what you think - and then we can try and update it as required.

First,thank you so much for uploading the project.I'm a beginner and I have some problems.I get a lot of error messages when I paste the code on my arduino software.So I'm wondering where should I put these code and what else should I do to make it work?

Hi! I really like your project!I'd like to do something similar like this for my final year project so I would like to ask you a few questions if you don't mind.If I'm not mistaken, you have connected this to your computer and you are watching all of this through your monitor, right?Is it possible instead of the computer to attach this to the LCD screen and to bring external power supply so you can get portable device?Can you suggest how to do it?Best regards,LeVu

Hi Levu - obviously you would have to connect the wires directly to the heartbeat sensor - and would not be able to use the grove base shield, but the code should still work on the Arduino Pro Mini - I cannot see why it wouldn't work?? I am assuming you are referring to a 5V version of pro mini? If not, then you will need to check the operating instructions for that heart-beat sensor to see if it can operate at 3.3V

Well you see, I'm making my own sensor with the optocoupler in SMD technology, because I want it to be as smaller as possible, that's why I used Pro Mini instead of Uno. Im going to plase sensor to the botom side of Arduino and attach it directly from there. Now I only need to find solution for the power supply, because it must have small dimensions too, so it wont ruin the size of this project.Thank you for your answers Scott C!

Hi, I tried with this code its working with the arduino but the processing code is not working it shows as calibrating for a long time not displaying any thing , what to do further, do i want to make any change with code.

Ok - you definitely need to run the Arduino Code at the same time as the processing code. Make sure that the Serial monitor on the Arduino IDE is closed before you run the Processing code. Also make sure you have the Arduino code running before you start the Processing code. And yes - you may have to specifically assign the com port in the processing code. You may want to use a number of Print statements within the Processing code to see where it is failing or why it continues to say Calibrating. What that calibrating message means (when it stays like that forever) is that it is not receiving the 1023 values from the Arduino. It needs to acquire about 10 beats before it will show you the Average BPM.

Hey So I'm stuck in "calibrating" also. I'm getting 0 1023 0 1023 as well. Not sure what do do next. I've real all the comments here and it hasn't been that helpful. How DO I change the COM Port. What else can I try?

The COM port is determined by the following line:myPort = new Serial(this, Serial.list()[0], 9600);

If you have more than one active COM port, you could possibly try to use Serial.list()[1] instead.

Sometimes it is helpful to print the Serial.list() to the debug window to see the available COM ports, and choose the SAME one as that in Arduino IDE (i.e. the COM port you use to upload your sketch to the Arduino).

Great job sir...I am currently working on the project"health monitoring ",where i need to measure the BPM ,and whenever it exceeds certain limit it alerts ...so i would be thankful if you provide calculation of BPM from "only the arduino code"...I don't need any animations and processing thakning youwaiting for your reply sir

I didn't use the Arduino to do the BPM calculations. I used processing. You just have to transfer the calculations to the Arduino.Calculate the time between beats. Divide 1 minute, by that calculated time to get BPM. Make sure you use the same units for the numerator and denominator.

No you don't need the Grove base shield for Processing. It is used as an interface between the heart-rate sensor and the Arduino. If you know what you are doing, you can bypass the Grove base shield, however, it is easier to use it when you have it.

Hello, I have to program this sensor on arduino uno using test code for my project and also I don't need the animation with the rectangle. Someone who can give me a test code of this sensor ? I try to use only the arduino code but i just get 0 and 1023 values. Thanks

What values were you expecting from this sensor ? It sends a digital reading to the Arduino (0 or 1), the code converts this to 0 or 1023. I am not exactly sure why I made this conversion.. I could have just left it to send a 0 or 1 to the Processing sketch on the computer. If you were looking for an analog reading, then this sensor is not suitable for your project.

Thanks for uploading the project.I'm working on a project using an app developed by the App Inventor to receive data from this heart rate sensor via bluetooth and react if there's no heartbeat.Can you give me some suggestions?Um...like how can I know if there's a heartbeat or not and give my app the signal?

I am working on my dissertation and looking to guage user heart beats. Having set up the arduino code and the processing and followed all your instructions read in the comments, I still encountered the following error.

Hi!I am a part of a group project on heart beat detector, we are using Arduino Uno with a KY-039 sensor to sense the heart beat.We are very new to Arduino and processing, and want to display the readings of the sensor as a graph using processing. Could you guide us on how to do that? It would be really helpful!Thanks a lot!

HI,I am currently working on one project in which i have to use the bio-medical sensor for sense the signal which is generated by human body during some typical condition (like, pain due to injury) and it is in micro volts. so, anyone can suggest appropriate sensor which i will interface with commercial controller

Hi, in my project, I'm thinking of using a RGB LED to show the 3 different range of heart rates during an exercise. I can't seem to figure out the code to to get Green to blink at 60-100bpm, Blue at 101-150bpm and Red at 151-200bpm. Can you help me with this?

Hi ScottFirst of all great project, absolutely fantastic. I am doing a very similar final year project except i want it my device to be portable. in this case how would i execute it without connecting the arduino to a computer and still display BPM on a lcd screen? thanks

Firstly, did you use both the Arduino IDE and Processing IDE?Note that this tutorial uses two seperate IDEs.The Arduino IDE is used to upload the Arduino code to the Arduino Microcontroller.The Processing IDE is used to run the Processing sketch on your computer.

The titles of each section are actually a link to the relevant IDE download page. So if you click on the "Processing Sketch" title just before the code is displayed, it will take you to the Processing IDE download page.

You do not need to download any libraries for this tutorial. The processing sketch uses a Serial library which is inbuilt into the IDE.

Thank you for a very useful tutorial. I am thinking of trying this out myself but instead of a serial connection to a PC I was thinking of a WiFi connection can you see any big problems with my idea or is it not possible? Your input would be greatly appreciated?

Hi, I really need your help, it`s an emergency :( I would like to ask you the following question: Is it the same fritzing sketch that I need to follow if I`m just gonna make the arduino code? I have the grove base shield and all the requiered material, but I don`t know if just because I`m making only the arduino code the fritzing sketch changes. Thank you so much!

I am currently working on a project which would just display the BPM on an LCD Arduino Shield. should this code work for this, if I just copy the BPM calculation code from the processing file and run it in the arduino code? I am using the Grove Heart rate sensor with the wrist strap and don't have the base shield, instead I am just connecting using a grove to jumper wire, does this also work in the same way? Thanks Olivia

Hi Olivia,The Arduino sends HIGH and LOW signals to the computer, and the computer does the necessary calculations to works out the BPM, and from that BPM, the animations are created. There is no reason why this project could not be adapted to run on an LCD screen, but you may find it easier if you run the "animation" from a seperate Arduino. It may be possible to use just one Arduino, but using two will give you some added flexibility. So one Arduino will take the readings, and the second one will display the heart beat on the LCD. Either way, it should be possible. You can definitely calculate the BPM on the Arduino, but it may need to be adpted somewhat from the Processing code. Calculate the amount of time between beats, using millis() function, and go from there.The Grove base shield just makes the connections to the Arduino easier and neater, but of course, you could just use jumper wires if you wanted to.