IoT用クラウドサービス「Ambient」と心拍センサーを使った心拍モニターです。心拍センサー「Pulse Sensor Amped」の値をmbed「Simple IoT Board」で読み、「Ambient」に送信してモニターします。 https://ambidata.io

Dependencies:   AmbientLib SimpleIoTBoardLib mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pulseSensor.cpp Source File

pulseSensor.cpp

00001 /*
00002  * The MIT License (MIT)
00003  * 
00004  * Copyright (c) 2015 Pulse Sensor
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a copy
00007  * of this software and associated documentation files (the "Software"), to deal
00008  * in the Software without restriction, including without limitation the rights
00009  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00010  * copies of the Software, and to permit persons to whom the Software is
00011  * furnished to do so, subject to the following conditions:
00012  * 
00013  * The above copyright notice and this permission notice shall be included in all
00014  * copies or substantial portions of the Software.
00015  * 
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00019  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00020  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00021  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00022  * SOFTWARE.
00023  */
00024 #include "mbed.h"
00025 
00026 AnalogIn pulsePin(dp13);
00027 DigitalOut led(dp6);
00028 
00029 #define SAMPLING 2000.0f  //  Sampling period in micro seconds  2msec
00030 
00031 volatile int rate[10];                    // array to hold last ten IBI values
00032 volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
00033 volatile unsigned long lastBeatTime = 0;           // used to find IBI
00034 volatile int P =512;                      // used to find peak in pulse wave, seeded
00035 volatile int T = 512;                     // used to find trough in pulse wave, seeded
00036 volatile int thresh = 525;                // used to find instant moment of heart beat, seeded
00037 volatile int amp = 100;                   // used to hold amplitude of pulse waveform, seeded
00038 volatile bool firstBeat = true;           // used to seed rate array so we startup with reasonable BPM
00039 volatile bool secondBeat = false;         // used to seed rate array so we startup with reasonable BPM
00040 
00041 // Volatile Variables, used in the interrupt service routine!
00042 volatile int BPM;                           // int that holds raw Analog in 0. updated every 2mS
00043 volatile int Signal;                        // holds the incoming raw data
00044 volatile int IBI = 600;                     // int that holds the time interval between beats! Must be seeded! 
00045 volatile bool Pulse = false;                // "True" when User's live heartbeat is detected. "False" when not a "live beat". 
00046 volatile bool QS = false;                   // becomes true when Arduoino finds a beat.
00047 
00048 Ticker t2;
00049 
00050 // THIS IS THE TICKER INTERRUPT SERVICE ROUTINE. 
00051 // Ticker makes sure that we take a reading every 2 miliseconds
00052 void sampling() {                             // triggered every 2 miliseconds
00053   Signal = (int)(pulsePin.read()*1023);       // read the Pulse Sensor 
00054   sampleCounter += 2;                         // keep track of the time in mS with this variable
00055   int N = sampleCounter - lastBeatTime;       // monitor the time since the last beat to avoid noise
00056 
00057     //  find the peak and trough of the pulse wave
00058   if(Signal < thresh && N > (IBI/5)*3){       // avoid dichrotic noise by waiting 3/5 of last IBI
00059     if (Signal < T){                          // T is the trough
00060       T = Signal;                             // keep track of lowest point in pulse wave 
00061     }
00062   }
00063 
00064   if(Signal > thresh && Signal > P){          // thresh condition helps avoid noise
00065     P = Signal;                               // P is the peak
00066   }                                           // keep track of highest point in pulse wave
00067 
00068   //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
00069   // signal surges up in value every time there is a pulse
00070   if (N > 250){                                   // avoid high frequency noise
00071     if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){        
00072       Pulse = true;                               // set the Pulse flag when we think there is a pulse
00073       IBI = sampleCounter - lastBeatTime;         // measure time between beats in mS
00074       lastBeatTime = sampleCounter;               // keep track of time for next pulse
00075 
00076       if(secondBeat){                        // if this is the second beat, if secondBeat == TRUE
00077         secondBeat = false;                  // clear secondBeat flag
00078         for(int i=0; i<=9; i++){             // seed the running total to get a realisitic BPM at startup
00079           rate[i] = IBI;                      
00080         }
00081       }
00082 
00083       if(firstBeat){                         // if it's the first time we found a beat, if firstBeat == TRUE
00084         firstBeat = false;                   // clear firstBeat flag
00085         secondBeat = true;                   // set the second beat flag
00086         return;                              // IBI value is unreliable so discard it
00087       }
00088 
00089       // keep a running total of the last 10 IBI values
00090       unsigned runningTotal = 0;              // clear the runningTotal variable    
00091 
00092       for(int i=0; i<=8; i++){                // shift data in the rate array
00093         rate[i] = rate[i+1];                  // and drop the oldest IBI value 
00094         runningTotal += rate[i];              // add up the 9 oldest IBI values
00095       }
00096 
00097       rate[9] = IBI;                          // add the latest IBI to the rate array
00098       runningTotal += rate[9];                // add the latest IBI to runningTotal
00099       runningTotal /= 10;                     // average the last 10 IBI values 
00100       BPM = 60000/runningTotal;               // how many beats can fit into a minute? that's BPM!
00101       QS = true;                              // set Quantified Self flag 
00102       // QS FLAG IS NOT CLEARED INSIDE THIS ISR
00103       led = 1;
00104     }                       
00105   }
00106 
00107   if (Signal < thresh && Pulse == true){   // when the values are going down, the beat is over
00108     Pulse = false;                         // reset the Pulse flag so we can do it again
00109     amp = P - T;                           // get amplitude of the pulse wave
00110     thresh = amp/2 + T;                    // set thresh at 50% of the amplitude
00111     P = thresh;                            // reset these for next time
00112     T = thresh;
00113     led = 0;
00114   }
00115 
00116   if (N > 2500){                           // if 2.5 seconds go by without a beat
00117     thresh = 512;                          // set thresh default
00118     P = 512;                               // set P default
00119     T = 512;                               // set T default
00120     lastBeatTime = sampleCounter;          // bring the lastBeatTime up to date        
00121     firstBeat = true;                      // set these to avoid noise
00122     secondBeat = false;                    // when we get the heartbeat back
00123   }
00124 
00125 }
00126 
00127 void interruptSetup(){
00128     // Initializes Ticker to throw an interrupt every 2mS.
00129     t2.attach_us(&sampling, SAMPLING);
00130 }
00131 
00132