Heart Beat Monitoring over Internet using Arduino and ThingSpeak

In this project we are going to make a Heart Beat Detection and Monitoring System using Arduino that will detect the heart beat using the Pulse Sensor and will show the readings in BPM (Beats Per Minute) on the LCD connected to it. It will also send the readings to ThingSpeak server using the Wi-Fi module ESP8266, so that Heart Beats can be monitored from anywhere in the world over the internet. ThingSpeak is a great source for displaying the data online and you can access the data from ThingSpeak at any time and at any place.

We have previously built a simple Heart Beat Monitor without showing data on Internet. This time we have used ThingSpeak to monitor the system over internet, and this will put this project into IOT category.

 

Components Required:

  • Pulse sensor
  • Wi-Fi module ESP8266
  • Arduino Uno
  • LCD
  • Bread Board
  • 10k potentiometer
  • 1k resistors
  • 220 ohm resistors
  • LED
  • Connecting wires

 

Circuit Diagram and Explanation:

First of all we will connect the ESP8266 with the Arduino. ESP8266 runs on 3.3V and if you will give it 5V from the Arduino then it won’t work properly and it may get damage. Connect the VCC and the CH_PD to the 3.3V pin of Arduino. The RX pin of ESP8266 works on 3.3V and it will not communicate with the Arduino when we will connect it directly to the Arduino. So, we will have to make a voltage divider for it which will convert the 5V into 3.3V. This can be done by connecting three resistors in series like we did in the circuit. Connect the TX pin of the ESP8266 to the pin 9 of the Arduino and the RX pin of the ESP8266 to the pin 10 of Arduino through the resistors.

ESP8266-wifi-module

ESP8266 Wi-Fi module gives your projects access to Wi-Fi or internet. It is a very cheap device and make your projects very powerful. It can communicate with any microcontroller and it is the most leading devices in the IOT platform. Learn more about using ESP8266 with Arduino here.

 

Then connect the Pulse Sensor with the Arduino. The connections of the pulse sensor are very easy. Pulse sensor has three pins. Connect 5V and the ground pin of the pulse sensor to the 5V and the ground of the Arduino and the signal pin to the A0 of Arduino.

pulse_sensor

Then connect the LED to pin 13 of Arduino. You do not have to connect a resistor with because the Arduino has built in resistor at pin 13.

In last, we will connect LCD with the Arduino. The connections of the LCD are as follows

  • Connect pin 1 (VEE) to the ground.
  • Connect pin 2 (VDD or VCC) to the 5V.
  • Connect pin 3 (V0) to the middle pin of the 10K potentiometer and connect the other two ends of the potentiometer to the VCC and the GND. The potentiometer is used to control the screen contrast of the LCD. Potentiometer of values other than 10K will work too.
  • Connect pin 4 (RS) to the pin 12 of the Arduino.
  • Connect pin 5 (Read/Write) to the ground of Arduino. This pin is not often used so we will connect it to the ground.
  • Connect pin 6 (E) to the pin 11 of the Arduino. The RS and E pin are the control pins which are used to send data and characters.
  • The following four pins are data pins which are used to communicate with the Arduino.

Connect pin 11 (D4) to pin 5 of Arduino.

Connect pin 12 (D5) to pin 4 of Arduino.

Connect pin 13 (D6) to pin 3 of Arduino.

Connect pin 14 (D7) to pin 2 of Arduino.

  • Connect pin 15 to the VCC through the 220 ohm resistor. The resistor will be used to set the back light brightness. Larger values will make the back light much more darker.
  • Connect pin 16 to the Ground.

Heart-rate-monitoring-over-internet-circuit-diagram

 

ThingSpeak Setup:

ThingSpeak provides very good tool for IoT based projects. By using ThingSpeak site, we can monitor our data and control our system over the Internet, using the Channels and webpages provided by ThingSpeak. ThingSpeak ‘Collects’ the data from the sensors, ‘Analyze and Visualize’ the data and ‘Acts’ by triggering a reaction. We have previously used ThingSpeak in Weather station project using Raspberry Pi and using Arduino, check them to learn more about ThingSpeak. Here we are briefly explaining to use ThingSpeak for this IoT Heart Beat Monitoring Project.

First of all, user needs to Create a Account on ThingSpeak.com, then Sign In and click on Get Started.

thingspeak-signup

After creating an account, go to channels and create a new channel. Now write the name of the Channel and name of the Fields. Also tick the check box for ‘Make Public’ option below in the form and finally Save the Channel. Now your new channel has been created.

Hear-rate-Monitoring-ThingSpeak-newchannel

 

After this go to API keys and copy your Write API key. You will need this in the code. Check the Full Code at the end.

Thingspeak-API-key

 

Working Explanation:

First we need to attach the Pulse Sensor to any organ of body where it can detect the pulse easily like finger, check the video below. Then the Pulse Sensor will measure the change in volume of blood, which occurs when every time heart pumps blood in the body. This change in volume of blood causes a change in the light intensity through that organ. The Arduino will then convert this change into the heart beat per minute (BPM). The LED connected at pin 13 will also blink according the Heart Beat.

The ESP8266 will then communicate with the Arduino and will send the data to ThingSpeak. The ESP8266 will connect the network of your router that you will provide in the code and will send the data of the sensor online. This data on the ThingSpeak will be shown in a Graph form showing the past readings too and can be accessed from anywhere over internet. The LCD connected will also show you the BPM.

Arduino-based-Heart-rate-monitoring-over-thingspeak Arduino-Heart-rate-monitoring-over-internet-reading

 

Code Explanation:

First of all, add the libraries. Software serial library is for enabling the RX and TX at pin 9 and pin 10. The default RX and TX pins of Arduino are pin 0 and 1 but if you want to enable it at other pins that you will have to use the software serial library. Then initialize the liquid crystal library (LiquidCrystal.h) and declare the pins at which you have connected the LCD.

#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(9,10); 
#include <LiquidCrystal.h>
#include <stdlib.h>
LiquidCrystal lcd(12,11,5,4,3,2);

 

Enter the Wi-Fi name, password and IP address of ESP8266. Then enter the API key from ThingSpeak that you saved earlier.

#define SSID "Your Wifi Name"
#define PASS "Your Wifi Password"
#define IP "184.106.153.149"
String msg = "GET /update?key=9YS21NU0HY5YS1IKU";

 

The following code will start the LCD and will set the baud rate. Enter the baud rate according to your ESP8266. Every ESP8266 has its own baud rate. Some have baud rate of 9600, some have 115200 or other.

void setup()
{
  lcd.begin(16, 2);
  lcd.print("circuitdigest.com");
  delay(100);
  lcd.setCursor(0,1);
  lcd.print("Connecting...");
  Serial.begin(9600); //or use default 115200.
  esp8266.begin(9600);
  Serial.println("AT");
  esp8266.println("AT");
  delay(5000);
  if(esp8266.find("OK")){
    connectWiFi();
  }
  interruptSetup(); 
}

 

Following function void updatebeat() will send the data at the IP address that we have entered and also will set the data in the field we set for heart beat.

void updatebeat(){
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  Serial.println(cmd);
  esp8266.println(cmd);
  delay(2000);
  if(esp8266.find("Error")){
    return;
  }
  cmd = msg ;
  cmd += "&field1=";   
  cmd += BPM;
  ..... .....
  ...... .....

 

The following code will connect the ESP8266 with the Wi-Fi network that you entered earlier and then it will use this network to send the data to the ThingSpeak.

boolean connectWiFi(){
  Serial.println("AT+CWMODE=1");
  esp8266.println("AT+CWMODE=1");
  delay(2000);
  String cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  .... .....
  ..... .....

 

The following code will read the sensor and will convert the output of the sensor into heart beat per minute (BPM). It will also blink the LED connected at the pin 13 according to the BPM.

ISR(TIMER2_COMPA_vect){
  cli();
  Signal = analogRead(pulsePin);
  sampleCounter += 2;
  int N = sampleCounter - lastBeatTime;
  if(Signal < thresh && N > (IBI/5)*3){
    if (Signal < T){
      T = Signal; 
      ... ....
       ...... ..

Further check the Full Code below, code has been well explained by comments can be easily understandable.

Code: 

#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(9,10); 
#include <LiquidCrystal.h>
#include <stdlib.h>
LiquidCrystal lcd(12,11,5,4,3,2);

#define SSID "Your Wifi Name"     // "SSID-WiFiname" 
#define PASS "Your Wifi Password"       // "password"
#define IP "184.106.153.149"// thingspeak.com ip
String msg = "GET /update?key=9YS21NU0HY5YS1IKU"; //change it with your api key like "GET /update?key=Your Api Key"

//Variables
float temp;
int hum;
String tempC;
int error;
int pulsePin = 0;                 // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13;                // pin to blink led at each beat
int fadePin = 5;
int fadeRate = 0;

// Volatile Variables, used in the interrupt service routine!
volatile int BPM;                   // int that holds raw Analog in 0. updated every 2mS
volatile int Signal;                // holds the incoming raw data
volatile int IBI = 600;             // int that holds the time interval between beats! Must be seeded! 
volatile boolean Pulse = false;     // "True" when heartbeat is detected. "False" when not a "live beat". 
volatile boolean QS = false;        // becomes true when Arduino finds a beat.

// Regards Serial OutPut  -- Set This Up to your needs
static boolean serialVisual = true;   // Set to 'false' by Default.  Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse 
volatile int rate[10];                    // array to hold last ten IBI values
volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
volatile unsigned long lastBeatTime = 0;           // used to find IBI
volatile int P =512;                      // used to find peak in pulse wave, seeded
volatile int T = 512;                     // used to find trough in pulse wave, seeded
volatile int thresh = 525;                // used to find instant moment of heart beat, seeded
volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
volatile boolean firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = false;      // used to seed rate array so we startup with reasonable BPM

void setup()
{
  lcd.begin(16, 2);
  lcd.print("circuitdigest.com");
  delay(100);
  lcd.setCursor(0,1);
  lcd.print("Connecting...");
  Serial.begin(9600); //or use default 115200.
  esp8266.begin(9600);
  Serial.println("AT");
  esp8266.println("AT");
  delay(5000);
  if(esp8266.find("OK")){
    connectWiFi();
  }
  interruptSetup(); 
}

void loop(){
  lcd.clear();
  start: //label 
  error=0;
  lcd.setCursor(0, 0);
  lcd.print("BPM = ");
  lcd.print(BPM);
  delay (100);
  lcd.setCursor(0, 1); // set the cursor to column 0, line 2
  delay(1000);
  updatebeat();
  //Resend if transmission is not completed 
  if (error==1){
    goto start; //go to label "start"
  }
  
  delay(1000); 
}

void updatebeat(){
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  Serial.println(cmd);
  esp8266.println(cmd);
  delay(2000);
  if(esp8266.find("Error")){
    return;
  }
  cmd = msg ;
  cmd += "&field1=";   
  cmd += BPM;
  cmd += "\r\n";
  Serial.print("AT+CIPSEND=");
  esp8266.print("AT+CIPSEND=");
  Serial.println(cmd.length());
  esp8266.println(cmd.length());
  if(esp8266.find(">")){
    Serial.print(cmd);
    esp8266.print(cmd);
  }
  else{
   Serial.println("AT+CIPCLOSE");
   esp8266.println("AT+CIPCLOSE");
    //Resend...
    error=1;
  }
}

boolean connectWiFi(){
  Serial.println("AT+CWMODE=1");
  esp8266.println("AT+CWMODE=1");
  delay(2000);
  String cmd="AT+CWJAP=\"";
  cmd+=SSID;
  cmd+="\",\"";
  cmd+=PASS;
  cmd+="\"";
  Serial.println(cmd);
  esp8266.println(cmd);
  delay(5000);
  if(esp8266.find("OK")){
    Serial.println("OK");
    return true;    
  }else{
    return false;
  }
}

void interruptSetup(){     
  TCCR2A = 0x02;     // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
  TCCR2B = 0x06;     // DON'T FORCE COMPARE, 256 PRESCALER 
  OCR2A = 0X7C;      // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE
  TIMSK2 = 0x02;     // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
  sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED      

ISR(TIMER2_COMPA_vect){                       // triggered when Timer2 counts to 124
  cli();                                      // disable interrupts while we do this
  Signal = analogRead(pulsePin);              // read the Pulse Sensor 
  sampleCounter += 2;                         // keep track of the time in mS
  int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise

    //  find the peak and trough of the pulse wave
  if(Signal < thresh && N > (IBI/5)*3){      // avoid dichrotic noise by waiting 3/5 of last IBI
    if (Signal < T){                         // T is the trough
      T = Signal;                            // keep track of lowest point in pulse wave 
    }
  }

  if(Signal > thresh && Signal > P){        // thresh condition helps avoid noise
    P = Signal;                             // P is the peak
  }                                         // keep track of highest point in pulse wave

  //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
  // signal surges up in value every time there is a pulse
  if (N > 250){                                   // avoid high frequency noise
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
      Pulse = true;                               // set the Pulse flag when there is a pulse
      digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
      IBI = sampleCounter - lastBeatTime;         // time between beats in mS
      lastBeatTime = sampleCounter;               // keep track of time for next pulse

      if(secondBeat){                        // if this is the second beat
        secondBeat = false;                  // clear secondBeat flag
        for(int i=0; i<=9; i++){             // seed the running total to get a realistic BPM at startup
          rate[i] = IBI;                      
        }
      }

      if(firstBeat){                         // if it's the first time beat is found
        firstBeat = false;                   // clear firstBeat flag
        secondBeat = true;                   // set the second beat flag
        sei();                               // enable interrupts again
        return;                              // IBI value is unreliable so discard it
      }   
      word runningTotal = 0;                  // clear the runningTotal variable    

      for(int i=0; i<=8; i++){                // shift data in the rate array
        rate[i] = rate[i+1];                  // and drop the oldest IBI value 
        runningTotal += rate[i];              // add up the 9 oldest IBI values
      }

      rate[9] = IBI;                          // add the latest IBI to the rate array
      runningTotal += rate[9];                // add the latest IBI to runningTotal
      runningTotal /= 10;                     // average the last 10 IBI values 
      BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
      QS = true;                              // set Quantified Self flag 
      // QS FLAG IS NOT CLEARED INSIDE THIS ISR
    }                       
  }

  if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
    digitalWrite(blinkPin,LOW);            // turn off pin 13 LED
    Pulse = false;                         // reset the Pulse flag so we can do it again
    amp = P - T;                           // get amplitude of the pulse wave
    thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
    P = thresh;                            // reset these for next time
    T = thresh;
  }

  if (N > 2500){                           // if 2.5 seconds go by without a beat
    thresh = 512;                          // set thresh default
    P = 512;                               // set P default
    T = 512;                               // set T default
    lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
    firstBeat = true;                      // set these to avoid noise
    secondBeat = false;                    // when we get the heartbeat back
  }

  sei();     
  // enable interrupts when youre done!
}// end isr

Video: 

Comments (6)

  • vijayan s's picture
    vijayan s

    Your Projects are very useful for me. Thank you so much.

    Dec 20, 2016
  • nidhya's picture
    nidhya

    Gud evng Mr.vijayan,
    I am nidhya ,I would like to do this project as my final year project!! have u done this project ? did u get the output in thinks speak actually I am not getting the output in think speach...verrrrry sad !! did u get it?? can u help me in finding IP address of my module... plz help me!!..

    Feb 17, 2017
  • sujay's picture
    sujay

    i need the actual img..coz the mobile clicked img is different then the actual shown connection diagm...so please refer me the actual connection diagram with transister been present in ckt

    Feb 02, 2017
  • nidhya's picture
    nidhya

    Can I create an account in think speak !! Do I require any authorization?.. Can I create it in my computer.

    Feb 06, 2017
  • sheetal's picture
    sheetal

    it gives BPM=235 and more than it ..plz help me

    Mar 05, 2017
  • Prudhvi's picture
    Prudhvi

    I also getting BPM=190 and more than it.You made any corrections regarding to this issue?

    Mar 20, 2017

Leave a comment