Add in Blood Oxygen support#1607
Conversation
|
Was tested on my pebble watch. Power draw was for obvious reasons, higher than having just HR or neither activated. Code was tested, and from my testing over the week, seems to work well. |
|
very cool! do you happen to have any other SP02 enabled devices to benchmark against? did you add UI to display this on watch? cc @sjp4 |
There was a problem hiding this comment.
Thanks for the contribution, however, this is not mergeable as is. Make sure to remove unnecessary changes (e.g. why enable a demo app at board level?), group changes in logical commits, CI green, etc. (check contributing guidelines). Changes in the nonfree repo also need better explanation.
I sadly do not have any devices to monitor SpO2 outside of my Pebble. Well I guess my Bangle could work? But they also dont have blood oxygen support 😂 If anyone does have one though feel free to test. |
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Appreciate the feedback, I'll fixup the PR and get it ready when I get some free time. |
aab5d91 to
385cbe3
Compare
|
If you have any other requests just lmk! I'm pretty open, and have 2 days off work of free time. |
|
I'm installing this and going to compare it with Ultrahuman Air ring which has SpO2 sensor. Will report back. From looking at the code - it looks quite good! I like One thing I found that may or may not be an actual problem (I'm not that intimately familiar with the codebase yet) is the teardown path |
Appreciate it man! ❤️ |
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
Signed-off-by: Gavin X <gavinx2031@triro.net>
385cbe3 to
2eff2f1
Compare
Good catch, was indeed a bug. Fixed it. |
|
It works, and it tracks with Ultrahuman Ring Air within 1%! I haven't encountered any crashes. Activity detection algo works with it, too. I don't have any battery stats info due to the app being built by me (not Core Devices) and lacking ability to login with my Pebble account, unfortunately. BTW, it seems like you're building the SpO2 test app into retail firmware. Looking at other test apps - they aren't included when release config is enabled. |
Awesome, appreciate the testing. As for battery, I'm on day 2, at 44%. So battery drain is definitely higher when SpO2 is enabled (which is expected) I have SpO2 track interval at 10 minutes, same thing for the HR, so honestly not bad. |
|
Whoa - no way you lost 56% in 2 days! 😅 I'm on day 2 as well and I'm at 83% with doing tons of comms (flashing firmware and debugging watchfaces), occasional runs of SpO2 tester app and a custom watchface that loves haptic feedback. Honestly, for me at least, I have not noticed any drastic change in battery drain. |
I have HR + SpO2 tracking on. With intervals of 10 minutes between readings. It'd probably be better if I set spo2 to 30 minute intervals. Not sure if you're also using background tracking |
|
Update on the power draw: over last ~5 days, I observed about 8-10% drop per day with 10-minute measurement (both HR + SpO2). I now lowered it to read SpO2 once per hour and will report back in a few days on how that changed things. |
|
exciting to see, thanks for sharing the progress |
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com>
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
Recompiled the OS, my power usage is more in line with yours. Must've screwed something up on my end I guess. |
|
If measuring power consumption, remember to compile with debug flags off so you're compiling as a release build. Debug builds turn UART RX on and use 10% per day |
|
Have I screwed something up with my build as well?.. 😅 It seems like there is no difference in power draw between sampling every 10 minutes and every hour. I'm seeing the same 8-10% per day drop even when the setting is in 1hr position. |
|
I was under impression that I had release config enabled previously, but just in case, I recompiled with |
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
Good to know. |
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>
|
I am seeing same-ish power consumption no matter what setting I select for polling period. Maybe it's the fact of sensor configuration for SpO2 that makes it consume power, and LEDs are relatively small factor in this?.. |
Hm. perhaps external factors. I did a quick rereview, don't see any apparent issues with the period settings. So its possible its just unrelated factors such as HR. |
|
I haven't noticed anything that might've predict such behaviour either when I reviewed the code earlier. I am going to revert to stock firmware for about a week - just to exclude "toxuin is taking crazy pills" factor. I am very much looking forwards to getting this merged - me running the original firmware is not an indication of there being anything wrong with this branch. Quite the opposite: I think I mentioned before that I got literally zero crashes or weirdness during the entire 20+ days of testing. And I did a manual (not AI lol) review of this branch and found some good decisions in it (stated above in my previous comments) and only a single issue - rather minor and already fixed. Installing stock firmware to exclude my usage patterns, my hardware or my settings affecting it. Will report back in about a week. |
|
On the battery question — while testing my own HRV sampling work (#1670), I hit something that surprised me: I'd been refreshing my watch app's screen on every sensor event, and switching to a static screen while recording overnight gave markedly better battery life. A much bigger improvement than I expected — enough that it overshadowed the sensor's own draw in my tests. Might be worth keeping the display static across runs when comparing battery, in case it's a factor for you too. |
Change hrm_enable() to take the requested HRMFeature set (matching the direction of coredevices#1607) and a low_latency flag (reserved, unused here). hrm_manager computes the union of active subscriber features, passes it to the driver, and restarts the sensor when the needed feature set changes, so HRV is only collected while a subscriber holds HRMFeature_HRV. In the GH3X2X driver, when HRV is requested: enable the HRV function, mirror the HR PPG channel map onto it (the shipped register config only maps channels for HR/SpO2/ADT, so HRV otherwise comes up with zero channels and never receives frames), and run it at the HR sampling rate. gh3x2x_hrv_result_report() forwards each valid RR interval from the Goodix HRV algorithm to hrm_manager. hrm_manager broadcasts HRV results as HealthEventHRVUpdate so apps subscribed through health_service receive them without a raw HRM session. Everything is behind the new HRM_HRV Kconfig, default n. Part of coredevices#1630. Signed-off-by: karthakon <33638614+karthakon@users.noreply.github.com> Co-Authored-By: Claude <noreply@anthropic.com>


Adds in blood oxygen support.
Related commits :
coredevices/pebbleos-nonfree#4
coredevices/mobileapp#267