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
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With