Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
MAX30100_PulseOximeter.cpp
00001 /* 00002 Arduino-MAX30100 oximetry / heart rate integrated sensor library 00003 Copyright (C) 2016 OXullo Intersecans <x@brainrapers.org> 00004 This program is free software: you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation, either version 3 of the License, or 00007 (at your option) any later version. 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 You should have received a copy of the GNU General Public License 00013 along with this program. If not, see <http://www.gnu.org/licenses/>. 00014 */ 00015 00016 #include <mbed.h> 00017 #include "MAX30100_PulseOximeter.h" 00018 00019 00020 PulseOximeter::PulseOximeter() : 00021 state(PULSEOXIMETER_STATE_INIT), 00022 // tsFirstBeatDetected(0), 00023 // tsLastBeatDetected(0), 00024 // tsLastSample(0), 00025 // tsLastBiasCheck(0), 00026 // tsLastCurrentAdjustment(0), 00027 redLedPower((uint8_t)RED_LED_CURRENT_START), 00028 onBeatDetected(NULL) 00029 { 00030 } 00031 00032 bool PulseOximeter::begin(PulseOximeterDebuggingMode debuggingMode_) 00033 { 00034 debuggingMode = debuggingMode_; 00035 00036 if(!hrm.begin()) 00037 return false; 00038 if(!hrm.setMode(MAX30100_MODE_SPO2_HR)) 00039 return false; 00040 if(!hrm.setLedsCurrent(IR_LED_CURRENT, RED_LED_CURRENT_START)) 00041 return false; 00042 00043 irDCRemover = DCRemover(DC_REMOVER_ALPHA); 00044 redDCRemover = DCRemover(DC_REMOVER_ALPHA); 00045 00046 state = PULSEOXIMETER_STATE_IDLE; 00047 return true; 00048 } 00049 00050 00051 void PulseOximeter::update() 00052 { 00053 checkSample(); 00054 checkCurrentBias(); 00055 } 00056 00057 float PulseOximeter::getHeartRate() 00058 { 00059 return beatDetector.getRate(); 00060 } 00061 00062 uint8_t PulseOximeter::getSpO2() 00063 { 00064 return spO2calculator.getSpO2(); 00065 } 00066 00067 uint8_t PulseOximeter::getRedLedCurrentBias() 00068 { 00069 return redLedPower; 00070 } 00071 00072 void PulseOximeter::setOnBeatDetectedCallback(void (*cb)()) 00073 { 00074 onBeatDetected = cb; 00075 t_Sample.start(); 00076 t_CurrentBias.start(); 00077 } 00078 00079 void PulseOximeter::checkSample() 00080 { 00081 if (t_Sample.read_ms() > 1.0 / SAMPLING_FREQUENCY * 1000.0) { 00082 t_Sample.reset(); 00083 if(hrm.update()){ 00084 00085 float irACValue = irDCRemover.step(hrm.rawIRValue); 00086 float redACValue = redDCRemover.step(hrm.rawRedValue); 00087 00088 // The signal fed to the beat detector is mirrored since the cleanest monotonic spike is below zero 00089 float filteredPulseValue = lpf.step(-irACValue); 00090 bool beatDetected = beatDetector.addSample(filteredPulseValue); 00091 00092 if (beatDetector.getRate() > 0) { 00093 state = PULSEOXIMETER_STATE_DETECTING; 00094 spO2calculator.update(irACValue, redACValue, beatDetected); 00095 } else if (state == PULSEOXIMETER_STATE_DETECTING) { 00096 state = PULSEOXIMETER_STATE_IDLE; 00097 spO2calculator.reset(); 00098 } 00099 /* 00100 switch (debuggingMode) { 00101 case PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES: 00102 Serial.print("R:"); 00103 Serial.print(hrm.rawIRValue); 00104 Serial.print(","); 00105 Serial.println(hrm.rawRedValue); 00106 break; 00107 00108 case PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES: 00109 Serial.print("R:"); 00110 Serial.print(irACValue); 00111 Serial.print(","); 00112 Serial.println(redACValue); 00113 break; 00114 00115 case PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT: 00116 Serial.print("R:"); 00117 Serial.print(filteredPulseValue); 00118 Serial.print(","); 00119 Serial.println(beatDetector->getCurrentThreshold()); 00120 break; 00121 00122 default: 00123 break; 00124 } 00125 */ 00126 if (beatDetected && onBeatDetected) { 00127 onBeatDetected(); 00128 } 00129 } 00130 } 00131 } 00132 00133 void PulseOximeter::checkCurrentBias() 00134 { 00135 // Follower that adjusts the red led current in order to have comparable DC baselines between 00136 // red and IR leds. The numbers are really magic: the less possible to avoid oscillations 00137 if (t_CurrentBias.read_ms() > CURRENT_ADJUSTMENT_PERIOD_MS) { 00138 bool changed = false; 00139 if (irDCRemover.getDCW() - redDCRemover.getDCW() > 70000 && redLedPower < MAX30100_LED_CURR_50MA) { 00140 ++redLedPower; 00141 changed = true; 00142 } else if (redDCRemover.getDCW() - irDCRemover.getDCW() > 70000 && redLedPower > 0) { 00143 --redLedPower; 00144 changed = true; 00145 } 00146 00147 if (changed) { 00148 hrm.setLedsCurrent(IR_LED_CURRENT, (LEDCurrent)redLedPower); 00149 //tsLastCurrentAdjustment = millis(); 00150 } 00151 00152 t_CurrentBias.reset(); 00153 } 00154 }
Generated on Wed Jul 13 2022 10:11:08 by
1.7.2