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