Example code to create a heartbeat sensor using the Si1146 on Silicon Lab's Biometrics expansion board for the Wonder Gecko
Dependencies: EFM32_SegmentLCD Si114x mbed
main.cpp
00001 /* 00002 Heart rate example for the SiLabs biometrics board using the Si1146 00003 00004 Since their own example code is all hidden behind precompiled libraries, here an 00005 example which is actually useful :D. Take into account this is an example, I just screwed 00006 around a bit and observed some output waveforms to make it work reasonable, there are 00007 for sure better ways to implement this. 00008 00009 User manual: 00010 If the Gecko symbol turns on on the LCD it is connected to the sensor 00011 Place your finger on the sensor. In the biometrics board manual it is explained how, 00012 but you can also try until it works properly. You don't want to use the extreme tip of your 00013 finger, but a bit further back. 00014 The battery indicator will flash briefly when a beat is detected. 00015 00016 Every beat it re-calculates your heartbeat using the time of the previous beat, since no 00017 filtering happens here, it can jump around a bit, but this should be limitted. 00018 00019 And just to be sure since we can never overestimate human stupidity: This is not a medical tool... 00020 00021 00022 Todo: 00023 1. Get rid of my hardcoded value used as threshold 00024 2. Measure PO2 00025 */ 00026 00027 00028 #include "mbed.h" 00029 #include "Si114x.h" 00030 #include "EFM32_SegmentLCD.h" 00031 00032 00033 DigitalOut myled(LED1); 00034 silabs::EFM32_SegmentLCD segmentDisplay; 00035 00036 00037 int main() { 00038 segmentDisplay.AllOff(); 00039 Si114x sensor(PD6, PD7); 00040 while(sensor.verifyConnection() != 1); 00041 segmentDisplay.Symbol(LCD_SYMBOL_GECKO, 1); 00042 00043 int curval; 00044 int prevval = 0; 00045 int mvingavg[3] = {0}; 00046 int sum; 00047 int prevtime = 0; 00048 int timesincelast; 00049 float abssum; 00050 float abssum_iir = 0.0f; 00051 00052 Timer timey; 00053 timey.start(); 00054 while(1) { 00055 curval=sensor.getProximity(2); //We use visible light, seems to work alot better than IR 00056 00057 //Three times moving average of the diff of the output 00058 mvingavg[2] = mvingavg[1]; 00059 mvingavg[1] = mvingavg[0]; 00060 mvingavg[0] = curval - prevval; 00061 sum = mvingavg[2] + mvingavg[1] + mvingavg[0]; 00062 00063 //Float val for abs(sum) to calculate threshold dynamically 00064 abssum = (float)abs(sum); 00065 abssum_iir = abssum_iir * 0.99f + abssum * 0.01f; 00066 00067 //Now we know the 'average' absolute 'noise' ( plus some part of the heartbeat) 00068 //We multiply this by four (yes randomly chosen) and use it as threshold for heartbeat 00069 //Possibly this is too much if you are really excited, but haven't been excited enough to check this 00070 if (sum < (int)(-4.0f * abssum_iir)) { 00071 segmentDisplay.Battery(4); 00072 timesincelast = timey.read_ms() - prevtime; 00073 if (timesincelast > 250) { 00074 uint32_t hearthrate = 60000 / timesincelast; 00075 segmentDisplay.Number(hearthrate); 00076 prevtime = timey.read_ms(); 00077 } 00078 } 00079 else { 00080 segmentDisplay.Battery(0); 00081 } 00082 00083 prevval = curval; 00084 00085 } 00086 00087 }
Generated on Tue Jul 12 2022 14:26:46 by 1.7.2