Andrewf1
Published © GPL3+

Cardiograph

Here I show you how an ESP32 can take ECG and send this data to cloud. And how to set up web app to look at this data.

IntermediateFull instructions provided4 hours1,282
Cardiograph

Story

Read more

Schematics

Hardware diagram for ESP32 dev module

Code

favicon.ico

HTML
It's simply icon.
HTML language is just for placeholder.
No preview (download only).

cardio_test

Arduino
This code used to test does Heart rate module works.
void setup() {
  // initialize the serial communication:
  Serial.begin(115200);
}

void loop() {
  Serial.println(analogRead(A0));

  delay(1);
}

index.html

HTML
<!DOCTYPE html>
<html lang="fr">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Cardiogram</title>
	<link rel="stylesheet" href="style.css">

	
	<script src="https://www.gstatic.com/firebasejs/5.5.9/firebase-app.js"></script>
	
	<script src="https://www.gstatic.com/firebasejs/5.5.9/firebase-database.js"></script>

	<!-- Include Plotly.js -->
	<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
	<script src="script.js"></script>
</head>

<body onload="last_pack()">
	<!-- Plotly chart will be drawn inside this div. -->
	<div id="myPlot" style="width: 100vw; max-height:75vh"></div>
	<p>Give time in which you want to see data</p>
	<span>Date-time<input id="start-time" type="datetime-local"/></span>	
	<button onclick="update_plot()">Get data</button> 
	
	
</body>

</html>

script.js

JavaScript
// REPLACE <...> BY YOUR FIREBASE PROJECT CONFIGURATION:
const config = {
    apiKey: "AIzaSyDk98ptFwtdejYhzdc3XXZpaNb563dFxH8",
    authDomain: "cardiograph-e4731.firebaseapp.com",
    databaseURL: "https://cardiograph-e4731.firebaseio.com",
    projectId: "cardiograph-e4731",
    storageBucket: "",
    messagingSenderId: "111365254746"
};

firebase.initializeApp(config);

function last_pack() {
    firebase.database().ref('measures').limitToLast(1).on('value', ts_measures => {
        console.log("last_pack");
        let timestamps = [];
        let values = [];
        let pack_time;
        ts_measures.forEach(ts_measure => {
            let list = ts_measure.val().data;
            pack_time=new Date(ts_measure.val().timestamp);
            document.getElementById("start-time").value=pack_time.toLocaleString();
            time = 0;
            for (i in list) {
                timestamps.push(time);
                time = time + 0.01;
                values.push(list[i]);
            }
        });

        myPlotDiv = document.getElementById('myPlot');

        const data = [{
            x: timestamps,
            y: values
        }];

        const layout = {
            title: '<b>Cardiogram('+pack_time.toLocaleString()+')</b>',
            titlefont: {
                family: 'Courier New, monospace',
                size: 16,
                color: '#000'
            },
            xaxis: {
                linecolor: 'black',
                linewidth: 2
            },
            yaxis: {
                title: '<b>8-bit value</b>',
                titlefont: {
                    family: 'Courier New, monospace',
                    size: 14,
                    color: '#000'
                },
                linecolor: 'black',
                linewidth: 2,
            },
            margin: {
                r: 50,
                pad: 0
            }
        }

        Plotly.newPlot(myPlotDiv, data, layout, { responsive: true });
    });
}

function update_plot() {
    finish = new Date(document.getElementById("start-time").value).getTime();
    start = finish - 12 * 60 * 60 * 1000;
    console.log(start + "--" + finish)
    firebase.database().ref('measures').orderByChild("timestamp").startAt(start).endAt(finish).limitToLast(1).on('value', ts_measures => {

        let timestamps = [];
        let values = [];
        let pack_time;
        let dataFound=false;
        ts_measures.forEach(ts_measure => {
            dataFound=true;
            var list = ts_measure.val().data;
            pack_time=new Date(ts_measure.val().timestamp);
            time = 0;                                
            for (i in list) {
                timestamps.push(time);
                time = time + 0.01;
                values.push(list[i]);
            }
        });
        if(dataFound){
        myPlotDiv = document.getElementById('myPlot');

        const data = [{
            x: timestamps,
            y: values
        }];

        const layout = {
            title: '<b>Cardiogram('+pack_time.toLocaleString()+')</b>',
            titlefont: {
                family: 'Courier New, monospace',
                size: 16,
                color: '#000'
            },
            xaxis: {
                linecolor: 'black',
                linewidth: 2
            },
            yaxis: {
                title: '<b>8-bit value</b>',
                titlefont: {
                    family: 'Courier New, monospace',
                    size: 14,
                    color: '#000'
                },
                linecolor: 'black',
                linewidth: 2,
            },
            margin: {
                r: 50,
                pad: 0
            }
        }

        Plotly.newPlot(myPlotDiv, data, layout, { responsive: true });
    }else{
        last_pack();
    }
    });

}

style.css

CSS
body
{
    font-family: Roboto, Helvetica, Arial, sans-serif; 
    margin: 0   
}

cardio_sender

Arduino
This code collecting measures and sends them to the cloud.
#include <WiFi.h>
#include "FirebaseESP32.h"


#define FIREBASE_HOST "your_project_id.firebaseio.com" //Do not include https:// in FIREBASE_HOST
#define FIREBASE_AUTH "DpAi4PO2uW5pBGdYAk5dBJUbedLOmwE93Cz0P9MY"
#define WIFI_SSID "TP"
#define WIFI_PASSWORD "qwerty73"


//Define Firebase Data object
FirebaseData firebaseData;

String path = "/measures";
String jsonStr;

FirebaseJson json;
FirebaseJsonArray jsonArr;

uint8_t previous_measure = 0;
uint8_t measure = 0;
void setup() {

  Serial.begin(115200);
  Serial.println();
  Serial.println();

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED)  {
    Serial.print(".");
    delay(300);
  }
  Serial.println();
  Serial.print("Connected with IP: ");
  Serial.println(WiFi.localIP());
  Serial.println();

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.reconnectWiFi(true);

  //Set database read timeout to 1 minute (max 15 minutes)
  Firebase.setReadTimeout(firebaseData, 1000 * 60);
  //tiny, small, medium, large and unlimited.
  //Size and its write timeout e.g. tiny (1s), small (10s), medium (30s) and large (60s).
  Firebase.setwriteSizeLimit(firebaseData, "tiny");

}

void loop() {
  FirebaseJsonArray jsonArr;

  Serial.println("Collecting measures");
  previous_measure = analogRead(36) >> 4;

  for (int i = 0; i < 500; i++) {
    measure = analogRead(36) >> 4;
    measure = previous_measure/2 + (measure-30)/2;

    jsonArr.addInt(measure);
    delay(10);
  }
  Serial.println("Forming pack of data");
  json.clear().addArray("data", &jsonArr).addInt("timestamp", 0);  

  
  if (Firebase.pushJSON(firebaseData, "/measures/", json))  {
    Serial.println("PASSED");
    Serial.println("PATH: " + firebaseData.dataPath());
    Serial.print("PUSH NAME: ");
    Serial.println(firebaseData.pushName());
    Serial.println("ETag: " + firebaseData.ETag());
    Serial.println("------------------------------------");
    Serial.println();
  }
  else  {
    Serial.println("FAILED");
    Serial.println("REASON: " + firebaseData.errorReason());
    Serial.println("------------------------------------");
    Serial.println();
  }
  delay(10*60*1000);
}

Credits

Andrewf1

Andrewf1

7 projects • 11 followers

Comments