Comments (14)
All right, I know what happened. All the sampling parameters are OK, the problem is your unusually high heart rate (HR). 87 bpm while just sitting on a chair is very high, indeed. Mine, for example, is ~60 bpm while sitting and ~50 bpm while sleeping.
First, let me refresh you on how the HR detection algorithm works: it is supposed to detect a local maximum of the first peak in the autocorrelation graph. The X value at this maximum (lag) corresponds to the raw data shifted by the averaged distance between neighbor peaks in the raw R/IR data graphs. This distance (D) is expressed as the number of samples between peaks, therefore heart rate (in bpm) is calculated as
HR = (60*FS)/D
where FS is the sampling frequency. Looking at the autocorrelation graph from your data you can see the first peak at around 68 samples, which leads to HR = 6000/68 = 88.23 - right in the ballpark of where it should be.
Hence, a perfect algorithm would detect the correct maximum of the first peak every time. However, this means a lot of calculations which eat up precious CPU time. My simple device is not equipped with a real time clock, thus I rely on MAX30102 sampling as an approximation of real time clock. For that, all the calculations done by rf_heart_rate_and_oxygen_saturation() must be very fast in order not to delay the measure of real time. The algorithm is successful in this respect, but at the cost of some sacrifices. The D detection routine, rf_signal_periodicity(), relies on an initial guess, D0, to find the appropriate maximum. The routine looks at autocorrelation values at D0, D0+1, and D0-1 to determine direction in which the peak resides. If, for example, D0=50 in your case, then the routine marches to the right at D1=51, D2=52, etc., until reaching peak at optimal Dn=68. The optimal value is then remembered as a new D0 for the next cycle. Since HR at night does not change much, the cost of obtaining its value from the next batch of samples is quite low - no more than a few evaluations of autocorrelation function.
Which brings me back to the initial guess, D0. Ideally, it should be in the range between first two local minima, e.g., 32 and 96 in your case. I tailored it to myself setting it to 25 at the beginning of rf_heart_rate_and_oxygen_saturation() function:
static int32_t n_last_peak_interval=FS; // Initialize it to 25, which corresponds to heart rate of 60 bps, RF
because HR=60 bpm was quite a safe bet. But in your case 60 bpm is just a bit too low. D0=100 is actually on the wrong side of the local minimum and rf_signal_periodicity() actually finds the second maximum at about 130 samples, which corresponds to twice the distance between heart beats and translates to too low HR=46.
I guess, all you have to do to adjust the code to your physiology is to update the D0 to, say, 67?
static int32_t n_last_peak_interval=67;
or
static int32_t n_last_peak_interval=2*FS/3;
from max30102_by_rf.
It happens because of this:
#define FS 25 //sampling frequency
#define BUFFER_SIZE (FS*4)
then
int8_t i;
for(i=0;i<BUFFER_SIZE;++i)
The index "i" is just an 8-bit signed integer. As such, it can't exceed 127. If you want to use higher sampling rates, then you have to replace all "int8_t" by integer types with higher byte count.
from max30102_by_rf.
@aromring thank you for the hint, but there is no int8_t i, it is int32_t in the code https://github.com/aromring/MAX30102_by_RF/blob/master/algorithm_by_RF.cpp
from max30102_by_rf.
It's in RD117_ARDUINO.ino
from max30102_by_rf.
@aromring I replace int8_t with int32_t, it crash. I tested with esp8266 and esp32, remove code with sdcard and change the setting of the sensor to no average(if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x00f)) ) and sample rate 100hz, take 400 samples, fix n_last_peak_interval by 25 (because you use the FS for this value). Have you ever try the board with 100hz sample?
from max30102_by_rf.
@aromring Never mind. Finally i can make it work. But your code not good with high sample rate, with 100 hz it give like 240 bpm, 70 % and jump to 99% in 1 minute.
from max30102_by_rf.
No, I've never tried my circuit with higher sampling rates, since they offer almost no improvement at much higher computing cost. Nevertheless, if you still insist on using 100 Hz, then read on.
You should have read my Instructable, especially Step 3 on preprocessing. You would notice that in order to save some CPU time I've pre-calculated the mean-centered sum of squares:
sum_X2 = S{t=-49.5;49.5} (t^2) = 83325
because FS=25 times 4 seconds gives 100 data points. With 100 Hz sampling rate the number of points increases to 400 and, correspondingly, the sum_X2 spans "t" values from -199.5 to 199.5:
sum_X2 = S{t=-199.5;199.5} (t^2) = 5333300
Thus, update the sum_X2 parameter in algorithm_by_RF.h by the above number and your measurements should fall back into the proper range.
from max30102_by_rf.
@aromring Yes, after apply your sum_X2 it work. Your code much more reliable than MAXIM code, but it only with SPO2 and not with heart rate. From my test both with 25hz and 100Hz, heart rate from 50 to 61 bpm but the real heart rate is 80.
from max30102_by_rf.
Well, I am afraid this perceived discrepancy is not the result of my code, but either an error in your setup, or a misunderstanding. I have checked heart rate results by countless tests not just one, but two independent methods. My MAX30102 provides essentially identical heart rates (HR) when compared to: 1) another medical device, 2) simple count with a stopwatch.
I don't know why you claim 80 bpm as "the real heart rate" - how did you verify it? The HR range between 50 and 61 bpm certainly seems like a perfectly normal heart rate of a sleeping human, while 80 does not.
If you still suspect my code being at fault here, then please post raw waveforms - all 100 or 400 samples for both R and IR channels - and let me know why you think the calculations are wrong in this case.
from max30102_by_rf.
@aromring I upload the code include the raw IR and RED data here https://www.dropbox.com/s/qakvdpi5cdz6klb/Maxim_SPO2.zip?dl=0. The raw data file RawData2018_4_21_87bpm_99SPO2.txt With the data first column is RED and second is IR.
Original your code not work with me like in #1 , the sensor not turn on so I use https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library and adapt your code. The sample data is from my heart rate it is 87bpm when take(sitting on the chair). I have an Galaxy S8 which include MAX30102 sensor, left index finger i use sensor with your code(run on NodeMCU ESP 8266) and the right hand use Galaxy S8 with Samsung Health app at the same time, Your code adapt in the file above show 56bpm/99.3% and Samsung app show 87 bpm and 99%.
from max30102_by_rf.
Thank you. Hopefully (and finally), I will have some time tonight to take a look at it.
At what sampling rate was the data in RawData2018_4_21_87bpm_99SPO2.txt obtained? 100 or 25 sps?
from max30102_by_rf.
It is 100Hz
from max30102_by_rf.
I haven't heard from you in a long time. Hence, I consider this issue to be closed.
from max30102_by_rf.
@aromring Thanks you again.
from max30102_by_rf.
Related Issues (20)
- Heart Rate Stuck at 93 HOT 1
- New code bug HOT 3
- File names and case sensitivity HOT 1
- using esp8266-12e HOT 3
- new code bug HOT 3
- MAX30102 FIFO returns IR data first (i.e. LED1 = IR & LED2 = Red) HOT 2
- Accurate HR and inaccurate spo2 with inaccurate low spo2 test sample HOT 4
- min_autocorrelation_ratio = 0.5??? HOT 1
- I cant found more detail sensor settings, problems with get values HOT 6
- HR always -999 or invalid while wearing sensor on wrist. HOT 11
- if (!sensor.begin()) HOT 1
- RED/IR sensor value looks strange HOT 4
- BUG and Improvement suggestions HOT 4
- Unable to understand the meaning/derivation of the way of calculating the slope of baseline HOT 1
- Max30102 is not powering up
- Need to change 50 Sampling Frequency / 1 Sampling Time HOT 6
- 30102 not working HOT 1
- Calibration issue -> Potential issue with maxim_max30102_read_fifo HOT 3
- Error while compiling HOT 3
- Float buffer allocation uses unnecessary memory HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from max30102_by_rf.