Project tutorial

Measure Heart Rate and SpO2 with MAX30102 © GPL3+

Interfacing MAX30102 with Arduino + BPM measure project with OLED + buzzer.

  • 6,475 views
  • 11 comments
  • 52 respects

Components and supplies

About this project

Video tutorial if needed

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

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.

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.

Make Bitmaps for the OLED

The heart (small) you see is a bitmap picture, and everytime the sensor detects a 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

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)

Download LCD Assistant and open it (few steps below)

And here are your "numbers"

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

MAX_BPM_OLED_Buzzer.inoArduino
Modified from the SparkFun MAX3010x library
/* 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);
     }

}

Schematics

Wiring_MAX30102_OLED_Buzzer
Both modules have i²c interface, if you're using a 2 pin buzzer (-) with GND and (+) with a resistor then D3
Wiring cwuvopzpmr

Comments

Similar projects you might like

DIY Heart Rate Sensor

by Ingeimaks Ingeimaks

  • 3,306 views
  • 2 comments
  • 22 respects

Heart Rate Monitoring System

Project tutorial by HRMS

  • 17,219 views
  • 4 comments
  • 30 respects

Heart Rate Monitor Using IoT

Project tutorial by Technopaths

  • 9,935 views
  • 3 comments
  • 29 respects

From KY-039 To Heart Rate

Project tutorial by Johan_Ha

  • 4,670 views
  • 3 comments
  • 24 respects

Detecting Heart Rate with a Photoresistor

Project tutorial by 3 developers

  • 10,667 views
  • 4 comments
  • 33 respects

Measure LUX with Arduino Using BH1750

Project tutorial by afsh_ad

  • 2,353 views
  • 0 comments
  • 3 respects
Add projectSign up / Login