How to measure batter 118650 with adc internal

quangminh.le0701
Posts: 6
Joined: Mon Jul 01, 2019 2:55 pm

How to measure batter 118650 with adc internal

Postby quangminh.le0701 » Wed Jul 03, 2019 9:16 am

i want to measure battery 3.0 min/3.6 norminal/ 4.2 max. my battery is 3.6 now. follow the doc the internal adc have 0db-->1.1 max sclae, 11db for 3.9 max sclae.
1st) i power up board by usb, gpio6 wiring to +battery, ground to ground, no divider set 11db for 3.9 max scale like the code. i hope i can get adc value ~~550 for 3.6v but it's always 3.9v.
2nd)i power up board by usb, gpio6 wiring to +battery, ground to ground, divider 4.2-->27k-->measure here-->10k-->ground. set 11db for 3.9 max scale like the code. get 3.66v seem good.
3rd)i power up board by usb, gpio6 wiring to +battery, ground to ground, no divider set 0db for 1.1 max scale like the code. it's always 2047 for max adc resolution, like 1st case.
I dont get the point, i think if i use max scale 3.9, i apply 3.6v in adc pin, i think i will get adc value <2047. or anny voltage above 3.3v i apply to adc will return 2047

Code: Select all

#include <driver/adc.h>

float battery_read()
{
    //read battery voltage per %
    long sum = 0;                  // sum of samples taken
    float voltage = 0.0;           // calculated voltage
    float output = 0.0;            //output value
    const float battery_max = 3.6; //maximum voltage of battery
    const float battery_min = 3.0; //minimum voltage of battery before shutdown

    float R1 = 27000.0; // resistance of R1 (100K) 
    float R2 = 10000.0;  // resistance of R2 (10K)

    for (int i = 0; i < 500; i++)
    {
        sum += adc1_get_voltage(ADC1_CHANNEL_0);
        delayMicroseconds(1000);
    }
    // calculate the voltage
    voltage = sum / (float)500;
    Serial.println(voltage);
    voltage = (voltage * 3.9) / 2047.0; //for internal 3.9v reference
    // use if added divider circuit
    //voltage = voltage / (R2/(R1+R2));//uncomment for no divider	
    //round value by two precision
    voltage = roundf(voltage * 100) / 100;
    Serial.print("voltage: ");
    Serial.println(voltage, 2);
    output = ((voltage - battery_min) / (battery_max - battery_min)) * 100;
    if (output < 100)
        return output;
    else
        return 100.0f;
}

void setup()
{
    adc1_config_width(ADC_WIDTH_11Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11); //set reference voltage to internal
    Serial.begin(9600);
}

void loop()
{
    Serial.print("Battery Level: ");
    Serial.println(battery_read(), 2);

    delay(1000);
}

wyattisawesome
Posts: 2
Joined: Sun Jul 07, 2019 4:16 am

Re: How to measure batter 118650 with adc internal

Postby wyattisawesome » Sun Jul 07, 2019 4:40 am

I don't fully understand your questions but I can share some info that maybe can help (some of this you may know):

1. If you're using a lipo battery you should use a protection circuit and not rely on the code to shut it off once it is discharged/overcharged past a certain level.

2. Using a voltage divider and the internal ADC wont give you a perfectly accurate reading of the capacity of your lipo battery. Lipo's drain at a exponential rate as opposed to a linear one so you would have to do some testing and find a formula that works to convert any voltage drain to an accurate percentage. This exponential drop is fast at the end of the batter life however and wouldn't let you give an accurate 0-100% read out over its life and rather it would more or less indicate you when it is low, okay, and fully charged.

3. If you are planning on charging the lipo battery with the ESP you will need separate circuitry for this and cannot charge it directly from the ESP.

4. To accurately read a lipo you need some kind of lipo fuel gauge otherwise if knowing when it is low, good, and charged is enough for you, using something like a TP4056 is a good low cost solution.

Who is online

Users browsing this forum: No registered users and 107 guests