Heart Rate remote monitoring using Arduino and Thingspeak, with SMS Notification using Twilio

Overview

A heart rate sensor detects the electrical activity of the heart and translates it into numerical value that represents the heart rate. This project aims to create a heart rate monitoring system using an Arduino board connected to the internet via ethernet. The system will send the heart rate data to Thingspeak web app and display the readings in BPM (Beats Per Minute). This allows for remote heart rate monitoring over the internet from any location. This will also send SMS notification when an unusual HIGH or LOW heart rate is detected to alert the user of the emergency. 

Hardware and software components:

Hardware Used:

Software Used:

 

Application Description

Hardware:

  • Ethernet Module - ENC28J60 

This is an Ethernet module based on the ENC28J60 chip, providing 10BASE-T stand alone Ethernet connectivity with on board MAC & PHY, 8 Kbytes of Buffer RAM and an SPI serial interface for 3.3V and 5V logic levels. With a small size the ENC28J60 module minimizes complexity, board space and cost. Target applications include VoIP, Industrial Automation, Building Automation, Home Control, Security and Instrumentation.

Work well with all AVR(Arduino), STM, and ARM development boards

  • Heart Rate Pulse Sensor

  • Pulse Sensor is a plug-and-play heart-rate sensor for Arduino and Arduino compatible boards. It can be used to easily incorporate live heart-rate data into projects.
  • Sensors can be put on the finger or earlobe, through interconnected lines connected to the Arduino.
  • In essence it has an integrated optical amplifying circuit and noise eliminating circuit to properly measure heart rate sensor.

Specification:

  • Working voltage: 5V
  • Working current: 4mA
  • Diameter: 16MM
  • Magnification: 330
  • LED wavelength: 609 nm

 

 

Hardware Set-up

Connect the ENC28J60 Ethernet module to Arduino:

ENC28J60 (VCC)  -     Arduino Uno (3.3 V)

ENC28J60 (GND)  -     Arduino Uno (GND)

ENC28J60 (SCK)   -     Arduino Uno (PIN13)

ENC28J60 (SO)     -     Arduino Uno (PIN12)

ENC28J60 (SI)       -     Arduino Uno (PIN11)

ENC28J60 (CS)      -     Arduino Uno (PIN10)

 

Connect the Heart Rate Pulse Sensor to Arduino:

Heart Rate Pulse Sensor (+)         -   Arduino Uno (5.5V)

Heart Rate Pulse Sensor (-)           -  Arduino Uno (GND)

Heart Rate Pulse Sensor (Signal)  -  Arduino Uno  (AO)

Software Set-up

NOTE: We must first download the following libraries before we proceed with the coding.

  • #include <SPI.h>
  • #include <UIPEthernet.h>

Thingspeak Setup:

  1. Create a ThingSpeak account: Go to ThingSpeak.com and create an account. 

  2. Create a new channel: Once you've logged in, click on "Channels" and then click on "New Channel." Give your channel a name and fill out any other relevant fields (e.g. field names, units of measurement, etc.). 

  3. Get your ThingSpeak API key: Once you've created your channel, click on "API Keys" and then click on "New API Key." Select "Write" permissions and click "Save." This will generate an API key that you'll use in your Arduino code.  
  4. Connect your Ethernet module to your Arduino. Make sure the module is receiving power and connected to the internet.

  5. Test out your setup with THingspeak. Write a test Arduino code that will send data to your ThingSpeak channel. See below example: 

     
    #include <SPI.h>
    //change the following line to #include <Ethernet.h> to use the ethernet shield
    #include <UIPEthernet.h>

    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 
    EthernetClient client;

    String apiKey = "YOUR_API_KEY"; // replace with your ThingSpeak API key
    const char* server = "api.thingspeak.com";

    void setup() {
      Ethernet.begin(mac);
      Serial.begin(9600);
    }

    void loop() {
      float sensorValue = analogRead(A0); // replace with your sensor reading code
      Serial.println(sensorValue);

      if (client.connect(server, 80)) {
        String postStr = apiKey;
        postStr += "&field1=";
        postStr += String(sensorValue);
        postStr += "\r\n";

        client.print("POST /update HTTP/1.1\n");
        client.print("Host: api.thingspeak.com\n");
        client.print("Connection: close\n");
        client.print("X-THINGSPEAKAPIKEY: " + apiKey + "\n");
        client.print("Content-Type: application/x-www-form-urlencoded\n");
        client.print("Content-Length: ");
        client.print(postStr.length());
        client.print("\n\n");
        client.print(postStr);
        Serial.println("Sent data to ThingSpeak");
      }
      else {
        Serial.println("Connection failed");
      }

      delay(15000); // wait 15 seconds before sending the next data point
    }
  6. Once done uploading the codes you should see the data from thingspeak.

Twilio Setup:

  1. Create a Twilio account: Go to https://www.twilio.com/try-twilio and create a new account. 

  2. Create a new Twilio phone number: Once you're logged in, go to the Twilio Console and create a new phone number.

  3. Obtain your Twilio Account SID and Auth Token: In the Twilio Console, click on the "Settings" icon and then click on "API Keys." Copy your Account SID and Auth Token to a safe location, as you'll need them later in your code.

  4. Go back to ThingSpeak and go to "Apps" tab on the upper right and click on "ThingHTTP" and then you are going to create a new "ThingHTTP" and fill up all the information needed. Here are some example of the information that you need to fill up you just need to change the Account SID and Auth Token. 

  5. Test out your setup with Twilio. Write a test Arduino code that will send SMS using Twilio. See below example: 
     
    #include <SPI.h>

    //change the following line to #include <Ethernet.h> to use the eithent shield
    #include <UIPEthernet.h>

    // Enter a MAC address for your controller below.
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

    //thingspeak server
    char server[] = "api.thingspeak.com";

    //if DHCP fails, use a static IP
    IPAddress ip(192,168,0,177);

    // Initialize the Ethernet client library
    EthernetClient client;

    //API key for the Thingspeak ThingHTTP already configured
    const String apiKey = "BUEC78IIKJWVTG8W";

    //the number the message should be sent to
    const String sendNumber = "YOUR PHONE NUMBER";

    void setup()
    {
      Serial.begin(9600);

      //set up Ethernet:
      setupEthernet();
     
      //send the sms
      Serial.println("Sending SMS");
     
      //this function will send the sms
      //the first argument is the number to send to, formatted like this +12345678901
      //the second argument is the body of the text message, which must be within URLEncode()
      sendSMS(sendNumber, URLEncode("Hello World!"));

    }

    void loop()
    {
    //You can put your code here on how do you like your program to work!!
    }


    void sendSMS(String number,String message)
    {
      // Make a TCP connection to remote host
      if (client.connect(server, 80))
      {

        //should look like this...
        //api.thingspeak.com/apps/thinghttp/send_request?api_key={api key}&number={send to number}&message={text body}

        client.print("GET /apps/thinghttp/send_request?api_key=");
        client.print(apiKey);
        client.print("&number=");
        client.print(number);
        client.print("&message=");
        client.print(message);
        client.println(" HTTP/1.1");
        client.print("Host: ");
        client.println(server);
        client.println("Connection: close");
        client.println();
      }
      else
      {
        Serial.println(F("Connection failed"));
      }

      // Check for a response from the server, and route it
      // out the serial port.
      while (client.connected())
      {
        if ( client.available() )
        {
          char c = client.read();
          Serial.print(c);
        }      
      }
      Serial.println();
      client.stop();
    }



    void setupEthernet()
    {
      Serial.println("Setting up Ethernet...");
      // start the Ethernet connection:
      if (Ethernet.begin(mac) == 0) {
        Serial.println(F("Failed to configure Ethernet using DHCP"));
        // no point in carrying on, so do nothing forevermore:
        // try to congifure using IP address instead of DHCP:
        Ethernet.begin(mac, ip);
      }
      Serial.print("My IP address: ");
      Serial.println(Ethernet.localIP());
      // give the Ethernet shield a second to initialize:
      delay(1000);
    }

    String URLEncode(const char* msg)
    {
      const char *hex = "0123456789abcdef";
      String encodedMsg = "";

      while (*msg!='\0'){
        if( ('a' <= *msg && *msg <= 'z')
          || ('A' <= *msg && *msg <= 'Z')
          || ('0' <= *msg && *msg <= '9') ) {
          encodedMsg += *msg;
        }
        else {
          encodedMsg += '%';
          encodedMsg += hex[*msg >> 4];
          encodedMsg += hex[*msg & 15];
        }
        msg++;
      }
      return encodedMsg;
    }


  6. Once done uploading the code you should receive a message from Twilio.

-----------------------------------

Integrated Source Code:

 
#include <SPI.h>
#include <UIPEthernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char server[] = "api.thingspeak.com";
IPAddress ip(192, 168, 0, 177);

// Initialize the Ethernet client library
EthernetClient client;

const String apiKey = "LKU9CUFRJFO2YEZ8";
const String apiKeyBPM = "IX2R7JEPW7PWVX64";
const String sendNumber = "+639665865215";

//Assign Variables!
unsigned long nexTimeSendThingspeakBPM = 0, nexTimeSenSMSTwilioBPM = 0;
int sensorPin = A0;     // A0 is the input pin for the heart rate sensor
float sensorValue = 0;  // Variable to store the value coming from the sensor
int count = 9;
unsigned long starttime = 0;
int heartrate = 0;
boolean counted = false;

void setup() {
  Serial.begin(9600);
  setupEthernet();
}

void loop() {
  getBPM();

  // Thingspeak BPM Send 
  if (millis() >= nexTimeSendThingspeakBPM) {
    nexTimeSendThingspeakBPM += 1000L;
    sendBPM(heartrate);
  }

  if (heartrate > 110) {
      sendSMS(sendNumber, URLEncode("- High BPM"));
  }
  if (heartrate < 50) {
          sendSMS(sendNumber, URLEncode("- Low BPM"));

  }
  delay(20);
}

void getBPM() {
 
  starttime = millis();
  while (millis() < starttime + 10000) {
    sensorValue = analogRead(sensorPin);
    if (sensorValue > 550 && counted == false) 
    {
      count++;
      Serial.print("count = ");
      Serial.println(count);
      delay(50);
      counted = true;
    } else if (sensorValue < 550) {
      counted = false;
    }
  }

  heartrate = count * 6;  
  Serial.println();
  Serial.print("BPM = ");
  Serial.println(heartrate);  
  Serial.println();
  count = 0;
}


void sendSMS(String number, String message) {
  if (client.connect(server, 80)) {

    client.print("GET /apps/thinghttp/send_request?api_key=");
    client.print(apiKey);
    client.print("&number=");
    client.print(number);
    client.print("&message=");
    client.print(message);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println(F("Connection failed"));
  }

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  }
  Serial.println();
  client.stop();
}

void sendBPM(int heartrate) {
  if (client.connect(server, 80)) {
    client.print("GET /update?api_key=");
    client.print(apiKeyBPM);
    client.print("&field1=");
    client.print(heartrate);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println(F("Connection failed"));
  }

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  }
  Serial.println();
  client.stop();
}



void setupEthernet() {
  Serial.println("Setting up Ethernet...");
  if (Ethernet.begin(mac) == 0) {
    Serial.println(F("Failed to configure Ethernet using DHCP"));
    Ethernet.begin(mac, ip);
  }
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
  delay(1000);
}

String URLEncode(const char* msg) {
  const char* hex = "0123456789abcdef";
  String encodedMsg = "";

  while (*msg != '\0') {
    if (('a' <= *msg && *msg <= 'z')
        || ('A' <= *msg && *msg <= 'Z')
        || ('0' <= *msg && *msg <= '9')) {
      encodedMsg += *msg;
    } else {
      encodedMsg += '%';
      encodedMsg += hex[*msg >> 4];
      encodedMsg += hex[*msg & 15];
    }
    msg++;
  }
  return encodedMsg;
}

Code Breakdown:

The code first includes the required libraries for Ethernet and SPI. It then initializes the MAC address of the Ethernet controller, the IP address of the Arduino, and the server address for ThingSpeak. It also initializes the Ethernet client library and sets the API keys for both the ThingSpeak channel and the Twilio SMS service.


#include "spi.h"
#include "uipethernet.h"

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char server[] = "api.thingspeak.com";
IPAddress ip(192, 168, 0, 177);

// Initialize the Ethernet client library
EthernetClient client;

const String apiKey = "LKU9CUFRJFO2YEZ8";
const String apiKeyBPM = "IX2R7JEPW7PWVX64";
const String sendNumber = "+639665865215";

 

The code then defines the pin that will be used to read the heart rate sensor and sets up some variables for counting and storing the BPM data.


unsigned long nexTimeSendThingspeakBPM = 0, nexTimeSenSMSTwilioBPM = 0;
int sensorPin = A0;     // A0 is the input pin for the heart rate sensor
float sensorValue = 0;  // Variable to store the value coming from the sensor
int count = 9;
unsigned long starttime = 0;
int heartrate = 0;
boolean counted = false;

 

The setup() function initializes the Ethernet connection and the loop() function continuously checks the heart rate sensor for BPM data, sends it to ThingSpeak, and sends an SMS if the heart rate is above or below a certain threshold.

getBPM() -  function reads the heart rate sensor and calculates the BPM.


sendSMS() and sendBPM() -  functions make HTTP requests to the Twilio and ThingSpeak APIs, respectively, to send the SMS message and upload the BPM data.

 

Thingspeak Output:

Twilio SMS Output:

Video demonstration:

Conclusion: 

In this project, the data from a heart rate sensor is read by an Arduino Uno with an Ethernet Module to send to the cloud. It uses the ThingSpeak API to send the heart rate data to ThingSpeak web dashboard, and the Twilio API to send an SMS message if the heart rate is too low. Overall, this project demonstrates how to use the Ethernet Module with an Arduino Uno to send data to ThingSpeak and send SMS messages using the Twilio API.

 

References: 

  • https://arduinodiy.wordpress.com/2014/12/19/connecting-to-thingspeak-with-ethernetshield-or-esp8166/
  • https://www.youtube.com/watch?v=9F_GURMziec
  • https://www.youtube.com/watch?v=jYjuxWUefhg
  • https://www.youtube.com/watch?v=lKxWtU5oneo

Heart rateHeart rate pulse sensorPulse sensorThinghttpThingspeakTwilio

Leave a comment

All comments are moderated before being published