BLE Heart Rate Sample Program for HRM1017 which is using Nordic nRF51822 confirmed the connection of nRFToolbox on Android.

Dependencies:   BLE_API mbed nRF51822 color_pixels

Fork of BLE_HTM_HRM1017 by Switch Science

Committer:
YoshinoTaro
Date:
Sun Oct 16 14:25:59 2016 +0000
Revision:
11:d32f4f43161d
Enable Heart Rate Sensor and PixelLeds;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
YoshinoTaro 11:d32f4f43161d 1 #include "mbed.h"
YoshinoTaro 11:d32f4f43161d 2 #include <limits.h>
YoshinoTaro 11:d32f4f43161d 3
YoshinoTaro 11:d32f4f43161d 4 #ifdef __cplusplus
YoshinoTaro 11:d32f4f43161d 5 extern "C" {
YoshinoTaro 11:d32f4f43161d 6 #endif // __cplusplus
YoshinoTaro 11:d32f4f43161d 7
YoshinoTaro 11:d32f4f43161d 8 #define NEED_DEBUG
YoshinoTaro 11:d32f4f43161d 9 #ifdef NEED_DEBUG
YoshinoTaro 11:d32f4f43161d 10 #define DEBUG(...) { printf(__VA_ARGS__); }
YoshinoTaro 11:d32f4f43161d 11 #else
YoshinoTaro 11:d32f4f43161d 12 #define DEBUG(...) /* nothing */
YoshinoTaro 11:d32f4f43161d 13 #endif
YoshinoTaro 11:d32f4f43161d 14
YoshinoTaro 11:d32f4f43161d 15 #define N 10
YoshinoTaro 11:d32f4f43161d 16 #define DEFAULT_THRESHOLD 500
YoshinoTaro 11:d32f4f43161d 17 #define DEFAULT_AMP 100
YoshinoTaro 11:d32f4f43161d 18
YoshinoTaro 11:d32f4f43161d 19
YoshinoTaro 11:d32f4f43161d 20 volatile int BPM = 60;
YoshinoTaro 11:d32f4f43161d 21 volatile int IBI = 600;
YoshinoTaro 11:d32f4f43161d 22
YoshinoTaro 11:d32f4f43161d 23 volatile bool Pulse = false;
YoshinoTaro 11:d32f4f43161d 24 volatile bool QS = false;
YoshinoTaro 11:d32f4f43161d 25
YoshinoTaro 11:d32f4f43161d 26 volatile int Rate[N];
YoshinoTaro 11:d32f4f43161d 27 volatile int CurrentBeatTime = 0;
YoshinoTaro 11:d32f4f43161d 28 volatile int LastBeatTime = 0;
YoshinoTaro 11:d32f4f43161d 29
YoshinoTaro 11:d32f4f43161d 30 volatile uint16_t Signal;
YoshinoTaro 11:d32f4f43161d 31 volatile uint16_t P = DEFAULT_THRESHOLD;
YoshinoTaro 11:d32f4f43161d 32 volatile uint16_t T = DEFAULT_THRESHOLD;
YoshinoTaro 11:d32f4f43161d 33 volatile uint16_t Threshold = DEFAULT_THRESHOLD;
YoshinoTaro 11:d32f4f43161d 34
YoshinoTaro 11:d32f4f43161d 35 volatile int Amplifier = DEFAULT_AMP;
YoshinoTaro 11:d32f4f43161d 36
YoshinoTaro 11:d32f4f43161d 37 Timer timer;
YoshinoTaro 11:d32f4f43161d 38 AnalogIn ain(p5);
YoshinoTaro 11:d32f4f43161d 39
YoshinoTaro 11:d32f4f43161d 40 void initPulseSensor(void) {
YoshinoTaro 11:d32f4f43161d 41 for (int i = 0; i < N; ++i) {
YoshinoTaro 11:d32f4f43161d 42 Rate[i] = 0;
YoshinoTaro 11:d32f4f43161d 43 }
YoshinoTaro 11:d32f4f43161d 44 timer.start();
YoshinoTaro 11:d32f4f43161d 45 LastBeatTime = timer.read_ms();
YoshinoTaro 11:d32f4f43161d 46 }
YoshinoTaro 11:d32f4f43161d 47
YoshinoTaro 11:d32f4f43161d 48 int getBPM(void) {
YoshinoTaro 11:d32f4f43161d 49 return BPM;
YoshinoTaro 11:d32f4f43161d 50 }
YoshinoTaro 11:d32f4f43161d 51
YoshinoTaro 11:d32f4f43161d 52 bool isQS(void) {
YoshinoTaro 11:d32f4f43161d 53 bool qs = QS;
YoshinoTaro 11:d32f4f43161d 54 QS = false;
YoshinoTaro 11:d32f4f43161d 55 return qs;
YoshinoTaro 11:d32f4f43161d 56 }
YoshinoTaro 11:d32f4f43161d 57
YoshinoTaro 11:d32f4f43161d 58
YoshinoTaro 11:d32f4f43161d 59 void reset() {
YoshinoTaro 11:d32f4f43161d 60 Threshold = DEFAULT_THRESHOLD;
YoshinoTaro 11:d32f4f43161d 61 Amplifier = DEFAULT_AMP;
YoshinoTaro 11:d32f4f43161d 62 P = T = DEFAULT_THRESHOLD;
YoshinoTaro 11:d32f4f43161d 63 }
YoshinoTaro 11:d32f4f43161d 64
YoshinoTaro 11:d32f4f43161d 65 void calcHeartRate(void) {
YoshinoTaro 11:d32f4f43161d 66
YoshinoTaro 11:d32f4f43161d 67 Signal = ain.read_u16();
YoshinoTaro 11:d32f4f43161d 68 CurrentBeatTime = timer.read_ms();
YoshinoTaro 11:d32f4f43161d 69 // DEBUG("%d\t%d\r\n", CurrentBeatTime, Signal);
YoshinoTaro 11:d32f4f43161d 70
YoshinoTaro 11:d32f4f43161d 71 int interval = 0;
YoshinoTaro 11:d32f4f43161d 72 if (CurrentBeatTime < LastBeatTime) {
YoshinoTaro 11:d32f4f43161d 73 interval = INT_MAX - CurrentBeatTime + LastBeatTime;
YoshinoTaro 11:d32f4f43161d 74 } else {
YoshinoTaro 11:d32f4f43161d 75 interval = CurrentBeatTime - LastBeatTime;
YoshinoTaro 11:d32f4f43161d 76 }
YoshinoTaro 11:d32f4f43161d 77
YoshinoTaro 11:d32f4f43161d 78 if ((Signal < Threshold) && (interval > IBI * 3/5)) {
YoshinoTaro 11:d32f4f43161d 79 if (Signal < T) { // hold bottom
YoshinoTaro 11:d32f4f43161d 80 T = Signal;
YoshinoTaro 11:d32f4f43161d 81 // DEBUG("T:%d\r\n", T);
YoshinoTaro 11:d32f4f43161d 82 }
YoshinoTaro 11:d32f4f43161d 83 } else if ((Signal > Threshold) && (Signal > P)) {
YoshinoTaro 11:d32f4f43161d 84 P = Signal; // hold peak
YoshinoTaro 11:d32f4f43161d 85 // DEBUG("P:%d\r\n", P);
YoshinoTaro 11:d32f4f43161d 86 }
YoshinoTaro 11:d32f4f43161d 87
YoshinoTaro 11:d32f4f43161d 88 if (interval > 250 && interval < 2500) { // msec
YoshinoTaro 11:d32f4f43161d 89
YoshinoTaro 11:d32f4f43161d 90 if ((Signal > Threshold) && !Pulse && (interval > IBI * 3/5)) {
YoshinoTaro 11:d32f4f43161d 91 Pulse = true;
YoshinoTaro 11:d32f4f43161d 92 IBI = interval;
YoshinoTaro 11:d32f4f43161d 93
YoshinoTaro 11:d32f4f43161d 94 if (Rate[0] < 0) { // first time
YoshinoTaro 11:d32f4f43161d 95 Rate[0] = 0;
YoshinoTaro 11:d32f4f43161d 96 LastBeatTime = timer.read_ms();
YoshinoTaro 11:d32f4f43161d 97 return;
YoshinoTaro 11:d32f4f43161d 98 } else if (Rate[0] == 0) { // second time
YoshinoTaro 11:d32f4f43161d 99 for (int i = 0; i < N; ++i) {
YoshinoTaro 11:d32f4f43161d 100 Rate[i] = IBI;
YoshinoTaro 11:d32f4f43161d 101 }
YoshinoTaro 11:d32f4f43161d 102 }
YoshinoTaro 11:d32f4f43161d 103
YoshinoTaro 11:d32f4f43161d 104 int running_total = 0;
YoshinoTaro 11:d32f4f43161d 105 for (int i = 0; i < N-1; ++i) {
YoshinoTaro 11:d32f4f43161d 106 Rate[i] = Rate[i+1];
YoshinoTaro 11:d32f4f43161d 107 running_total += Rate[i];
YoshinoTaro 11:d32f4f43161d 108 }
YoshinoTaro 11:d32f4f43161d 109
YoshinoTaro 11:d32f4f43161d 110 Rate[N-1] = IBI;
YoshinoTaro 11:d32f4f43161d 111 running_total += IBI;
YoshinoTaro 11:d32f4f43161d 112 running_total /= N;
YoshinoTaro 11:d32f4f43161d 113 BPM = 60000 / running_total;
YoshinoTaro 11:d32f4f43161d 114 QS = true;
YoshinoTaro 11:d32f4f43161d 115 LastBeatTime = timer.read_ms();
YoshinoTaro 11:d32f4f43161d 116 // DEBUG("P:%d T:%d AMP:%d THR:%d BPM:%d\r\n"
YoshinoTaro 11:d32f4f43161d 117 // ,P ,T ,Amplifier ,Threshold ,BPM);
YoshinoTaro 11:d32f4f43161d 118 }
YoshinoTaro 11:d32f4f43161d 119 }
YoshinoTaro 11:d32f4f43161d 120
YoshinoTaro 11:d32f4f43161d 121 // check if Signal is under Threshold
YoshinoTaro 11:d32f4f43161d 122 // if (Pulse) {
YoshinoTaro 11:d32f4f43161d 123 if ((Signal < Threshold) && Pulse) {
YoshinoTaro 11:d32f4f43161d 124 Pulse = false;
YoshinoTaro 11:d32f4f43161d 125 if (P >= T) {
YoshinoTaro 11:d32f4f43161d 126 Amplifier = P - T;
YoshinoTaro 11:d32f4f43161d 127 Threshold = Amplifier/2 + T; // update Threshold
YoshinoTaro 11:d32f4f43161d 128 P = T = Threshold;
YoshinoTaro 11:d32f4f43161d 129 // DEBUG("Update Threshold:%d\r\n", Threshold);
YoshinoTaro 11:d32f4f43161d 130 } else {
YoshinoTaro 11:d32f4f43161d 131 // DEBUG("Error: T(%d) over P(%d)\r\n", T, P);
YoshinoTaro 11:d32f4f43161d 132 reset();
YoshinoTaro 11:d32f4f43161d 133 }
YoshinoTaro 11:d32f4f43161d 134 }
YoshinoTaro 11:d32f4f43161d 135
YoshinoTaro 11:d32f4f43161d 136 // check if no Signal is over 2.5 sec
YoshinoTaro 11:d32f4f43161d 137 if (interval >= 2500) {
YoshinoTaro 11:d32f4f43161d 138 DEBUG("No Signal over 2.5sec\r\n");
YoshinoTaro 11:d32f4f43161d 139 reset();
YoshinoTaro 11:d32f4f43161d 140 LastBeatTime = timer.read_ms();
YoshinoTaro 11:d32f4f43161d 141 for (int i = 0; i < N; ++i) {
YoshinoTaro 11:d32f4f43161d 142 Rate[i] = -1;
YoshinoTaro 11:d32f4f43161d 143 }
YoshinoTaro 11:d32f4f43161d 144 }
YoshinoTaro 11:d32f4f43161d 145 }
YoshinoTaro 11:d32f4f43161d 146
YoshinoTaro 11:d32f4f43161d 147 #ifdef __cplusplus
YoshinoTaro 11:d32f4f43161d 148 }
YoshinoTaro 11:d32f4f43161d 149 #endif