Zhihan Zhang / PulseSensor

Dependents:   4180_FinalProject

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PulseSensor.cpp Source File

PulseSensor.cpp

00001 #include "PulseSensor.h"
00002 
00003 
00004 PulseSensor::PulseSensor(PinName analogPin, void (*printDataCallback)(int), int callbackRateMs)
00005 {
00006     _started = false;
00007     
00008     _pAin = new AnalogIn(analogPin);
00009     
00010     _callbackRateMs = callbackRateMs;
00011     
00012     _printDataCallback = printDataCallback;
00013 }
00014 
00015 
00016 PulseSensor::~PulseSensor()
00017 {
00018     delete _pAin;
00019 }
00020 
00021 
00022 void PulseSensor::process_data_ticker_callback(void)
00023 {
00024     //_printDataCallback('S', Signal);     // send Processing the raw Pulse Sensor data
00025     if (QS == true) { // Quantified Self flag is true when a heartbeat is found
00026         //fadeRate = 255;                  // Set 'fadeRate' Variable to 255 to fade LED with pulse
00027         //_printDataCallback('B',BPM);   // send heart rate with a 'B' prefix
00028         _printDataCallback(BPM);
00029         //_printDataCallback('Q',IBI);   // send time between beats with a 'Q' prefix
00030         QS = false;                      // reset the Quantified Self flag for next time
00031     }
00032 }
00033 
00034 
00035 void PulseSensor::sensor_ticker_callback(void)
00036 {
00037     Signal = 1023 * _pAin->read();              // read the Pulse Sensor
00038     
00039     
00040     sampleCounter += 2;                         // keep track of the time in mS with this variable
00041     int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise
00042 
00043     //  find the peak and trough of the pulse wave
00044     if(Signal < thresh && N > (IBI/5)*3) {      // avoid dichrotic noise by waiting 3/5 of last IBI
00045         if (Signal < T) {                       // T is the trough
00046             T = Signal;                         // keep track of lowest point in pulse wave
00047         }
00048     }
00049 
00050     if(Signal > thresh && Signal > P) {         // thresh condition helps avoid noise
00051         P = Signal;                             // P is the peak
00052     }                                        // keep track of highest point in pulse wave
00053 
00054     //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
00055     // signal surges up in value every time there is a pulse
00056     if (N > 250) {                                  // avoid high frequency noise
00057         if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ) {
00058             Pulse = true;                               // set the Pulse flag when we think there is a pulse
00059             //digitalWrite(blinkPin,HIGH);                // turn on pin 13 LED
00060             IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
00061             lastBeatTime = sampleCounter;               // keep track of time for next pulse
00062 
00063             if(firstBeat) {                        // if it's the first time we found a beat, if firstBeat == TRUE
00064                 firstBeat = false;                 // clear firstBeat flag
00065                 return;                            // IBI value is unreliable so discard it
00066             }
00067             if(secondBeat) {                       // if this is the second beat, if secondBeat == TRUE
00068                 secondBeat = false;                 // clear secondBeat flag
00069                 for(int i=0; i<=9; i++) {        // seed the running total to get a realisitic BPM at startup
00070                     rate[i] = IBI;
00071                 }
00072             }
00073 
00074             // keep a running total of the last 10 IBI values
00075             long runningTotal = 0;                   // clear the runningTotal variable
00076 
00077             for(int i=0; i<=8; i++) {               // shift data in the rate array
00078                 rate[i] = rate[i+1];              // and drop the oldest IBI value
00079                 runningTotal += rate[i];          // add up the 9 oldest IBI values
00080             }
00081 
00082             rate[9] = IBI;                          // add the latest IBI to the rate array
00083             runningTotal += rate[9];                // add the latest IBI to runningTotal
00084             runningTotal /= 10;                     // average the last 10 IBI values
00085             BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
00086             QS = true;                              // set Quantified Self flag
00087             // QS FLAG IS NOT CLEARED INSIDE THIS ISR
00088         }
00089     }
00090 
00091     if (Signal < thresh && Pulse == true) {    // when the values are going down, the beat is over
00092         Pulse = false;                         // reset the Pulse flag so we can do it again
00093         amp = P - T;                           // get amplitude of the pulse wave
00094         thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
00095         P = thresh;                            // reset these for next time
00096         T = thresh;
00097     }
00098 
00099     if (N > 2500) {                            // if 2.5 seconds go by without a beat
00100         thresh = 512;                          // set thresh default
00101         P = 512;                               // set P default
00102         T = 512;                               // set T default
00103         lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date
00104         firstBeat = true;                      // set these to avoid noise
00105         secondBeat = true;                     // when we get the heartbeat back
00106     }
00107 }
00108 
00109 
00110 bool PulseSensor::start()
00111 {
00112     if (_started == false)
00113     {
00114         sampleCounter = 0;
00115         lastBeatTime = 0;
00116         P =512;
00117         T = 512;
00118         thresh = 512;
00119         amp = 100;
00120         firstBeat = true;
00121         secondBeat = true;
00122         
00123         BPM=0;
00124         Signal=0;
00125         IBI = 600;
00126         Pulse = false;
00127         QS = false;
00128         
00129         _pulseSensorTicker.attach(this, &PulseSensor::sensor_ticker_callback, ((float)_sensorTickRateMs/1000));
00130         _processDataTicker.attach(this, &PulseSensor::process_data_ticker_callback,  ((float)_callbackRateMs/1000));
00131         _started = true;
00132         return true;
00133     }
00134     else
00135     {
00136         return false;
00137     }
00138 }
00139 
00140 bool PulseSensor::stop()
00141 {
00142     if(_started == true)
00143     {
00144         _pulseSensorTicker.detach();
00145         _processDataTicker.detach();
00146         _started = false;
00147         return true;
00148     }
00149     else
00150     {
00151         return false;
00152     }
00153 }
00154 
00155 uint8_t PulseSensor::get_bpm(){
00156     return BPM;
00157 }