#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include "MAX30100.h"
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <U8x8lib.h>
#include <avr/dtostrf.h>
#define REPORTING_PERIOD_MS 500 //update rate of hr, spo2, ambient, object, hrv, etc parameters in milli seconds
#define DISPLAY_INTERVAL 5 //update rate for the i2c display = REPORTING_PERIOD_MS*DISPLAY_INTERVAL
#define COMPENSATION 5 //compensation in object temperature. Different body parts have different temperatures. Fingers are around 5 degF lower than core body temperature
// objects
PulseOximeter pox; //this offers spo2 and hr calculation
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
MAX30100 sensor;
//variables
uint32_t tsLastReport = 0;
int hr, spo2, count = 0, flag = 0, PatientID = 0;
float ambient, object, hrv;
long time1 = 0, time2 = 0;
uint16_t ir = 0, red = 0, ecg = 0, mic; ;
char str_hrv[10], str_object[10], str_ambient[10], str_ir[10], str_red[10];
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
time1 = micros() - time2;
time2 = micros();
}
void setup()
{
//display connected
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFont(u8x8_font_chroma48medium8_r);
//pinMode(10, INPUT); // Setup for leads off detection LO +
//pinMode(11, INPUT); // Setup for leads off detection LO -
Serial.begin(115200);
/*
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
*/
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES)) {
//Serial.println("FAILED");
for(;;);
} else {
//Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
pox.setIRLedCurrent(MAX30100_LED_CURR_11MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
mlx.begin();
time2 = micros();
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
sensor.update();
//reading continuous functions (signals) every loop
while (sensor.getRawValues(&ir, &red)) {}
ecg = analogRead(A0);
ecg = map(ecg, 250, 500, 0, 100);
mic = analogRead(A1);
delay(1);
// Asynchronously calculate other variables every REPORTING_PERIOD_MS
// For hr and spo2, a value of 0 means "invalid", for object and ambient temperatures a value less than 70 degF or higher than 110 degF can be considered abnormal
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
hr = pox.getHeartRate();
spo2 = pox.getSpO2();
ambient = mlx.readAmbientTempF();
object = mlx.readObjectTempF() + COMPENSATION;
hrv = (60000000/hr - (float)time1)/1000;
//send_serial();
tsLastReport = millis();
count++;
flag = 0;
}
//Display all variables on the display after DISPLAY_INTERVAL seconds
if ((count%DISPLAY_INTERVAL == 0) && (flag != 1)) {
flag = 1; //This flag makes sure the display is updated only once every DISPLAY_INTERVAL seconds
Wire.end();
send_display();
Wire.begin();
}
Telemetry();
}
//serial monitor print function.
//Not required actually as telemetry function prints all values in csv format on the serial monitor
void send_serial() {
Serial.print("bpm / SpO2:");
Serial.print("Heart rate:");
Serial.print(hr);
Serial.print(spo2);
Serial.print("% / hrv:");
Serial.print(hrv);
Serial.print("ms / Ambient:");
Serial.print(ambient);
Serial.print("*F / tObject = ");
Serial.print(object);
Serial.println("*F");
}
//display print function
void send_display() {
u8x8.clearDisplay();
u8x8.setCursor(0,1);
u8x8.print("HRV:");
u8x8.print(hrv);
u8x8.print(" ms");
u8x8.setCursor(0,2);
u8x8.print("SpO2:");
u8x8.print(spo2);
u8x8.print(" %");
u8x8.setCursor(0,3);
u8x8.print("HR:");
u8x8.print(hr);
u8x8.print(" bpm");
u8x8.setCursor(0,4);
u8x8.print("Temp:");
u8x8.print(object);
u8x8.print(" degF");
u8x8.setCursor(0,5);
u8x8.print("ecg:");
u8x8.print(ecg);
u8x8.setCursor(0,6);
u8x8.print("mic");
u8x8.print(mic);
//delay(200);
}
//serial telemetry for edge impulse data forwarder
void Telemetry() {
char buffer[150];
dtostrf(hrv, 4, 2, str_hrv);
dtostrf(object, 4, 2, str_object);
dtostrf(ambient, 4, 2, str_ambient);
dtostrf((float)ir/100, 5, 2, str_ir);
dtostrf((float)red/100, 5, 2, str_red);
sprintf(buffer,"%d,%d,%d,%d,%s,%s,%s,%s,%s,%d,%d",PatientID,count/10,hr,spo2,str_hrv,str_object,str_ambient,str_ir,str_red,ecg,mic);
Serial.println(buffer);
Comments