Heartbeat monitoring with ESP32 and IoT cloud over MQTT

Remote health monitoring is rapidly growing in the healthcare field. With tools like the Fitbit and Apple watch, people are able to monitor vital health data from anywhere in the world.

This tutorial uses the KY039 sensor connected to the ESP32 development board to measure the heartbeat pulses and send the heartbeat measurement to the AskSensors platform over MQTT.

The AskSensors IoT cloud gives us easy-to-use tools to store data and manage sensors devices data. It also provides smart dashboards to visualize data using widgets. The AskSensors web application can be used to monitor real-time heartbeat data remotely from a mobile phone or laptop, from anywhere in the world over the internet.

1) Prerequisites :

Setting up the AskSensors IoT platform is very easy. Followings are the prerequisites you need to be able to monitor the heartbeat with AskSensors IoT cloud.

  • Before beginning with this tutorial, if you are new to AskSensors, create an AskSensors account.
  • You should be familiar with the AskSensors IoT platform: Read the Getting Started with AskSensors.
  • After sign up, create a new sensor device with at least one module to connect your Heartbeat sensor.
  • Now after this click on ‘Add graph’ and select the graph type you prefer to show the measurements.
  • Copy down your sensor API KEY IN, we will use it later when we attempt to write data or send data from the ESP32.

2) Required Materials 

These are the parts required to build the circuit.

  • ESP32 development board.
  • Heart/pulse rate sensor module KY039.
  • Jumper wires.
  • Computer running Arduino IDE software.
  • USB micro cable to connect ESP32 development board to the computer.

3) KY039 Features

The KY039 module is a plug-and-play Sensor that collects heart rate data and pulses from the human body.

  • It uses bright infrared (IR) LED and a phototransistor to detect the pulse of the finger (Heartbeat).
  • A red LED flashes with each pulse.
  • The analog output gives an analog signal that matches the heart rate.
  • Power supply: 3.3V to 5V DC Voltage
  • Output: Analogue based on a heart rate measurement (maximum voltage equal to supply voltage)
  • Pin description:

    • Ground : min/ground of input voltage
    • Vcc : 3.3V or 5V DC input voltage
    • S : Analog output Signal
  • Notes:
    • This KY039 module is NOT a professional medical device and should not be used to treat medical case that may put life in danger.
    • This product is designed to work when the user is not moving and far from home lighting 50Hz/60Hz noises. Otherwise, it will give inaccurate results.

4) Circuit schematic

The connections are so simple. The following figure shows the schematic diagram of the circuit we will be using in this tutorial.



  • Connect the “+” pin of the KY039 to the 3V3 of the ESP32 board.
  • Connect the “-” pin to the ESP32 ground.
  • The signal pin of the pulse sensor must be connected to an analog pin of ESP32.  Connect the Analog pin of the KY039 to the A0 pin of the ESP32 (ADC values from 0 to 4095).
  • Last, connect your ESP32 to the computer through a USB cable. The ESP32 will be powered from the USB 5V.

5) Install the ESP32 in Arduino IDE

The ESP32 will be programmed using Arduino IDE. There’s an add-on for the Arduino IDE (1.8.7 or higher) that allows you to program the ESP32 using the Arduino IDE and its programming language. Follow the instructions below:

  • Open the preferences window from the Arduino IDE : File> Preferences.
  • Go to the “Additional Board Manager URLs” field, Enter the following URL:


  • If you already have the ESP8266 boards URL, separate the URLs with a comma as shown below:
https://dl.espressif.com/dl/package_esp32_index.json, http://arduino.esp8266.com/stable/package_esp8266com_index.json
  • Open boards manager (Tools > Board > Boards Manager), search for ESP32 and click the install button for the “ESP32 by Espressif Systems”.

6) Download the libraries

  • The PubSubClient library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT.

o Download the PubSubClient library from github.

o Unzip the .zip folder and you should get pubsubclient-master folder.

o Rename your folder from pubsubclient-master to pubsubclient.

o Move the pubsubclient folder to your Arduino IDE installation libraries folder.

o Then, re-open your Arduino IDE.

The library comes with a number of example sketches that are not fully compatible with the ESP32. However, the example provided in this tutorial is working very reliably in the Arduino IDE software.

  • The AskSensors MQTT Publish/Subscribe API is described in detail in this guide.

7) Write the code

Download this complete demo from the AskSensors github page. You need to edit the code with your own SSID, password, username and MQTT topic.

const char* ssid = ".................."; // Wifi SSID
const char* password = ".................."; // Wifi Password 
const char* username = "................."; // my AskSensors username 
const char* pubTopic = "publish/..../....."; // publish/username/apiKeyIn 
const unsigned int writeInterval = 2000; // write interval (in ms)

8) Upload the code

  • Connect your ESP32 board to your computer through the micro-USB cable. Make sure the power LED goes high on the module to ensure power supply.
  • Open your arduino IDE and select Tools options for your ESP32 board type and serial port where it’s connected then click upload. The code will be running automatically after Reset.
  • Open the serial terminal to supervise the ESP32 software sequence step by step.
  • Now, we will return back to the AskSensors web application to monitor the heartbeat measurements sent by the ESP32(Beats Per Minute).

9) Source code

A basic source code is shown below. Please refer to the AskSensors Github page to get the latest version and updates.

* Description: Heartbeat Pulse Sensor monitoring with ESP32 and AskSensors IoT
* Author: https://asksensors.com, 2020
* github: https://github.com/asksensors

#include <WiFi.h>
#include <PubSubClient.h>

//TODO: ESP32 MQTT user config
const char* ssid = ".................."; // Wifi SSID
const char* password = ".................."; // Wifi Password
const char* username = "................."; // my AskSensors username
const char* pubTopic = "publish/..../....."; // publish/username/apiKeyIn

const unsigned int writeInterval = 2000; // write interval (in ms)
//AskSensors MQTT config
const char* mqtt_server = "mqtt.asksensors.com";
unsigned int mqtt_port = 1883;

// KY039 defines
#define TAB_LENGTH 4
#define CALIB_OFFSET 0

WiFiClient askClient;
PubSubClient client(askClient);

void setup() {
Serial.println("********** Program Start : ESP32 publishes KY039 Heartbeat data to AskSensors over MQTT");
Serial.print("********** connecting to WIFI : ");

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
Serial.println("->WiFi connected");
Serial.println("->IP address: ");

client.setServer(mqtt_server, mqtt_port);


void loop() {

float analog_Tab[TAB_LENGTH], analog_sum;
float last, analog_average, start;
float KY039_data, first, second, third, before;
bool rising;
int rise_count, n_reads;
long int last_beat, now, ptr;
// WiFi connection 
if (!client.connected()) 
// Init variables
for (int i = 0; i < TAB_LENGTH; i++) analog_Tab[i] = 0;
analog_sum = 0;
ptr = 0;
while(1) {
// calculate an average of the sensor during a 20 ms period to eliminate the 50 Hz noise caused by electric light
n_reads = 0;
start = millis();
analog_average = 0.;
do {
analog_average += analogRead(A0);
now = millis();
while (now < start + 20); 
analog_average /= n_reads; // we got an average
// Add the newest measurement to an array and subtract the oldest measurement from the array
// to maintain a sum of last measurements
analog_sum -= analog_Tab[ptr];
analog_sum += analog_average;
analog_Tab[ptr] = analog_average;
last = analog_sum / TAB_LENGTH;
// now last holds the average of the values in the array
// check for a rising curve (= a heart beat)
if (last > before) {
if (!rising && rise_count > RISE_THRESHOLD) {
// we have detected a rising curve, which implies a heartbeat.
// Record the time since last beat, keep track of the two previous times (first, second, third) to get a weighed average.
// The rising flag prevents us from detecting the same rise more than once.
rising = true;
first = millis() - last_beat;
last_beat = millis();
// Calculate the weighed average of heartbeat rate according to the three last beats
KY039_data = 60000. / (0.4 * first + 0.3 * second + 0.3 * third)+CALIB_OFFSET;
Serial.println(" BPM\n"); // Unit
third = second;
second = first;
Serial.println("********** Publish MQTT data to ASKSENSORS");
char mqtt_payload[30] = "";
snprintf (mqtt_payload, 30, "m1=%f", KY039_data);
Serial.print("Publish message: ");
client.publish(pubTopic, mqtt_payload);
Serial.println("> MQTT data published");
Serial.println("********** End ");
delay(writeInterval);// delay
// Ok, the curve is falling
rising = false;
rise_count = 0;
before = last;
ptr %= TAB_LENGTH;

// MQTT callback
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print("] ");
for (int i = 0; i < length; i++) {

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("********** Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP32Client", username, "")) { 
Serial.println("-> MQTT client connected");
} else {
Serial.print("failed, rc=");
Serial.println("-> try again in 5 seconds");
// Wait 5 seconds before retrying


What’s Next?

That’s it! We are done with this tutorial. Thanks for your reading!

Ready to start connecting other sensors to the cloud? Have a look at this tutorials list on how to connect Things to the AskSensors IoT platform in few steps.

We will be happy to hear your thoughts

      Leave a reply