Go Down

Topic: Pulse Sensor Amped issues (Read 581 times) previous topic - next topic

millerr01

Hi! I'm having a few issues with coding my pulse sensor.

I used the A_PulseSensor06  code. I am relatively new to programming, so im not entirely sure what most of the code does.

Essentially, for my project i am using 3 LED's one connected to pin 13 that blinks at the rate of the heart rate, and the other two on pins 12 & 11 to light up depending on the value returned from the sensor. I know i do not need half of the code, as my project is very basic in comparison with the pulse sensor code im using.

The LED on pin 13 blinks erratically and im sure it's not correctly blinking at the rate of my heart beat. Secondly the LED's connected to pins 11 & 12  light up erratically i place the pulse sensor on my finger.

The values returned from the pulse sensor are high between 600-1000 so i used quite high ranges, i am unsure whether the values being returned from the pulse sensor are correct or not.

I have modified the code slightly to add the LED's in and added ranges in.

Any help would be greatly appreciated! Many Thanks in advance!

millerr01

Code: [Select]
long Hxv[4]; // these arrays are used in the digital filter
long Hyv[4]; // H for highpass, L for lowpass
long Lxv[4];
long Lyv[4];

unsigned long readings; // used to help normalize the signal
unsigned long peakTime; // used to time the start of the heart pulse
unsigned long lastPeakTime = 0;// used to find the time between beats
volatile int Peak;     // used to locate the highest point in positive phase of heart beat waveform
int rate;              // used to help determine pulse rate
volatile int BPM;      // used to hold the pulse rate
int offset = 0;        // used to normalize the raw data
int sampleCounter;     // used to determine pulse timing
int beatCounter = 1;   // used to keep track of pulses
volatile int Signal;   // holds the incoming raw data
int NSignal;           // holds the normalized signal
volatile int FSignal;  // holds result of the bandpass filter
volatile int HRV;      // holds the time between beats
volatile int Scale = 13;  // used to scale the result of the digital filter. range 12<>20 : high<>low amplification
volatile int Fade = 0;

boolean first = true; // reminds us to seed the filter on the first go
volatile boolean Pulse = false;  // becomes true when there is a heart pulse
volatile boolean B = false;     // becomes true when there is a heart pulse
volatile boolean QS = false;      // becomes true when pulse rate is determined. every 20 pulses

int pulsePin = 0;  // pulse sensor purple wire connected to analog pin 0

int LowHeartRate = 11;
int HighHeartRate = 12;


void setup(){
pinMode(13,OUTPUT);    // pin 13 will blink to your heartbeat
pinMode(LowHeartRate, OUTPUT); //PIN 11
pinMode(HighHeartRate, OUTPUT); /PIN 12
Serial.begin(115200); // we agree to talk fast!
// this next bit will wind up in the library. it initializes Timer1 to throw an interrupt every 1mS.
TCCR1A = 0x00; // DISABLE OUTPUTS AND BREAK 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

}



void loop(){
// Serial.print("S");          // S tells processing that the following string is sensor data
// Serial.println(Signal);     // Signal holds the latest raw Pulse Sensor signal
// if (B == true){             //  B is true when arduino finds the heart beat
//   Serial.print("B");        // 'B' tells Processing the following string is HRV data (time between beats in mS)
//   Serial.println(HRV);      //  HRV holds the time between this pulse and the last pulse in mS
//   B = false;                // reseting the QS for next time
// }
// if (QS == true){            //  QS is true when arduino derives the heart rate by averaging HRV over 20 beats
//   Serial.print("Q");        //  'QS' tells Processing that the following string is heart rate data
//   Serial.println(BPM);      //  BPM holds the heart rate in beats per minute
//   QS = false;               //  reset the B for next time
// }
// Fade -= 15;
// Fade = constrain(Fade,0,255);
// analogWrite(11,Fade);
 
delay(20);                    //  take a break

}

// THIS IS THE TIMER 1 INTERRUPT SERVICE ROUTINE. IT WILL BE PUT INTO THE LIBRARY
ISR(TIMER1_OVF_vect){ // triggered every time Timer 1 overflows
// Timer 1 makes sure that we take a reading every milisecond
Signal = analogRead(pulsePin);

// First normailize the waveform around 0
readings += Signal; // take a running total
sampleCounter++;     // we do this every milisecond. this timer is used as a clock
if ((sampleCounter %300) == 0){   // adjust as needed
 offset = readings / 300;        // average the running total
 readings = 0;                   // reset running total
}
NSignal = Signal - offset;        // normalizing here

// IF IT'S THE FIRST TIME THROUGH THE SKETCH, SEED THE FILTER WITH CURRENT DATA
if (first = true){
 for (int i=0; i<4; i++){
   Lxv[i] = Lyv[i] = NSignal <<10;  // seed the lowpass filter
   Hxv[i] = Hyv[i] = NSignal <<10;  // seed the highpass filter
 }
first = false;      // only seed once please
}
// THIS IS THE BANDPAS FILTER. GENERATED AT www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html
//  BUTTERWORTH LOWPASS ORDER = 3; SAMPLERATE = 1mS; CORNER = 5Hz
   Lxv[0] = Lxv[1]; Lxv[1] = Lxv[2]; Lxv[2] = Lxv[3];
   Lxv[3] = NSignal<<10;    // insert the normalized data into the lowpass filter
   Lyv[0] = Lyv[1]; Lyv[1] = Lyv[2]; Lyv[2] = Lyv[3];
   Lyv[3] = (Lxv[0] + Lxv[3]) + 3 * (Lxv[1] + Lxv[2])
         + (3846 * Lyv[0]) + (-11781 * Lyv[1]) + (12031 * Lyv[2]);
//  Butterworth; Highpass; Order = 3; Sample Rate = 1mS; Corner = .8Hz
   Hxv[0] = Hxv[1]; Hxv[1] = Hxv[2]; Hxv[2] = Hxv[3];
   Hxv[3] = Lyv[3] / 4116; // insert lowpass result into highpass filter
   Hyv[0] = Hyv[1]; Hyv[1] = Hyv[2]; Hyv[2] = Hyv[3];
   Hyv[3] = (Hxv[3]-Hxv[0]) + 3 * (Hxv[1] - Hxv[2])
         + (8110 * Hyv[0]) + (-12206 * Hyv[1]) + (12031 * Hyv[2]);
FSignal = Hyv[3] >> Scale;  // result of highpass shift-scaled

//PLAY AROUND WITH THE SHIFT VALUE TO SCALE THE OUTPUT ~12 <> ~20 = High <> Low Amplification.

if (FSignal >= Peak && Pulse == false){  // heart beat causes ADC readings to surge down in value.  
 Peak = FSignal;                        // finding the moment when the downward pulse starts
 peakTime = sampleCounter;              // recodrd the time to derive HRV.
}
//  NOW IT'S TIME TO LOOK FOR THE HEART BEAT
if ((sampleCounter %20) == 0){// only look for the beat every 20mS. This clears out alot of high frequency noise.
 if (FSignal < 0 && Pulse == false){  // signal surges down in value every time there is a pulse
    Pulse = true;                     // Pulse will stay true as long as pulse signal < 0
    digitalWrite(13,HIGH);            // pin 13 will stay high as long as pulse signal < 0  
    Fade = 255;                       // set the fade value to highest for fading LED on pin 11 (optional)  
    HRV = peakTime - lastPeakTime;    // measure time between beats
    lastPeakTime = peakTime;          // keep track of time for next pulse
    B = true;                         // set the Quantified Self flag when HRV gets updated. NOT cleared inside this ISR    
    rate += HRV;                      // add to the running total of HRV used to determine heart rate
    beatCounter++;                     // beatCounter times when to calculate bpm by averaging the beat time values
    if (beatCounter == 10){            // derive heart rate every 10 beats. adjust as needed
      rate /= beatCounter;             // averaging time between beats
      BPM = 60000/rate;                // how many beats can fit into a minute?
      //Serial.println(BPM);              // print the BMP to the console
      // set up our LEDs
      // in our test run the BPM varies from 500 - 1000!!
      // lets set up values for lights
     
      if (BPM < 750)
      {
        digitalWrite(LowHeartRate, HIGH);
        digitalWrite(HighHeartRate, LOW);
        Serial.println("LOW HEART RATE");
      }
     
     if (BPM > 800)
     {
       digitalWrite(LowHeartRate, LOW);
       digitalWrite(HighHeartRate, HIGH);
       Serial.println("High Heart Rate");  
     }
     // else to capture anything other than the abovwe
     else
     {
       digitalWrite(LowHeartRate, LOW);
       digitalWrite(HighHeartRate, LOW);
       Serial.println("You are Dead- No Heart Rate");
     }
     
     
     
      beatCounter = 0;                 // reset counter
      rate = 0;                        // reset running total
      QS = true;                       // set Beat flag when BPM gets updated. NOT cleared inside this ISR
    }
 }
 if (FSignal > 0 && Pulse == true){    // when the values are going up, it's the time between beats
   digitalWrite(13,LOW);               // so turn off the pin 13 LED
   Pulse = false;                      // reset these variables so we can do it again!
   Peak = 0;                           //
 }
}

// write the BPM to the console

//Serial.println(BPM);

}// end isr

Go Up