Pages: [1]   Go Down
Author Topic: Pulse/Heartbeat Sensor Problems.  (Read 1438 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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!
  }
  
}
« Last Edit: January 09, 2013, 03:44:02 am by Harrison_Rusinyak » Logged

Offline Offline
Edison Member
*
Karma: 64
Posts: 2484
The last thing you did is where you should start looking.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you read this?
http://arduino.cc/forum/index.php/topic,97455.0.html
Logged

Offline Offline
Faraday Member
**
Karma: 80
Posts: 3790
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Seems it's not the easiest sensor to get working....
Logged

Although I answer in good faith, remember always: Your Mileage May Vary.
Get me on LinkedIn: za.linkedin.com/in/jimbrownza/

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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;
  }
     
}
Logged

Pages: [1]   Go Up
Jump to: