Heart Monitor











Intro

Hi, in this tutorial we gonna interface MAX30102: pulse oximetry and heart rate monitor module with Arduino UNO board, and then make a project for measuring BPM using this module + OLED display and a Buzzer.

BPM are the "beats per minute" and they are around 65-75 while resting for a normal person, athletics may have lower than that, and the SpO2 is the Oxygen saturation level, and for a normal person it's above 95%.

The MAX30102 can be found in different modules, I have a WAVGAT version, it's not a problem as long as the IC is MAX30102.



Components

Here are the things I'm gonna use


Arduino UNO


Arduino UNO

MAX30102


MAX30102

128x32 OLED display (Optional)


128x32 OLED display (Optional)

Buzzer (Optional)



Tests:

The codes I used in the tutorial are pretty clear and they are just examples from the Sparkfun_MAX3010x library.

For the code I made for the OLED and Buzzer, it's a modified version of the "HeartRate" example, it asks you to put your finger on the sensor.


If no finger is detected


If no finger is detected

Once you put your finger, 

remain calm for a while, until you start hearing the Buzzer's "Beeps" synchronized with your heart beats or the OLED animation is synchronized with it, and then you can read a correct BPM.

N.B: In the code I actually print the Average BPM, since it do the average of 4 BPMs it's more accurate just give it some time.


After a while you'll have a good BPM reading and a synchronized animation/"Beeps"


After a while you'll have a good BPM reading and a synchronized animation/"Beeps"


Make Bitmaps for the OLED

The heart (small) you see is a bitmap picture, and everytime the sensor detects heart beat we switch to another heart (big) bitmap picture for a while and it gives the impression of a heart beats alongside with a beep from the buzzer.

Here are the two bitmaps in the code that we call later on the code


I called them logo2_bmp and logo3_bmp I don't know why


I called them logo2_bmp and logo3_bmp I don't know why

To make these, Look for a picture (black with white background) for wathever you want to see in the screen just don't forget about the size, the one I'm using is 128x32 px and the pictures are smaller than that (32x32 px) and (24x21 px)



Make sure the little pictures have Monochrome Bitmap format


Make sure the little pictures have Monochrome Bitmap format




Download LCD Assistant and open it (few steps below)


Open the Assistant Try these operations in both Vertical and Horizontal until it's right


Open the Assistant Try these operations in both Vertical and Horizontal until it's right

Look for you image


Look for you image

Note the Width and Height of the image


Note the Width and Height



Give the file a name and path then save it


Open the file with note pad or anything similar

And here are your "numbers"


Copy this and put it in your code, add PROGMEM to put it in the Arduino Flash and save some space


Copy this and put it in your code, add PROGMEM to put it in the Arduino Flash and save some space


And here's how I called it in the code

display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);

Which means

 display.drawBitmap(Starting x pos, Starting y pos, Bitmap name, Width, Height, Color);

And as you can see in the code one is called when a finger is detected and the other one if a heart beat is detected.

And here you go make what you want.



Code:-

/* This code works with MAX30102 + 128x32 OLED i2c + Buzzer and Arduino UNO
 * It's displays the Average BPM on the screen, with an animation and a buzzer sound
 * everytime a heart pulse is detected
 * It's a modified version of the HeartRate library example
 * Refer to www.surtrtech.com for more details or SurtrTech YouTube channel
 */

#include <Adafruit_GFX.h>        //OLED libraries
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include "MAX30105.h"           //MAX3010x library
#include "heartRate.h"          //Heart rate calculating algorithm

MAX30105 particleSensor;

const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
float beatsPerMinute;
int beatAvg;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET    -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)

static const unsigned char PROGMEM logo2_bmp[] =
{ 0x03, 0xC0, 0xF0, 0x06, 0x71, 0x8C, 0x0C, 0x1B, 0x06, 0x18, 0x0E, 0x02, 0x10, 0x0C, 0x03, 0x10,              //Logo2 and Logo3 are two bmp pictures that display on the OLED if called
0x04, 0x01, 0x10, 0x04, 0x01, 0x10, 0x40, 0x01, 0x10, 0x40, 0x01, 0x10, 0xC0, 0x03, 0x08, 0x88,
0x02, 0x08, 0xB8, 0x04, 0xFF, 0x37, 0x08, 0x01, 0x30, 0x18, 0x01, 0x90, 0x30, 0x00, 0xC0, 0x60,
0x00, 0x60, 0xC0, 0x00, 0x31, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x04, 0x00,  };

static const unsigned char PROGMEM logo3_bmp[] =
{ 0x01, 0xF0, 0x0F, 0x80, 0x06, 0x1C, 0x38, 0x60, 0x18, 0x06, 0x60, 0x18, 0x10, 0x01, 0x80, 0x08,
0x20, 0x01, 0x80, 0x04, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xC0, 0x00, 0x08, 0x03,
0x80, 0x00, 0x08, 0x01, 0x80, 0x00, 0x18, 0x01, 0x80, 0x00, 0x1C, 0x01, 0x80, 0x00, 0x14, 0x00,
0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x40, 0x10, 0x12, 0x00, 0x40, 0x10, 0x12, 0x00,
0x7E, 0x1F, 0x23, 0xFE, 0x03, 0x31, 0xA0, 0x04, 0x01, 0xA0, 0xA0, 0x0C, 0x00, 0xA0, 0xA0, 0x08,
0x00, 0x60, 0xE0, 0x10, 0x00, 0x20, 0x60, 0x20, 0x06, 0x00, 0x40, 0x60, 0x03, 0x00, 0x40, 0xC0,
0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x30, 0x0C, 0x00,
0x00, 0x08, 0x10, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00  };


void setup() {  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Start the OLED display
  display.display();
  delay(3000);
  // Initialize sensor
  particleSensor.begin(Wire, I2C_SPEED_FAST); //Use default I2C port, 400kHz speed
  particleSensor.setup(); //Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running

}

void loop() {
 long irValue = particleSensor.getIR();    //Reading the IR value it will permit us to know if there's a finger on the sensor or not
                                           //Also detecting a heartbeat
if(irValue > 7000){                                           //If a finger is detected
    display.clearDisplay();                                   //Clear the display
    display.drawBitmap(5, 5, logo2_bmp, 24, 21, WHITE);       //Draw the first bmp picture (little heart)
    display.setTextSize(2);                                   //Near it display the average BPM you can display the BPM if you want
    display.setTextColor(WHITE); 
    display.setCursor(50,0);                
    display.println("BPM");             
    display.setCursor(50,18);                
    display.println(beatAvg); 
    display.display();
    
  if (checkForBeat(irValue) == true)                        //If a heart beat is detected
  {
    display.clearDisplay();                                //Clear the display
    display.drawBitmap(0, 0, logo3_bmp, 32, 32, WHITE);    //Draw the second picture (bigger heart)
    display.setTextSize(2);                                //And still displays the average BPM
    display.setTextColor(WHITE);             
    display.setCursor(50,0);                
    display.println("BPM");             
    display.setCursor(50,18);                
    display.println(beatAvg); 
    display.display();
    tone(3,1000);                                        //And tone the buzzer for a 100ms you can reduce it it will be better
    delay(100);
    noTone(3);                                          //Deactivate the buzzer to have the effect of a "bip"
    //We sensed a beat!
    long delta = millis() - lastBeat;                   //Measure duration between two beats
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);           //Calculating the BPM

    if (beatsPerMinute < 255 && beatsPerMinute > 20)               //To calculate the average we strore some values (4) then do some math to calculate the average
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

}
  if (irValue < 7000){       //If no finger is detected it inform the user and put the average BPM to 0 or it will be stored for the next measure
     beatAvg=0;
     display.clearDisplay();
     display.setTextSize(1);                    
     display.setTextColor(WHITE);             
     display.setCursor(30,5);                
     display.println("Please Place "); 
     display.setCursor(30,15);
     display.println("your finger ");  
     display.display();
     noTone(3);
     }

}


Apply for sponsorship >>
1600+ Projects Sponsored
Dec 15,2019
1,970 viewsReport item
  • Comments(0)
  • Likes(1)
You can only upload 1 files in total. Each file cannot exceed 2MB. Supports JPG, JPEG, GIF, PNG, BMP
0 / 10000