Mako SHIMURA
/
HeartPulseModify
LED Pierce and pulse program.
Interrupt.cpp@0:a78b08608d76, 2014-01-11 (annotated)
- Committer:
- asagin
- Date:
- Sat Jan 11 12:50:28 2014 +0000
- Revision:
- 0:a78b08608d76
- Child:
- 1:171a73d84261
I cannnot understand interrupt.;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
asagin | 0:a78b08608d76 | 1 | |
asagin | 0:a78b08608d76 | 2 | volatile int rate[10]; // used to hold last ten IBI values |
asagin | 0:a78b08608d76 | 3 | volatile unsigned long sampleCounter = 0; // used to determine pulse timing |
asagin | 0:a78b08608d76 | 4 | volatile unsigned long lastBeatTime = 0; // used to find the inter beat interval |
asagin | 0:a78b08608d76 | 5 | volatile int P =512; // used to find peak in pulse wave |
asagin | 0:a78b08608d76 | 6 | volatile int T = 512; // used to find trough in pulse wave |
asagin | 0:a78b08608d76 | 7 | volatile int thresh = 512; // used to find instant moment of heart beat |
asagin | 0:a78b08608d76 | 8 | volatile int amp = 100; // used to hold amplitude of pulse waveform |
asagin | 0:a78b08608d76 | 9 | volatile bool firstBeat = true; // used to seed rate array so we startup with reasonable BPM |
asagin | 0:a78b08608d76 | 10 | volatile bool secondBeat = true; // used to seed rate array so we startup with reasonable BPM |
asagin | 0:a78b08608d76 | 11 | |
asagin | 0:a78b08608d76 | 12 | |
asagin | 0:a78b08608d76 | 13 | void interruptSetup(){ |
asagin | 0:a78b08608d76 | 14 | // Initializes Timer2 to throw an interrupt every 2mS. |
asagin | 0:a78b08608d76 | 15 | TCCR2A = 0x02; // DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE |
asagin | 0:a78b08608d76 | 16 | TCCR2B = 0x06; // DON'T FORCE COMPARE, 256 PRESCALER |
asagin | 0:a78b08608d76 | 17 | OCR2A = 0X7C; // SET THE TOP OF THE COUNT TO 124 FOR 500Hz SAMPLE RATE |
asagin | 0:a78b08608d76 | 18 | TIMSK2 = 0x02; // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A |
asagin | 0:a78b08608d76 | 19 | sei(); // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED |
asagin | 0:a78b08608d76 | 20 | } |
asagin | 0:a78b08608d76 | 21 | |
asagin | 0:a78b08608d76 | 22 | |
asagin | 0:a78b08608d76 | 23 | // THIS IS THE TIMER 2 INTERRUPT SERVICE ROUTINE. |
asagin | 0:a78b08608d76 | 24 | // Timer 2 makes sure that we take a reading every 2 miliseconds |
asagin | 0:a78b08608d76 | 25 | ISR(TIMER2_COMPA_vect){ // triggered when Timer2 counts to 124 |
asagin | 0:a78b08608d76 | 26 | cli(); // disable interrupts while we do this |
asagin | 0:a78b08608d76 | 27 | Signal = analogRead(pulsePin); // read the Pulse Sensor |
asagin | 0:a78b08608d76 | 28 | sampleCounter += 2; // keep track of the time in mS with this variable |
asagin | 0:a78b08608d76 | 29 | int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise |
asagin | 0:a78b08608d76 | 30 | |
asagin | 0:a78b08608d76 | 31 | // find the peak and trough of the pulse wave |
asagin | 0:a78b08608d76 | 32 | if(Signal < thresh && N > (IBI/5)*3){ // avoid dichrotic noise by waiting 3/5 of last IBI |
asagin | 0:a78b08608d76 | 33 | if (Signal < T){ // T is the trough |
asagin | 0:a78b08608d76 | 34 | T = Signal; // keep track of lowest point in pulse wave |
asagin | 0:a78b08608d76 | 35 | } |
asagin | 0:a78b08608d76 | 36 | } |
asagin | 0:a78b08608d76 | 37 | |
asagin | 0:a78b08608d76 | 38 | if(Signal > thresh && Signal > P){ // thresh condition helps avoid noise |
asagin | 0:a78b08608d76 | 39 | P = Signal; // P is the peak |
asagin | 0:a78b08608d76 | 40 | } // keep track of highest point in pulse wave |
asagin | 0:a78b08608d76 | 41 | |
asagin | 0:a78b08608d76 | 42 | // NOW IT'S TIME TO LOOK FOR THE HEART BEAT |
asagin | 0:a78b08608d76 | 43 | // signal surges up in value every time there is a pulse |
asagin | 0:a78b08608d76 | 44 | if (N > 250){ // avoid high frequency noise |
asagin | 0:a78b08608d76 | 45 | if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) ){ |
asagin | 0:a78b08608d76 | 46 | Pulse = true; // set the Pulse flag when we think there is a pulse |
asagin | 0:a78b08608d76 | 47 | digitalWrite(blinkPin,HIGH); // turn on pin 13 LED |
asagin | 0:a78b08608d76 | 48 | IBI = sampleCounter - lastBeatTime; // measure time between beats in mS |
asagin | 0:a78b08608d76 | 49 | lastBeatTime = sampleCounter; // keep track of time for next pulse |
asagin | 0:a78b08608d76 | 50 | |
asagin | 0:a78b08608d76 | 51 | if(firstBeat){ // if it's the first time we found a beat, if firstBeat == TRUE |
asagin | 0:a78b08608d76 | 52 | firstBeat = false; // clear firstBeat flag |
asagin | 0:a78b08608d76 | 53 | return; // IBI value is unreliable so discard it |
asagin | 0:a78b08608d76 | 54 | } |
asagin | 0:a78b08608d76 | 55 | if(secondBeat){ // if this is the second beat, if secondBeat == TRUE |
asagin | 0:a78b08608d76 | 56 | secondBeat = false; // clear secondBeat flag |
asagin | 0:a78b08608d76 | 57 | for(int i=0; i<=9; i++){ // seed the running total to get a realisitic BPM at startup |
asagin | 0:a78b08608d76 | 58 | rate[i] = IBI; |
asagin | 0:a78b08608d76 | 59 | } |
asagin | 0:a78b08608d76 | 60 | } |
asagin | 0:a78b08608d76 | 61 | |
asagin | 0:a78b08608d76 | 62 | // keep a running total of the last 10 IBI values |
asagin | 0:a78b08608d76 | 63 | word runningTotal = 0; // clear the runningTotal variable |
asagin | 0:a78b08608d76 | 64 | |
asagin | 0:a78b08608d76 | 65 | for(int i=0; i<=8; i++){ // shift data in the rate array |
asagin | 0:a78b08608d76 | 66 | rate[i] = rate[i+1]; // and drop the oldest IBI value |
asagin | 0:a78b08608d76 | 67 | runningTotal += rate[i]; // add up the 9 oldest IBI values |
asagin | 0:a78b08608d76 | 68 | } |
asagin | 0:a78b08608d76 | 69 | |
asagin | 0:a78b08608d76 | 70 | rate[9] = IBI; // add the latest IBI to the rate array |
asagin | 0:a78b08608d76 | 71 | runningTotal += rate[9]; // add the latest IBI to runningTotal |
asagin | 0:a78b08608d76 | 72 | runningTotal /= 10; // average the last 10 IBI values |
asagin | 0:a78b08608d76 | 73 | BPM = 60000/runningTotal; // how many beats can fit into a minute? that's BPM! |
asagin | 0:a78b08608d76 | 74 | QS = true; // set Quantified Self flag |
asagin | 0:a78b08608d76 | 75 | // QS FLAG IS NOT CLEARED INSIDE THIS ISR |
asagin | 0:a78b08608d76 | 76 | } |
asagin | 0:a78b08608d76 | 77 | } |
asagin | 0:a78b08608d76 | 78 | |
asagin | 0:a78b08608d76 | 79 | if (Signal < thresh && Pulse == true){ // when the values are going down, the beat is over |
asagin | 0:a78b08608d76 | 80 | digitalWrite(blinkPin,LOW); // turn off pin 13 LED |
asagin | 0:a78b08608d76 | 81 | Pulse = false; // reset the Pulse flag so we can do it again |
asagin | 0:a78b08608d76 | 82 | amp = P - T; // get amplitude of the pulse wave |
asagin | 0:a78b08608d76 | 83 | thresh = amp/2 + T; // set thresh at 50% of the amplitude |
asagin | 0:a78b08608d76 | 84 | P = thresh; // reset these for next time |
asagin | 0:a78b08608d76 | 85 | T = thresh; |
asagin | 0:a78b08608d76 | 86 | } |
asagin | 0:a78b08608d76 | 87 | |
asagin | 0:a78b08608d76 | 88 | if (N > 2500){ // if 2.5 seconds go by without a beat |
asagin | 0:a78b08608d76 | 89 | thresh = 512; // set thresh default |
asagin | 0:a78b08608d76 | 90 | P = 512; // set P default |
asagin | 0:a78b08608d76 | 91 | T = 512; // set T default |
asagin | 0:a78b08608d76 | 92 | lastBeatTime = sampleCounter; // bring the lastBeatTime up to date |
asagin | 0:a78b08608d76 | 93 | firstBeat = true; // set these to avoid noise |
asagin | 0:a78b08608d76 | 94 | secondBeat = true; // when we get the heartbeat back |
asagin | 0:a78b08608d76 | 95 | } |
asagin | 0:a78b08608d76 | 96 | |
asagin | 0:a78b08608d76 | 97 | sei(); // enable interrupts when youre done! |
asagin | 0:a78b08608d76 | 98 | }// end isr |