Gaku Hibi
Published © GPL3+

Pulse oximeter with alert function

Making a pulse oximeter with alert function based on M5Stack Basic and LPWA Network.

BeginnerProtip4,164
Pulse oximeter with alert function

Things used in this project

Hardware components

ESP32 Basic Core IoT Development Kit
M5Stack ESP32 Basic Core IoT Development Kit
×1
Mini Heart Rate Unit MAX30100 Module Sensor
M5Stack Mini Heart Rate Unit MAX30100 Module Sensor
×1
Sigfox Breakout board BRKWS01
Available to use other breakout board like UnaMKR mini
×1

Software apps and online services

Arduino IDE
Arduino IDE
Sigfox backend cloud

Story

Read more

Schematics

Pin assignment of breakout board

Code

M5Stack-Pulse-oximeter

Arduino
#include <M5Stack.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include "xbm.h"  //my bitmap

#define REPORTING_PERIOD_MS     1000

PulseOximeter pox;
uint8_t Heart_rate = 0;
uint8_t Spo2 = 0;
uint32_t tsLastReport = 0;

// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
  printHRandSPO2(true);
}

void setup()
{
  Serial.begin(115200); // to PC via USB
  Serial2.begin(9600, SERIAL_8N1, 16, 17);   // to Sigfox module

  M5.begin();
  M5.Power.begin();
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextSize(4);
  
  // Initialize sensor
  if (!pox.begin()) {
    M5.Lcd.println("FAILED");
    for(;;);
   } else {
    M5.Lcd.println("SUCCESS");
  }

  //LED Configuration
  pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
  //Register a callback for the beat detection
  pox.setOnBeatDetectedCallback(onBeatDetected);
}

void loop()
{
  M5.update();  //update button state
  pox.update(); //update pulse oximeter

  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
    Heart_rate = (int)pox.getHeartRate();
    Spo2 = pox.getSpO2();
    printHRandSPO2(false);
    tsLastReport = millis();
  }

  if (M5.BtnA.wasReleased()) {
    sendSigfoxMessage();
  }
}

void printHRandSPO2(bool beat)
{
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(4);
  if (beat) {
    M5.Lcd.drawXBitmap(0, 5, hb2_bmp, 64, 32, TFT_RED);
  } else {
    M5.Lcd.drawXBitmap(0, 5, hb1_bmp, 64, 32, TFT_WHITE);
  }
  M5.Lcd.setCursor(0,70);
  M5.Lcd.print("HR:   "); M5.Lcd.println(Heart_rate);
  M5.Lcd.print("SPO2: "); M5.Lcd.println(Spo2);  
}

void sendSigfoxMessage() 
{
  String msg = "AT$SF=" + String(Heart_rate, HEX) + String(Spo2, HEX);
  Serial2.println(msg);
  M5.Lcd.setCursor(0,160);
  M5.Lcd.println("MSG Sent!");
  delay(10000);
}

xbm.h

Arduino
#include <pgmspace.h>  // PROGMEM support header

#define imgWidth  64  // logo width
#define imgHeight 32  // logo height

static const uint8_t hb1_bmp[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 
  0xDC, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 
  0x00, 0x3C, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 
  0x8C, 0x01, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x8C, 0x01, 0x00, 0x00, 
  0x00, 0xE6, 0x00, 0x00, 0x8E, 0x01, 0x00, 0x00, 0xF8, 0xC7, 0x0F, 0xFF, 
  0x87, 0xFF, 0xC0, 0x0F, 0xF0, 0x83, 0x1F, 0xFF, 0x07, 0xFF, 0xC1, 0x0F, 
  0x00, 0x00, 0x18, 0x03, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x00, 0x9C, 0x01, 
  0x00, 0x80, 0x61, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x80, 0x63, 0x00, 
  0x00, 0x00, 0xB0, 0x01, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0xF8, 0x01, 
  0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0x00, 
  0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xF0, 0x00, 
  0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0E, 0x00, 
  0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, };

static const uint8_t hb2_bmp[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x87, 0x0F, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0xFE, 0x8F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 
  0x3F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F, 0x7F, 0x00, 0x00, 
  0x00, 0x00, 0xC0, 0xFF, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 
  0xE3, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xC3, 0xFF, 0x01, 0x00, 
  0x00, 0x00, 0xE0, 0xFF, 0x99, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xE0, 0xFF, 
  0x99, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x3C, 0xFF, 0x03, 0x00, 
  0x00, 0x18, 0xE0, 0xFF, 0x3C, 0xFF, 0x03, 0x00, 0x00, 0x1C, 0xF0, 0xFF, 
  0x3C, 0xFF, 0x03, 0x00, 0x00, 0x3C, 0xE0, 0x7F, 0x6E, 0xFE, 0x03, 0x00, 
  0x00, 0x3E, 0xE0, 0x7F, 0x66, 0xFE, 0x01, 0x00, 0x00, 0x66, 0x60, 0x00, 
  0xE6, 0x00, 0x01, 0x00, 0x20, 0x67, 0x04, 0x11, 0xC7, 0x20, 0x01, 0x01, 
  0xF8, 0xE3, 0x07, 0xFF, 0xC3, 0x7F, 0xE0, 0x03, 0xF0, 0xC1, 0x8F, 0xFF, 
  0x83, 0x7F, 0xF0, 0x03, 0x00, 0x00, 0x8C, 0x01, 0x18, 0xE0, 0x30, 0x00, 
  0x00, 0x00, 0xDC, 0x11, 0xBC, 0xC2, 0x38, 0x00, 0x00, 0x00, 0xD8, 0xFC, 
  0xFF, 0xCF, 0x18, 0x00, 0x00, 0x00, 0xD8, 0xFC, 0xFF, 0xCF, 0x19, 0x00, 
  0x00, 0x00, 0xF8, 0xF8, 0xFF, 0x8F, 0x0D, 0x00, 0x00, 0x00, 0x78, 0xF0, 
  0xFF, 0x87, 0x0F, 0x00, 0x00, 0x00, 0x70, 0xE0, 0xFF, 0x83, 0x07, 0x00, 
  0x00, 0x00, 0x70, 0xC0, 0xFF, 0x01, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 
  0x7F, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x02, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, };

Credits

Gaku Hibi

Gaku Hibi

0 projects • 2 followers

Comments