Overview: IoT BPM Monitoring on ThingSpeak using ESP8266 & Pulse Sensor
In this project, we are going to make IoT BPM Monitoring on ThingSpeak using Pulse Sensor, ESP8266 & Arduino. The device will detect the pulse rate using the Pulse Sensor and will show the readings in BPM (Beats Per Minute) on the LCD display. It will send the readings to the ThingSpeak server via the Wi-Fi module ESP8266. This will help us to monitor the heartbeat via the Internet from any part of the world.
ThingSpeak is an open-source Internet of Things (IoT) application and API to store and retrieve data from things using the HTTP protocol over the Internet or via a Local Area Network.
Before moving ahead, you can check our earlier version of the project. You can learn about the basics of Pulse Sensor. This will clear your doubts about the Sensor working.
Bill of Materials:
Following is the list of components that you need for this project. You can purchase all the components easily from the Amazon.
S.N. | Components Name | Quantity | Purchase Links |
---|---|---|---|
1 | Arduino Nano Board | 1 | Amazon | AliExpress |
2 | ESP8266-01 WiFi Module | 1 | Amazon | AliExpress |
3 | 16x2 LCD Display | 1 | Amazon | AliExpress |
4 | Potentiometer 10K | 1 | Amazon | AliExpress |
5 | Pulse Sensor | 1 | Amazon | AliExpress |
6 | Resistor 2K | 1 | Amazon | AliExpress |
7 | Resistor 1K | 1 | Amazon | AliExpress |
8 | LED 5mm Any Color | 1 | Amazon | AliExpress |
9 | Connecting Wires | 10-20 | Amazon | AliExpress |
10 | Breadboard | 1 | Amazon | AliExpress |
Pulse Sensor:
The Pulse Sensor is a plug-and-play heart-rate sensor for Arduino. It can be used by students, artists, athletes, makers, and game & mobile developers who want to easily incorporate live heart-rate data into their projects. The essence is an integrated optical amplifying circuit and noise eliminating circuit sensor.
Clip the Pulse Sensor to your earlobe or fingertip and plug it into your Arduino. You are now ready to read heart rate. Also, it has an Arduino demo code that makes it easy to use.
The pulse sensor has three pins: VCC, GND & Analog Pin.
There is an LED at the center of this sensor module which helps in detecting the heartbeat. Below the LED, there is a noise elimination circuitry that keeps away the noise from affecting the readings.
ESP8266:
The ESP8266 is a very user-friendly and low-cost device to provide internet connectivity to your projects. The module can easily fetch data and upload it to the internet. It can also fetch data from the internet using API’s hence your project could access any information that is available on the internet, thus making it smarter. Another exciting feature of this module is that you can program it using the Arduino IDE.
The ESP8266 module works with 3.3V only. Anything more than 3.7V would kill the module. Hence be cautious with your circuits. Here is its pins description.
Pin 1 : Ground : Connected to the ground of the circuit
Pin 2 : Tx/GPIO – 1 : Connected to Rx pin of programmer/uC to upload program
Pin 3 : GPIO – 2 : General purpose Input/output pin
Pin 4 : CH_EN : Chip Enable/Active high
Pin 5 : Flash/GPIO – 0 : General purpose Input/output pin
Pin 6 : Reset : Resets the module
Pin 7 : RX/GPIO – 3 : General purpose Input/output pin
Pin 8 : Vcc : Connect to +3.3V only
Circuit Diagram & Connections:
For designing IoT BPM Monitoring on ThingSpeak using ESP8266 & Pulse Sensor, assemble the circuit as shown in the figure below.
1. Connect Pulse Sensor output pin to A0 of Arduino and other two pins to VCC & GND.
2. Connect the LED to Digital Pin 7 of Arduino via a 220-ohm resistor.
3. Connect Pin 1,3,5,16 of LCD to GND.
4. Connect Pin 2,15 of LCD to VCC.
5. Connect Pin 4,6,11,12,13,14 of LCD to Digital Pin12,11,5,4,3,2 of Arduino.
6. The RX pin of ESP8266 works on 3.3V. Therefore, 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 the 2.2K & 1K resistor. Thus the RX pin of the ESP8266 is connected to pin 10 of Arduino through the resistors.
7. Connect the TX pin of the ESP8266 to pin 9 of the Arduino.
Setting the ThingSpeak:
ThingSpeak provides a very good tool for IoT based projects. By using the ThingSpeak site, we can monitor our data and control our system over the Internet, using the Channels and web pages provided by ThingSpeak. So first you need to sign up for ThingSpeak. So visit https://thingspeak.com and create an account.
Then create a new channel and set up what you want. The tutorial in the video below. Follow the video for more clarification.
Then create the API keys. This key is required for programming modifications and setting your data.
Then upload the code to the Arduino UNO by assembling the circuit shown above. Open the serial monitor and it will automatically connect to Wi-Fi and set up everything.
Now click on channels so that you can see the online data streaming, i.e Pulse Rate Monitoring over the Internet using ThingSpeak & ESP8266 with Arduino as shown in the figure here.
Source Code/Program:
The source code for the project PIoT BPM Monitoring on ThingSpeak using ESP8266 & Pulse Sensor is given below. Simply copy the code and paste it to your Arduino IDE. Then compile the code and upload it to your Arduino UNO Board.
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
#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 "Alexahome" // "SSID-WiFiname" #define PASS "98765432" // "password" #define IP "184.106.153.149"// thingspeak.com ip String msg = "GET /update?key=W86OQNB83XEQIMN4"; //change it with your api key //Variables float temp; int hum; String tempC; int error; int pulsePin = 0; // Pulse Sensor connected to analog pin int blinkPin = 7; // 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. 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 volatile int T = 512; // used to find trough in pulse wave volatile int thresh = 525; // used to find instant moment of heart beat volatile int amp = 100; // used to hold amplitude of pulse waveform volatile boolean firstBeat = true; // used to seed rate array volatile boolean secondBeat = false; // used to seed rate array void setup() { lcd.begin(16, 2); lcd.print("Connecting..."); Serial.begin(9600); esp8266.begin(9600); Serial.println("AT"); esp8266.println("AT"); delay(5000); if(esp8266.find("OK")){ connectWiFi(); } interruptSetup(); } void loop(){ lcd.clear(); start: 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(); 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"); 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 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 } } 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(); } |
Video Tutorial & Explanation:
Watch this full video for full understanding and setting up things.
The Pulse sensor is good for learning purposes. However, there are so many issues with the sensor like stability and accuracy issues. Therefore, you can use the Easy Pulse Sensor which is a better version of this sensor.
I already implemented the IoT Based Heart Rate Monitor using ESP8266 & Arduino on Ubidots MQTT Server. You can check the project for more information.
12 Comments
sir i got an error it’s saying that software serial ep8266 redeclared as different kind of symbol
Hi, I keep getting this code in the serial monitor when i excute this program. Can you tell me what the reason for this could be?
20:07:09.697 -> AT+CIPSTART=”TCP”,”184.106.153.149″,80
20:07:12.711 -> AT+CIPSEND=29
20:07:13.722 -> AT+CIPCLOSE
20:07:14.840 -> AT+CIPSTART=”TCP”,”184.106.153.149″,80
20:07:17.916 -> AT+CIPSEND=29
20:07:18.900 -> AT+CIPCLOSE
20:07:20.025 -> AT+CIPSTART=”TCP”,”184.106.153.149″,80
20:07:23.071 -> AT+CIPSEND=29
20:07:24.102 -> AT+CIPCLOSE
20:07:25.211 -> AT+CIPSTART=”TCP”,”184.106.153.149″,80
Hi is it possible that you can add I2C oled display instead of lcd?
Yes possible, simple code modification needed
how it is possible to get readings on LCD display without potentiometer? I I can’t understand how to see words(values) with out varying the potentiometer.
getting error about softwareSerial esp8266 redeclared as different kind of symbol
i did everything just as it is , downloaded libraries codes and everything seems correct but Esp8266 is not working it seems that the connectwifi function is not working can you help please !
thank you
same thing did you find the solution for this problem
please help
i had completed hardware work…but my problem is that im not getting the output wave form in thingspeak.
pls help me
I am not getting output in the thingspeak… But getting the output in serial monitor… Can you help
Did anyone has a problem with uploading the code to arduino(uno). I copied the code ,paste it in arduino IDE but when I try to upload it I get the same “problem uploading the code to board”
I’m also having same problem, if anyone knows the reason please tell.