/* This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. * If not, see . * Copyright 2020,CEREBRUM srl * * More details by CEREBRUM Srl * www.cerebrum.it * ITALY * * Please consider that this application, sensors and functional device are NOT tested for * medical purpose and the single parts aren't calibrated and aren't certified. * Please use this simple device for preventive scope and to monitorate patients only under * emergency situation when no other medical deviced and Pulse-oximeters are available. * * CEREBRUM-oximeter dev. 2.4 - version 1.1 // April, 6 2020 * * Arduino NANO - 3,3v | i2c A4 (SDA) , A5 (SCL) * Arduino NANO Every - 3,3v | i2c A4 (SDA) , A5 (SCL) * Arduino MICRO - 3,3v | i2c 2 (SDA), 3 (SCL) * * MAX30100 - PulseOximeter board (+3.3v | GND | SCA/SCL) * OLED SSD1306 128x32 (+3.3v | GND | SCA/SCL) */ #include #include "MAX30100_PulseOximeter.h" #include "MAX30100.h" #include #define REPORTING_PERIOD_MS 1000 #define PULSE_WIDTH MAX30100_SPC_PW_1600US_16BITS #define IR_LED_CURRENT MAX30100_LED_CURR_40MA #define LED_CURRENT MAX30100_LED_CURR_20_8MA #define SAMPLING_RATE MAX30100_SAMPRATE_100HZ U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0); PulseOximeter pox; MAX30100 sensor; uint32_t tsLastReport = 0; uint32_t last_beat=0; bool initialized=false; int HRclean; int SpO2; void onBeatDetected() { show_beat(); last_beat=millis(); } void show_beat() { u8g2.setFont(u8g2_font_cursor_tr); u8g2.setCursor(118,10); u8g2.print("_"); u8g2.sendBuffer(); } void initial_display() { if (not initialized) { u8g2.clearBuffer(); u8g2.setCursor(15,12); u8g2.setFont(u8g2_font_crox2hb_tr); u8g2.print("CEREBRUM.it"); u8g2.setFont(u8g2_font_crox2h_tr); u8g2.setCursor(30,29); u8g2.print("Initializing..."); u8g2.sendBuffer(); delay(4000); initialized=true; u8g2.clearBuffer(); u8g2.setFont(u8g2_font_crox2hb_tr); if (!pox.begin()) { u8g2.setCursor(40,12); u8g2.print("FAILED"); u8g2.setCursor(15,29); u8g2.print("Check Sensor !"); u8g2.sendBuffer(); for(;;); } else { u8g2.setCursor(20,12); u8g2.print("INITIALIZED"); u8g2.setCursor(0,29); u8g2.print("Wear the Sensor..."); u8g2.sendBuffer(); } delay(2000); } } void setup() { u8g2.begin(); initial_display(); pox.begin(); pox.setOnBeatDetectedCallback(onBeatDetected); pox.setIRLedCurrent(LED_CURRENT); sensor.setMode(MAX30100_MODE_SPO2_HR); sensor.setLedsPulseWidth(PULSE_WIDTH); sensor.setSamplingRate(SAMPLING_RATE); } void loop() { pox.update(); HRclean = pox.getHeartRate(); SpO2 = pox.getSpO2(); if ((millis() - tsLastReport > REPORTING_PERIOD_MS) and (HRclean>30 and HRclean<220 and SpO2>30 and SpO2<100)) { u8g2.clearBuffer(); u8g2.setFont(u8g2_font_crox2h_tr); u8g2.setCursor(0,12); u8g2.print("HR"); u8g2.setCursor(75,12); u8g2.print("Bpm"); u8g2.setCursor(0,30); u8g2.print("SpO2 "); u8g2.setCursor(75,30); u8g2.print("%"); u8g2.setFont(u8g2_font_fub11_tf); u8g2.setCursor(45,12); u8g2.print(HRclean); u8g2.setCursor(45,30); u8g2.print(SpO2); u8g2.setFont(u8g2_font_cursor_tr); u8g2.setCursor(118,10); u8g2.print("^"); u8g2.sendBuffer(); tsLastReport = millis(); } }