# Measure battery with adc internal in esp32

my circuit to measure battery right now is esp32, nrf24l01, and 18650. i powered up esp32 with 18650 3.6v norminal/4.2 max battery. run a voltage divider 100k, 27k then it's 0.893v a measure point. at 3.6v measure point like ~0.72.

i use internal 1.1v adc but why i only receive ~3v at monitor

``````adc1_config_width(ADC_WIDTH_BIT_11);
{
long sum = 0;                  // sum of samples taken
float voltage = 0.0;           // calculated voltage
float output = 0.0;            //output value
const float battery_max = 4.2; //maximum voltage of battery
const float battery_min = 3.0; //minimum voltage of battery before shutdown

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

for (int i = 0; i < 100; i++)
{
delayMicroseconds(1000);
}
// calculate the voltage*/

voltage = sum / (float)100;
Serial.println(voltage);
voltage = (voltage *1.1) / 2047.0; //for internal 1.1v reference
// use if added divider circuit
voltage = voltage / (R2/(R1+R2));
}
``````

``````// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
// set up A:D channels
/*
When VDD_A is 3.3V: 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V
*/

{
String localBuffer;
localBuffer.reserve ( StringBufferSize300 );
int iBit = 1;
float offSET = 1.0f;
float r1 = 100800.0f; // R1 in ohm, 100k = 100,800.0 //
float r2 = 38780.0f; // R2 in ohm, 38k = 38000.0 //actual 38780K
float uPvolts = 3.3f;
// ADC1 channel 0 is GPIO36
// ADC1 channel 1 is GPIO37
// ADC1 channel 6 is GPIO34
// to get resistor R2 go to:
// http://www.ohmslawcalculator.com/voltage-divider-calculator
//   used 12 volts for the input voltage to calculate R2, used 100K for R1
for (;;)
{
// group handle, WaitForBits, ClearOnExitBit, WaitForAllBits, TicksToWait
iBit = iBit << 1;
if ( iBit == 1073741824 )
{
if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
{
Vbatt_LIDAR += ( ((( uPvolts * adc1_get_raw(ADC1_CHANNEL_6)) / ADbits) / r2 * ( r1 + r2)) + offSET );
Vbatt_LIDAR = Vbatt_LIDAR /2; // average readings
xSemaphoreTake( sema_Time, xSemaphoreTicksToWait );
fMakeTimeStamp ( localBuffer );
xSemaphoreGive( sema_Time ); // give up semaphore
} // if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
iBit = 1;
} // if ( iBit == 1073741824 )
}
}
``````

Is what I use to read a supply voltage, works pretty good.

1 Like

Idahowalker:

``````// https://dl.espressif.com/doc/esp-idf/latest/api-reference/peripherals/adc.html
``````

// set up A:D channels
/*
When VDD_A is 3.3V: 11dB attenuation (ADC_ATTEN_11db) gives full-scale voltage 3.9V
*/

{
String localBuffer;
localBuffer.reserve ( StringBufferSize300 );
int iBit = 1;
float offSET = 1.0f;
float r1 = 100800.0f; // R1 in ohm, 100k = 100,800.0 //
float r2 = 38780.0f; // R2 in ohm, 38k = 38000.0 //actual 38780K
float uPvolts = 3.3f;
// ADC1 channel 0 is GPIO36
// ADC1 channel 1 is GPIO37
// ADC1 channel 6 is GPIO34
// to get resistor R2 go to:
// Voltage Divider Calculator
//   used 12 volts for the input voltage to calculate R2, used 100K for R1
for (;
{
// group handle, WaitForBits, ClearOnExitBit, WaitForAllBits, TicksToWait
iBit = iBit << 1;
if ( iBit == 1073741824 )
{
if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
{
Vbatt_LIDAR += ( ((( uPvolts * adc1_get_raw(ADC1_CHANNEL_6)) / ADbits) / r2 * ( r1 + r2)) + offSET );
Vbatt_LIDAR = Vbatt_LIDAR /2; // average readings
xSemaphoreTake( sema_Time, xSemaphoreTicksToWait );
fMakeTimeStamp ( localBuffer );
xSemaphoreGive( sema_Time ); // give up semaphore
} // if ( xSemaphoreTake( sema_AnalogVoltRead_LIDAR, xSemaphoreTicksToWait ) == pdTRUE )
iBit = 1;
} // if ( iBit == 1073741824 )
}
``````