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
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 I set it to zero for 1.1v, next you can simply 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 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 to create a resistor divider circuit to reduce the voltage level because if your input power supply drops down, the Arduino would feed directly from Analog input which is undesirable, also 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 divider circuit change battery_min
and battery_max
according to the new output of divider circuit.