Tjoms99 / xiao_sense_nrf52840_battery_lib

A battery management library for the XIAO BLE and XIAO BLE Sense board using Zephyr.
Apache License 2.0
21 stars 3 forks source link

High current with the lib initialized #6

Closed felipejfc closed 1 week ago

felipejfc commented 3 weeks ago

I'm developing a battery powered low power application that currently uses ~17ua while sleeping, when I initialize the lib the fact that we keep these 3 gpios active (I think that's the cause)

   ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGING_ENABLE, GPIO_OUTPUT | GPIO_ACTIVE_LOW);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_READ_ENABLE, GPIO_OUTPUT | GPIO_ACTIVE_LOW);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGE_SPEED, GPIO_OUTPUT | GPIO_ACTIVE_LOW);

makes my current go up to ~180ua which invalidates the lib for my use case. A workaround is to disable the pins

    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGING_ENABLE, GPIO_DISCONNECTED);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_READ_ENABLE, GPIO_DISCONNECTED);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGE_SPEED, GPIO_DISCONNECTED);

while sleeping and reenable them when I want e.g. to read the batt voltage, this way I can achieve ~17ua current again. however, it's far from ideal since I will lose "on-demand" charging ability when I plug the usb cable in, right?

thoughts?

Tjoms99 commented 2 weeks ago

Thanks for the feedback @felipejfc!

This is an issue and I think the main driver for your current consumption is the LED that is active when GPIO_BATTERY_CHARGING_ENABLE is set.

You could also try to decrease the number of samples the ADC does to create an average voltage. This can be done on line 36 in battery.c, and decreasing this will come at the expense of a noisier voltage reading.

// Change this to a higher number for better averages
// Note that increasing this holds up the thread / ADC for longer.
#define ADC_TOTAL_SAMPLES 10
int16_t sample_buffer[ADC_TOTAL_SAMPLES];

Something I have not investigated is which charging chip is used (can read more about that discussion in issue #2 ). If it is the BQ25101, then you are in luck! The driver is made for the BQ25100 which uses the PRE-TERM input on the charging chip, while the BQ25101 sends out the charging status. You can then hook up the GPIO_BATTERY_CHARGING_ENABLE to be an input (read) and register interrupts when the state of the pin changes. Then, hook up a callback function to enable or disable the two other GPIO's depending on the charging state. I have not had the time or the available hardware to investigate which chip is used.

I can see if I can look into it next week if you do not want the challenge. If you do, feel free to do a pull request! -Tjoms

felipejfc commented 2 weeks ago

You could also try to decrease the number of samples the ADC does to create an average voltage. This can be done on line 36 in battery.c, and decreasing this will come at the expense of a noisier voltage reading.

The problem is not consumption while reading the voltage, but right after initializing the lib and during idle period.

Something I have not investigated is which charging chip is used (can read more about that discussion in issue https://github.com/Tjoms99/xiao_sense_nrf52840_battery_lib/issues/2 ). If it is the BQ25101, then you are in luck! The driver is made for the BQ25100 which uses the PRE-TERM input on the charging chip, while the BQ25101 sends out the charging status. You can then hook up the GPIO_BATTERY_CHARGING_ENABLE to be an input (read) and register interrupts when the state of the pin changes. Then, hook up a callback function to enable or disable the two other GPIO's depending on the charging state. I have not had the time or the available hardware to investigate which chip is used.

It should be BQ25101 then, even if I don't initialize this lib, or if I initialize it and disable the GPIO pins it use to save power, the charging LED will go green the moment I plug in the USB-C cable, and turn off by itself too. So I guess what I will do for now is use this lib only to read the voltage and let charging ON/OFF be managed by the board's internal circiut

Tjoms99 commented 2 weeks ago

Please check out PR #7 @felipejfc and see if there is an improvement in the current consumption. I will measure this over the weekend, but this is just in case you want a head start.

Tjoms99 commented 1 week ago

The current consumption should be better now after the merged PR. There are a few more things I can do to limit the current consumption, like you proposed, disabling some of the GPIO's (charging speed & battery read) when they are not in use. I expect these changes will come by the end of this week. Ill close this issue for now.
-Tjoms

felipejfc commented 1 week ago

Thx for the improvements. I've been running for some time with just disabling the GPIO before deep sleep and re-enabling them during awake period without problems like this:

int battery_enable_pins()
{
    int ret = 0;
    // GPIO
    if (!device_is_ready(gpio_battery_dev))
    {
        LOG_ERR("GPIO device not found!");
        return -EIO;
    }

    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGING_ENABLE, GPIO_OUTPUT | GPIO_ACTIVE_LOW);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_READ_ENABLE, GPIO_OUTPUT | GPIO_ACTIVE_LOW);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGE_SPEED, GPIO_OUTPUT | GPIO_ACTIVE_LOW);

    ret |= battery_enable_read();
    ret |= battery_set_slow_charge();

    return ret;
}

int battery_disable_pins()
{
    int ret = 0;

    // ADC
    if (!device_is_ready(adc_battery_dev))
    {
        LOG_ERR("ADC device not found!");
        return -EIO;
    }

    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGING_ENABLE, GPIO_DISCONNECTED);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_READ_ENABLE, GPIO_DISCONNECTED);
    ret |= gpio_pin_configure(gpio_battery_dev, GPIO_BATTERY_CHARGE_SPEED, GPIO_DISCONNECTED);

    return ret;
}

I don't need callbacks for charging start and stop for the device I was developing but I will use the lib on future projects for sure!