Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to measure battery voltage with internal adc ESP32

i'm doing wireless sensor node using (esp32, DHT11, soil moisture and nrf24l01) and i want to add an battery to supply those sensors, also need to measure battery voltage. For the battery, voltage always change to cant use as a Vcc reference, so i find there is an internal reference voltage. Could anyone done with this give me some instruction. Thank you

i'm gonna use LIFEPO4 3.3v normaly (3.6v at max) or 18650 3.7v/4.2v max

like image 994
Quang Minh Lê Avatar asked Jul 01 '19 09:07

Quang Minh Lê


People also ask

Is there a way to monitor the battery voltage with the ADC?

An ADC can be used for measuring battery voltage and current. Battery voltage is directly measured by the ADC, while current is measured indirectly using a current sensor. The current sensor has a resistive component—when current flows on the current sensor, it produces a voltage drop.

Can ESP32 measure voltage?

Reading an analog value with the ESP32 means you can measure varying voltage levels between 0 V and 3.3 V. The voltage measured is then assigned to a value between 0 and 4095, in which 0 V corresponds to 0, and 3.3 V corresponds to 4095.

How do you use ADC in ESP32?

The simplest way to provide variable analog voltage is with the help of a Potentiometer. Connect the ends of POT to 3.3V and GND of ESP32 Development Board and connect the Wiper to any of the ADC Pin. To keep things simple, I used the ADC1_CH0 i.e., GPIO 36 (A0) as the ADC Pin.


1 Answers

According to docs:

The default ADC full-scale voltage is 1.1V. To read higher voltages (up to the pin maximum voltage, usually 3.3V) requires setting >0dB signal attenuation for that ADC channel.

So set it to zero for 1.1v; next, you can read the voltage (in a loop for better accuracy) and then convert it to a valid voltage and find the percentage of battery level.

In the below example, the function would return the percentage of battery level. Remember to edit battery_max and battery_min based on your battery voltage levels. I assumed that you connect the battery to ADC1 channel 0 (GPIO 36).

Also, I recommend you create a resistor divider circuit to reduce the voltage level. If your input power supply drops down, the Arduino will feed directly from Analog input, which is undesirable. Remember that your voltage level should not exceed above 3.9v.

#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.3; //minimum voltage of battery before shutdown

    float R1 = 100000.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;
    voltage = (voltage * 1.1) / 4096.0; //for internal 1.1v reference
    // use if added divider circuit
    // voltage = voltage / (R2/(R1+R2));
    //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_12Bit);
    adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_0db); //set reference voltage to internal
    Serial.begin(9600);
}

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

If you add a divider circuit, you need to change battery_min and battery_max according to the new output of the divider circuit.

like image 153
Masoud Rahimi Avatar answered Sep 21 '22 17:09

Masoud Rahimi