Bangle.js 2 - Battery always 100%

Posted on
of 2
/ 2
  • I received my Bangle.js 2 a couple weeks ago. I was giving it as a Christmas present, so I didn't do much with it other than charge it fully and install the latest software/apps including the newest firmware update. Since yesterday, it has mysteriously shut down several times and would not power back up until connected to the charger. Once on the charger, it will immediately boot up and the battery shows as 100% charged. At that point, if you disconnect it from the charger, it will run for a few minutes and then shut down again. I finally figured out that the indicated battery level always shows as 100% even when it's almost discharged. I charged it for a couple of hours and it has run overnight without shutting down (but the battery still shows 100%). Has anyone else seen this behavior?

  • Hi, Im pretty sure you and the OP in this thread have a similar underlying hardware issue. Try doing the steps there to see what the reported voltages are, I assume that could help further troubleshooting this issue:­370718/

  • Here's what I get for a sequence of E.getBattery() and analogRead(D3) calls:



  • Just thought I'd better point out that I had very similar problems until I upgraded to the latest firmware version, 2v11. After upgrading to 2v11, the battery life has been much better (and stable). The firmware upgrade can be a little problematic, however, so be sure to read the posts related to updating the firmware if you run into any issues.

  • I've already updated the watch firmware to 2v11 last week and unfortunately it didn't help.

  • I think this is a different issue to the above linked one. In the linked issue, a missing connection meant the voltage readings were small negative numbers. Your voltages are higher than usual. If the entire range of voltages on your device is higher than 0.3144 you will always get 100% all the time.

    Were the readings above near full charge or near empty? Getting readings from both ends might be interesting, but I am not a hardware guy and have no idea what if any hardware difference your device has. There have been at least 2 other threads about different voltages. If there is a lot of variation then perhaps determining the voltage range on a per device basis is necessary.

  • I've done some experimenting and it looks like my watch maxes out around 0.481 on the D3 when fully charged and shuts down around 0.375. These values are about 1.5x the values used to calculate battery percentage (0.246 and 0.3144). Not sure if my watch was built with the wrong value resistors for the voltage divider that feeds D3 or if the ADC is programmed incorrectly for that input.


    Fully charged:


    Just prior to shutdown:


  • That's the sort of thing I was expecting based on your previous message. @Gordon or one of the other hardware experts might be able to have a guess based on that what the cause is. My idea as to the solution, but someone else might have a better idea, would be writing the max and min voltage to storage and reading the value on boot. Max is easy, whereas Min would probably take a few cycles to get accurate.

  • I've worked around it for now by editing widbatpc.wid.js on the watch, replacing E.getBattery() with a call to a custom getBattery() function:

    function getBattery() {
        var battery = Math.round((analogRead(D3) - 0.375) / .00106);
        return battery;

    That should tide me over until @Gordon returns.

  • You can make a global change to getBattery() by following the instructions at­cation

    For me, it appears my high and low D3 readings are about 0.293 and 0.230 respectively, although I'm getting a sharp dropoff at about 0.255.

    I'm currently running some charge/discharge tests. The results can be seen at:­y57CRYdBSTXJgn4zsKDiUv6glE0sOzib2GQscZfg­7Qo/edit?usp=sharing

  • Thanks for the tip!

  • I've decided to go with:

    E.getBattery = function() {
      const lo=0.255,hi=0.293;
      var b=Math.max(lo,Math.min(hi,analogRead(D3)­));
      return Math.round((b-lo)*100/(hi-lo));

    and saved it as "getbattery.boot.js". Adjust "hi" and "lo" as required.

  • Hi - thanks for looking into this and dumping the voltages. It sure looks like in your case the resistors fitted for the voltage divider are wrong. I have no idea how that one could have happened!

    Really sorry about that, although I don't think it should affect your Bangle in other ways... I think the best fix would be as @andrewg_oz has done. Installing the 'Custom Boot Code' app and pasting in:

    E.getBattery = function() {
      const lo=0.38,hi=0.48
      var b=Math.max(lo,Math.min(hi,analogRead(D3)­));
      return Math.round((b-lo)*100/(hi-lo));

    should properly fix the problem for you.

  • @Gordon What kind of battery is in the Bangle.js 2? I read that that analog input is supposed to read 1/4 of the battery voltage, which means that a full battery is about 1.25V. That sounds about right for a NiMH battery. A lithium battery would be quite a bit higher (3.7V?)

  • The Bangle's got a LiPo battery (so yes, around 3.7v, 4.2v when it's just come off the charger)

    The value from analogRead is actually the 3.3v reading scaled to the 0..1 range, so 0.293 = 0.97v - which would definitely fit with 1/4 idea.

    Resistor/capacitor values are notoriously bad though. Normally you get them with 10% tolerance, but they sell the 5% tolerance (and 2, and 1) for a premium - so if you use a 10% tolerance resistor you're basically guaranteed that it isn't the resistance you ordered, but is at least 5% higher or lower.

    With LiPo batteries, that 5% can actually make quite a big difference in what's reported.

    It might make sense to add a 'calibration' to the Bangle.js firmware that allows you to charge your Bangle up and then flatten it (just by turning everything on) and use that to come up with an accurate battery usage figure.

  • to charge your Bangle up and then flatten it

    I never needed the lo - minimum. Since the voltage division is linear, for calibration it should be enough to just measure the highest value ever, claim that it is e.g. 4.2 and then everything else is computed from that. So e.g. if maximum in F07 fitness tracker is 0.18 then

    function battVolts(){
    return 4.20/0.18*analogRead(D5);

    Then I do percentage based on volts e.g. like

    function battLevel(v){
      var l=3.5,h=4.19;
      if(v>=h)return 100;
      if(v<=l)return 0;
      return 100*(v-l)/(h-l);

    But it doesn't matter much. Important is that only one measured value (maximum ever) seems to be enough.

    it appears my high and low D3 readings are about 0.293 and 0.230 respectively, although I'm getting a sharp dropoff at about 0.255.

    so for you
    (4.20/0.293)*0.255 = 3.65V for the dropoff
    (4.20/0.293)*0.230 = 3.29V for the minimum

  • @fanoush You're right, only hi should be needed. I'm now experimenting with trying to get getBattery to be more accurate since volts/% is not linear. My daughter noted that her watch was claiming 40% remaining battery shortly before it shut down. Based on a discharge graph shown here­poly-batteries/voltages, I've come up with the following:

    E.getBattery = function () {
        const hi = 0.48;
        var v = analogRead(D3) / hi * 4.2;
        if (v >= 4.2) {
            return 100;
        } else if (v >= 4.1) {
            return Math.round(97 + 30 * (v - 4.1));
        } else if (v >= 4.0) {
            return Math.round(87 + 100 * (v - 4.0));
        } else if (v >= 3.9) {
            return Math.round(75 + 120 * (v - 3.9));
        } else if (v >= 3.8) {
            return Math.round(59 + 160 * (v - 3.8));
        } else if (v >= 3.7) {
            return Math.round(26 + 330 * (v - 3.7));
        } else if (v >= 3.6) {
            return Math.round(12 + 140 * (v - 3.6));
        } else if (v >= 3.5) {
            return Math.round(6 + 60 * (v - 3.5));
        } else if (v >= 3.4) {
            return Math.round(3 + 30 * (v - 3.4));
        } else {
            return 0;
  • Hi Gordon,
    I seem to have the same issue, but as I am completely new to Bangle World could you give me some pointers about where to begin making this custom boot code fix, please?
    Apologies if it is literally in andrew_oz's comments above - I just need to know where to begin :)

  • Hi, sorry about that. I think based on this and the few other folks having issues recently it makes sense for me to build the adjustment into the firmware. So please hang on for a few days and I'll try and release a new firmware that has it built in.

  • Ok, the cutting edge builds now have this functionality in now (and better mapping of the discharge curve). So, if you:

    • Install the latest 'cutting edge' build
    • Put your Bangle on charge for maybe 2 hours to ensure the battery is fully charged
    • Open the Web IDE ( and connect to your Bangle
    • Copy and paste this code into the left-hand side of the IDE

      (function() {
      var s=require("Storage").readJSON("setting.j­son");
      s.batFullVoltage = (analogRead(D3)+analogRead(D3)+analogRea­d(D3)+analogRead(D3))/4;

    Then your battery percentage meter should then read perfectly.

    I'd be interested to see how this works out. Longer term I'll probably tweak the battery widget so when the charge cable is removed, if the Bangle has been on charge for 2+ hours it'll automatically set itself up.

  • @Gordon I'm charging my Bangle 2 right now and will test the new algorithm this week.

  • @Gordon The new battery monitor algorithm is working really well. I've been using my watch as regular for the past week and haven't charged it since my message above.

    The battery percentage has been much more "normal" without any sudden drops, but there is one quirk.

    For the first 5 days there was nothing special, although I did feel that the battery was depleting slightly faster than normal. By day 5 the level was down to 9% and usually I can get a week of battery life without issue. But, then the level stayed at 9% for more than 24 hours and have since started dropping very slowly. Now, almost exactly 7 days since taking the watch of the charger, and 48-ish hours since it hit 9% the level is down to 5%.

    Seems like the voltage levels in the algorithm needs a bit of tweaking...

  • Did the watch start off after a full charge showing 100% on the battery meter, or was it showing less? And did you run that code while the Bangle was on charge, or when you'd taken it off? I guess it could be that the 'start voltage' that got set for your Bangle wasn't 100% correct.

    This is what I get when graphing the battery voltage (blue) over time alongside the battery percent reported (red) when I've left the LCD backlight on to flatten it down. The graph stops when the Bangle runs out of battery completely

    You can see the change in the blue line is tiny, and at least on my device I feel like I've done pretty much the best I can to get that line linear.

    1 Attachment

    • battery-discharge.png
  • The watch did start off at 100% and I ran the code immediately after taking the watch off the charger. And looking at your graph, the battery percentage you've recorded pretty much exactly matches what I saw (with the plateau at 9-ish percent and then another plateau at 0).

    That blue line looks spot on though, so perhaps this is something we'll have to live with.

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

Bangle.js 2 - Battery always 100%

Posted by Avatar for user138058 @user138058