Dependencies:   BLE_API mbed nRF51822 color_pixels

Fork of BLE_HTM_HRM1017 by Switch Science

Files at this revision

API Documentation at this revision

Comitter:
YoshinoTaro
Date:
Sun Oct 16 14:25:59 2016 +0000
Parent:
10:8a67578c3ef0
Commit message:
Enable Heart Rate Sensor and PixelLeds;

Changed in this revision

PulseSensor.cpp Show annotated file Show diff for this revision Revisions of this file
PulseSensor.h Show annotated file Show diff for this revision Revisions of this file
color_pixels.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 8a67578c3ef0 -r d32f4f43161d PulseSensor.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PulseSensor.cpp	Sun Oct 16 14:25:59 2016 +0000
@@ -0,0 +1,149 @@
+#include "mbed.h"
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define NEED_DEBUG 
+#ifdef NEED_DEBUG
+#define DEBUG(...) { printf(__VA_ARGS__); }
+#else
+#define DEBUG(...) /* nothing */
+#endif 
+
+#define N 10
+#define DEFAULT_THRESHOLD 500
+#define DEFAULT_AMP 100
+
+
+volatile int BPM = 60;
+volatile int IBI = 600;
+
+volatile bool Pulse = false;
+volatile bool QS = false;
+
+volatile int Rate[N];
+volatile int CurrentBeatTime = 0;
+volatile int LastBeatTime = 0;
+
+volatile uint16_t Signal;
+volatile uint16_t P = DEFAULT_THRESHOLD;
+volatile uint16_t T = DEFAULT_THRESHOLD;
+volatile uint16_t Threshold = DEFAULT_THRESHOLD;
+
+volatile int Amplifier = DEFAULT_AMP;
+
+Timer timer;
+AnalogIn ain(p5);
+
+void initPulseSensor(void) {
+    for (int i = 0; i < N; ++i) {
+        Rate[i] = 0;
+    }
+    timer.start();
+    LastBeatTime = timer.read_ms();
+}
+
+int getBPM(void) {
+    return BPM;
+}
+
+bool isQS(void) {
+    bool qs = QS;
+    QS = false;
+    return qs;
+}
+
+
+void reset() {
+    Threshold = DEFAULT_THRESHOLD;
+    Amplifier = DEFAULT_AMP;
+    P = T = DEFAULT_THRESHOLD;
+}
+
+void calcHeartRate(void) {
+    
+    Signal = ain.read_u16();
+    CurrentBeatTime = timer.read_ms();
+    // DEBUG("%d\t%d\r\n", CurrentBeatTime, Signal);
+    
+    int interval = 0;
+    if (CurrentBeatTime < LastBeatTime) {
+        interval = INT_MAX - CurrentBeatTime + LastBeatTime;
+    } else {
+        interval = CurrentBeatTime - LastBeatTime;
+    }
+    
+    if ((Signal < Threshold) && (interval > IBI * 3/5)) {
+        if (Signal < T) {   // hold bottom 
+            T = Signal;
+            // DEBUG("T:%d\r\n", T);
+        }
+    } else if ((Signal > Threshold) && (Signal > P)) {
+        P = Signal; // hold peak 
+        // DEBUG("P:%d\r\n", P);
+    }
+    
+    if (interval > 250 && interval < 2500) { // msec
+    
+        if ((Signal > Threshold) && !Pulse && (interval > IBI * 3/5)) {
+            Pulse = true;
+            IBI = interval;
+            
+            if (Rate[0] < 0) {  // first time
+                Rate[0] = 0;
+                LastBeatTime = timer.read_ms();
+                return;
+            } else if (Rate[0] == 0) { // second time
+                for (int i = 0; i < N; ++i) {
+                    Rate[i] = IBI;
+                }
+            }
+            
+            int running_total = 0;
+            for (int i = 0; i < N-1; ++i) {
+                Rate[i] = Rate[i+1];
+                running_total += Rate[i];
+            }
+            
+            Rate[N-1] = IBI;
+            running_total += IBI;
+            running_total /= N;
+            BPM = 60000 / running_total;
+            QS = true;
+            LastBeatTime = timer.read_ms();
+            // DEBUG("P:%d T:%d AMP:%d THR:%d BPM:%d\r\n"
+            //        ,P ,T ,Amplifier ,Threshold ,BPM);
+        }
+    }
+    
+    // check if Signal is under Threshold
+    // if (Pulse) {
+    if ((Signal < Threshold) && Pulse) {
+        Pulse = false;
+        if (P >= T) {
+            Amplifier = P - T;
+            Threshold = Amplifier/2 + T;  // update Threshold
+            P = T = Threshold;
+            // DEBUG("Update Threshold:%d\r\n", Threshold);
+        } else {
+            // DEBUG("Error: T(%d) over P(%d)\r\n", T, P);
+            reset();
+        }
+    }
+    
+    // check if no Signal is over 2.5 sec
+    if (interval >= 2500) {
+        DEBUG("No Signal over 2.5sec\r\n");
+        reset();
+        LastBeatTime = timer.read_ms();
+        for (int i = 0; i < N; ++i) {
+            Rate[i] = -1;
+        }
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff -r 8a67578c3ef0 -r d32f4f43161d PulseSensor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PulseSensor.h	Sun Oct 16 14:25:59 2016 +0000
@@ -0,0 +1,18 @@
+#ifndef PULSE_SENSOR_H
+#define PULSE_SENSOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+void initPulseSensor(void);
+void calcHeartRate(void);
+bool isQS();
+int getBPM();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+
+#endif //PULSE_SENSOR_H
\ No newline at end of file
diff -r 8a67578c3ef0 -r d32f4f43161d color_pixels.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/color_pixels.lib	Sun Oct 16 14:25:59 2016 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/Seeed/code/color_pixels/#16ef874fa57f
diff -r 8a67578c3ef0 -r d32f4f43161d main.cpp
--- a/main.cpp	Mon Aug 22 06:12:27 2016 +0000
+++ b/main.cpp	Sun Oct 16 14:25:59 2016 +0000
@@ -1,10 +1,12 @@
 #include "mbed.h"
 #include "BLE.h"
+#include "color_pixels.h"
 #include <math.h>
 
+#include "PulseSensor.h"
 
-#define NEED_DEBUG 1 
-#if NEED_DEBUG
+#define NEED_DEBUG
+#ifdef NEED_DEBUG
 #define DEBUG(...) { printf(__VA_ARGS__); }
 #else
 #define DEBUG(...) /* nothing */
@@ -87,11 +89,16 @@
     triggerSensorPolling = true;
 }
 
+ColorPixels pixels(6,8);
+int ledfade = 0;
+void pixelPattern(int n, uint8_t r, uint8_t g, uint8_t b);
+
+
 int main(void)
-{    
+{   
     Ticker ticker;
     ticker.attach(periodicCallback, 1);
-       
+        
     DEBUG("Initialising the nRF51822\r\n");
     ble.init();
     DEBUG("Init done\r\n");
@@ -114,6 +121,14 @@
     ble.gattServer().addService(battService);
     ble.gattServer().addService(deviceInformationService);
     DEBUG("Add Service\r\n");
+    
+    initPulseSensor();
+
+    Ticker hrm_ticker;
+    hrm_ticker.attach(calcHeartRate, 0.02);
+    
+    int counter = 0;
+    uint8_t cl = 193;
 
     while (true) {
         if (triggerSensorPolling) {
@@ -122,9 +137,20 @@
         } else {
             ble.waitForEvent();
         }
+        if (counter % 3 == 0) {
+            if (ledfade) {
+                --ledfade;
+                pixelPattern(ledfade, cl, cl, cl);
+                counter = 0;
+            }
+        }
+        ++counter;
     }
+    
 }
 
+
+
 void updateServiceValues(void)
 {
     /* Decrement the battery level. */
@@ -132,7 +158,77 @@
     ble.gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
 
     /* Randomize the heart rate. */
-    hrmCounter = (rand() % 150) + 30;
+    // hrmCounter = (rand() % 150) + 30;
+    if (isQS()) {
+        hrmCounter = getBPM();
+        DEBUG("BPM: %d\r\n", hrmCounter);
+        ledfade = 5;
+    }
+        
     bpm[1] = hrmCounter;
     ble.gattServer().write(hrmChar.getValueAttribute().getHandle(), bpm, sizeof(bpm));
 }
+
+
+void pixelPattern(int n, uint8_t r, uint8_t g, uint8_t b) {
+    
+    if (n < 0 || n > 4) return;
+    
+    switch (n) {
+    case 4:
+        pixels.set_color(7, r, g, b);
+        pixels.set_color(6, r, g, b);
+        pixels.set_color(5, r, g, b);
+        pixels.set_color(4, r, g, b);
+        pixels.set_color(3, r, g, b);
+        pixels.set_color(2, r, g, b);
+        pixels.set_color(1, r, g, b);
+        pixels.set_color(0, r, g, b);
+        pixels.update();
+        break;
+    case 3:
+        pixels.set_color(7, 0, 0, 0);
+        pixels.set_color(6, r/2, g/2, b/2);
+        pixels.set_color(5, r*3/4, g*3/4, b*3/4);
+        pixels.set_color(4, r, g, b);
+        pixels.set_color(3, r, g, b);
+        pixels.set_color(2, r*3/4, g*3/4, b*3/4);
+        pixels.set_color(1, r/2, g/2, b/2);
+        pixels.set_color(0, 0, 0, 0);
+        pixels.update();
+        break;
+    case 2:
+        pixels.set_color(7, 0, 0, 0);
+        pixels.set_color(6, 0, 0, 0);
+        pixels.set_color(5, r/2, g/2, b/2);
+        pixels.set_color(4, r*3/4, g*3/4, b*3/4);
+        pixels.set_color(3, r*3/4, g*3/4, b*3/4);
+        pixels.set_color(2, r/2, g/2, b/2);
+        pixels.set_color(1, 0, 0, 0);
+        pixels.set_color(0, 0, 0, 0);
+        pixels.update();
+        break;
+    case 1:
+        pixels.set_color(7, 0, 0, 0);
+        pixels.set_color(6, 0, 0, 0);
+        pixels.set_color(5, 0, 0, 0);
+        pixels.set_color(4, r/2, g/2, b/4);
+        pixels.set_color(3, r/2, g/2, b/4);
+        pixels.set_color(2, 0, 0, 0);
+        pixels.set_color(1, 0, 0, 0);
+        pixels.set_color(0, 0, 0, 0);
+        pixels.update();
+        break;
+    case 0:
+    default:
+        pixels.set_color(7, 0, 0, 0);
+        pixels.set_color(6, 0, 0, 0);
+        pixels.set_color(5, 0, 0, 0);
+        pixels.set_color(4, 0, 0, 0);
+        pixels.set_color(3, 0, 0, 0);
+        pixels.set_color(2, 0, 0, 0);
+        pixels.set_color(1, 0, 0, 0);
+        pixels.set_color(0, 0, 0, 0);
+        pixels.update();
+    }
+}
\ No newline at end of file