Bangle.js 2 Cutting Edge - new heart rate algorithm #7232
Replies: 2 comments
-
Posted at 2023-04-24 by @fanoush Oh, interesting. Maybe the FLOAT_ABI_HARD won't be needed for all espruino code. It breaks passing floats to inline C in regular registers. I think with some other HR library the only hardfp method that needed linking in was sqrt and it was possible to do some workaround and keep the rest in softfp calling convention. it is not super important but I'll check it. Or is the hardfp otherwise preferred and produces shorter/faster code? Posted at 2023-04-24 by @gfwilliams
It seems hard to mix, but if you can find a solution I'm open to it - in a way I'd prefer not to change. But it is only for Bangle.js 2 - I've kept everything else as softfp to avoid things getting broken. But I did a quick test with:
And as far as I can tell, hardfp is faster - maybe 5.5s vs 5.7s so not a lot, but it's noticeable and reproducible. Seems a shame to have everything running slower just for the extremely rare case of floats + inline C that I'd argue literally only you currently uses (and you make your own builds anyway!) Posted at 2023-04-24 by user113695 Well, the STL Viewer and Mandel apps also use floats, although I haven't officially ported either to Bangle 2 (just running hacked versions privately). Don't have the watch near me at the moment, I will see how things break - I usually pass floats in flat arrays in and out of compiled C via pointers in my code, so I am not sure where the passing in registers comes in here... Posted at 2023-04-24 by @fanoush Well, I am not against hardfp. If it is faster or otherwise better then so be it. I was thinking that since JavaScript uses doubles, it is working with software floats anyway. Not sure how the calling convention works for double precision numbers with hardfp and single precision fpu, are they put into two vfp registers before calling and unloaded back in software emulation? Need to try (EDIT: here https://gist.github.com/fanoush/0da3e47aee9e20fb11b010cc3aa4e16e - updated my older test, now using Posted at 2023-04-24 by @fanoush
It is hopefully not 'either or' situation. You can link code using both calling conventions, we did it before - old arduino for nrf52 is using softfp callling convention and we linked such hardfp vendor HR library before and it worked, need to check. may take few days. And btw one can set attributes on each method so both calling conventions can be used even in same source code, was testing this few years ago https://gist.github.com/fanoush/85ebe50c5c4a54ca15bf2867e27f7cd3 OTOH if whole espruino linked as hardfp is faster and/or smaller I hope we'll somehow figure out inline C code passing hard floats too. Well, maybe it is not an issue and will even work 'as is' if the inline C compiler keeps soft float conventions as it is now despite espruino fw using hard floats internally. When thinking about it, it may not break as they are separate and the float arguments are passed as integers. Posted at 2023-04-25 by user140377 Does the proprietary firmware also provide a SpO2 value? Posted at 2023-04-25 by @fanoush Here is output from the library so I think it does not Posted at 2023-04-25 by @gfwilliams
Yes, in that case it won't be an issue. I think it's when trying to call a function like
So it's a bit contrived. However @fanoush you're totally right - we don't pass any floats into the library, so I guess as long as it's not using anything external it doesn't really matter. It's just a matter of convincing the Linker it's ok, as that was what was throwing the error before. So I guess it may be enough to edit the As you say, since Espruino uses doubles for most stuff the hardfp doesn't feel like it'd be needed. And in fact double passing may in fact be an issue (or maybe it's just for floats?). In the current build Espruino assumes the doubles are passed in registers/stack just like ints - so switching to hardfp may actually break stuff (although in initial tests it doesn't seem to have).
@user140377 The one included at the moment doesn't. There are separate binaries for SpO2 sensing that could be included, but you have to put the sensor into a special mode first where it samples a lot faster and also samples the Infrared at the same rate. It's definitely possible and I can provide the binaries to anyone who is interested in looking into it, but it's quite a lot of work. Posted at 2023-04-25 by @fanoush
Yes, and when dumping the object files I don't even see any floating point code inside at all. it is all integer math.
gives nothing. I tried to make a library from it
and trying to pass I see the
and looks like it is gone from .o files but this was not enough so the flag is somewhere else. But still if you see hardfp being faster then it is also good. But I find it strange since it must shuffle between those registers more than before, if you check https://gist.github.com/fanoush/0da3e47aee9e20fb11b010cc3aa4e16e then it can be seen that for math operation Posted at 2023-04-25 by @fanoush
I tried the objcopy trick from https://stackoverflow.com/a/51439150 and it links fine. Not sure whether it still works :-) Posted at 2023-04-25 by @gfwilliams I just did some more tests - this time on a bare nRF52 with a minimal build.
So there is a repeatable difference, but it's very very small, and I'd definitely err on the side of keeping softfp and not breaking anything if at all possible :) I just tried building a minimal C file with hard/softfp and I see a few binary differences in the object file, but I do see:
And of course the Posted at 2023-04-25 by @gfwilliams That's great! Much better than my attempt - I'll just remove the header from those files then and switch back to softfp ... and it works! Just committed. Thanks for your help! I just hope folks actually notice some difference with the new algorithm Posted at 2023-04-25 by @fanoush
And is the hardfp version larger? so the extra register moves for double precision math are there? OTOH I can imagine that if you use single precision float type argument/return value somewhere internally in Espruino then it could make such code shorter and may not overwrite integer registers. But that should affect only method calling. vfp single precision math inside methods should be there already even with softfp calling convention. EDIT: Posted at 2023-04-26 by @halemmerich Without comparing to a BTHRM and without testing with much movement, the values given by the HRM seem to be a lot closer to reality. Having a resting pulse with the old algo of under 50 would be nice to have, but for me it is not exactly realistic :) So at least in the constraints of it being an optical sensor it now works much better. I had the chance to play around with a Garmin Fenix 7X which should have one of the best optical sensor available. That worked impressively well, but even that thing wasn't able to keep up with steep rises and falls in pulse rate during movement like an EEG based sensor does. Posted at 2023-04-26 by user140377 I did a small test with two Bangle.js2 on the same forearm. One with the old firmware and a bt chest belt connected to it (blue) and its firmware PPG result (red) and another Bangle.js2 with new firmware and and its firmware PPG result (green). While recording I was
Attachments: Posted at 2023-04-27 by @fanoush Great results, thank you! There are actually more modes listed here https://github.com/espruino/Espruino/blob/master/libs/misc/vc31_binary/algo.h#L10 Posted at 2023-04-27 by @fanoush I wonder if some other activity guessing code could preselect this mode automatically from accelerometer data. Or maybe it could do it by itself for normal mode since the accelerometer data is passed there too https://github.com/espruino/Espruino/blob/master/libs/misc/heartrate_vc31_binary.c#L61 but at least for walking phase it didn't work well. Posted at 2023-04-27 by @gfwilliams That's great! Thanks for the graphs @user140377 it's really good to see some side by side results!
There is actually another binary library for activity guessing that could be added. I've been meaning to try it out though - it's an entirely 'black box' with just one function that you pass xyz values to, so I'm not too sure how good it is.
Yes, I just tried again - 233196 hard, 232156 soft. So it's another reason to try and keep softfp :) Posted at 2023-04-27 by @gfwilliams Ok, I just tried the black box library and it's useless. It returns 1 if you're moving, 0 otherwise. I just decompiled it to verify as well, and there's nothing in there. So realistically we'd need some other way to guess the activity type. Having said that, I got curious and decompiled the heart rate algorithm, and despite all those sport types the only ones that are handled in any way are:
And it looks like SPORT_TYPE_RUNNING and SPORT_TYPE_RIDE_BIKE do the same thing, and SPORT_TYPE_SPINNING just makes the algorithm more sensitive to accelerometer data. So maybe that activity detection function is correct - maybe if the step counter is counting steps we should just tell the heart rate monitor it's in running mode. Having said that, looking at the graph running is actually handled properly, so maybe we shouldn't worry too much about setting the activity mode! Posted at 2023-04-27 by @fanoush
running (third part?) looks OK, it is the second part (walking?) which is a bit off so maybe if that would be in RUNNING mode instead of NORMAL it could be better however running part is now measured in NORMAL mode too and is OK(?) Posted at 2023-04-27 by user140377 Please note that I was walking fast, not slow or medium. This is almost running, I was intentionally testing extreme cases. Posted at 2023-04-27 by @gfwilliams
Yes, that's my concern. I guess I could expose the sport mode in some way so that anyone interested could fiddle with it, but I feel like for the moment the current solution is still a lot better than it was before! Posted at 2023-04-27 by @fanoush
that's even more interesting because when you was running the NORMAL mode managed to do quite well but fast walking did not work so well (20-10BPM lower) i just suppose that you were for x coordinate Posted at 2023-04-27 by user140377 Sorry forgot to mention that but yes we have approx one 1 pwm per second with event number on x axis.
Maybe I'll do different plots for difference activities in the future (walking slow/fast, running, stairs, bicycle) Posted at 2023-04-28 by user140377 And let me remind you that even algorithms like WPFV [1] do produce values that differs significantly from the actual BPM, e.g. 15BPM for several seconds. [1] https://github.com/andtem2000/PPG Posted at 2023-04-30 by @andresdju Thanks Gordon. With 2v17.55 the HR data looks at least plausible, although it seems a bit low. Before I was just ignoring HR data. I'm in the early stage of writing a sportwatch app specially for supporting running "reps" workouts and eventually workout programming. It would be relatively easy to guess if it's running strides, jogging recovery or still recovery from the app (and for sure with workout programming). A way of changing the mode from activity apps would be handy. Posted at 2023-05-02 by @gfwilliams Just added Posted at 2023-05-02 by user140377 ok similar to the last time I did the following small test with each part for approx one minute:
Result is bt chest belt in blue, firmware 2v17.55 in green, firmware 2v17.56 in sports mode in red. X-Axis is hrm event count (~1 second), y-axis is BPM. Attachments: Posted at 2023-05-03 by HughB Wow, I will settle for that!!! Posted at 2023-05-04 by @gfwilliams Yes, that's very nice! And thanks again for these tests - nothing beats having real data to make decisions with. So what do we think about setting the sport mode up? We have a few options:
Posted at 2023-05-06 by HughB Sounds like all 3 would work. Could you explain, option 2, motion value? Posted at 2023-05-06 by stweedo What would the battery usage be like comparing 1 and 2? Would polling the accelerometer increase power consumption vs keeping it always in sports mode? Is there any advantage to the regular mode vs sports mode besides possibly faster HR acquisition like you mentioned? Posted at 2023-05-06 by HughB Don't think battery will be a problem, the accelerometer is always on anyway. Posted at 2023-05-09 by @gfwilliams Yes, none of those would hurt power consumption any noticeable amount.
We store a movement value for http://www.espruino.com/Reference#l_Bangle_getHealthStatus But what I'd do is basically just store a running average of acc.diff, and if that went above a certain level we assume there's enough movement that we could switch to running mode Posted at 2023-05-10 by user140377 I guess we can not do much wrong with #2 if the original firmware does something similar (or just make it configurable). Posted at 2023-05-10 by KTibow Is this in the latest firmware yet? Posted at 2023-05-12 by @gfwilliams Not 2v17, but cutting edge. It'll be in 2v18 when released. Automatic sport mode switch isn't done yet Posted at 2023-05-17 by @fanoush I tested cutting edge build and for me the HR is still about 10BPM off (lower) when sitting in steady state. I tried one Q3 with Bangle2 firmware, second Q3 with original firmware, GT101 fitness tracker and B5 fitness tracker both with original firmware. So on both hands I had one Q3 watch and one fitness tracker. When sitting still the three of them agreed my rate is about 70-75 while Bangle 2 showed 60-65 often with 100% confidence. Once I started moving and HR grew higher the difference went away and I had cases when all 4 agreed on my HR above 80 but when I went sitting still again and HR went lower then again there was about 10BPM difference. @gfwilliams is that binary from same source as used in original Q3 firmware? Because that one shows 'correct' value different from Bangle2. Maybe you can even try yourself with one still with Q3 firmware. I don't have anything else than all those watches and fitness trackers all using similar PPG sensors so not sure if my HR is actually 60 or 70 when sitting. And BTW the Q3 also shows blood pressure with VC31 sensor, do you have access to that binary too? The B5 fitness tracker (from SMA too but differenf HR sensor) shows blood pressure too and they show very similar values. And when I had blood pressure monitor from my doctor for a day I tried to use B5 at the same time and it showed very similar values for normal pressure I have so I was surprised it actually worked. Posted at 2023-05-17 by @gfwilliams
Well, more or less - it was provided by SMA who make the watch so I assume they used the same firmware. Are you saying that the Bangle 2 reported 10bpm different with both old (open source) and new (proprietary) firmwares? Maybe it is more of a timing issue.
I do have that code as well, yes. The only issue there is it puts the sensor into a different mode (making IR + visible readings at the same (higher) rate) and the code to set that mode is something I'd have to sort out and test. I also don't have a blood pressure tester here so it's not something I'd have any confidence in testing - I never had much confidence in using PPG for blood pressure, but if it worked for you maybe there's hope :) If someone wanted to have a go with it I'm happy to send over what I have though. Posted at 2023-05-17 by @fanoush
I tried only the new (binary) one now in cutting edge. And that one was 10BPM below what other 3 devices including Q3 showed. When sitting still. Maybe you can try with Q3 on the other hand too?
You mean like feeding the algorithm with bad timing?
Well, neither do I. As I understand it tries to match the shape to some pre-trained data set as explained e.g. in https://www.mdpi.com/1424-8220/23/8/4145 so could be pretty bad based on the dataset used. I only know the B5 showed quite similar values to the one doctor gave me but as I have pretty normal blood pressure I could not test with too low or high one. And yesterday when I tried B5 and Q3 at the same time it gave almost exactly the same values. Could still be some fake average :-) Posted at 2023-05-17 by @gfwilliams
Yes... One potential issue is I think the algorithm was designed to work at ~10Hz but we're giving it more like 25Hz at the moment - but as you can see from the graphs above it definitely looks like it's doing a reasonable job for @user140377 at least. Posted at 2023-05-17 by @andresdju Right now, while I'm typing this, I'm using the Polar H10 chest sensor (one of the most accurate non-medical devices) and bangle.js2 in the left wrist (firmware 2v17.113). Polar Beat (using H10): 60bpm Walking fast the internal sensor's reading is quite higher than the Polar H10, but running the internal is slower increasing the value and it tends to read lower). The values with H10 are always more stable, it doesn't fluctuate as much as bangle.js2. HR with H10 is consistent with the ECG data from the same H10 sensor, and my HR doesn't fluctuate as much as bangle.js2 shows. Bangle.js2 is more sensitive to movement (is BT Heart Rate Monitor using "running mode"?). All in all, to me the readings with the newer firmware versions seem good enough for an optical sensor. Posted at 2023-05-17 by @andresdju How are you recording and plotting the graphs? Posted at 2023-05-17 by user140377 If you want to compare the Bangle.Js please only compare it to a chest belt like the "Polar H10" mentioned above. All wrist measurement devices do lie you can not decide for each indidivual which one does lie more without a reference measurement. @andresdju
The json is converted to csv and then given to PlotJuggler. Posted at 2023-05-18 by @gfwilliams
Not by default, unless you set the value with Posted at 2023-05-18 by @fanoush
Well Bangle.js is also wrist measurement device :-) BTW it feels to me that initially the difference is not so high but once stuff settles after few seconds Bangle2 drifts down and stays there. It was also interesting that the confidence varies even if sitting still, I see nice regular bumps drawn and then it draws basically flat line and then it 'refocuses' and is OK again. Can't match it to my movements (tried to not move at all of course). And it is off by ~10 even when I see those nice regular bumps (and confidence 100%). I used the Heart Rate Monitor (v0.11) app The most interesting to me is that one of the watches is Q3 = same hardware as Bangle2 with firmware that may even have same HR library linked inside. I also tried to switch hands of course. Posted at 2023-05-18 by @gfwilliams Stupid question, but have you removed the protective film from the HRM? That could be messing readings up a bit Posted at 2023-05-18 by @fanoush I don't know for sure but I think it is not there, here is photo of the back https://ibb.co/pjHdsYN This is the device I got initially from you and runs Espruino, I have another one bought directly from SMA (later in the same year) still running original firmware. Both are probably same old "pre-kickstarter" models without hole and older VC31. So you don't see it when trying two devices - one with Espruino with Heart Rate Monitor (v0.11) app and one with SMA firmware on each hand? Posted at 2023-05-18 by @andresdju The picture is too blurry, but either you have the protective film or the window is very scratched. It happened to me that I used it without peeling it for my first run. About the revision of the device, mine is from January 2023, so maybe that's the cause of the discrepancy. Gordon, is it possible that the proprietary firmware for VC31 and VC31B should be different? Posted at 2023-05-18 by @halemmerich Either you managed to scratch the glass or the protector is still on. If I remember correctly it had no tab or something like that to pull it off. On my first Bangle I thought I had received a scratched one and only a few days later I discovered it to be a protector. It was a tiny bit "frosted". Without the protector you should have a mirror finish just like the display glass has. Edit: @andresdju hehe, you ninjaed my post very closely :D Posted at 2023-05-18 by @fanoush Here is video recorded, exactly 60 seconds, reported HR is 57-61 but if you count all the beats drawn it is actually 70 https://streamable.com/vvulja Also I tried Cardiograph android app https://play.google.com/store/apps/details?id=com.macropinch.hydra.android on my phone and it matches what my other watches/fitness trackers show. I disabled network before starting it as some people in reviews claim that showing ads make it less relible. For me it worked pretty well with no ads shown. Posted at 2023-05-19 by @gfwilliams I just tried, and they are identical for me - more or less. The Bangle.js one moves around a bit more (I guess it'd not filtered) but they were within 1 bpm after a while.
I don't believe so, no... the distribution I had seems to deal with both models. I'm not really sure what to suggest... I mean you could try setting the heart rate period down so it's at 12.5hz with Bangle.setOptions - but it seems really strange to me that it seems to work well for me and others but not you. You don't have any apps installed that might be adjusting the time on your Bangle.js while the HRM is running do you? Posted at 2023-05-19 by @fanoush OK, good that it works for you, did you try same HR monitoring app - the one that draws continuously (if that could perhaps slow it down)? I have nothing special there, the clock showing time is OK, it does not go faster or slower. Will try to remove all apps. Posted at 2023-05-19 by @fanoush
How would I do that? That is not described here https://www.espruino.com/Reference#l_Bangle_setOptions I set it to 2o and the monitor was drawing much faster but the HR is still off by same fraction Anyway, if it is not a common issue that others see too then don't bother. I did factory reset, then installed just heart rate monitor app on top of that and it behaves still the same. Posted at 2023-05-19 by @fanoush Funny thing, I downgraded to 2.17 release to get back the older open source HR code and that one is correct! When confidence is 100 it basically shows same numbers as my other watches. Posted at 2023-05-22 by @gfwilliams Hmm, well that's interesting then - I guess at least we know it's not hardware then. I know you tried hrmPollInterval with 20 - did you try it with 80? The HRM algorithm expects data to come in more slowly and I wonder if sending it data too quickly is actually impacting its accuracy (although as I say, it seemed to work ok for me and at least also when those graphs were made). I'm not actually 100% sure if I used the HRM app or not. As I understand the HRM should be done in an interrupt so it wouldn't matter, but I guess you could try using a Clock face with ClockInfo and then switching to the HRM clockinfo. ... or just reading the value in code with Posted at 2023-05-23 by @fanoush
With 80 the confidence almost never reach 100% and is overall much worse so the heart rate is more random and it does not look like it has any effect on this. With this I've seen it even 'stabilize' on numbers over 110 while fitness tracker was showing below 90 but I also saw cases when it gave similar numbers like with poll interval 40 (too low)
I tried this with hrmPollInterval back to 40 and 2v17.120 and it makes no difference when compared to running Heart Rate Monitor (v0.11), still about 8-12 less than what my fitness tracker says or what can I count myself on the visible data coming from Heart Rate Monitor (v0.11) when I start it. I just retried again to switch between 80 and 40 with logging in IDE, see attached file. According to my fitness tracker my HR was about 76 Attachments: Posted at 2023-06-06 by @halemmerich I have tried comparing the new algorithm with my BT belt during a few hours of hiking. There are still differences, but I think that is at least partly to be expected. It is a massive improvement over the old one which would show everything from 40 to 90 on similar levels of exertion. The y-axis does not start at 0 to show the differences a bit more clearly. So it looks worse than it is :) Attachments: Posted at 2023-06-06 by @fanoush When looking at it maybe you could also replicate my experience that the BPM is about 10 lower? Most of your graph looks like that. Maybe you could also record part when you are sitting still so that it is less random? Posted at 2023-06-08 by @halemmerich Yes, sure seems that way. This was sitting and snacking. So not completely without movement but close. Kickstarter version Bangle. Attachments: Posted at 2023-06-08 by @gfwilliams Hmm - that's interesting then - so it looks like maybe you have a similar issue to @fanoush with the HRM differences. @fanoush yours is one of the earlier watches too? eg not with the VC31B I wonder whether maybe for some reason we're getting duplicate readings - maybe the VC31 code still forwards HRM data when there is nothing. @fanoush if you look at HRM-raw can you see duplicate entries? I just tried with an original bangle here:
And I see it returning false reliably - but if it was reporting true 1 in 10 times then I guess we might expect that would be causing a lower HRM to be reported? But even so I don't really see it. Posted at 2023-06-09 by @fanoush
for me there is true but very rarely. in 10 out of 2749 samples. Posted at 2023-06-09 by @fanoush Attached is output of your code with getTime() added Attachments: Posted at 2023-06-09 by @gfwilliams Ok, thanks - yes you'd expect a few duplicates just because there's always a chance the value really will be the same two times in a row. So on yours, even with the old algorithm it was still out? Because I could imagine the new algorithm might be expecting the time difference between samples to stay constant rather than varying slightly per sample, and that might throw it off - but the old one should have been fine Posted at 2023-06-09 by @fanoush the old open source one worked fine when sitting still, mostly same value as other devices Posted at 2023-06-09 by @fanoush
And from the log I attached you see this is the case? You see it is better on newer watches? Posted at 2023-06-09 by @gfwilliams Ahh ok, so it may well be an issue with the algorithm expecting almost identical time differences - in their example the HRM is calibrated to give readings at the right rate, not the other way around. Looking at you file there is some variation - but worryingly I actually see some much bigger gaps every so often - like one sample is being missed which I guess is just due to a difference in frequency between the HRM and the bangle:
But maybe that one long sample throws the algorithm off (when the original one would cope with it).
Well, when I tested the HRM measurements I got against a Bangle running old firmware, they were almost identical. Maybe you could try - in
to:
So it effectively just splits the double-length gap into 2 Posted at 2023-06-09 by Mi FYI: just checked here with kickstarter bangle2: HR is 10bpm(+-2) below chest belt in rest Posted at 2023-06-10 by @fanoush
unfortunately no change with that, still ~10BPS below
and it shows approx. every second when starting the HRM monitoring app
Posted at 2023-06-10 by @fanoush It is not so regular, I added time in ms
and it looks like this, it is a lot from the start, then once or few times per second and then there are long periods where it does not happen at all and in these HRM is wrong too
Uncaught TypeError: Puck.connect is not a function
Bangle.setOptions({
Bangle.hrmWr(0x17,15)
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2023-12-27 by d3nd3-o0 This code can be used to view the data, might be useful. It is using analogRead from old method of reading pin directly instead of talk through i2c. Could be interesting to compare outputs. Pass hrm.raw into instead of val to c.onHRM to see difference. (You have to adjust graph constraints too, hrm.raw are huge numbers between 0 - 10000 ).
Posted at 2023-12-27 by d3nd3-o0 To set constraints of graph with min/max...
The heartrate.c implementation also applies a band pass filter, which greatly helped before. Posted at 2023-12-27 by Graham_Jones @user140377 If there is a plastic film cover over my sensor, it is very well attached - I can't detect it. Posted at 2023-12-27 by user140377 The watch is usually shipped with the cover, so unless you removed it or it accidently fall off I would check again.
Thats because of noise due to motion artifacts, e.g. when walking with 60 BPM with heart rate = 100 BPM the sensor will give you the 60 BPM walking (or a mix of both). This does not apply when sitting still. Posted at 2023-12-27 by d3nd3-o0 This has a rolling average windows of size 8. And includes the hrm band pass filter from heartrate.c https://gist.github.com/d3nd3/0f15665e2dfe03c949449bfae9a50ae5 Posted at 2023-12-28 by d3nd3-o0 The output from hrm.raw stops working for me when Posted at 2023-12-28 by Graham_Jones Thank you very much for this example, d3nd3-o0. I have never seen inline C code in javascript before, so this is a bit of an education for me! I see from the source code that there is another register that is supposed to adjust the LED current - but I find that if I try to set this, then the HRM stops updating after about 50 samples. I can see the LED intensity changing with register 0x17 as you suggested though. Posted at 2023-12-28 by d3nd3-o0 I have just tested a garmin heartrate strap compared to the Heart Rate Monitor app of Bangle2. The readings are Way off, so far that the strap was reading 120 and the app 60. This was whilst being on a gym bike. So I don't know what to call the current HR reliability, its almost non-existent I would imagine. It has also shown 120, whilst the strap shows 80. Considering the watch is fed accel data, would the faulty readings(spikes noticed with onTap) affect it? Part of the reason the first test was super bad for me was because riding a stationary gym bike doesnt' trigger accel changes, so automatic sportsMode didnt' kick in. After using I will try hrmSportMode 2, for bike. Ok results: I was actually surprised how But something is also wrong with it :D, like it gets stuck often. Or wanders into weird hrm territory for no reason. Btw its fair to assume hrmSportMode 1==2, as gordon pointed out previously, haven't noticed a difference between the two yet. Posted at 2023-12-29 by user140377 I can confirm the indoor bike issue, had the same in the last weeks, it measured the cadence of ~80 BPM.
I would not go that far, when walking or cycling outdoor it is not that off. Posted at 2023-12-29 by user140377 ... I wonder if we should just make a small app that forces one of the sport modes: Posted at 2023-12-29 by d3nd3-o0 I think hrmSportsMode is the algorithm that becomes dependent on Accel data, because in the example source it takes x,y,z input. hrmSportsMode 0 also worked well for me too at times. I think its either slow and has to take a while to follow true heartrate or the signal is sometimes too noisy for the current alg. Because at times, I am very impressed, but its short-lived. Does anyone know if its best to measure time between 2 consecutive beats, or to count peaks over time? I'm starting to think the time-measuring is the way to go. Posted at 2023-12-29 by user140377 Algorithms like Tapir do count the time between peaks after some filtering. Posted at 2023-12-29 by d3nd3-o0 ROFL, I was measuring wrong pin entire team I think haha.!!! :D I used the pin from Bangle 1!! Posted at 2023-12-30 by user140377 Did a small test on indoor bike (not very representative): so far "running" was best, so lets try another sample: Posted at 2023-12-30 by d3nd3-o0
What is this line representing? Ah, the motion removal app! Posted at 2023-12-30 by Graham_Jones I have made a little test app that will record raw HRM data to a file, and allow me to vary the LED power by swiping the screen up or down.
As long as I don't try to plot the graph on the watch screen, I can log at about 40 ms intervals, and can pull it into a speadsheet to look at it: From a visual inspection of the first 5 seconds, I can see about 5 peaks, which is consistent with my actual heart rate of around 60 bpm, which is encouraging. Unfortunately the watch is reporting over 100 bpm, which is not so impressive. It sounds like this is the opposite to what other users are reporting, as others are reporting low indicated heart rate compared to actual. So I'm still not sure what to make of this, so I'm going to try to do the same on Pinetime and see how it compares, as I am still suspecting that the HRM sensor in my watch is not really working very well. If anyone else could try to collect a similar set of data on a different watch, I'd be interested in seeing the comparison of different BangleJs watches. Graham. Posted at 2023-12-30 by Graham_Jones
I found that I was getting occasional I2C errors when reading registers from the HRM device. In the end I caught these errors and re-set the HRM device when it occurred - that seems to have stopped my problem with logging freezing (https://github.com/OpenSeizureDetector/BangleSD/blob/master/apps/hrmtest/app.js#L240) Posted at 2023-12-31 by user140377 Something like this? Attachments: Posted at 2023-12-31 by Graham_Jones Thank you for the graph. The peaks in your data do look easier to see than mine (but that might just be the graph scale - I'll have a proper look later) It looks like just over 60 bpm. Is that right? Did the watch report something similar? Graham Posted at 2023-12-31 by user140377 ~80 BPM was reported by the Bangle Posted at 2023-12-31 by d3nd3-o0 Pin 29 was not true. Its only for bangle 1, please delete that information, sorry for that. I am in the progress of testing your app, I'll keep you posted. Posted at 2023-12-31 by d3nd3-o0 @Graham_Jones My sensor only begins to work at Also your app, I can't see a graph, its empty below it. It seems that the Some kind of effect like that. Its interesting that, I didn't notice this before, thanks to your app :) I think the real max value is 8190, despite it being stored in a 16 bit short? Based on this idea, perhaps the target I will try in different lighting condition. Even in dark room, the conditions are same for me. The 0x80 last bit of the LedCurrent value is a PpgGain btw, so at values between 129->136, I get some numbers , but it seems gain is bad because the swings are higher so you need to adjust led more often. Would be nice to see if @user140377 has anything similar to this ( the low LED current requirement ), we could compare to figure if any of our bangles are different/defective. What I like others to test:
Also, confirm your output of : @Graham_Jones There are hrm->csv recorder apps already on the app store (namely the "recorder" app by gordon (seems beats only), or "HRM Accelerometer event recorder" by halemmerich, your app store is a bit out of date. Just in case you did not know. https://github.com/espruino/BangleApps/tree/master/apps/hrmaccevents https://github.com/gfwilliams/EspruinoHRMTestHarness Posted at 2023-12-31 by Graham_Jones
No problem - that accounts for why I was measuring noise! Posted at 2023-12-31 by Graham_Jones @d3nd3-o0 - thanks for this detail - I will go through it and reply properly, but it might be tomorrow evening or the one after. A couple of quick thoughts: I will check the ID from the sensor - I was starting to wonder if maybe I have a different sensor (I only purchased the Bangle2 recently) For me, a LED current value of 15 seemed about right - the automatic adjuster varied it from about 13 to 22, so our watches do seem to be behaving differently if you had to use a much lower current (unless our skin colours are very different maybe - that might have an effect, so could be another reason for needing automatic current control for different users.). My copy of the app store is very minimalist on purpose - I am thinking of pointing users of my seizure detector app to it if I can get the heart rate measurement working reliably, and I only want them to install apps that I now will not interfere with the seizure detector (some users like to fiddle.....). Alas, I had to disable the graph drawing part of my little HRM test app because drawing to the screen seemed to take such a long time (over 1 second), and it blocked the HRM measurement while it was happening - it seems that the HRM measurements are not interrupt driven so if I want to achieve 40ms sample period I have to be very careful about not doing too much.... My little app is based on one of the others in the app store - I modified it to try to make it easier to try out different settings (and the idea was to have a graph at the same time to see the effect in real time). I don't get on very well with javascript so had a bit of a sense-of-humour failure at it and de-scoped my intentions for the test app! Regards Graham. Posted at 2023-12-31 by d3nd3-o0
Look at the object from I conclude that proof:
Posted at 2023-12-31 by d3nd3-o0
# 5 = beats
Posted at 2023-12-31 by d3nd3-o0 Created using : https://github.com/espruino/BangleApps/tree/master/apps/hrmaccevents and gnuplot file above. Longer recording. ( Did some bike activity at end, real HR went way above 100 ). Shows ppgOffset in green, which is when the ledCurrent is adjusted. I now just have to get some chest strap comparison data. Attachments: Posted at 2023-12-31 by d3nd3-o0 Acceleration data plotted against ppg Attachments: Posted at 2023-12-31 by d3nd3-o0 Whats interesting is that the amplitude of the ppg seems to exist in the beat count, I wonder if that is an error or a feature. Posted at 2024-01-02 by @gfwilliams @d3nd3-o0 you're trying to use analogRead on Bangle.js 2? If so that's not going to work - it doesn't have an analog sensor. With the LED brightness, the heart rate monitor code attempts to adjust the LED brightness to keep the reading from the HRM within range. So if the HRM isn't pointing at anything the LED brightness isn't going to be the 'real' brightness you see. If anything it's surprising you can see it at all, as Bangle.js should turn off the green LED after a few seconds of the HRM sensor not being near anything. Posted at 2024-01-02 by d3nd3-o0
Not sure which part this is response to. Keep in mind these tests were often done with @gfwilliams Welcome Back, hope you had a merry holiday period. Posted at 2024-01-04 by @gfwilliams Hi - thanks! I was referring to https://forum.espruino.com/conversations/385922/?offset=75#17235864 Posted at 2024-01-10 by d3nd3-o0 What I can tell others from my experience: This is because
Using So ye, the When testing, remember to use I believe the algorithm relies on something similar to : The method I have been testing recently was a threshold based peak detection on the time-domain. I'm personally grateful we have something that works so well, considering how the signal looks, its kind of a miracle. Posted at 2024-01-11 by @gfwilliams Yes, I think as you say the binary blob is frequency based - it works on blocks of data, rather than instantaneously (as the 'open' algorithm does). I think the benefit there is it's relatively straightforward to discount readings where there's high acceleration. Posted at 2024-02-26 by user157584 Hey all. Thanks for all the hard work tinkering and testing the HRM settings. I've read the 6 pages of back and forth and just want to confirm a couple of things. As a non-technical end user and based on the current firmware, overall how accurate is the HRM? What are the key things to presently be aware of when considering HRM data (ex: certain activities are more prone to bad data VS resting HRM, etc.)? Thanks in advance! Posted at 2024-02-28 by @gfwilliams I think someone else needs to jump in here and answer as I haven't done a great deal of comparison testing, but my experience has been that with the new algorithm, HRM works well enough for everyday use. However it's not going to compete with a device that uses an actual ECG - it's a different technology that is much less susceptible to movement. Posted at 2024-02-28 by user157584 Thanks for the reply Gordon! I didn't realize that we weren't really comparing apples-to-apples. It sounds like it'll be most useful to gather a really good understanding of my resting heart rate and maybe my sleep heart rate, but that I should take it with a grain of salt when moving. I'd be curious if someone else can comment on if light movement walking HRM tends to be accurate. Also, does it find its "groove" over the course of exercise (I.e. maybe the first few minutes of a 30-60 min walk might be a bit funky, but perhaps it settles into a rhythm once movement is detected)? Posted at 2024-03-25 by thinkpoop Very late response, but I don't know how useful it is anyway: Compared to a Fitbit Versa 3, I usually get within 5-10bpm consistently. They both use the photosomethingorother sensor, but in case there was some secret algorithm Fitbit uses, here's a roughly what I've found: Fitbit likes to draw their graphs as "landscape" as possible, with a thick line that hides how spikey it gets, but usually it has the exact same peaks and valleys as Bangle. Attached are screenshots of the graphs of both while shoveling and using a snowblower on and off for about an hour and a half. Peaks in the Fitbit graph are 117bpm, then 132, 132, 132. Attachments: Posted at 2024-03-27 by user157584 Appreciate the insights :) Posted at 2024-05-03 by user107850 @gfwilliams I am working with 2 students on the algorithms for HR and steps. We would like to integrate with your work in the most efficient way so that, in case they come up with something promising, you can integrate their code easily into the firmware. What we are going to do:
I am aware of these two repos that you have created: We can simply push code to those 2, or, maybe more efficiently, we could merge them into one? Thanks... Posted at 2024-05-03 by @thyttan
Out of interest, what do you use for capturing the reference data? Posted at 2024-05-03 by user107850
HR: Polar HR sensor with BLE (based on ECG) Posted at 2024-05-03 by @gfwilliams That's great! It's up to you - I guess I'd be inclined just to keep the two repos separate - I would imagine the test data in each case might not always have that much in common (no need to have HRM data if you only want to test out step counting and so on) although it sounds like in your case you'll be gathering both at the same time. ... also the way you'll want to compare algorithms for step counts and HRM is probably different too. We can't easily run the binary algorithm 'offline' so it might be worth logging the Bangle's reported HRM as well so you can test. One thing to note is the binary algo 'windows' the data and runs a filter over it, so it can't report instantaneous beat data - which would be really nice for heart rate variability values. Realistically the important thing for integration is that the algorithms themselves are normal, self-contained C files like https://github.com/espruino/Espruino/blob/master/libs/misc/heartrate.c that implement this API: https://github.com/espruino/Espruino/blob/master/libs/misc/heartrate.h So Same for step counting and https://github.com/espruino/Espruino/blob/master/libs/misc/stepcount.c I'm sure you know this already, but getting good algorithms is really all about getting good test data. For step counting for a while we were using data gathered from just one person and we did a great job of step counting for them - it just sucked for most other people :) Posted at 2024-05-03 by @gfwilliams I should also add, on the data front it's important to have a bunch of non-walking data too. Working at a computer, cooking, and driving especially. Posted at 2024-05-21 by user107850 hello again, some news about the new algorithms benchmark. Data: we have prepared a data collection protocol, we aim at 20 people, doing different activities, both on treadmill and outdoor walking. The protocol will get an ethical approval from Politecnico di Milano. Right now we don't have the permission to publish the data, but we are planning to obtain it. I understand that the data is what you would mostly appreciate, so I am keen to publish those files, but it may take some time. We are planning to acquire the data at its default sampling frequency for both acceleration and PPG. Would that be OK for you, or would it make more sense to acquire at higher frequencies, in case you want to test out different frequencies? Tests: the repository for the tests that you have may need some adaptation though. We are starting with the step counter and we can already see some changes to make. Concretely:
If you are OK with these, we will be sending pull requests, as we advance with the task. You can of course review those and suggest changes if there's anything you don't like. Another issue: from what I understand the current API for the step counter (stepcount_new(int accMagSquared)) return a 1 if a step is detected or a 0 otherwise (and in some cases it tries to make up for lost steps too? haven't studied this well yet). I would suggest to change the signature to something that is more generalisable for other algorithms, for example instead of returning the "new" steps, it would return the total step count, since the algorithm was inited (or reset) and instead of accepting the magnitude as argument, it could accept the raw x, y and z. I know that this has repercussions in many places within the Esrpuino code, so it's a lot to ask, but it would make the signature compatible with algorithms that are based on different approaches. Let me know how doable this would be. We can of course decide later, if and when we have some good alternative candidate algorithm. Thanks! Posted at 2024-05-21 by @gfwilliams
That's a tricky one. A higher sample rate means the HRM sensor will adjust quicker, so even if you take samples out it may not give an accurate comparison. I think maybe just stick with the default rate (for that and the step counting). It's worth noting that right now we don't calibrate the frequency so it can depend slightly on the watch. In the OEM firmwares they fine-tune the sampling frequency to exactly 10Hz. In terms of changes to the test harness - yes, that all sounds good. I would appreciate it if you could try and ensure the existing step count data can run with the step counter too so we can have a clear idea of how new algorithms perform with that too. I don't care about HRM as we don't have much data there.
I'd prefer not to handle 'total step count' because we're juggling a few different step totals inside Espruino already and I don't want one more. It feels like a trivial for an algorithm to just keep an internal counter and output the difference between current and last? We can always ensure we handle negative step differences if that needs to happen. But on the x/y/z front, yes, that makes complete sense to change the signature. Ideally pass accMagSquared too so existing algorithms aren't having to calculate it out twice. ... but before we mess with the Espruino repo, let's get some data and algorithms - you can always ensure your repo uses the new call signature, and then you can just have a stub:
I'm not sure if this is a good extra thing to have, but some trackers have an 'activity' value for what it thinks you're doing - sleeping, walking, running, etc. Something that could detect that would be a really neat addition (but obviously your data would need marking up somehow) Posted at 2024-05-21 by user107850 thanks for the availability and the suggestions! You will be receiving pull requests soon 😃. I'll keep the signature as it is for now, and only change it if it is required. One little note about the code, I see that you mostly use generic types like short, int, float etc. We will try to keep that style too, although I wonder if it wouldn't make more sense to be more specific and indicate also the n. of bits? What's the philosophy here? Re. activity detection: it is not planned at the moment, but it's something I'd like to work on at some point. Posted at 2024-05-22 by @gfwilliams Great. I'm very happy to use uint8_t/etc types. In Espruino it's generally assumed that Posted at 2024-11-29 by user107850 Hi Gordon, I have some news. The students have completed their work on development and bencharming of the algorithms. They had time to work only on the step counting, we have left the heart rate measurement for later. We decided to create our own repository for this, as it was more practical. It doesn't follow the code conventions of Espruino completely, but it should be relatively simple to adapt the code in case you want to try it within the firmware. The repository is here: https://github.com/VirginiaSek/Algo But I guess that you would be more interested in the results from the tests the students have done. I am sharing their thesis here in attachment. If you want to discuss these results, I am happy to do it here or by email or a call. As for the data they collected and used, we would need to take it privately. Hope this helps! Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2023-04-24 by @gfwilliams
I have now switched over to the proprietary heart rate algorithm provided by the sensor manufacturer - which I hope will do a better job at giving you accurate heart rate readings, especially when moving around.
It can be supplied with some different sports modes - for instance it may be possible to switch it to a mode that'll make it work better for Running - but I haven't tried this yet.
It's a shame to move away from an Open Source implementation, but realistically despite making a test harness nobody seems to have been very interested in trying out better solutions.
In the end, I think most Bangle.js users care more about a working Heart rate sensor than an open one - although anyone who does care can still build their own firmwares with the open one with relative ease.
Beta Was this translation helpful? Give feedback.
All reactions