Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BPM sometimes shoots up without a change in heart beat #73

Open
jens-k opened this issue May 25, 2018 · 9 comments
Open

BPM sometimes shoots up without a change in heart beat #73

jens-k opened this issue May 25, 2018 · 9 comments

Comments

@jens-k
Copy link

jens-k commented May 25, 2018

I have a problem similar to at least two others that have been reported (but I couldn't find a solution so far). The bpm output of the sensor sometimes goes up to unrealistic values (~150) while the times series of the heartbeat appears to be transmitted truthfully. The problem becomes evident already when I look at the 'raw' output in the serial monitor (so its not my later processing of that output). Even without being attached to a finger the bpm shoots up once in a while, while the heart beat time series remains quite constant and certainly below my provided threshold.

I'm using an Arduino Uno Rev 3. To the same board I have attached a GSR and an EMG sensor (which is handled in the code below, too). I use version 1.2.3 of the PulseSensor Playground library (since later versions gave me compiler errors).

I know that other people had the same problem too, but in one case the sensor was fake, in the other I think no solution was found. I'm using the sensor to teach medical students how mental states influence physiological responses by visualizing several physiological parameters with matlab while they perform mentally stressful tasks. I and they would be really grateful if there was a solution to the problem.

Find attached a photo of my sensor and my code.

Thanks!
Jens


#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>

const int OUTPUT_TYPE = SERIAL_PLOTTER;

const int PIN_INPUT = A0;
const int PIN_BLINK = 13; // Pin 13 is the on-board LED
const int THRESHOLD = 720; // tried this with values up to 950
int h1;
int h2;
int h3;
int g;
int m;

PulseSensorPlayground pulseSensor; // all the PulseSensor Playground functions.

void setup() {

Serial.begin(115200);

// Configure the PulseSensor manager.
pulseSensor.analogInput(PIN_INPUT);
pulseSensor.blinkOnPulse(PIN_BLINK);

pulseSensor.setSerial(Serial);
pulseSensor.setOutputType(OUTPUT_TYPE);
pulseSensor.setThreshold(THRESHOLD);

// Now that everything is ready, start reading the PulseSensor signal.
if (!pulseSensor.begin()) {
/*
If your Sketch hangs here, try ProcessEverySample.ino,
which doesn't use interrupts.
*/
for (;;) {
// Flash the led to show things didn't work.
digitalWrite(PIN_BLINK, LOW);
delay(50);
digitalWrite(PIN_BLINK, HIGH);
delay(50);
}
}
}

void loop() {
delay(20); // was 20

// Get the sensor data
h1 = pulseSensor.getLatestSample();
h2 = pulseSensor.getBeatsPerMinute();
h3 = pulseSensor.getInterBeatIntervalMs();
g = analogRead(A1);
m = analogRead(A2);

// Send data to serial port
Serial.print(h1); // Full heart time series
Serial.print(F(","));
Serial.print(h2); // BPM
Serial.print(F(","));
Serial.print(h3); // IBI
Serial.print(F(","));
Serial.print(g); // GSR
Serial.print(F(","));
Serial.print(m); // Muscle
Serial.println();

if (pulseSensor.sawStartOfBeat()) {
pulseSensor.outputBeat();
}
}

img_20180525_182644

@biomurph
Copy link
Contributor

First off, I am using Arduino 1.8.5, along with the PulseSensor Playground version 1.4.5, and I am able to compile for the UNO board. What is the error message you are getting? BTW, I will be updating to 1.4.6 today.

I just tried your code (targeting a Leonardo, which shouldn't make a difference). I don't have any GSR or EMG sensors, so I see cross-talk on the A1 and A2 pins (lower amplitude pulse wave). I don't get any of the high value BPM that you're talking about... Granted I did not run it for a long time.

You can comment out or remove the lines
if (pulseSensor.sawStartOfBeat()) {
pulseSensor.outputBeat();
}
Since you are already reporting the values of BPM and IBI in the code you wrote. The outputBeat function will simply report those values.

When the PulseSensor is idle, it is possible to get erroneous pulses. We don't have any stock noise cancelling code, because each individual setup is different, but if you look at the Tools page, there is a function call that returns the amplitude of the pulse wave. You may be able to use that to remove erroneous beats.

Please share a screen shot of the issue that you are seeing.
Also, this is the deprecated code repo. This conversation really belongs on the Playground repo.

@jens-k
Copy link
Author

jens-k commented May 25, 2018

Hi biomurph,
thanks for the reply. If I remember correctly, there was some function that now took a different number of input parameters but was still called with the old number. I tried to debug it for some time but then gave up. Do you think the issue could be solved by an update?

The issue comes up about every 10 sec for me, so you don't have to test for long.

K thx, I will remove those lines.

I gave the idle scenario because it shows best how strong the dissociation of reported heart beat and reported bpm is. It is not simply that there is high-frequency noise (assuming the bpm calculation is done on the same signal that is provided by getLatestSample and not on a signal that is filtered differently).

I can send a screenshot once I'm back in the lab but its really just one column that shows reasonable heartbeat values over time and a second column that shows reasonable bpms but intermittently goes up to 150 or so.

Sorry for posting in the wrong repo, I just looked for issues and opened a new one. I cannot transfer it now, though. Should I open a new one and close this?

@jens-k
Copy link
Author

jens-k commented May 28, 2018

After updating to PulseSensor Playground 1.4.5 I get the following compilation error (with my script but also all playground example scripts):

C:\Users\XXX\Documents\Arduino\libraries\PulseSensor_Playground\src\PulseSensorPlayground.cpp: In member function 'void PulseSensorPlayground::setThreshold(int, int)': C:\Users\XXX\Documents\Arduino\libraries\PulseSensor_Playground\src\PulseSensorPlayground.cpp:194:13: error: return-statement with a value, in function returning 'void' [-fpermissive] return -1; // out of range. ^ Error compiling.

I'm currently using Arduino 1.6.5 (company-provided computer), if this might be an issue, I can try to update next week.

@biomurph
Copy link
Contributor

@jens-k please update to the latest library version. That should fix the problem of compilation.

@jens-k
Copy link
Author

jens-k commented May 30, 2018

Thanks biomurph. I now updated to Arduino 1.8.5 and PulseSensorPlayground library version 1.4.9 (interestingly, my old Arduino version did not show me library versions > 1.4.5). I also took out the pulseSensor.outputBeat(); command.

The code compiles, but the main problem still persists. Here is a screenshot of the serial plotter. Please note that pulse (red) and IBI (green) appear to vary surprisingly independently (seem to have different update cycles) and both change drastically while the heart beat time series looks rather stationary. The threshold was set to 850 and thus far higher than the secondary pulse peak.

plotter

@biomurph
Copy link
Contributor

OK, I think I can see what the problem might be. It looks like there is a second upward going wave in the signal that you are getting. That second wave seems to be the culprit. What happens inside the library is that the threshold value is dynamic, and it adjust with every beat to ensure that it is basically triggering on the middle of the upward going pulse wave. It looks like your signal is tricking the library into thinking there is a pulse when there is not a pulse... here's a possible fix for your situation.

On line 147 of the PulseSensor.cpp file inside the library, there is a line
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI / 5) * 3) ) {
What that is doing is it's checking the signal to see if it has risen above the threshold. Then, it checks to see if we are not already inside of a 'pulse', then it checks to see if it has been long enough. In this case, 'long enough' means 3/5 of the last IBI time. Here's where you could make an adjustment, in the timing.
3/5 is 0.6 of the last IBI
3/4 is 0.75 of the last IBI
4/5 is 0.8 of the last IBI

Try these alternatives to the formula

(N > (IBI/4) * 3)
or
(N > (IBI/5) * 4)

That could help you 'clear' the pulse wave timing thing. Does that make sense?

I offer this suggestion, because the way that the threshold is set and then 'travels' with the pulse wave is more tedious to 'fix'. And, if this works, then we know what the problem is.

@jens-k
Copy link
Author

jens-k commented May 31, 2018

I tried all of those, without much of an effect, even with a threshold of 920 and setting the 146 to N>500. The maximum BPM is lower now, at around 130 instead of 160, but most of the time I'm shown to be at ~100 (while actually I have a resting heart rate in the 70s).

By the way, I tried the same with another arduino and another one of your PulseSensors, same problem.

Would you have any other suggestions?

@biomurph
Copy link
Contributor

Huh. Well, in my experience with pulse signals that are very large or small I don't get this effect. Even running for a long time.

I think the next thing to try is to get more verbose. For example, serial print the thresh variable...

Also, looking at your serial monitor data, I can see that every time the green IBI wave changes, Arduino thinks there is a beat. Notice that it corresponding with peaks that are not actual pulse. This is the problem.

Try commenting out the line

thresh = amp / 2 + T;

In the PulseSensor.cpp file. That will disable the self adjusting threshold

@jens-k
Copy link
Author

jens-k commented May 31, 2018

Oh yeah, that gives me much more realistic and consistent readings (see below). It's probably not optimal to use a static threshold but, considering others had the same problem, could you maybe add a method to turn the threshold off without getting into the library code?
..e.g.: pulseSensor.dynamicThreshold(false);

Thanks for your help. I'll try that out with students soon.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants