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