SoC returns 0.00 at times (bsom eval board)

I have 5 bsom eval boards and this is happening on one of my boards.
I have tested the battery on my scope and it is outputting a very stable 4v, but when this boron awakes it thinks the battery is dead :frowning:

Is there a better way to get this or should I just read it a few times and hope it stabilizes?

SYSTEM_MODE(MANUAL);
FuelGauge fuelGuage;
void setup(){
    fuelGuage.begin();
}

void loop() {
    Log.info("\n\n==== LOOP ====");
    Log.info(Time.timeStr());
    Log.info("SoC=%.2f", System.batteryCharge());
    Log.info("Cellular = %d.  Cloud = %d.", (int)Cellular.ready(), (int)Particle.connected());

    float soc = System.batteryCharge();
    if (soc < 5.0) {
        Log.error("SoC is < 5% going to emergency sleep %.2f", soc);
        // Battery is very low, go back to sleep immediately
        SystemSleepConfiguration config;
        config.mode(SystemSleepMode::ULTRA_LOW_POWER)
            .duration(60min);
        System.sleep(config);
        return;
    }
}

output

==== LOOP ====
0000002699 [app] INFO: Sat Jan  1 00:00:02 2000
0000002700 [app] INFO: SoC=0.00
0000002701 [app] INFO: Cellular = 0.  Cloud = 0.
0000002703 [app] ERROR: SoC is < 5 0oing to emergency sleep 0.00

Sometimes it even outputs

0000002704 [app] INFO: SoC=-1.00

Tonight I turned it off, waited a few minutes and then I got

0001182232 [app] INFO: Sun Apr 11 10:51:24 2021
0001182233 [app] INFO: SoC=97.68

but this certainly isn’t an option when out in the field.

What device OS version are you running?
What do your fuelGauge.getVCell() and fuelGauge.getSoC() report?

2.0.1

    float fuelSoC = fuelGuage.getSoC();
    float vCell = fuelGuage.getVCell();
    Log.info("SoC fuelguage= %.2f", fuelSoC);
    Log.info("vCell= %.2f", vCell);

0000002919 [app] INFO: Sat Jan  1 00:00:02 2000
0000002920 [app] INFO: SoC=0.00
0000002920 [app] INFO: Cellular = 0.  Cloud = 0.
0000002922 [app] INFO: SoC fuelguage= 0.00
0000002923 [app] INFO: vCell= 4.06
0000002924 [app] ERROR: SoC is < 5 0oing to emergency sleep 0.00

I just finished assembling another board and had this happen again was I was able to capture the error.

IIRC the SoC reading is derived off of the vCell reading via a correlation function based on some parameters stored in the fuel gauge which get adapted over time by the fuel gauge “observing” the charge/discharge cycles.

Since your vCell reading seems fine it could be that the parameters got wiped somehow.

You can try to explicitly call fuelGauge.wakeUp() and fuelGauge.quickStart() after waking from sleep to see if this helps.
If not, you may want to flash some alternative firmware that gives the fuel gauge some chance to consciously observe several discharge/charge cycles without interruption and then see whether the SoC reading comes back to life.

Unfortunately the reference docs on the fuel gauge are still some intellectual waste land :wink:

I already had fuelGauge.wakeUp right under my sleep code, but I’ve added the quickstart now too.

Hmm, didn’t see it anywhere :wink:

@tunahammer ,

I am seeing this issue as well. Did @ScruffR 's suggestion fix the issue?

Thanks, Chip

chipmc
this is what I’ve gone with and it’s been ok…

  float soc = System.batteryCharge();
    Log.info("SoC System= %.2f", soc);
    float fuelSoC = fuelGuage.getSoC();
    float vCell = fuelGuage.getVCell();
    Log.info("SoC fuelguage= %.2f", fuelSoC);
    Log.info("vCell= %.2f", vCell);
    if (soc < 5.0 && vCell < 3.7) {
        Log.error("SoC is < 5% going to emergency sleep %.2f", soc);
        // TODO - determine if this is useful....
        // Battery is very low, go back to sleep immediately
        SystemSleepConfiguration config;
        config.mode(SystemSleepMode::ULTRA_LOW_POWER)
            .duration(120min);
        System.sleep(config);
        return;
    }
1 Like

Thank you for sharing.

So no, fuelGauge.quickStart() or fuelGauge.wakeup() commands needed?

Thanks,

Chip

Oh sorry - that wasn’t the complete sketch by any means.

setup(){
    fuelGuage.begin();
}

loop(){
    float soc = System.batteryCharge();
    float fuelSoC = fuelGuage.getSoC();
    float vCell = fuelGuage.getVCell();
    if (soc < 5.0 && vCell < 3.7) {
        Log.error("SoC is < 5% going to emergency sleep %.2f", soc);
        // Battery is very low, go back to sleep immediately
        SystemSleepConfiguration config;
        config.mode(SystemSleepMode::ULTRA_LOW_POWER)
            .duration(120min);
        System.sleep(config);
        return;
    }

//   inside my sleep function
    fuelGuage.sleep();
        ... sleep code to actually sleep
// wakes up
    fuelGuage.wakeup();
    fuelGuage.quickStart();
    

// optional console logging
    Log.info("SoC System= %.2f", soc);
    Log.info("SoC fuelguage= %.2f", fuelSoC); // not used, the other one seemed better at the time maybe?
    Log.info("vCell= %.2f", vCell);


}


1 Like

@tunahammer ,

Wow, that is a lot of instructions when what you need to know is the state of charge.

All of this is because you can’t rely on the new System.batteryCharge() call that was added after deviceOS@1.5.0? And the reason it does not work is because you are checking the charge level after coming out of sleep?

I am just wondering if we should be pressing for the System call to be fixed rather than adding management of the fuel gauge to our code.

BTW, I have been using this approach for a few days and it does seem to fix the issue of incorrect battery charge readings after sleep.

Thanks,

Chip

I am having a related issue with an Electron, again with a Solar powered application that checks System.batteryCharge()
after reset from sleep.
I have the situation where the cell (a 3400mAh LiPo) is reading just over 4V, charge light is off, Vin supplied a reliable 5V, and the SoC is reported as somewhere below 40%, persisting for some hours over several sleep cycles.
I will also give your code a try to see if it improves matters. Failing that, is there a relatively simple mapping that I can do myself from fuel.getVCell()?