WorldFamousElectronics / PulseSensorPlayground

A PulseSensor library (for Arduino) that collects our most popular projects in one place.
https://PulseSensor.com
MIT License
200 stars 97 forks source link

High value of BPM using PulseSensor_BPM_Alternative #123

Closed Sofyanjm closed 12 months ago

Sofyanjm commented 4 years ago

Hello,

I am using Arduino Nano 33 BLE sense and PulseSensor_BPM_Alternative code. It is working for the serial plotter, but I get very high values in the serial monitor. Is there an explanation to get the correct values of BPM?

Screen Shot 2020-04-02 at 3 50 42 AM

Thank you

biomurph commented 4 years ago

@Sofyanjm when you say it's working in the plotter, what do you mean? Can you send a screen shot of that? Also, the Serial output that you are seeing is the data that is sent to the plotter. The first number is BPM, second number is the IBI, and third is the raw sensor data. This should be the same as the data that you're seeing in the plotter.

Also, please send a picture of your Pulse Sensor so I can check your setup.

Sofyanjm commented 4 years ago

Screen Shot 2020-04-02 at 4 21 12 PM Screen Shot 2020-04-02 at 4 22 54 PM IMG_2340 This is the pulse sensor that I use. @biomurph

biomurph commented 4 years ago

@Sofyanjm Thanks for the images. Yep, you got a legit Pulse Sensor. You'd be surprised how many clones are out there.

The serial plotter looks good! So does the serial monitor in the latest screen shot. Not sure what the issue might be in the previous post....

There is a little bit of high frequency noise visible in the bottom part of the pulse wave. Do you have your computer plugged into a power supply? Sometimes the power line noise can creep into the signal when plugged in. If you care about that, check out the signal when you are running on just the laptop battery.

amanm27 commented 4 years ago

@biomurph Hello! I'm having a similar problem, getting high values for BPM using the PulseSensor_BPM_Alternative sketch (consistently above 100bpm, usually between 100 and 150bpm). I'm running it on a Adafruit Bluefruit Feather (nRF52832). Below are screenshots of the serial monitor and plotter running the Alternative sketch, as well as the packaging of the PulseSensor I'm using. Any guidance on what might be causing these unusually high values would be greatly appreciated. Thank you!

monitor plotter

pulse_sensor_packaging

biomurph commented 4 years ago

@amanm27 The pulse waveform looks pretty good, however there does show a rather large 'second wave' of the pulse form. The largest upward spike is the heartbeat, and the secondary, smaller spike is an artifact of the dicrotic notch. The red line is the IBI value, that is the measured time between beats, and it does appear to be changing when the tallest spike of the pulse wave happens, which it should. Notice, however just to the left of the X axis '4262' label, where the red line changes with that secondary spike. That could be contributing to the high values of BPM, because the BPM uses a rolling average of 10 IBI values. You can sort of see that in the blue line (BPM), how it raises a bit for a while, then drops back down.

That said, your BPM values are a bit high, but not unreasonably high. Can you check this against some other Arduino hardware, like an UNO?

amanm27 commented 4 years ago

@biomurph Thanks for the pointers! Unfortunately I don't have access to other Arduino hardware at the moment. I see your point about the dicrotic notch potentially contributing to high BPM, but I tested more and looked at the waveform and that only seems to happen very rarely so that doesn't seem like a recurring issue. It's puzzling because as you said the pulse waveform and IBI's look good, it's just the BPM values are higher than expected. We're really interested in extracting breaths per minute using the IBI's, so the magnitude of the HR doesn't really affect our goal directly as long as the IBI's follow a nice pattern, but if you have any other ideas about what might contribute to higher-than-normal HR readings that would be great. Thanks again!

biomurph commented 4 years ago

@amanm27 I don't have an nRF52832 on hand, but I do have an nRF52840, and I can try on that hardware. The thing is that you are using the BPM_Alternative sketch, which uses micros() to time the samples, so there really shouldn't be any issues. Can you tell my anything else about your setup? Have you modified the PulseSensor Playground example sketch at all?

amanm27 commented 4 years ago

@biomurph I haven't modified the sketch at all. As far as my setup, I'm using the PulseSensor with an Adafruit Bluefruit Feather (nRF52832), running Arduino 1.8.13 on a MacBook Pro with macOS Catalina 10.15.5. I don't have my Mac plugged in to charge when the PulseSensor and Feather are also connected; I've attached a picture of my setup below as well. If you could let me know if any similar problems arise with the nRF52840 that would be awesome. Thank you!

IMG_5714

IMG_5715

biomurph commented 4 years ago

I was able to upload the BPM_Alternative sketch to my nRF52840 and I'm getting a very similar result to your data. I also loaded the code onto an Arduino UNO, and got legit results. I have the on-board LED blinking to my heartbeat, and the pulse signal trace looks good.

This seems to have something to do with the way the nRF52 boards are interpreting the timing of our software timer. I will look under the hood and see if I can find out what's going on. @bneedhamia Could you take a look at this issue if you have a chance? I'm getting an IBI of around 500 on the nRF52 board, and on the UNO the IBI is more like 750 or so. Something is up.

amanm27 commented 4 years ago

@biomurph ahh that makes sense. Thank you so much!

biomurph commented 4 years ago

@amanm27 Well, at least finding the bug didn't take too long! Here's the relevant links https://forums.adafruit.com/viewtopic.php?f=53&t=162235&p=802573 https://github.com/adafruit/Adafruit_nRF52_Arduino/issues/451 TLDR: We use micros() in our software sample timer, and micros() is not usable on the Adafruit nRF52 under this current implementation.

What to do? Well, you could run the Pulse Sensor code on a separate microcontroller that can more accurately time the samples (yuck).

It may be be possible to use the hardware to set up a timer. This is kind of crazy, but it might work as a work around. Basically, the nRF52 supports pin interrupts. If you can get a pin to go high or low at the right frequency, this might work as a useful timer. Add to that the fact that you can output tone() on a pin, then you could maybe tie the tone() output pin to the interrupt pin to hack a hardware timer? Or, perhaps you could set a pin to output a tone, and also use that pin as an interrupt (woah...).

In any event, a fix is not trivial, but it might be fun?

amanm27 commented 4 years ago

@biomurph we seem to have fixed the issue of high HR values, and are now consistently getting HR values below 90 bpm.

The main fix was to disengage our code base from the PulseSensor Playground library (no longer including any of the header files and such), which commonly used the micros() timer that was in conflict with our nRF52832 board. So, we basically just took the example code for the beat extraction process (the processSample() function from PulseSensor.cpp) and used that in our own code separate from the library altogether. On top of that, we implemented our own hardware interrupt timer to read samples from the sensor at 500 Hz, which we validated indeed fires off every 2ms. After all that, we've been getting much better HR values.

Thank you so much once again for all your guidance!

ghost commented 3 years ago

Hello,

I am using Arduino Nano 33 BLE sense and PulseSensor_BPM_Alternative code. It is working for the serial plotter, but I get very high values in the serial monitor. Is there an explanation to get the correct values of BPM?

Screen Shot 2020-04-02 at 3 50 42 AM

Thank you

biomurph commented 3 years ago

Please read the thread. Reach out to previous posters for help until we get this resolved in the library

bneedhamia commented 3 years ago

@biomurph I deeply apologize for missing your request months ago. Do I understand the root cause from this thread as: the micros() function on nRF52 processors has too low a time resolution to be used with the pulse library? ...or have I missed something here (which is quite likely, since I haven't looked at this code in so long)?

Thanks, and again, apologies for the long delay in my response to this thread.

biomurph commented 3 years ago

@bneedhamia Hey, nice to see you!

Yes, you hit the nail on the head. I suppose it should be entered as a 'to do'. A few users have been able to commandeer the nRF52 timer and get some working projects from that. This issue tab does refer to that. I suggest that we start a conversation on a different channel to address this issue.

Vandanadr commented 2 years ago

@amanm27 Hi, could you please share the code that worked for you. I am using an Arduino Nano ble 33 sense with the pulse sensor and I am having the same issues with the timers. The controller is the nrf52840 and It'd be really helpful if you could share your implementation. Thanks!

neuromerca commented 2 years ago

I have the same problem on Arduino MKR WiFi 1010

biomurph commented 2 years ago

@0xfunes This thread is old. Your problem description is vague. What is your hardware setup? Please post a picture of your hardware? Please post the exact example sketch you're using?

biomurph commented 12 months ago

PulseSensor Playground library supports nRF52 hardware.