Heart Rate Monitor, help finding BPM and automatically stopping after 5 beats

Hello, I am doing a heart rate monitor project for a class, and cannot figure out how to complete it. The professor has said it is okay to get help and use code from the web as long as we understand it. The task is below as well as my code. I've included my non-working code for the 5 iterations and stopping but it is commented out. Thanks!

Problems: + Cannot figure out how to stop after 5 beats + Cannot decide on upper and lower thresholds since the sensor is finnicky and depending on how tightly it is attached the values returned at peak and minimum values are different. + Cannot get BPM from just 5 cycles.

Task:

"Write a program that will capture five pulses worth of data in the Serial Monitor then stop the Arduino. For full credit on this problem, use a combination of if and while() statements to automatically stop the program after five pulses."

Code:

int HRmonitor = A0; // select the input pin for the photoplethysmograph int i = 0; // variable to store the value coming from the sensor int LED13 = 13; // The on-board LED int UpperThreshold = 520; // Determines which signals to count as a beat and which to ignore int LowerThreshold = 490; int reading = 0; float BPM = 0.0; bool IgnoreReading = false; bool FirstPulseDetected = false; unsigned long FirstPulseTime = 0; unsigned long SecondPulseTime = 0; unsigned long PulseInterval = 0; int count=0;

void setup() { pinMode(LED13,OUTPUT); Serial.begin(9600); }

void loop() { i = analogRead(HRmonitor);// Reads the value from the sensor

if(i > UpperThreshold){ // If the signal is above 525 the LED will blink indicating a heartbeat. digitalWrite(LED13,HIGH); } else { digitalWrite(LED13,LOW); // Else, the signal must be below 525 to turn-off this LED. }

//int count=count++; //while(count<5);

delay(10);

// Heart beat leading edge detected. if(i > UpperThreshold && IgnoreReading == false){ if(FirstPulseDetected == false){ FirstPulseTime = millis(); FirstPulseDetected = true; } else{ SecondPulseTime = millis(); PulseInterval = SecondPulseTime - FirstPulseTime; FirstPulseTime = SecondPulseTime; } IgnoreReading = true; }

// Heart beat trailing edge detected. if(i < LowerThreshold){ IgnoreReading = false; }

BPM = (1.0/PulseInterval) * 60.0 * 1000;

Serial.print(i); Serial.print("\t"); Serial.print(BPM); Serial.println(" BPM"); Serial.flush(); }

if(i > UpperThreshold){                          // If the signal is above 525 the LED will blink indicating a heartbeat.
     digitalWrite(LED13,HIGH);
   } else {
     digitalWrite(LED13,LOW);                //  Else, the signal must be below 525 to turn-off this LED.
   }

//int count=count++;
//while(count<5);

If that if statement is where you are detecting a beat, and the stuff inside of it is what runs when you detect a beat, and the stuff outside of the block runs all the time beat or not...

then where do you think it makes sense to put the code that adds one to the number of beats? Inside the part that only runs when there is a beat? Or out in the part that runs over and over regardless of the beat?

REAL hearth rate monitors (I mean medical grade!) often need more than 5 beats before they learn the curve and are able to detect pulses reliably. And sometimes they fail completely. Without some standardized setup (known upper and lower threshold) the task is impossible IMHO.

Delta_G: ``` if(i > UpperThreshold){                          // If the signal is above 525 the LED will blink indicating a heartbeat.     digitalWrite(LED13,HIGH);   } else {     digitalWrite(LED13,LOW);                //  Else, the signal must be below 525 to turn-off this LED.   }

//int count=count++; //while(count<5);




If that if statement is where you are detecting a beat, and the stuff inside of it is what runs when you detect a beat, and the stuff outside of the block runs all the time beat or not...

then where do you think it makes sense to put the code that adds one to the number of beats? Inside the part that only runs when there is a beat? Or out in the part that runs over and over regardless of the beat?

@Delta_G I would say inside the part where it only runs on a beat, right? Since I only want to add 1 each beat. When I apply the included while(count<5) it totally stopped working. I didn't get an error message, but it didn't work either. Does this mean there is a logic error? This is my first time doing anything in arduino (or anything other than MATLAB for that matter), so I apologize for my ignorance.

Right. You would want to put it inside. Now which line is it that adds one to the count? And where is it? Is it inside the { and } after the if statement that only runs when there is a beat detected.

If you're not sure which part, check your comments.

Hi could you please elaborate more on the while loop? thanks!!

while()

Tutorial

argrant1115: Hi could you please elaborate more on the while loop? thanks!!

I don't think you want a while loop in this program. Let the loop function do the looping.

int HRmonitor = A0;    // select the input pin for the photoplethysmograph
int i = 0;  // variable to store the value coming from the sensor
int LED13 = 13;   //  The on-board LED
int UpperThreshold = 550;            // Determines which signals to count as a beat and which to ignore
int LowerThreshold = 490;
int reading = 0;
float BPM = 0.0;
bool IgnoreReading = false;
bool FirstPulseDetected = false;
unsigned long FirstPulseTime = 0;
unsigned long SecondPulseTime = 0;
unsigned long PulseInterval = 0;
int count=0;

void setup() {
pinMode(LED13,OUTPUT);        
Serial.begin(9600);
}

void loop() 
{
//while(count<5)
    {
i = analogRead(HRmonitor);// Reads the value from the sensor
{
if(i > UpperThreshold){                          // If the signal is above the upper threshold the LED will blink indicating a heartbeat.
     digitalWrite(LED13,HIGH); 
     count=count+1;
   } 
   else {
     digitalWrite(LED13,LOW);                //  Else, the signal must be below the upper threshold to turn-off this LED.
   }
   delay(10);
}
delay(10);


      
if(i > UpperThreshold && IgnoreReading == false)// Heart beat leading edge detected.
{ 
        if(FirstPulseDetected == false){
          FirstPulseTime = millis();
          FirstPulseDetected = true;
        }
        else{
          SecondPulseTime = millis();
          PulseInterval = SecondPulseTime - FirstPulseTime;
          FirstPulseTime = SecondPulseTime;
        }
        IgnoreReading = true;
     }

      
 if(i < LowerThreshold)// Heart beat trailing edge detected.
 {
        IgnoreReading = false;
      }  

      BPM = (1.0/PulseInterval) * 60.0 * 1000;

      delay(10);
      Serial.print("Count: ");
      Serial.print(count);
      Serial.print("\t");
      Serial.print("\t");
      Serial.print(i);
      Serial.print("\t");
      Serial.print(BPM);
      Serial.println(" BPM");
      Serial.print("\t");
      Serial.flush();

}

}

I figured it out. Thanks so much for the help @Delta_G! I had to put the while loop before the if statement. One of the largest issues though is the sensor itself, it was very inconsistent on readings so I had to keep changing my threshold values but I finally got it to work.

Your while statement is commented out. You could just delete it.