So I am making a project that measures biometrics during exercise and outputs them both to the serial monitor as well as to a set of external speakers for use by athletes with visual impairments. I have a problem where the heart rate sensor I am using (Default one from Pulsesensor.com) reads the first few beats as being super high (~160-250BPM) or low (~20-40BPM).
Is there some kind of "calibration" sequence I can add to the setup function to get a few values processed before it goes to the loop I have below? I already tried to implement one, as you can see but the program just skips to the loop when it doesn't immediately detect a heartbeat. Code is below.
#define USE_ARDUINO_INTERRUPTS true // Set-up low-level interrupts for most accurate BPM math
#include "DallasTemperature.h"
#include "OneWire.h"
#include "PulseSensorPlayground.h"
#include "Talkie.h"
#include "Vocab_US_Large.h"
#include "Vocab_Special.h"
#include <Wire.h>
#include "Adafruit_TPA2016.h"
Adafruit_TPA2016 audioamp = Adafruit_TPA2016();
Talkie voice;
const int PulseWire = 0; // PulseSensor PURPLE WIRE connected to ANALOG PIN 0
const int LED = LED_BUILTIN; // The on-board Arduino LED, close to PIN 13.
int Threshold = 550; // Determine which Signal to "count as a beat" and which to ignore.
int ZoneThresholdHigh, ZoneThresholdLow; //defines the ZoneThreshold variables for use in the setup and loop funcitons
int waitForInput() { //This loop accounts for the repeated waiting and retrieving of user-entered Data
while (!Serial.available()) { //While the serial monitor is active and waiting for input
delay(500);
}
return (Serial.readStringUntil('\n')).toInt(); //Returns the serial monitor input "readStringUntil" the enter "\n" key is pressed, and sets the input to an integer "toInt"
}
#define ONE_WIRE_BUS 13 // Data wire is plugged into pin 13 on the Arduino
PulseSensorPlayground pulseSensor;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass the oneWire reference to Dallas Temperature
DallasTemperature sensors(&oneWire);
void setup() {
audioamp.begin();
audioamp.enableChannel(true, true);
audioamp.setGain(20);
Serial.begin(9600);
sensors.begin();
// Variable definitions first
// Ask for age
Serial.println("Bootup");
Serial.println("------------------------------");
Serial.println("Please enter your age");
int AGE = 16;
//delay(5000);
Serial.println("------------------------------");
// Ask for resting heart rate
Serial.println("Please enter your resting heart rate: ");
int RESTING = 60;
//delay(5000);
Serial.println("------------------------------");
// Ask for workout zone
Serial.println("Please enter your desired workout zone (1-4, or 5 for a resting benchmark): ");
int WorkoutZone = waitForInput();
//delay(5000);
Serial.println("------------------------------");
Serial.println("You selected these values:");
Serial.println("Age: ");
Serial.println(AGE);
Serial.println("Resting HR: ");
Serial.println(RESTING);
Serial.println("Workout Zone: ");
Serial.println(WorkoutZone);
Serial.println("------------------------------");
Serial.println("Your Heart Rate information is being calculated");
int HRMAX = (207-(0.7*(AGE)));
int HRR = ((HRMAX)-(RESTING));
Serial.println("Maximum Heart Rate: ");
Serial.println(HRMAX);
Serial.println("Heart Rate Reserve: ");
Serial.println(HRR);
if (WorkoutZone == 1) {
//55-65%
ZoneThresholdLow = (((HRR)*0.55)+(RESTING));
ZoneThresholdHigh = (((HRR)*0.65)+(RESTING));
}
if (WorkoutZone == 2) {
//65-75%
ZoneThresholdLow = (((HRR)*0.65)+(RESTING));
ZoneThresholdHigh = (((HRR)*0.75)+(RESTING));
}
if (WorkoutZone == 3) {
//75-80%
ZoneThresholdLow = (((HRR)*0.75)+(RESTING));
ZoneThresholdHigh = (((HRR)*0.80)+(RESTING));
}
if (WorkoutZone == 4) {
//80-88%
ZoneThresholdLow = (((HRR)*0.80)+(RESTING));
ZoneThresholdHigh = (((HRR)*0.88)+(RESTING));
}
if (WorkoutZone == 5) {
//Resting Zone
ZoneThresholdHigh = (RESTING+20);
ZoneThresholdLow = (RESTING);
}
pulseSensor.analogInput(PulseWire);
pulseSensor.setThreshold(Threshold);
// Double-check the "pulseSensor" object was created and "began" seeing a signal.
if (pulseSensor.begin()) {
Serial.println("Pulse Sensor is on and active!"); //This prints one time at Arduino power-up, or on Arduino reset.
}
Serial.println("----------------------------------");
Serial.println("Maximum Heart Rate: ");
Serial.println(ZoneThresholdHigh);
Serial.println("----------------------------------");
Serial.println("Minimum Heart Rate: ");
Serial.println(ZoneThresholdLow);
Serial.println("----------------------------------");
delay(1000);
Serial.println("The Pulse Sensor is now calibrating, please rest your finger with the tip touching the green light on the HR sensor.");
delay(1000);
Serial.println("The high heart rate extremum will now be calibrated. Remain still.");
if (pulseSensor.sawStartOfBeat()) {
int SetupBPM = pulseSensor.getBeatsPerMinute();
while ((SetupBPM) > ZoneThresholdHigh){
delay(20);
Serial.println("Calibrated BPM:");
Serial.print(SetupBPM);
}
if ((SetupBPM) < ZoneThresholdHigh) {
Serial.println("High heart rate extremum calibration completed-initializing low extremum now");
while ((SetupBPM) < ZoneThresholdLow) {
delay(20);
Serial.println("Calibrated BPM:");
Serial.print(SetupBPM);
}
if ((SetupBPM) > ZoneThresholdLow){
Serial.println("Low heart rate extremum calibration completed. Workout Starting");
}
}
}
}
void loop() {
if (pulseSensor.sawStartOfBeat()) { // Constantly test to see if "a beat happened".
int BPM = pulseSensor.getBeatsPerMinute(); // Calls function on our pulseSensor object that returns BPM as an "int".
Serial.println("BPM: ");
Serial.println(BPM);
delay(20);
if ((BPM) > ZoneThresholdHigh) {
Serial.println("Heart Rate above max threshold");
Serial.println("----------------------------------");
voice.say(spPAUSE2);
voice.say(sp2_SPEED);
voice.say(sp2_HIGH);
voice.say(spPAUSE1);
voice.say(sp2_SLOW);
voice.say(sp5_DOWN);
}
if ((BPM) < ZoneThresholdLow) {
Serial.println("Heart Rate below min threshold");
Serial.println("----------------------------------");
voice.say(spPAUSE2);
voice.say(sp2_SPEED);
voice.say(sp2_LOW);
voice.say(spPAUSE1);
voice.say(sp2_SPEED);
voice.say(sp2_UP);
}
}
}