Updated answer:
The sketch is reading the data and sending the data to the serial monitor every 50ms because of the delay(50). What if we changed that to 1000 ms? The serial monitor would update once per second which would be more "human readable". The problem with that idea is for heart rates faster than 60 BPM, the reading would be inaccurate. I don't have a sensor to test with but I'm guessing a 1 second delay would make the code inoperable.
Before we add more complexity to this sketch we really should get rid of that delay. It would be nice to have one "timer" that we could use to update the BPM calculation and a second "timer" to update the serial monitor every second, or half second, or what ever you want it to be.
We can do that without any libraries using millis(). Here is an updated sketch using millis() for timers. This sketch has the blinking of the on board LED added to it. I'm using an Uno so you'll have to change LED_BUILTIN to what ever pin number you are using.
int UpperThreshold = 518;
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;
const unsigned long delayTime = 10;
const unsigned long delayTime2 = 1000;
const unsigned long baudRate = 9600;
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
void setup(){
Serial.begin(baudRate);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
}
void loop(){
// Get current time
unsigned long currentMillis = millis();
// First event
if(myTimer1(delayTime, currentMillis) == 1){
reading = analogRead(0);
// Heart beat leading edge detected.
if(reading > UpperThreshold && IgnoreReading == false){
if(FirstPulseDetected == false){
FirstPulseTime = millis();
FirstPulseDetected = true;
}
else{
SecondPulseTime = millis();
PulseInterval = SecondPulseTime - FirstPulseTime;
FirstPulseTime = SecondPulseTime;
}
IgnoreReading = true;
digitalWrite(LED_BUILTIN, HIGH);
}
// Heart beat trailing edge detected.
if(reading < LowerThreshold && IgnoreReading == true){
IgnoreReading = false;
digitalWrite(LED_BUILTIN, LOW);
}
// Calculate Beats Per Minute.
BPM = (1.0/PulseInterval) * 60.0 * 1000;
}
// Second event
if(myTimer2(delayTime2, currentMillis) == 1){
Serial.print(reading);
Serial.print("\t");
Serial.print(PulseInterval);
Serial.print("\t");
Serial.print(BPM);
Serial.println(" BPM");
Serial.flush();
}
}
// First event timer
int myTimer1(long delayTime, long currentMillis){
if(currentMillis - previousMillis >= delayTime){previousMillis = currentMillis;return 1;}
else{return 0;}
}
// Second event timer
int myTimer2(long delayTime2, long currentMillis){
if(currentMillis - previousMillis2 >= delayTime2){previousMillis2 = currentMillis;return 1;}
else{return 0;}
}
The code compile size with delay is 4,732 vs the millis timers at 4,682 (with the LED code removed). Two timers for less than the price of one delay :)
The LED will remain on for the duration of the heart beat reading above the LowerThreshold. If you want to have it on longer or decide how long it should be on for, I won't write the code for you but I will give you a hint. You can copy myTimer1() again and make a third timer.