I have been trying this for a while but still couldn't figure it out. I am using the pulse sensor for heart beat which is this one (https://pulsesensor.com/). As I have the Arduino BLE Sense and I am not sure how to use interrupts, I found the code that would calculate the beats per minute with out using the interrupts but not efficient from here (interrupt - pulse sensor + arduino mkr1000 to calculate BPM - Stack Overflow)
#define pulsePin A0
// VARIABLES
int rate[10];
unsigned long sampleCounter = 0;
unsigned long lastBeatTime = 0;
unsigned long lastTime = 0, N;
int BPM = 0;
int IBI = 0;
int P = 512;
int T = 512;
int thresh = 512;
int amp = 100;
int Signal;
boolean Pulse = false;
boolean firstBeat = true;
boolean secondBeat = true;
boolean QS = false;
void setup() {
Serial.begin(9600);
}
void loop() {
if (QS == true) {
Serial.println("BPM: "+ String(BPM));
QS = false;
} else if (millis() >= (lastTime + 20)) {
readPulse();
lastTime = millis();
// Serial.print("Last time = ");
// Serial.println(lastTime);
}
}
void readPulse() {
Signal = analogRead(pulsePin);
sampleCounter += 20; // keep track of the time in mS
int N = sampleCounter - lastBeatTime; // monitor the time since the last beat to avoid noise
detectSetHighLow();
if (N > 200) { // avoid high frequency noise
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3) )
pulseDetected();
}
if (Signal < thresh && Pulse == true) { // when the values are going down, the beat is over
Pulse = false; // reset the Pulse flag so we can do it again
amp = P - T; // get amplitude of the pulse wave
thresh = amp / 2 + T; // set thresh at 50% of the amplitude
P = thresh; // reset these for next time
T = thresh;
}
if (N > 2500) { // if 2.5 seconds go by without a beat
thresh = 512; // set thresh default
P = 512; // set P default
T = 512; // set T default
lastBeatTime = sampleCounter; // bring the lastBeatTime up to date
firstBeat = true;
secondBeat = true;
}
}
void detectSetHighLow() {
if (Signal < thresh && N > (IBI / 5) * 3) {
if (Signal < T) {
T = Signal; // keep track of lowest point in pulse wave
}
}
if (Signal > thresh && Signal > P) {
P = Signal; // keep track of highest point in pulse wave
}
}
void pulseDetected() {
Pulse = true; // set the Pulse flag when we think there is a pulse
IBI = sampleCounter - lastBeatTime; // measure time between beats in mS
Serial.print("IBI = ");
Serial.println(IBI);
lastBeatTime = sampleCounter; // keep track of time for next pulse
if (firstBeat) { // if it's the first time we found a beat, if firstBeat == TRUE
firstBeat = false; // clear firstBeat flag
secondBeat = true;
return;
}
if (secondBeat) { // if it's the secoond time we found a beat, if secondBeat == TRUE
secondBeat = false; // clear SecondBeat flag
for (int i = 0; i <= 9; i++) {
rate[i] = IBI;
}
}
word runningTotal = 0; // clear the runningTotal variable
for (int i = 0; i <= 8; i++) { // shift data in the rate array
rate[i] = rate[i + 1]; // and drop the oldest IBI value
runningTotal += rate[i]; // add up the 9 oldest IBI values
}
rate[9] = IBI; // add the latest IBI to the rate array
runningTotal += rate[9]; // add the latest IBI to runningTotal
runningTotal /= 10; // average the last 10 IBI values
BPM = 60000 / runningTotal; // how many beats can fit into a minute? that's BPM!
QS = true; // set Quantified Self flag (we detected a beat)
}
but the Interval between beats is not quite correct.
I don't have my finger tip on the sensor and it gives me values, where it should be printing zero.
when i start sensing the value this is the output.
What i want is to be able to detect the interval between two peaks and calculate the beats per minute.
This is the raw output from serial plotter when i sense the pulse.
I tried a lot, like
void loop() {
Input_Voltage = analogRead( A0 ) ;
sample_counter += 2;
// Serial.print("sample_counter = ");
// Serial.println(sample_counter);
// Serial.print("Input_Voltage = ");
// Serial.println(Input_Voltage);
if (Input_Voltage > threshold && Input_Voltage > sampleLast) {
peak = Input_Voltage;
// Serial.print("peak = ");
// Serial.println(peak);
ts_1 = sample_counter;
// delay(2);
}
if( Input_Voltage < sampleLast && Input_Voltage < threshold && (sample_counter - ts_1) > ((IBI / 5) * 3) ) {
first_peak = peak_2;
first_peak_ts = peak_2_ts;
peak_2 = peak;
peak_2_ts = ts_1;
flag = 1;
// Serial.print("peak_2_ts = ");
// Serial.println(peak_2_ts);
// Serial.print("first_peak_ts = ");
// Serial.println(first_peak_ts);
IBI = peak_2_ts - first_peak_ts;
if (IBI != 0 ){
Serial.print("IBI = ");
Serial.println(IBI);
}
}
when the sample value is greater than threshold and larger than previous value, I note the sensor value, in that case when sample value is lesser than previous value and greater than threshold, i have a peak, I use the same and detect the second peak and calculate the difference, then i replace the second peak as first peak and find new second peak, but it doesn't seem to work.
can someone give me the logic to find the interval between two peaks with quick sampling rate. thank you so much for your help.