Project 16 - An ECG (Heart Rate )Display (CleO IO )

<< Click to Display Table of Contents >>

Navigation:  Projects >

Project 16 - An ECG (Heart Rate )Display (CleO IO )

This project creates a Heart Rate Sensor using the MikroElectronica Heart Rate Click. CleO is used to display the current heart rate to plot the real-time sensor data and play a wave file on each detected beat. The Heart Rate Click, in turn, uses the MAX30100 Pulse Oximeter sensor.The Heart Rate Click is connected to the CleO IO hardware.

 

 

Component(s)

 

This project uses the following component(s) -

 

MikroE Heart Rate

CleO IO

56mm, 80hm 0.5W(RMS) / 1W(Peak) Internal CleO speaker

 

 

Wiring Diagram

 

 

Project 16- ECG (Heartrate) Display

 

 

Code

 

The Setup() routine initializes the CleO display and configures the HR Click for 100 SPS. An image of the heart is loaded into the CleO memory from the onboard flash, shown in the below code snippet.

 

void setup()

{

 CleO.begin();

 CleO.Start();

 CleO.Show();

 Wire.begin();

 Wire.setClock(400000L);

 

/* Load the heart bitmap */

 heart = CleO.LoadImageFile("@Pictures/heart.jpg", 0);

       Filt.DC(0, true);

 SampleAvg.Update(0, true);

 DispAvg.Update(0, true);

 Filt.Peak(0, 0, NULL, true);

 Filt.Decide(0, 0, true);

 plot_helper(0, true);

 

 error_1 = (Click.Init(i2c_write, i2c_write_byte, i2c_read) == true)? false : true; /* Set error flag if init fails */

 invalidate = true; /* force update display once (even if sensor is not present) */

}

 

The loop() routine polls the sensor for any new data. Each sample is filtered and passed through a peak detector algorithm. The display is refreshed for every new sample, and if a peak was detected, the heart image is animated, and a wave file is played. The average value of the Heart Rate is also shown on the screen. The size of the display buffer is 64 samples.

 

The signal processing algorithm to detect the new peaks are as follows:

 

1.Filter the DC offset from the signal using a differentiator followed by a leaky integrator.

2.Average over a moving window of 12 samples

3.Find the peak of the resulting waveform

4.Check if the peak is above an adaptive threshold to classify it as a valid peak, else reject it.

 

The usage of loop() routine is given in the following code snippet -

 

void loop() {

 process_click();

 if (!invalidate) return;

 process_graph();

 if (Beat == true) CleO.AudioPlay("@Music/beat.wav", PLAY_ONCE);

 invalidate = false;

 CleO.Start(); /* Plot the graph, animate heart and display new HR */

 CleO.LineWidth(3);

   CleO.LineColor(RED);

 for (int i = 0; i < PLOT_SIZ - 1; i++) {

 

  /* Don't connect the new signal with the old values in the buffer! */

   if (i != (sampleIdx - 1))

     CleO.Line(XTicks[i], dispBuffer[i], XTicks[i + 1], dispBuffer[i + 1]);

 }

 int hr = HRAvg.GetAvg();

 if ((hr < HR_MAX) && (hr > HR_MIN)) HRDisp = hr;

 

  /* Animate the Heart */

   if ((Beat == true) && (ha == LAST)) ha = 0;

   else if (ha != LAST) ha++;

   Beat = false;

 

  /* Select a factor for this cycle */

   CleO.BitmapTransform(anims[ha] / 8., 0);

 

  /* Change the heart color to white for 2 cycles */

  CleO.BitmapColor((ha < 2) ? WHITE : 0xff2020);

  CleO.BitmapJustification(MM);

 

  /* Locate the image at (X,Y) = (480 - 162 / 2, 100)*/

   CleO.Bitmap(heart, HEART_X, HEART_Y);

 

  /* Display the numerical value of the Heart Rate */

   char buf[4];

   sprintf(buf, "%d", HRDisp);

 

 /* Use the largest font and display string at (X,Y) = (480-162/2, 230) */

 CleO.StringExt(FONT_HUGE, BPM_X, BPM_Y, 0xffffffUL, MM, 0, 0, buf);

 if(error_1)

   CleO.StringExt(FONT_TINY, 0, 320, RED, BL, 0, 0, "No Heart Rate Click detected");

 CleO.Show(); /* End display update */

}

 

Note: If no hardware is detected, then an appropriate error message is displayed.

 

 

Output

 

 

Project 16 HeartClick