Core2 how to know the current battery level

  • With the Fire using the function M5.Power.getBatteryLevel(); gives you the battery level. With Core2 it is not clear to me. I have used a number of functions connected and not connected to the USB. I detail them below:

    float batVol = M5.Axp.GetBatVoltage(); // 4.21
    float batCur = M5.Axp.GetBatCurrent(); // 14.00
    float batPow = M5.Axp.GetBatPower(); // 0.00
    float batCha = M5.Axp.GetBatChargeCurrent(); // 14.00
    bool charging = M5.Axp.isCharging(); // 1

    Without USB:
    float batVol = M5.Axp.GetBatVoltage(); // 4.16
    float batCur = M5.Axp.GetBatCurrent(); // -88.5
    float batPow = M5.Axp.GetBatPower(); // 462.39
    float batCha = M5.Axp.GetBatChargeCurrent(); // 0.00
    bool charging = M5.Axp.isCharging(); // 0

    I see very different values depending on whether it is connected or not. Can someone explain to me if this is correct or if there is a problem with the unit?

    Thanks in advance

  • Hello @Carles-B

    your numbers look about right.

    In your example with USB the battery is almost full but is still being charged with 14mA as indicated by GetBatChargeCurrent(). And those 14mA are going into the battery (positive) as indicated by GetBatCurrent(). If you keep USB attached and wait for the battery to be fully charged isCharging() will go to 0 (false).

    W/o USB the battery now is being discharge with 88.5mA (the minus sign indicates energy going out of the battery). And obviously w/o USB the battery no longer is being charged, hence GetBatChargeCurrent() is 0 and isCharging() is 0 (or false).

    Which value(s) are not what you'd expect?


  • Hello @felmue
    I would just like to know if the values were correct. Thank you for your explanation.

    If I am not confused, my English is not good, there is no function like in Fire M5.Power.getBatteryLevel(), to know the percentage or actal battery level.

    Thanks for your time

  • In Core2_factory_test.ino you find the following lines (ca. 900) with the magic value 3.2, i.e. battery empty.
    They use the variables in their code to make up some nice graphics about battery status.

       float batVoltage = M5.Axp.GetBatVoltage();
        float batPercentage = ( batVoltage < 3.2 ) ? 0 : ( batVoltage - 3.2 ) * 100;

  • Thanks for the reply @wa-berlin. I see that each core is different and the way to calculate the battery level are completely different between Fire and Core2. Particularly I think that being from the same company should be similar programming with the prefix difference of the core, ie: M5.Power.xxxxxxxx = M5.Axp.xxxxxxxx


  • I implemented and tested this last night; While the calculation in the m5core2 factory test is linear - the battery performance is not.

    alt text

    My little Core2 lasted for 5 hours and 40 minutes.

    At about 5 hours and 25 minutes it was showing 20% (my battery meter turns red at 20% :) ), but the last 20% dropped off in 15 minutes. You can see this shown in the graph above for Li-ion batteries (i dont really know how close that is to the real performance of these batteries.

    We can extrapolate that as being a total life of 1 hour and 15 minutes - based onthe last 20%

    Does anyone know of a better curve solution someone has already done?

    If not I know the solution:
    Leave it to run down, pinging out to sdcard its battery voltage, current draw (for information) and the time elapsed.
    Then we can build a graph - just like the one I linked to based on the specific battery in this device - a new, healthy battery at room temperature - using a fairly normal level of power consumption.

    Then I can build a lookup table to represent this in code for this device.

    We could also build tables at different consumptions/temperatures if we wish as this will all affect when the "last 20%" fade kicks in. Upshot would be it will be much more accurate than this basic linear calculation is - so I'm going to do this later.

  • @pensive

    Thank you for running that test! I thought that's how it worked but didnt have time to get around testing it. The idea I had was to integrate either the time on or approx consumption and store it using the "preferences" library. The library saves whatever to the non-volatile memory so you wouldnt need the SD card. There was a write up of the libaray on the forums here:

    So the two ideas:

    1. track how long the device has been on, update a preference with the time, subtract time on from the 5 hours 40 mins to get time remaining. It wont always be accurate, but probably close enough for most uses.

    2. Calculate the current consumption based on screen/wifi/bluetooth/etc being on, integrate all that and compare to total mah of the battery. (This would have a lot of factors, but could probably get you closer if you figured all them out.)

    I think the first one is the "easiest", do you have any thoughts?

  • @revta Here is the data from a test I just ran with approx 70mA battery drain. As you can see the line is reasonably linear until the very end. My chart starts with the device on charge until fully charged (charging circuit switches off). Then I manually disconnect the charger

  • This post is deleted!

  • @jimwsmith said in Core2 how to know the current battery level:
    As you can see the line is reasonably linear until the very end.

    Great thank you! It's the super steep drop off at the end that is messing with everything as the algorithm in the example code just draws a straight line from 3.2v to 4.2v so up until the steep drop off it says you have almost 50% more battery than you actually have! at that dropoff point the voltage is about 3.65v - so the percentage calculation at that point in the graph will read 45%!!!

    I've observed the same phenomenon in reverse when charging - it looks like you are charging really quickly because you hit 45% really quickly then it takes forever to make it the rest of the way - no wonder - you're only 20% charged!

    the most accurate and lightweight solution would be a lookup table. It could mimick that curve exactly at every percentage point using only 100 float values - and a very simple function:

    byte returnBatteryLevel(float currentVoltage){}

    @jimwsmith would you be willing to share that spreadsheet with me so I can pull the voltages out? I'd be happy to commit this function back to the M5core2 master so we can all report (more) accurate percentages.

    @revta getting to a projected time left would be a step 2 in this process - the first being getting an accurate percentage left, the second projecting how quickly this will diminish based on knowlegde of the battery and the current draw. I think this part is getting much more complicated as it will be drastically affected by different battery capacities (Faces kit or the battery stack units etc.) as well as the current draw - this is not so much the case with Step 1 so step 1 would be much more universal function and I think will remain reasoably accurate across battery capacities.

  • @pensive said in Core2 how to know the current battery level:

    the most accurate and lightweight solution would be a lookup table. It could mimick that curve exactly at every percentage point using only 100 float values - and a very simple function:

    Actually I could do it using a handful of float "keyframes" at key points and calculate an interpolated percentage on the fly. Which is better - less ram / sketch ram? Or less CPU ticks? I would normally just burn a full lookup table to free up clockticks but memory can be a valuable resource too....

    100 * 4 bytes = 400 bytes + headers of sketch ram for the full lookup table.

    I could probably reduce this to 100 bytes but at a realtime processing cost (which will cost battery!). I'm leaning on the full lookup table idea.

  • Sorry for multipost but I could also store the values in byte values with the first byte for the unit and second byte for the decimal would probably retain accuracy across all 100 values but store it all in 200 bytes. Simple bit of code for each query.....more clockticks though, I dont want to underestimate the parasitic load of constnatly performaing unnecessary calculations.....

    Ahh: found this:

    But not supported by arduino which is freaking wierd. floating point iwth half the memory usage? Yes please.....

    But since its not supported a full lookup table is neater. others can save ram if they like but im not too bothered. This board has oodles of it.

  • @pensive Here is a link to the battery log code (it was done in Blocky for a workshop demo) and the log text file

  • @jimwsmith said in Core2 how to know the current battery level:

    @pensive Here is a link to the battery log code (it was do

    Thank you :D

    Will update here once it's implemented and pushed

  • @wa-berlin said in Core2 how to know the current battery level:

    batPercentage = ( batVoltage < 3.2 ) ? 0 : ( batVoltage - 3.2 ) * 100;

    micropython welcome :

    batPercentage=0 if batVoltage<0 else round((batVoltage-3.2)*100)