Go Down

Topic: Pulse/Heartbeat Sensor Problems. (Read 1 time) previous topic - next topic

Jan 09, 2013, 06:04 am Last Edit: Jan 09, 2013, 09:44 am by Harrison_Rusinyak Reason: 1
Hey Guys,

I'm sort of a newbie to the forum, and to the Arduino board (code managing) as well.

I have been working with the Arduino Uno to complete (for a second time) this project.
I am trying to connect the Pulse Sensor to the Arduino, as well as have the led light up with each heartbeat as well.

I've been pulling out my hair for days trying to find a permutation of coding that works. Initially after I bought the darned sensor -- weeks of code permutations -- I have finally made it working. Some underlying issue with the code was , but I have switched over computers; I have moved; the arduino [somehow] disappeared; I have misplaced the coding.

The code I'm attaching is the bit I'm having trouble with,. I'll supply the entire code in its original format (there are numerous circling the internet). I can't get it work simple and straightforward. Help/Suggestions would be much appreciated.

Thanks in advance.


Code: [Select]

volatile int rate[10];                    // used to get running average of HRV values
volatile unsigned long lastBeatTime = 0;  // used to find the time between beats
volatile int sampleCounter;               // used to determine pulse timing
volatile int runningTotal;                // used to keep track of pulses
volatile boolean firstBeat = true;        // used to seed rate array so we startup with reasonable BPM
volatile boolean secondBeat = true;       // used to seed rate array so we startup with reasonable BPM


void interruptSetup(){

 // Initializes Timer1 to throw an interrupt every 1mS.
 TCCR1A = 0x00; // DISABLE OUTPUTS AND PWM ON DIGITAL PINS 9 & 10
 TCCR1B = 0x11; // GO INTO 'PHASE AND FREQUENCY CORRECT' MODE, NO PRESCALER
 TCCR1C = 0x00; // DON'T FORCE COMPARE
 TIMSK1 = 0x01; // ENABLE OVERFLOW INTERRUPT (TOIE1)
 ICR1 = 8000;   // TRIGGER TIMER INTERRUPT EVERY 1mS  
 sei();         // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED

}


// THIS IS THE TIMER 1 INTERRUPT SERVICE ROUTINE.
ISR(TIMER1_OVF_vect){ // triggered every time Timer 1 overflows
 // Timer 1 makes sure that we take a reading every milisecond
 Signal = analogRead(pulsePin);  // read the Pulse Sensor
 sampleCounter++;                // keep track of the time with this variable (ISR triggered every 1mS

 //  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
 int H = sampleCounter-lastBeatTime;      // monitor the time since the last beat to avoid noise
 if ( (Signal > 520) && (Pulse == false) && (H > 500) ){  
   // signal surges up in value every time there is a pulse    
   Pulse = true;                       // set the Pulse flag when we think there is a pulse
   digitalWrite(13,HIGH);              // turn on pin 13 LED
   HRV = sampleCounter - lastBeatTime; // measure time between beats in mS
   lastBeatTime = sampleCounter;       // keep track of time for next pulse
   if(firstBeat){                      // if it's the first time we found a beat
     firstBeat = false;                // clear firstBeat flag
     return;                           // HRV value is unreliable so discard it
   }  
   if(secondBeat){                     // if this is the second beat
     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] = HRV;                      
     }
   }                          
   // keep a running total of the last 10 HRV values
   for(int i=0; i<=8; i++){
     rate[i] = rate[i+1];          // shift data in the rate array and drop the oldest HRV value
   }
 rate[9] = HRV;                    // add the latest HRV to the rate array
 runningTotal = 0;                 // clear the runningTotal variable
 for(int i=0; i<=9; i++){
   runningTotal += rate[i];        // add up the last 10 HRV values
 }  
 runningTotal /= 10;               // average the last 10 HRV values
 BPM = 60000/runningTotal;         // how many beats can fit into a minute? that's BPM!
 QS = true;                        // set Quantified Self flag when beat is found and BPM gets updated.
 // QS FLAG IS NOT CLEARED INSIDE THIS ISR
 }                      


 if (Signal < 500 && Pulse == true){   // when the values are going down, it's the time between beats
   digitalWrite(13,LOW);               // turn off pin 13 LED
   Pulse = false;                      // reset the Pulse flag so we can do it again!
 }
 
}

LarryD

Have you read this?
http://arduino.cc/forum/index.php/topic,97455.0.html
The way you have it in your schematic isn't the same as how you have it wired up!

JimboZA

There are two threads on this sensor by another member, here and here.

Seems it's not the easiest sensor to get working....
"Could you do the egg bacon spam and sausage without the spam then? "

No PMs for help please.
DO NOT power servos from Arduino 5V: give them their own power and connect the grounds.

Fixed -- for the most part -- the code for the Pulse Sensor (on my computer setup).
Don't know if there is any extraneous dialogue in the coding.
There is still some noise filtering which blinks chaotically.
Enjoy.

Code: [Select]

int pulsePin = 0;         
int blinkPin = 13;         
int fadePin = 5;           
int fadeRate = 0; 
volatile int BPM;                 
volatile int Signal;               
volatile int IBI = 600;             
volatile boolean Pulse = false;
volatile boolean QS = false; 
volatile int rate[10];                 
volatile unsigned long sampleCounter = 0;   
volatile unsigned long lastBeatTime = 0;     
volatile int P =512;               
volatile int T = 512;               
volatile int thresh = 512;       
volatile int amp = 100;         
volatile boolean firstBeat = true;       
volatile boolean secondBeat = true;

void setup(){

  TCCR2A = 0x02; 
  TCCR2B = 0x06;
  OCR2A = 0x7C; 
  TIMSK2 = 0x02; 
  sei();
}
void loop(){
}
ISR(TIMER2_COMPA_vect){
  Signal = analogRead(pulsePin);
  sampleCounter += 2;               
  int N = sampleCounter - lastBeatTime;
    if(Signal < thresh && N > (IBI/5)*3){
      if (Signal < T){
        T = Signal;   
      }
    }
    if(Signal > thresh && Signal > P){ 
        P = Signal;                     
      }
if (N > 250){
if ( (Signal > thresh) && (Pulse == false) && (N > ((IBI/5)*3) )){ 
    Pulse = true;                     
    digitalWrite(blinkPin,HIGH); 
    delay(200); //   
    IBI = sampleCounter - lastBeatTime;
    lastBeatTime = sampleCounter;       
   if(firstBeat){                     
      firstBeat = false;             
      return;                         
    }   
    if(secondBeat){             
      secondBeat = false;     
      for(int i=0; i<=9; i++){   
        rate[i] = IBI;                     
      }
    }   
word  runningTotal = 0;
    for(int i=0; i<=8; i++){
      rate[i] = rate[i+1];
      runningTotal += rate[i];     
    }
    rate[9] = IBI;                   
    runningTotal += rate[9];             
    runningTotal /= 10;             
    BPM = 60000/runningTotal;
    QS = true;                       
    }             
}     
  if (Signal < thresh && Pulse == true){ 
    digitalWrite(13,LOW);
    delay(200); //   
    Pulse = false;                     
    amp = P - T;                       
    thresh = amp/2 + T;           
    P = thresh;                         
    T = thresh;
  }
if (N > 2500){   
    thresh = 512;
    P = 512;
    T = 512;
    firstBeat = true;                 
    secondBeat = true;           
    lastBeatTime = sampleCounter;
  }
     
}

Go Up