Bangle GPS Power management

Posted on
of 3
/ 3
  • Had some success with the test bed code below.
    Be good if you could verify the result.

    Setting the update and search time to 120s and baud rate to 120s:
    After the GPS has settled down and established its first fix I can see a cylcle of about 40-50s at 31mA and about 70s at 7.8mA. Increasing the period will increase the time it consumes the 7.8mA. So there is a trade off in terms of how recent you want the last fix to be. The 120s setting will effectively average the consumption out to 15mA - but that will double the battery life when GPS is on. My requirement is to get a GRID REF when walking and I dont mind it ot was 2 minutes ago. At 15mA average consumption you would get about 20hrs time with the GPS on all day as opposed to 10hrs using the PMS/SuperE mode.

    test bed for working out lowest power consumption, with workable GPS
    Load into IDE and upload code to RAM when connected to watch
    Bangle.on('GPS-raw',function (d) {
      if (d[0]=="$") return;
      if (d.startsWith("\xB5\x62\x05\x01")) print("GPS ACK");
      else if (d.startsWith("\xB5\x62\x05\x00")) print("GPS NACK");
      // 181,98 sync chars  
      else print("GPS",E.toUint8Array(d).join(","))­;
    function writeGPScmd(cmd) {
      var d = [0xB5,0x62]; // sync chars
      d = d.concat(cmd);
      var a=0,b=0;
      for (var i=2;i<d.length;i++) {
        a += d[i];
        b += a;
    // quick hack
    function wait(ms){
      var start = new Date().getTime();
      var end = start;
      while(end < start + ms) {
        end = new Date().getTime();
    function UBX_CFG_PMS() {
      // UBX-CFG-PMS - enable power management - Super-E
      writeGPScmd([0x06,0x86, // msg class + type
             0x00,0x03, 0,0, 0,0, 0,0]);  
    function UBX_CFG_INTERVAL(period, ontime) {
      writeGPScmd([0x06,0x86, // msg class + type
             8,0, //length
             //v0,  interval     period             ontime           reserved
             0x00,  0x02,        period,        0,  ontime,     0,    0,      0  ]);
             // the values are little endian, least significant byte first
     * set update baud rate
     * the setting is in milliseconds in 2 bytes, max 65 seconds
     * we are passing in a value in seconds
     * we set the most significant byte only
     * 8 seconds ~ 8192ms 0x2000, 0x20 = 32 = 4*8
    function UBX_CFG_RATE(rate) {
      rate = (rate * 4) % 256;
      //console.log("rate=" + rate);
      writeGPScmd([0x06,0x08,  // class, id 
    	       0x06, 0,          // length
    	       0x00, rate,       // b0: 8192ms 0x2000,  0x00FF (~65sec)
    	       0x01, 0x00,       // b2: 
    	       0x01, 0x00]);     // b4: timeref GPS
     * Save configuration otherwise it will reset when the GPS wakes up
    function UBX_CFG_SAVE() {
      writeGPScmd([0x06, 0x09,   // class id
    	       0x0D, 0x00,   // length
    	       0x00, 0x00, 0x00, 0x00,  // clear mask
    	       0xFF, 0xFF, 0x00, 0x00,  // save mask
    	       0x00, 0x00, 0x00, 0x00,  // load mask
    	       0x07]);                  // b2=eeprom b1=flash b0=bat backed ram
                                            // code on github had 7 - all 3 set ?
       * Reset to factory settings using clear mask in UBX_CFG_CFG
      function UBX_CFG_RESET() {
        writeGPScmd([0x06, 0x09,   // class id 
                     0x0D, 0x00,
    		 0xFF, 0xFB, 0x00, 0x00,  // clear mask
    		 0x00, 0x00, 0x00, 0x00,  // save mask
    		 0xFF, 0xFF, 0x00, 0x00,  // load mask
    // convert an integer to an array of bytes
    function int_2_bytes( x ){
        var bytes = [];
        var i = 4;
        do {
          bytes[--i] = x & (255);
          x = x>>8;
        } while (i);
        return bytes;
       * Extended Power Management 
       * update and search are in seconds
    function UBX_CFG_PM2(update,search) {
      var u = int_2_bytes(update*1000);
      var s = int_2_bytes(search*1000);
      writeGPScmd([0x06, 0x3B,                   /* class id */
    	       44, 0,	                     /* length */
    	       0x01, 0x00, 0x00, 0x00,       /* v1, reserved 1..3 */
    	       0x00, 0x10, 0x00, 0x00,       /* on/off-mode, update ephemeris */
    	       // little endian, lsb first
    	       //0x30, 0x75, 0x00, 0x00,	/* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
    	       //0x88, 0x13, 0x00, 0x00,	/* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
    	       u[3], u[2], u[1], u[0],          /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
    	       s[3], s[2], s[1], s[0],          /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
    	       0x00, 0x00, 0x00, 0x00,    /* grid offset */
    	       0x00, 0x00,	          /* on-time after first fix */
    	       0x01, 0x00,                /* minimum acquisition time */
    	       0x00, 0x00, 0x00, 0x00,	  /* reserved 4,5 */
    	       0x00, 0x00, 0x00, 0x00,	  /* reserved 6 */
    	       0x00, 0x00, 0x00, 0x00,    /* reserved 7 */
    	       0x00, 0x00, 0x00, 0x00,    /* reserved 8,9,10 */
    	       0x00, 0x00, 0x00, 0x00]);  /* reserved 11 */
    // enable power saving mode, after configured with PM2
    function UBX_CFG_RXM() {
      writeGPScmd([0x06, 0x11,        /* UBX-CFG-RXM */
    	       2, 0,	          /* length */
    	       0x08, 0x01]);	  /* reserved, enable power save mode */
    function onGPS(fix) {
    function setupGPS() {
    // call setupGPS(); to run test
    // Bangle.setGPSPower(0); to end test
  • This works even better.

    function setupGPS() {
  • try to go out of the zip and touch and hold the zip to select it, don't go inside

    Yes, this - it seems modern Android releases don't do it, but there was a certain Android OS where it was a bit painful to select the zips!

  • Managed to get the firmware updated on the wired bangle, thanks for the help.

  • @Gordon - did you spot that I think I have low power working ?

  • Wow, that's great! No, sorry - I missed it. When I went to the thread I only saw Page 1 :)

    I'm a bit busy today but I'll look into this later in the week

  • Been doing a test, been running for 18 hours and have 45% battery left, woo hoo.
    I'll do a pull request, just tidying up a few things.

  • Wow, that's amazing. Maybe you could come up with a 'GPS Config' app? So you can configure the GPS for various power modes (or return it to default).

    You could just use E.showMenu for it:­owMenu

    If you're having difficulty with it, let me know. If you can provide functions a bit like setModeNormal, setModeSuperE, setMode2Minute I'm happy to do the rest.

  • Have done a gpsservice widget with a settings app that sets the kind of parameters you describe above. Full details in the README at:­/tree/master/apps/gpsservice

    Have sent a pull request.

  • Very nice!

  • Where did the pictures go?

  • Just merged in!

  • Thanks for that. Have done another pull request for a gps_set|get_settings() and I now restore to SuperE mode on power off of the GPS through the gpsservice widget.

  • If you have an app using this gpsservice widget what happens when that app exits? Does the gpsservice widget keep the GPS powered on? If so, is there a way to have the gpsservice power off the GPS on an app exit? Thx

  • Right now, whenever an app exits the GPS gets powered off - basically when you switch apps, Bangle.js resets everything to a 'power-on' state so apps always have the same state.

    It's a good way to keep Bangle.js nice and stable regardless of what each app does, but I am looking at adding a way of keeping the GPS powered on between apps that both use the GPS for a later firmware update.

  • @Gordon, what about introducing a descriptor about what should stay on during switch of apps... If descriptor is absent, behavior unchanged. If descriptor present, operation according to its multi-value statuses. Applications can then design what to do. There could even be an expiration in the description for each item keeping power so that things may not run down the battery when forgotten. Almost like power management of battery run laptops.

  • I've recently added the ability to do Bangle.setGPSPower(1, "myappid") which at least helps with stopping other apps/widgets powering off the GPS.

    The issue with letting apps request that stuff is kept running is that honestly it'd be so easy for it to be misused, and then it makes Bangle.js look bad for everyone when the battery life goes from weeks to a few hours any nobody knows why.

  • @Gordon, Thanks for the quick answer a couple of days ago. Sorry about the delay, I have 'been bush' field testing the Bangle.JS

    If I follow what you are saying :

    • A GPS app can call the GPS Low Power Service widget to set a power mode and power on the GPS.
    • The GPS Low Power Service powers on the GPS in the requested mode.
    • The GPS app exits and the GPS is automatically powered off.
    • The GPS Low Power service continues to run with a widget icon indicating the GPS is on but the GPS is actually off.

    Is that right?

    Thanks, Mike.

  • Hi Mike,

    I think things are a little 'in flux' at the moment - it turns out the GPS Low Power Service widget isn't required and we'll likely be removing it soon as it complicates matters. In a few days time, this will be the situation:

    • There's a GPS Settings app - you can go in there and adjust how you want the GPS to work - low power, normal, etc
    • These settings the apply to every other app that uses GPS (via the normal Bangle.js APIs)
    • There'll be a GPS Status widget which you can add that'll show you the current status of GPS (on/off) if you're interested and the app/other widgets don't show anything.

    Hope that helps!

  • Pretty close to pushing the GPS Setup app out in the next couple of days.

  • Bangle.setGPSPower(1, "myappid") - sounds a good idea. But I agree about the power, always my worry too, thats why I have done the tiny GPS widget, I want to know when the the power hungry parts of the hardware are on.

  • Sounds good but I am not using the widget in a static way so I hope I can still dynamically change mode as needed. Will there be an API to allow me to dynamically change the GPS mode?

    My speedalt app functions like a watch face in that it obeys the screen off timeouts etc. You can flick the screen on for 10 secs for a look with a wrist movement etc. While the screen is on it uses the current widget call to switch to SuperE mode and when the screen goes off it switches to PMOO mode. Worked really well over a two day hike plus 4 hours of driving on a single charge last weekend. ( Actually drops to PMOO mode 15 secs after the screen is turned off allowing a little time to restore the screen if you want to keep viewing it )

    Alternatively, perhaps make that behavior one of the baked-in options in your settings app?

  • Hi Gordon, I should have added. No rush. The work that you folk have done on the GPS power management improvements is just fantastic. Best to think it through and get it right so no pressure. Keen to help or test if I can. Cheers Mike

  • That's a really nice use-case! I think that probably what makes the most sense is to tweak the new GPS Settings app (now merged in!) such that it provides a module, and you can do something like:

    try {
    } catch (e) {
     // GPS settings not installed

    I'll do that before we do anything with the widget anyway. I think it's a bit more flexible as it means the widget isn't sitting there using RAM when you're not running a GPS app.

  • Do we need the equivalent of a library or will the GPS setup app work as a library if you use require() ?

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

Bangle GPS Power management

Posted by Avatar for HughB @HughB