Extend battery life by connecting intermittently

Posted on
  • Hi,

    A though jumped at me the other day.

    Could longer battery times (while still maintaining some connectivity) for for the Bangle.js be achieved by intermittently connecting/disconnecting to the watch on some schedule?

    Example schedules:

    • 5 seconds connected, 5 seconds disconnected.
    • 5 seconds connected per minute.

    I guess my basic question is - does holding the connection draw more battery than being disconnected but ready to connect (+ power draw related to reconnecting)?

    (Or maybe the watch's BLE could be disabled entirely during the periods of non-connectivity by syncing the schedule between it and Gadgetbridge.)

    The maintenance burden of something like this may not be worth it though, and I don't know when I would personally use it 🤷

  • Interesting thought, maybe we could find out a ballpark number by just turning off BLE generally for a while throughout the day and compare that with power usage when BLE is activated. Your BLE "strobing" approach could then be at the midpoint of these two measurements, given that establishing a connection is not particularly expensive.

    For example at night it might make sense to turn off BLE for longer periods of time to save on battery. The big question is if ble will use enough battery to be even noticeable when there is nothing being sent or received?

    Gadget bridge has a function to redeliver messages after reconnecting, so on the software side this should work out; there are scenarios where turning BLE off would also not be good UX such as navigation, where the notification is important to be delivered fast... Also something to think about :)

    Generally I like the idea to optimize battery life further, but first we need data to see if any effort could be worth it

  • there are scenarios where turning BLE off would also not be good UX such as navigation, where the notification is important to be delivered fast... Also something to think about :)

    Yes - I also think some consideration about such situations would be required.

    • when user interaction is detected, keep the next connected window open for longer generally.
    • on e.g. navigation/music playback/etc keep connection untill the task is done + some extra time at the end.
  • BLE connection can draw less power than advertising (= having a way to connect again). what draws power is the data transferred and cpu being awake handling the data, also connection being lost and reconnection, maintaining connection itself should not be costly as such. advertising packets are sent on 3 channels and device must wait for scan response on each channel, keeping connection is less heavy than that. both advertising and connection can be tuned by setting advertising and connection interval.

    So if GB is connected I guess power can be saved by less frequent data transfer and increasing connection interval, not by disconnection.

  • also there is no special 'ble turned off' state, the hardware is off all the time when not sending/receiving packet. so when you stop advertising the radio is off all the time. when you start advertising with 1000ms interval the radio is off all the time except 3 packets being sent every second + if device is connectable/scannable then it also briefly listens for scan response request or connection request after sending each of those 3 packets, that's all, there is no other extra cost or difference between BLE being 'on' or 'off'

    nrf5x is not raspberry pico w or esp32 where 'turning BLE on' draws extra power.

  • Thank you for your insight! I'm looking at the NRF class in the reference now thanks to your replies.

    EDIT:

    After reading about NRF.setConnectionInterval it seems much of the idea here can be achieved in a bangle app by some combination of:

    • the bangle scheduling library
    • NRF.setConnectionInterval (max 4000 ms)
    • NRF.sleep() + NRF.wake() (to go beyond 4000 ms interval)
  • yes and by default the connection interval in nrf52 Espruino is dynamic = there are two settings one for idle and one for active connection, currently hardcoded in source https://github.com/espruino/Espruino/blob/master/targets/nrf5x/bluetooth.c#L230
    somewhere I have small patch to move this setting to board file but still it is hardcoded at build time. it can be that GB traffic may keep it so it never goes idle. however NRF.setConnectionInterval overrides it so it is no longer dynamic, try to change it in WebIDE - you'll see how typing becomes slow when this is over 100 or 200ms. Not sure maybe it can already be tuned in bangle settings somewhere? even 50 or 100ms is much better than 7.5ms and saves a lot of power in average. I think when I measured it at 7.5ms the average current is like 0.5mA and when set to hundreds ms it is like 0.01mA
    see also for puckjs https://www.espruino.com/Puck.js#power-consumption
    Connected via BLE default - 600uA
    Connected via BLE default, inactive for 1 minute - 32uA
    Connected via BLE, NRF.setConnectionInterval(200) - 40uA

    It is not worth going to longer intervals or turning it off, other hardware draws more. As mentioned it is the activity of the watch (=running javascript) that draws much more. So when connected it is not BLE that is taking the power (unless it is at 7.5ms all the time) but possibly the data traffic triggering some activity in the watch making cpu busy.

  • I think when I measured it at 7.5ms the average current is like 0.5mA and when set to hundreds ms it is like 0.01mA

    So one would maybe want a configuration where connection interval upon user interaction is generally at some hundreds ms but kicks down to 7.5 ms when much data transfer is happening or is expected?

    EDIT: But that also seems to already be the case - so an extra app seems less and less useful.

    As mentioned it is the activity of the watch (=running javascript) that draws much more. So when connected it is not BLE that is taking the power (unless it is at 7.5ms all the time) but possibly the data traffic triggering some activity in the watch making cpu busy.

    Ok - gotcha 👍

  • So one would maybe want a configuration where connection interval upon user interaction is generally at some hundreds ms but kicks down to 7.5 ms when much data transfer is happening or is expected?

    maybe. connection interval is the time when both devices wake and data is sent in one or possibly more packets at once, so if we have MTU of 131 and maybe 2-4 packets are sent in one connection interval (not sure about this now, it varies) then if more data than131-3=128*number of packets needs to be sent it will slow things down. So if you use 200ms and 2 packets are sent in one interval you have transfer rate of 2*128*(1000/200)=1280 bytes per second

    EDIT: oh, we still send only one packet per connection interval (in watch->phone direction) https://github.com/espruino/Espruino/blob/master/targets/nrf5x/bluetooth.c#L972 , this is maybe too conservative

  • @fanoush I forgot about that - the comment above explains the reasoning, but I guess it could be a setting that can be changed by the user...

    Honestly, I don't think you'll find this that useful for power saving. Espruino automatically swaps power usage between high(~0.9mA) to low (>0.04mA) after a minute of inactivity, so as long as you're spending >5 minutes between sending data to Gadgetbridge you're not using that much power.

    Compare this to other sources of power drain and it's a pretty small amount: https://www.espruino.com/Bangle.js2#power-consumption

    So ~0.3mA in every-day use, and 0.04mA of that is BLE.

    One thing that I guess could be added if you really cared was a way to tell Espruino not to go into the high power mode for some things - for example when sending the health info every 10 minutes, there's no reason it should kick itself into high power mode for the next minute - but really that's something that'd need to be in the firmware.

    If you really want to increase battery life I think we could look at changing the default poll interval from 80ms to maybe 240ms, and to use the accelerometer's FIFO so we can still get all the data, but just wake up and poll 1/3 as often.

    That would add a small amount of lag to the 'wake on twist', but realistically I don't think most people use that anyway

  • One thing that I guess could be added if you really cared was a way to tell Espruino not to go into the high power mode for some things - for example when sending the health info every 10 minutes, there's no reason it should kick itself into high power mode for the next minute - but really that's something that'd need to be in the firmware.

    Actually NRF.setConnectionInterval disables it so if some setting on a watch had this optionally forced to some specific value it would override what the firmware does. So the 'no reason to kick itself into high power mode' is doable by this.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Extend battery life by connecting intermittently

Posted by Avatar for Ganblejs @Ganblejs

Actions