Esp32 Battery Voltage Calculation Issues

Hi all. I'm having some issues calculating the battery of my esp32 and was wondering if some of you smart people can help. I am using the esp32-C3-pico found here:C3 pico — WEMOS documentation

From the pinout you can see gpio pin3 should be VBAT. So in my code, I am doing an analogRead in setup and then saving the value to an integer called analogPinVolt. I am then passing it to a function called batteryLife to calculate the battery life as shown:

#define VOLTAGE_PIN 3
int batteryCharge;

// Calculate Battery Life
void batteryLife (int analogPinVolt){
  float batteryVoltage;
  float batteryLevel;
  batteryVoltage = 2*3.3/4095*analogPinVolt;
  if (batteryVoltage<3.5){
     batteryVoltage = 3.5;
  }
  if (batteryVoltage>4.2){
     batteryVoltage = 4.2;
  }
  batteryLevel = 3.5631457616E3*pow(batteryVoltage,4)-5.4787671494E4*pow(batteryVoltage,3)+3.1541375900E5*pow(batteryVoltage,2)-8.0559293115E5*batteryVoltage+7.7008357786E5;
  
batteryCharge = static_cast<int>(batteryLevel);
}

void setup() {
...
int analogPinVolt = analogRead(VOLTAGE_PIN);
     batteryLife(analogPinVolt);

I started to troubleshoot and it seems the "int analogPinVolt = analogRead(VOLTAGE_PIN);" in the setup subroutine is giving me all sorts of values. Almost seems random. That pin is connected to a pushbutton but I do not set the pinMode until after the analogRead. The idea is I only need to know the battery power at startup or after waking from deep sleep. The question is...could having a pushbutton connected to pin 3 be messing with the voltage? Is there any way to fix this other than removing the bushbutton from pin3 (I have no free gpios).

Also, so doing things like unplugging the usb and plugging in the battery have an effect, but if I put it to sleep and then wake it up, it always shows full battery.
Fish

That is a sign of a floating input.

The schematic shows a jumper that connects the voltage divider to the GPIO3 pin. Is that jumper closed or open?

Hi jremington. If you look at the second photo (bottom of the board) there is a pad that is marked (Battery to IO# (A3). Is that the jumper? Do I put a 0 Ohm resistor across the chevron on the pad to jump it (or maybe a small dab of solder)? Sorry...kinda new to the hobby.

Fish

That will do the job. You probably should not plan on using IO3 with a switch, unless you use analogRead() to detect switch closure (to GND).

Will it prevent me from using it as a gpio?

Yes.

dang! Well...appreciate the help. I'll figure out a way to free up a pin.

You could still use IO3 to detect a button push, as long as the button is normally open and connects to GND when pressed.

analogRead() should return 0 (or very close to that) while the button is pushed.

oh...so if after the anaolgRead, If I set pinMode(3, INPUT_PULLUP); then I could still use as a pushbutton? That's exactly what I wanted to use it for!

Do NOT use pinMode(). Just use analogRead() to get a value.
Nonzero = measuring battery voltage.
Zero = pushbutton pressed.

It isn't all over the place, so I think I am close. When I plug the battery in, I get a reasonable reading now and it is stable. However, when the esp32 goes into deep sleep and then wakes up, the reading I get is 4095. Why is it maxing out the read on wakeup?

No idea. Read the voltage twice and see if you get the same number.

I put the line analogPinVolt = analogRead(VOLTAGE_PIN); in my loop and it seems to be stuck on 4095. I have nothing connected to that pin and removed all references to it in my code. However, If I remove the usb and unplug the battery then plug it back in, I get a value of 2763ish but I see it updating. If I then put the module to sleep and wake it up, it goes to 4095 and stays there.

Post on the ESP32 forums, or ask the people who made the WEMOS C3 Pico.

The Espressif corporation is the main actor responsible for the ESP32 Arduino implementation.

o.k. got this working. The issue is the esp32-C3 isn't the same as the esp32-Sx in terms of available wakeup pin bitmask options. On the C3 you have the ability to hold the pins high with a pullup resistor during deep sleep and wake up when one of the pins goes low which is what I was doing. However, this means once the module goes to sleep, the pin gets pulled up and stays high even after the controller awakens and runs through setup. So once it goes to sleep, you cannot do an analogRead i.e. the pin doesn't reset (pinMode (GPIO#, 0x03) doesn't work ). So I just took the pin in question out of the bitmask for the pins that can awaken the esp32 and that fixed it.

Hi,

the ESP32-C3 has a dedicated function to read the voltage and give a results as millivolts.
Very usefull!
You only need to know your division factor and put it in the calculation!
To me the factor is 1,943, very close to "2" as I use 2 identical resistors to lower the voltage. The 1,943 was obtain by measuring the voltage with a multimeter at the exit of the battery, and after the resistor. Then I can include it in my code.

there is also a "blank" measure before the effective measure. Not sure if it is very usefull but it is an old habit from my previous arduino boards;

Pretty simple in my opinion. I hope you can use it! :+1:

void LECTURE_BATTERIE() {
  // lecture analogique compensée sur A0: fournit la tension en millivolt

  pinMode(Pin_batterie, INPUT);  // lecture voltage batterie par pont diviseur
  analogRead(Pin_batterie);
  delay(2);
  batterie = analogReadMilliVolts(Pin_batterie) * 1.943;  // *1,943 = ration pont diviseur (=1/2)
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.