hack gt final code

Dependencies:   4DGL-uLCD-SE BMP085 PinDetect SDFileSystem mbed wave_player

Files at this revision

API Documentation at this revision

Comitter:
otis22894
Date:
Sun Sep 21 01:38:00 2014 +0000
Parent:
7:6709324cd297
Child:
9:3b1f59782110
Commit message:
TIME: 9:37PM

Changed in this revision

Heart.cpp Show annotated file Show diff for this revision Revisions of this file
Heart.h 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Heart.cpp	Sun Sep 21 01:38:00 2014 +0000
@@ -0,0 +1,153 @@
+#include "Heart.h"
+#include "mbed.h"
+
+volatile int rate[10];                    // array to hold last ten IBI values
+volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
+volatile unsigned long lastBeatTime = 0;           // used to find IBI
+volatile int P =512;                      // used to find peak in pulse wave, seeded
+volatile int T = 512;                     // used to find trough in pulse wave, seeded
+volatile int thresh = 512;                // used to find instant moment of heart beat, seeded
+volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
+volatile bool firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
+volatile bool secondBeat = false;      // used to seed rate array so we startup with reasonable BPM
+volatile int BPM;                   // used to hold the pulse rate
+volatile int Signal;                // holds the incoming raw data
+volatile int IBI = 600;             // holds the time between beats, must be seeded! 
+volatile bool Pulse = false;     // true when pulse wave is high, false when it's low
+volatile bool QS = false;        // becomes true when Arduoino finds a beat.
+volatile bool isBeating = false;
+volatile int beatCount = 0;
+volatile int PulseLength = 0;
+
+AnalogIn ain(p17);
+DigitalOut myLED(LED1);
+Ticker pulseReader;
+
+Heart :: Heart() {
+}
+
+void Heart :: startReading() {
+    pulseReader.attach(this, &Heart::sample, .002f);
+}
+
+void Heart :: stopReading() {
+    pulseReader.detach();
+    __enable_irq();
+}
+
+void Heart :: reset() {
+    sampleCounter = 0;          // used to determine pulse timing
+    lastBeatTime = 0;           // used to find IBI
+    P =512;                      // used to find peak in pulse wave, seeded
+    T = 512;                     // used to find trough in pulse wave, seeded
+    thresh = 512;                // used to find instant moment of heart beat, seeded
+    amp = 100;                   // used to hold amplitude of pulse waveform, seeded
+    firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
+    secondBeat = false;      // used to seed rate array so we startup with reasonable BPM
+    IBI = 600;             // holds the time between beats, must be seeded! 
+    Pulse = false;     // true when pulse wave is high, false when it's low
+    QS = false;        // becomes true when Arduoino finds a beat.
+    isBeating = false;
+    beatCount = 0; 
+    PulseLength = 0;       
+}
+
+bool Heart :: beatDetected() {
+    return isBeating;
+}
+
+int Heart :: beatsCounted() {
+    return beatCount;
+}
+
+// THIS IS THE TIMER 2 INTERRUPT SERVICE ROUTINE. 
+// Timer 2 makes sure that we take a reading every 2 miliseconds
+void Heart :: sample() {                         // triggered when Timer2 counts to 124
+  __disable_irq();            
+  float readVal = ain;                          // disable interrupts while we do this
+  Signal = ain * 1024;              // read the Pulse Sensor 
+  sampleCounter += 2;                         // keep track of the time in mS with this variable
+  int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise
+
+    //  find the peak and trough of the pulse wave
+  if(Signal < thresh && N > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
+    if (Signal < T){                        // T is the trough
+      T = Signal;                         // keep track of lowest point in pulse wave 
+    }
+  }
+
+  if(Signal > thresh && Signal > P){          // thresh condition helps avoid noise
+    P = Signal;                             // P is the peak
+  }                                        // keep track of highest point in pulse wave
+
+  //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
+  // signal surges up in value every time there is a pulse
+  if (N > 250){                                   // avoid high frequency noise
+    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
+      Pulse = true;                               // set the Pulse flag when we think there is a pulse
+      IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
+      lastBeatTime = sampleCounter;               // keep track of time for next pulse
+
+      if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
+        secondBeat = false;                  // clear secondBeat flag
+        for(int i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
+          rate[i] = IBI;                      
+        }
+      }
+
+      if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
+        firstBeat = false;                   // clear firstBeat flag
+        secondBeat = true;                   // set the second beat flag
+        __enable_irq();                               // enable interrupts again
+        return;                              // IBI value is unreliable so discard it
+      }   
+
+
+      // keep a running total of the last 10 IBI values
+      unsigned short runningTotal = 0;                  // clear the runningTotal variable    
+
+      for(int i=0; i<=8; i++){                // shift data in the rate array
+        rate[i] = rate[i+1];                  // and drop the oldest IBI value 
+        runningTotal += rate[i];              // add up the 9 oldest IBI values
+      }
+
+      rate[9] = IBI;                          // add the latest IBI to the rate array
+      runningTotal += rate[9];                // add the latest IBI to runningTotal
+      runningTotal /= 10;                     // average the last 10 IBI values 
+      BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
+      QS = true;                              // set Quantified Self flag 
+      // QS FLAG IS NOT CLEARED INSIDE THIS ISR
+      myLED = 1;
+    }                       
+  }
+
+  if(Pulse) {
+    PulseLength+=2;
+    if (Signal < thresh){   // when the values are going down, the beat is over
+        myLED = 0;           // turn off pin 13 LED
+        Pulse = false;                         // reset the Pulse flag so we can do it again
+        amp = P - T;                           // get amplitude of the pulse wave
+        //if (PulseLength > 4 && amp > (T/2)) {
+        if (PulseLength > 4 && amp > (T/3)) {
+            isBeating = true;
+            beatCount++;
+        }
+        thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
+        P = thresh;                            // reset these for next time
+        T = thresh;
+        PulseLength = 0;
+    }
+  }
+
+  if (N > 2500){                           // if 2.5 seconds go by without a beat
+    thresh = 512;                          // set thresh default
+    P = 512;                               // set P default
+    T = 512;                               // set T default
+    lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
+    firstBeat = true;                      // set these to avoid noise
+    secondBeat = false;                    // when we get the heartbeat back
+    isBeating = false;
+  }
+
+  __enable_irq();                                   // enable interrupts when youre done!
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Heart.h	Sun Sep 21 01:38:00 2014 +0000
@@ -0,0 +1,11 @@
+class Heart {
+    public:
+    Heart();
+    void sample();
+    void startReading();
+    void stopReading();
+    void reset();
+    bool beatDetected();
+    int beatsCounted();
+    int Signal;
+};
\ No newline at end of file
--- a/main.cpp	Sat Sep 20 20:45:21 2014 +0000
+++ b/main.cpp	Sun Sep 21 01:38:00 2014 +0000
@@ -4,6 +4,7 @@
 #include "wave_player.h"
 #include "uLCD_4DGL.h"
 #include "PinDetect.h"
+#include "Heart.h"
 #include <string>
 #include <sstream>
 
@@ -30,6 +31,7 @@
 PinDetect repeatButton(p14);
 PinDetect nextButton(p13);
 Timer timer;
+Heart heart = Heart();
 float windSensorVoltage;
 const int address = 0x77 << 1;
 bool breathing; 
@@ -162,13 +164,21 @@
 }
 
 void getPulse(){
-    //SENSOR DATA
-    pulse = false; 
+    pulse = heart.beatDetected(); 
 }
 
 void getVitals(){
+    timer.start();
+    heart.startReading();
+    while(timer.read()<10){}
+    heart.stopReading();
+    
     getBreathing();
     getPulse();
+    
+    timer.stop();
+    timer.reset();
+    heart.reset();
 }
 
 bool checkBreath(){