Hi! I'm trying to get the exact time in ms between heart beats with 2 ms. precision and I found the problem that, apparently, the checkForBeat() takes 20ms. for execution. So all beat times I get are multiples of 20 with no precision of 2ms.
If I do a Serial.print(millis()) with a void loop I can see this:
20:53:04.602 -> 8680
20:53:04.640 -> 8680
20:53:04.640 -> 8681
20:53:04.640 -> 8681
20:53:04.640 -> 8682
20:53:04.640 -> 8682
20:53:04.640 -> 8683
20:53:04.640 -> 8683
20:53:04.640 -> 8684
20:53:04.640 -> 8684
20:53:04.640 -> 8685
20:53:04.640 -> 8686
20:53:04.640 -> 8686
20:53:04.640 -> 8687
20:53:04.640 -> 8687
20:53:04.640 -> 8688
So I can deduce that the loop is taking 0,5 ms for its execution. But if I add the if (checkForBeat(irValue) == true) then the output is like this:
21:02:10.509 -> Outside millis: 34681
21:02:10.541 -> Outside millis: 34701
21:02:10.587 -> Outside millis: 34721
21:02:10.587 -> Outside millis: 34741
21:02:10.629 -> Outside millis: 34761
21:02:10.629 -> Outside millis: 34781
21:02:10.629 -> Outside millis: 34801
21:02:10.665 -> Outside millis: 34821
21:02:10.709 -> Outside millis: 34841
21:02:10.709 -> Outside millis: 34861
21:02:10.709 -> Outside millis: 34881
21:02:10.742 -> Outside millis: 34901
21:02:10.774 -> Outside millis: 34921
21:02:10.774 -> Outside millis: 34941
21:02:10.809 -> Outside millis: 34961
21:02:10.809 -> Outside millis: 34981
21:02:10.850 -> Outside millis: 35001
21:02:10.850 -> Outside millis: 35021
21:02:10.850 -> millis: 35023
21:02:10.884 -> Outside millis: 35041
21:02:10.930 -> Outside millis: 35061
21:02:10.930 -> Outside millis: 35081
21:02:10.930 -> Outside millis: 35101
21:02:10.970 -> Outside millis: 35121
21:02:10.970 -> Outside millis: 35141
21:02:11.007 -> Outside millis: 35161
21:02:11.038 -> Outside millis: 35181
21:02:11.038 -> Outside millis: 35201
21:02:11.070 -> Outside millis: 35221
21:02:11.070 -> Outside millis: 35241
21:02:11.111 -> Outside millis: 35261
21:02:11.111 -> Outside millis: 35281
21:02:11.148 -> Outside millis: 35301
21:02:11.191 -> Outside millis: 35321
21:02:11.191 -> Outside millis: 35341
21:02:11.191 -> Outside millis: 35361
21:02:11.224 -> Outside millis: 35381
21:02:11.271 -> Outside millis: 35401
21:02:11.271 -> Outside millis: 35421
21:02:11.311 -> Outside millis: 35441
21:02:11.311 -> Outside millis: 35461
21:02:11.311 -> Outside millis: 35481
21:02:11.350 -> Outside millis: 35501
21:02:11.391 -> Outside millis: 35521
21:02:11.391 -> Outside millis: 35541
21:02:11.391 -> Outside millis: 35561
21:02:11.427 -> Outside millis: 35581
21:02:11.471 -> Outside millis: 35601
21:02:11.471 -> Outside millis: 35621
21:02:11.471 -> Outside millis: 35641
21:02:11.506 -> Outside millis: 35661
21:02:11.551 -> Outside millis: 35681
21:02:11.551 -> Outside millis: 35701
21:02:11.551 -> Outside millis: 35721
21:02:11.583 -> Outside millis: 35741
21:02:11.630 -> Outside millis: 35761
21:02:11.630 -> Outside millis: 35781
21:02:11.672 -> Outside millis: 35801
21:02:11.672 -> Outside millis: 35821
21:02:11.672 -> Outside millis: 35841
21:02:11.707 -> Outside millis: 35861
21:02:11.752 -> Outside millis: 35881
21:02:11.752 -> Outside millis: 35901
21:02:11.752 -> millis: 35903
21:02:11.752 -> Outside millis: 35921
21:02:11.784 -> Outside millis: 35941
21:02:11.831 -> Outside millis: 35961
21:02:11.831 -> Outside millis: 35981
21:02:11.874 -> Outside millis: 36001
21:02:11.874 -> Outside millis: 36022
21:02:11.874 -> Outside millis: 36042
21:02:11.910 -> Outside millis: 36062
21:02:11.955 -> Outside millis: 36082
21:02:11.955 -> Outside millis: 36102
21:02:11.955 -> Outside millis: 36122
21:02:11.987 -> Outside millis: 36142
21:02:12.033 -> Outside millis: 36162
21:02:12.033 -> Outside millis: 36182
21:02:12.033 -> Outside millis: 36202
21:02:12.074 -> Outside millis: 36222
That's why I can deduce that the time to execute the checkForBeat() is 20 ms. so there's no way to know the exact time of the beat and the exact difference between beats with 2ms precission.
Any idea for this? Any other way to do it or any other function on the library? I heard something about interruptions, but I'm not sure how to do it using them.
Thank you very much!
Miguel Gisbert
Optical Heart Rate Detection (PBA Algorithm) using the MAX30105 Breakout
By: Nathan Seidle @ SparkFun Electronics
Date: October 2nd, 2016
https://github.com/sparkfun/MAX30105_Breakout
This is a demo to show the reading of heart rate or beats per minute (BPM) using
a Penpheral Beat Amplitude (PBA) algorithm.
It is best to attach the sensor to your finger using a rubber band or other tightening
device. Humans are generally bad at applying constant pressure to a thing. When you
press your finger against the sensor it varies enough to cause the blood in your
finger to flow differently which causes the sensor readings to go wonky.
Hardware Connections (Breakoutboard to Arduino):
-5V = 5V (3.3V is allowed)
-GND = GND
-SDA = A4 (or SDA)
-SCL = A5 (or SCL)
-INT = Not connected
The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V
but it will also run at 3.3V.
*/
#include <Wire.h>
#include "MAX30105.h"
#include "heartRate.h"
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
MAX30105 particleSensor;
const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;
long lastBeat2 = 0;
int numBeats = 0;
long delta=0;
long delta2=0;
float beatsPerMinute;
int beatAvg;
void setup() {
Serial.begin(115200);
Serial.println("Initializing...");
lcd.begin(16,2);
lcd.clear();
lcd.backlight();
// Initialize sensor
while ( !particleSensor.begin(Wire, I2C_SPEED_FAST) ) { //Use default I2C port, 400kHz speed
lcd.print("Sensor error.");
}
// particleSensor.setup(); //Configure sensor with default settings
// particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
// particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
byte ledBrightness = 80; //Options: 0=Off to 255=50mA
byte sampleAverage = 2; //Options: 1, 2, 4, 8, 16, 32
byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 69; //Options: 69, 118, 215, 411
int adcRange = 16384; //Options: 2048, 4096, 8192, 16384
particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
}
void loop() {
long irValue = particleSensor.getIR();
Serial.print("Outside millis: ");
Serial.print(millis());
Serial.println();
if (checkForBeat(irValue) == true) { // Beat detected
// delta = millis() - lastBeat;
Serial.print(" millis: ");
Serial.print(millis());
Serial.println();
// Serial.println();
// Serial.print(" lastBeat: ");
// Serial.print(lastBeat);
// Serial.print(" Delta: ");
// Serial.print(delta);
// Serial.println();
// lastBeat = millis();
// // lcd.clear();
// // lcd.setCursor(0,0);
// // lcd.print(delta);
// // lcd.setCursor(0,1);
// // lcd.print(delta2);
// // lcd.setCursor(10,1);
// // lcd.print("bts:");
// // lcd.setCursor(13,1);
// // lcd.print(numBeats);
// // numBeats += 1;
// // beatsPerMinute = 60 / (delta / 1000.0);
// // if (beatsPerMinute < 255 && beatsPerMinute > 20)
// // {
// // rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
// // rateSpot %= RATE_SIZE; //Wrap variable
// // //Take average of readings
// // beatAvg = 0;
// // for (byte x = 0 ; x < RATE_SIZE ; x++)
// // beatAvg += rates[x];
// // beatAvg /= RATE_SIZE;
// // }
}
// if (irValue < 50000) {
// lcd.clear();
// lcd.setCursor(0,0);
// lcd.print("Put your finger");
// lcd.setCursor(0,1);
// lcd.print("on the sensor");
// }
// else {
// lcd.setCursor(0,0);
// lcd.print("HR: ");
// lcd.print(beatAvg);
// }
// Serial.print("IR=");
// Serial.print(irValue);
// Serial.print(", RRms=");
// Serial.print(delta);
// Serial.print(", RRus=");
// Serial.print(delta2);
// Serial.println();
}