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
- Committer:
- Sissors
- Date:
- 2015-08-25
- Revision:
- 1:b2b2924c3c48
- Parent:
- 0:f3705ec14cf0
File content as of revision 1:b2b2924c3c48:
/* Heart rate example for the SiLabs biometrics board using the Si1146 Since their own example code is all hidden behind precompiled libraries, here an example which is actually useful :D. Take into account this is an example, I just screwed around a bit and observed some output waveforms to make it work reasonable, there are for sure better ways to implement this. User manual: If the Gecko symbol turns on on the LCD it is connected to the sensor Place your finger on the sensor. In the biometrics board manual it is explained how, but you can also try until it works properly. You don't want to use the extreme tip of your finger, but a bit further back. The battery indicator will flash briefly when a beat is detected. Every beat it re-calculates your heartbeat using the time of the previous beat, since no filtering happens here, it can jump around a bit, but this should be limitted. And just to be sure since we can never overestimate human stupidity: This is not a medical tool... Todo: 1. Get rid of my hardcoded value used as threshold 2. Measure PO2 */ #include "mbed.h" #include "Si114x.h" #include "EFM32_SegmentLCD.h" DigitalOut myled(LED1); silabs::EFM32_SegmentLCD segmentDisplay; int main() { segmentDisplay.AllOff(); Si114x sensor(PD6, PD7); while(sensor.verifyConnection() != 1); segmentDisplay.Symbol(LCD_SYMBOL_GECKO, 1); int curval; int prevval = 0; int mvingavg[3] = {0}; int sum; int prevtime = 0; int timesincelast; float abssum; float abssum_iir = 0.0f; Timer timey; timey.start(); while(1) { curval=sensor.getProximity(2); //We use visible light, seems to work alot better than IR //Three times moving average of the diff of the output mvingavg[2] = mvingavg[1]; mvingavg[1] = mvingavg[0]; mvingavg[0] = curval - prevval; sum = mvingavg[2] + mvingavg[1] + mvingavg[0]; //Float val for abs(sum) to calculate threshold dynamically abssum = (float)abs(sum); abssum_iir = abssum_iir * 0.99f + abssum * 0.01f; //Now we know the 'average' absolute 'noise' ( plus some part of the heartbeat) //We multiply this by four (yes randomly chosen) and use it as threshold for heartbeat //Possibly this is too much if you are really excited, but haven't been excited enough to check this if (sum < (int)(-4.0f * abssum_iir)) { segmentDisplay.Battery(4); timesincelast = timey.read_ms() - prevtime; if (timesincelast > 250) { uint32_t hearthrate = 60000 / timesincelast; segmentDisplay.Number(hearthrate); prevtime = timey.read_ms(); } } else { segmentDisplay.Battery(0); } prevval = curval; } }