dszds

Committer:
zinnetyazicii53
Date:
Sun Jul 28 08:14:38 2019 +0000
Revision:
0:83277b73a1f8
commit

Who changed what in which revision?

UserRevisionLine numberNew 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 }