zinnet yazıcı
/
max30105Example
maxrefdes117
heartRate.cpp@0:78a2573ad768, 2019-08-06 (annotated)
- Committer:
- zinnetyazicii53
- Date:
- Tue Aug 06 12:19:46 2019 +0000
- Revision:
- 0:78a2573ad768
commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
zinnetyazicii53 | 0:78a2573ad768 | 1 | #include "heartRate.h" |
zinnetyazicii53 | 0:78a2573ad768 | 2 | int16_t IR_AC_Max = 20; |
zinnetyazicii53 | 0:78a2573ad768 | 3 | int16_t IR_AC_Min = -20; |
zinnetyazicii53 | 0:78a2573ad768 | 4 | |
zinnetyazicii53 | 0:78a2573ad768 | 5 | int16_t IR_AC_Signal_Current = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 6 | int16_t IR_AC_Signal_Previous; |
zinnetyazicii53 | 0:78a2573ad768 | 7 | int16_t IR_AC_Signal_min = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 8 | int16_t IR_AC_Signal_max = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 9 | int16_t IR_Average_Estimated; |
zinnetyazicii53 | 0:78a2573ad768 | 10 | |
zinnetyazicii53 | 0:78a2573ad768 | 11 | int16_t positiveEdge = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 12 | int16_t negativeEdge = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 13 | int32_t ir_avg_reg = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 14 | |
zinnetyazicii53 | 0:78a2573ad768 | 15 | int16_t cbuf[32]; |
zinnetyazicii53 | 0:78a2573ad768 | 16 | uint8_t offset = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 17 | static const uint16_t FIRCoeffs[12] = {172, 321, 579, 927, 1360, 1858, 2390, 2916, 3391, 3768, 4012, 4096}; |
zinnetyazicii53 | 0:78a2573ad768 | 18 | |
zinnetyazicii53 | 0:78a2573ad768 | 19 | bool heartRate::checkForBeat(int32_t sample) |
zinnetyazicii53 | 0:78a2573ad768 | 20 | { |
zinnetyazicii53 | 0:78a2573ad768 | 21 | bool beatDetected = false; |
zinnetyazicii53 | 0:78a2573ad768 | 22 | |
zinnetyazicii53 | 0:78a2573ad768 | 23 | // Save current state |
zinnetyazicii53 | 0:78a2573ad768 | 24 | IR_AC_Signal_Previous = IR_AC_Signal_Current; |
zinnetyazicii53 | 0:78a2573ad768 | 25 | |
zinnetyazicii53 | 0:78a2573ad768 | 26 | //This is good to view for debugging |
zinnetyazicii53 | 0:78a2573ad768 | 27 | //Serial.print("Signal_Current: "); |
zinnetyazicii53 | 0:78a2573ad768 | 28 | //Serial.println(IR_AC_Signal_Current); |
zinnetyazicii53 | 0:78a2573ad768 | 29 | |
zinnetyazicii53 | 0:78a2573ad768 | 30 | // Process next data sample |
zinnetyazicii53 | 0:78a2573ad768 | 31 | IR_Average_Estimated = averageDCEstimator(&ir_avg_reg, sample); |
zinnetyazicii53 | 0:78a2573ad768 | 32 | IR_AC_Signal_Current = lowPassFIRFilter(sample - IR_Average_Estimated); |
zinnetyazicii53 | 0:78a2573ad768 | 33 | |
zinnetyazicii53 | 0:78a2573ad768 | 34 | // Detect positive zero crossing (rising edge) |
zinnetyazicii53 | 0:78a2573ad768 | 35 | if ((IR_AC_Signal_Previous < 0) & (IR_AC_Signal_Current >= 0)) |
zinnetyazicii53 | 0:78a2573ad768 | 36 | { |
zinnetyazicii53 | 0:78a2573ad768 | 37 | |
zinnetyazicii53 | 0:78a2573ad768 | 38 | IR_AC_Max = IR_AC_Signal_max; //Adjust our AC max and min |
zinnetyazicii53 | 0:78a2573ad768 | 39 | IR_AC_Min = IR_AC_Signal_min; |
zinnetyazicii53 | 0:78a2573ad768 | 40 | |
zinnetyazicii53 | 0:78a2573ad768 | 41 | positiveEdge = 1; |
zinnetyazicii53 | 0:78a2573ad768 | 42 | negativeEdge = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 43 | IR_AC_Signal_max = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 44 | |
zinnetyazicii53 | 0:78a2573ad768 | 45 | //if ((IR_AC_Max - IR_AC_Min) > 100 & (IR_AC_Max - IR_AC_Min) < 1000) |
zinnetyazicii53 | 0:78a2573ad768 | 46 | if ((IR_AC_Max - IR_AC_Min) > 20 & (IR_AC_Max - IR_AC_Min) < 1000) |
zinnetyazicii53 | 0:78a2573ad768 | 47 | { |
zinnetyazicii53 | 0:78a2573ad768 | 48 | //Heart beat!!! |
zinnetyazicii53 | 0:78a2573ad768 | 49 | beatDetected = true; |
zinnetyazicii53 | 0:78a2573ad768 | 50 | } |
zinnetyazicii53 | 0:78a2573ad768 | 51 | } |
zinnetyazicii53 | 0:78a2573ad768 | 52 | |
zinnetyazicii53 | 0:78a2573ad768 | 53 | // Detect negative zero crossing (falling edge) |
zinnetyazicii53 | 0:78a2573ad768 | 54 | if ((IR_AC_Signal_Previous > 0) & (IR_AC_Signal_Current <= 0)) |
zinnetyazicii53 | 0:78a2573ad768 | 55 | { |
zinnetyazicii53 | 0:78a2573ad768 | 56 | positiveEdge = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 57 | negativeEdge = 1; |
zinnetyazicii53 | 0:78a2573ad768 | 58 | IR_AC_Signal_min = 0; |
zinnetyazicii53 | 0:78a2573ad768 | 59 | } |
zinnetyazicii53 | 0:78a2573ad768 | 60 | |
zinnetyazicii53 | 0:78a2573ad768 | 61 | // Find Maximum value in positive cycle |
zinnetyazicii53 | 0:78a2573ad768 | 62 | if (positiveEdge & (IR_AC_Signal_Current > IR_AC_Signal_Previous)) |
zinnetyazicii53 | 0:78a2573ad768 | 63 | { |
zinnetyazicii53 | 0:78a2573ad768 | 64 | IR_AC_Signal_max = IR_AC_Signal_Current; |
zinnetyazicii53 | 0:78a2573ad768 | 65 | } |
zinnetyazicii53 | 0:78a2573ad768 | 66 | |
zinnetyazicii53 | 0:78a2573ad768 | 67 | // Find Minimum value in negative cycle |
zinnetyazicii53 | 0:78a2573ad768 | 68 | if (negativeEdge & (IR_AC_Signal_Current < IR_AC_Signal_Previous)) |
zinnetyazicii53 | 0:78a2573ad768 | 69 | { |
zinnetyazicii53 | 0:78a2573ad768 | 70 | IR_AC_Signal_min = IR_AC_Signal_Current; |
zinnetyazicii53 | 0:78a2573ad768 | 71 | } |
zinnetyazicii53 | 0:78a2573ad768 | 72 | |
zinnetyazicii53 | 0:78a2573ad768 | 73 | return(beatDetected); |
zinnetyazicii53 | 0:78a2573ad768 | 74 | } |
zinnetyazicii53 | 0:78a2573ad768 | 75 | |
zinnetyazicii53 | 0:78a2573ad768 | 76 | // Average DC Estimator |
zinnetyazicii53 | 0:78a2573ad768 | 77 | int16_t heartRate::averageDCEstimator(int32_t *p, uint16_t x) |
zinnetyazicii53 | 0:78a2573ad768 | 78 | { |
zinnetyazicii53 | 0:78a2573ad768 | 79 | *p += ((((long) x << 15) - *p) >> 4); |
zinnetyazicii53 | 0:78a2573ad768 | 80 | return (*p >> 15); |
zinnetyazicii53 | 0:78a2573ad768 | 81 | } |
zinnetyazicii53 | 0:78a2573ad768 | 82 | |
zinnetyazicii53 | 0:78a2573ad768 | 83 | // Low Pass FIR Filter |
zinnetyazicii53 | 0:78a2573ad768 | 84 | int16_t heartRate::lowPassFIRFilter(int16_t din) |
zinnetyazicii53 | 0:78a2573ad768 | 85 | { |
zinnetyazicii53 | 0:78a2573ad768 | 86 | cbuf[offset] = din; |
zinnetyazicii53 | 0:78a2573ad768 | 87 | |
zinnetyazicii53 | 0:78a2573ad768 | 88 | int32_t z = mul16(FIRCoeffs[11], cbuf[(offset - 11) & 0x1F]); |
zinnetyazicii53 | 0:78a2573ad768 | 89 | |
zinnetyazicii53 | 0:78a2573ad768 | 90 | for (uint8_t i = 0 ; i < 11 ; i++) |
zinnetyazicii53 | 0:78a2573ad768 | 91 | { |
zinnetyazicii53 | 0:78a2573ad768 | 92 | z += mul16(FIRCoeffs[i], cbuf[(offset - i) & 0x1F] + cbuf[(offset - 22 + i) & 0x1F]); |
zinnetyazicii53 | 0:78a2573ad768 | 93 | } |
zinnetyazicii53 | 0:78a2573ad768 | 94 | |
zinnetyazicii53 | 0:78a2573ad768 | 95 | offset++; |
zinnetyazicii53 | 0:78a2573ad768 | 96 | offset %= 32; //Wrap condition |
zinnetyazicii53 | 0:78a2573ad768 | 97 | |
zinnetyazicii53 | 0:78a2573ad768 | 98 | return(z >> 15); |
zinnetyazicii53 | 0:78a2573ad768 | 99 | } |
zinnetyazicii53 | 0:78a2573ad768 | 100 | |
zinnetyazicii53 | 0:78a2573ad768 | 101 | // Integer multiplier |
zinnetyazicii53 | 0:78a2573ad768 | 102 | int32_t heartRate::mul16(int16_t x, int16_t y) |
zinnetyazicii53 | 0:78a2573ad768 | 103 | { |
zinnetyazicii53 | 0:78a2573ad768 | 104 | return((long)x * (long)y); |
zinnetyazicii53 | 0:78a2573ad768 | 105 | } |