isCharging() and getBatteryLevel()



  • The M5 Stack has: M5.Power.isCharging() and M5.Power.getBatteryLevel(), but Power (from M5Stack.h) is not in the M5 object for the stick (M5Stick.h). Is it possible to determine if the M5 stick is changing, and also determine what the battery level (percentage charged) is?



  • Hi,

    just do "uint8_t Bat_Level = M5.Power.getBatteryLevel()" and then you have it.

    Bye



  • Well, I wish I could. M5.Power is in M5Stack.h and is only available for the M5 Stack.

    I have a M5 Stick and have to use M5Stick.h, and M5.Power is not defined and is not available in M5Stick.h



  • Take look at this example:
    https://github.com/m5stack/M5StickC/tree/master/examples/Advanced/AXP192/PowerWake

    function 'M5.Axp.GetVapsData()' can be used for what you need. When value is above 4.5V it's charging.
    function M5.Axp.GetVbatData() will show you battery level.



  • Thanks for the tip @majrooo . I have been playing around w/the Axp class, and I'm closer, but not fully there. From your reply (and the PowerWake example), it sounds like GetVapsData() is supposed to return the overall capacity, and GetVbatData() is supposed to return the current voltage, but that's not whatI'm seeing though. Here is a sample:

    #include <M5StickC.h>
    
    RTC_TimeTypeDef RTC_TimeStruct;
    
    void displayInfo(void);
    void setCursorToLine(int lineNumber);
    
    
    void setup()
    {
      M5.begin();
      M5.Axp.begin();
    
      RTC_TimeTypeDef timeStruct;
      timeStruct.Hours = 0;
      timeStruct.Minutes = 0;
      timeStruct.Seconds = 0;
      M5.Rtc.SetTime(&timeStruct);
      
      M5.Lcd.setRotation(1);
    }
    
    void loop()
    {
      M5.Lcd.fillScreen(BLACK);
      displayInfo();
      delay(1000);
    }
    
    void displayInfo(void)
    {
      uint16_t vbatData = M5.Axp.GetVbatData();  // docs: "Get the battery voltage value"
      double vbat = vbatData * 1.1 / 1000;
      setCursorToLine(1);
      M5.Lcd.printf("vbat: %.3f V    ", vbat);
      // charging: 4.188 V
      // unplugged: 4.068 V (fully charged)
      // unplugged: 3.068 V (45 minutes later, about to turn off)
      
      uint16_t vapsData = M5.Axp.GetVapsData();  // docs: "Get battery capacity"
      double vaps = vapsData * 1.4 / 1000;
      setCursorToLine(2);
      M5.Lcd.printf("vaps: %.3f V    ", vaps);
      // charging: 4.971 V
      // unplugged: 4.068 V (fully charged)
      // unplugged: 3.066 V (45 minutes later, about to turn off)
      
      double batteryLevel = 100.0 * ((vaps - 3.0) / (vbat - 3.0));
      setCursorToLine(3);
      M5.Lcd.printf("batteryLevel: %.1f%%    ", batteryLevel);
      
      M5.Rtc.GetTime(&RTC_TimeStruct);
      setCursorToLine(4);
      M5.Lcd.printf("%02d:%02d:%02d", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
    }
    
    void setCursorToLine(int lineNumber)
    {
      const int X_LOCATION = 5;
      const int Y_LOCATION = 0;
      const int LINE_HEIGHT = 20;
      M5.Lcd.setCursor(X_LOCATION, Y_LOCATION + ((lineNumber - 1) * LINE_HEIGHT), 2);
    }
    

    When charging, I'm getting:

      uint16_t vbatData = M5.Axp.GetVbatData();   // docs: "Get the battery voltage value"
      double vbat = vbatData * 1.1 / 1000;
      // charging: 4.188 V
      
      uint16_t vapsData = M5.Axp.GetVapsData();   // docs: "Get battery capacity"
      double vaps = vapsData * 1.4 / 1000;
      // charging: 4.971 V
    

    After fully charge and then disconnected, I get:

      uint16_t vbatData = M5.Axp.GetVbatData();  // docs: "Get the battery voltage value"
      double vbat = vbatData * 1.1 / 1000;
      // unplugged: 4.068 V (fully charged)
      
      uint16_t vapsData = M5.Axp.GetVapsData();  // docs: "Get battery capacity"
      double vaps = vapsData * 1.4 / 1000;
      // unplugged: 4.068 V (fully charged)
    

    ..and later on, when the battery is around 3V and just about to power off, I had:

      uint16_t vbatData = M5.Axp.GetVbatData();  // docs: "Get the battery voltage value"
      double vbat = vbatData * 1.1 / 1000;
      // unplugged: 3.068 V (45 minutes later, about to turn off)
      
      uint16_t vapsData = M5.Axp.GetVapsData();  // docs: "Get battery capacity"
      double vaps = vapsData * 1.4 / 1000;
      // unplugged: 3.066 V (45 minutes later, about to turn off)
    

    I was expecting the value from GetVapsData() to remain constant, but as you can see, vbat tracked almost 1:1 with vaps.

    So I then hard-coded the "max battery capacity" value to 4.07 and changed batteryLevel to:

      //double batteryLevel = 100.0 * ((vaps - 3.0) / (vbat - 3.0));
      double batteryLevel = 100.0 * ((vaps - 3.0) / (4.07 - 3.0));
      setCursorToLine(3);
      M5.Lcd.printf("batteryLevel: %.1f%%    ", batteryLevel);
    

    ...and this works, but I don't like having to hard-code the max-battery-capacity value to 4.07 and would rather there was a way to programmatically get this value.

    I feel like there must be a way to do this, but I'm not seeing how with the methods in Axp.

    If I were to refactor my current code for batteryLevel into a function, it would be:

    double getBatteryLevel(void)
    {
      uint16_t vbatData = M5.Axp.GetVbatData();
      double vbat = vbatData * 1.1 / 1000;
      uint16_t vapsData = M5.Axp.GetVapsData();
      double vaps = vapsData * 1.4 / 1000;
      return 100.0 * ((vaps - 3.0) / (4.07 - 3.0));
    }
    

    What would be a better implementation for getBatteryLevel()?

    Thanks,

    Jeff



  • correction, it would be:

    double getBatteryLevel(void)
    {
      uint16_t vbatData = M5.Axp.GetVbatData();
      double vbat = vbatData * 1.1 / 1000;
      return 100.0 * ((vbat - 3.0) / (4.07 - 3.0));
    }
    

    ...what would be a better implementation for getBatteryLevel()?



  • Nice work guys is cracking this issue. I hope you guys solve it in a reliable way.

    Please excuse this foolish comment as I dont know enough but

    Isn't GetVapsData() used to measure how much draw from the battery is made by running software?



  • @jeffb said in isCharging() and getBatteryLevel():

    Well, I wish I could. M5.Power is in M5Stack.h and is only available for the M5 Stack.

    I have a M5 Stick and have to use M5Stick.h, and M5.Power is not defined and is not available in M5Stick.h

    Oh, i missed that you have the Stick. :-(
    But i think the routines posted here are MUTCH better than the one in the Lib.
    The BatteryStatus gives only 100%, 75%, 50%, 25%, .... :-(

    Bye



  • I use the battery voltage to try and work out a sensible idea of battery level. Anything equal or over 4.1 can be considered full, less than 3.4 is pretty much dead, and 3.7 is generally where it'll spend most of it's time. It's not a linear drop off, so it will take some calculations to try and get it accurate around the 3.6 to 3.8 volt range. This is probably why the M5Stack library only gives 0/25/50/75/100 battery levels.

    I then use battery current to know if it's charging, discharging or fully charged. By getting the value from M5.Axp.GetBatCurrent() if you see a negative value, it's discharging, a positive value is charging and a zero value means fully charged while plugged in. The values returned will give you an idea of how much current is being drained from the battery in mA, or indeed how much current is being used to charge the battery, all in realtime. On the M5StickC it would be 85mA typically when charging.