Heltec Wifi LoRa V2 battery management

I have some doubt about the discharge protection.
I have tested and the board did not cut the battery power when it reached 2.98V (measured with a multimeter). It is common practice to not allow a battery to go below 3.2 or 3V at worst to avoid damage. What is the voltage at which the power management chip cut the power?

Regarding the voltage measurement by the ESP32, I have found something that is working good for me, have a look here: Heltec battery power example not working

There is only charging protection on the development board, and no discharge protection. HelTec has a battery that matches the development board, which has discharge protection, and the discharge cut-off voltage is 2.75V. If you have not purchased a HelTec battery, you should check the discharge cut-off voltage of your battery.

Yes I also have a ā€œ1000 mAhā€ battery (more 650 in reality) that was sold with the board, not sure it was manufactured by Heltec as it does not have their brand on it but is seems it has cut out voltage at around 2.75 V which is a bit too low to be really safe for the battery but saying that the board has battery management is a bit an overstatement if it only has overcharge protection and not over discharge.

Hiā€¦It uses a special power management chip that can enable/disable power for parts of the board. I am not aware of its lowest possible current during deep-sleep though. If you do not need the GPS then this board is relatively expensive.

pcb design for manufacturing checklist

Hi, I am using Heltec LoRa Stick and want to calculate battery percentage through inbuilt method i.e through pin 13. I have attached 4500mAh, 3.7V battery. I tried your battery code and I am getting " you can see OLED printed OLED initial done! " on serial monitor. Can kindly someone guide me where I am wrong?

Hi, I am using Heltec LoRa Stick and want to calculate battery percentage through inbuilt method i.e through pin 13. I have attached 4500mAh, 3.7V battery. I tried your battery code and I am getting " you can see OLED printed OLED initial done! " on serial monitor. Can kindly someone guide me where I am wrong?

Hi, Iā€™m using Heltec LoRa Stick lite too (v 2.1). Iā€™m not able to read the battery level or convert it into voltage. For example I tried with 3,6V and the analog read result on pin 37 in digit was 822. With the old version of the stick (pin 13) the analog read result (in digit) for the same voltage was 1964. (same sketch and pin 21 LOW). Thankyou

Iā€™ve read the whole post and Iā€™d like to know, finaly how can I read the battery voltage on my Helte Esp32 LoRa V2, trought the pin 37, and detect when 5V charging power supply pin is disconnected.

Iā€™ve already tested the codes above, and the Jeff McClain code worked a little bit bad, and one another code I got from github ā€œbattery readā€ worked better but is an extensive code that I canā€™t include on my current sketch.

Does anyone know the easyest way to measure and detect whem USB or 5V power supply is disconnected?

Thanks to everyone.

true, i have the same issueā€¦ iā€™m still coming up with and idea how to deal with this.

Hello, I recently had to work through the battery measurement issue myself and it seems that there is still considerable questions about how it works. Bits and pieces of useful data were available on the discussion but the same questions kept coming up on this group and other groups. I am new to Arduino and even the ESP32 board but I am not new to battery powered devices and believe my input can help resolve the issue because I noticed these key points were not always made together:

  1. Knowing which version of the board you are using is important because version 2.1 changed the pin connected to the battery (I/O Pin 37) to solve a problem it was causing with the WiFi.
    https://heltec-automation-docs.readthedocs.io/en/latest/esp32%2Barduino/wifi_kit_32/hardware_update_log.html

  2. The divider is needed to correctly read the battery voltage. The maximum battery voltage can be over 4 volts (typically 3.7 V when fully charged) and the ADC can only measure up to 3.3 V.

  3. Most LiIon batteries have built in protection to keep them from over-charging, over-discharghing, shorting out and overheating. The batteries will not self-destruct if they have been discharged, they simply disconnect themselves from the circuit and will recover after a bit of charging. They trickle charge until the internal voltage is high enough for them to safely recharge at the fast rate.

  4. One last point to make is that the P-Ch FET connected to the divider there will still be some leakage current through the ADC pin which has a protection diode connected to 3.6V. The current will be (VBATT - 3.6) / 220K or ~5 uA. The leakage current will drop once the battery voltage drops below 3.6 Volts.

After some research and experimentation I was able to get my WIFI Kit 32 to reliably measure the battery voltage by doing the following:

void Battery::measure(){
  float dividerRatio = 3.2; 	// Used measured values to determine the ratio
  Serial.println("Inside Battery::Measure");

// 3.3 Volts is the theoretical value. The actual value depends on the 
// board's voltage regulator.
  float FS = 3.3 / 4095;		// Calculate the bit weight from Full Scale 
  uint16_t MULT = 1000; 		// Convert to milliVolts
  delay(10);					// Allow things to stabilize

// Make a measurement without the divider.
  uint16_t c  =  analogRead(bat.measure_pin)*FS*MULT;
  Serial.println("Batt V (undivided): " + String( c )); 
  digitalWrite(bat.divider_on_pin, LOW);
  delay(10);

// Make a measurement with the divider.
  c  =  analogRead(bat.measure_pin)*XS*MUL;
  Serial.println("Batt V (divided): " + String( c )); 
  
// Multiply the measured voltage by the divider ratio
  Serial.println("Batt V (calibrated): " + String( c*divider )); 
  digitalWrite(bat.divider_on_pin, HIGH); // open divider
  bat.voltage = c*divider;

Without the battery plugged in I measured about 5.1 Volts which is the USB voltage. With a battery connected the voltage will be below 4.1 volts depending on the batteries charge level.

Here is the Serial ouptput:
Inside Battery::Measure
Batt V (undivided): 3300
Batt V (divided): 1691
Batt V (calibrated): 5411.20

1 Like

I loaded your code on a V2.1 board, and itā€™s hanging after it sets ADC1_CHANNEL_1 to open drain. Not sure why that would be. FWIW, USB is connected, but no battery. Hereā€™s the output.

ADC Calibration: eFuse Vref
VBATT_GPIO LOW()
ADC1_CHANNEL_1 OPEN_DRAIN()
<nothing after this>

Modification to your code:

uint16_t ReadVBatt ()
{
  uint16_t reading = 666;

  Serial.printf ("VBATT_GPIO LOW()\n");
  delay (200);
  digitalWrite (VBATT_GPIO, LOW);

  delay (ADC_READ_STABILIZE);

  Serial.printf ("ADC1_CHANNEL_1 OPEN_DRAIN()\n");
  delay (200);
  pinMode (ADC1_CHANNEL_1, OPEN_DRAIN);

  Serial.printf ("adc1_get_raw()\n");
  delay (200);
  reading = adc1_get_raw (ADC1_CHANNEL_1);

  Serial.printf ("ADC1_CHANNEL_1 INPUT()\n");
  delay (200);
  pinMode (ADC1_CHANNEL_1, INPUT);

  Serial.printf ("esp_adc_cal_raw_to_voltage()\n");
  delay (200);
  uint16_t voltage = esp_adc_cal_raw_to_voltage (reading, adc_chars);
  voltage *= VOLTAGE_DIVIDER;

  Serial.printf ("Returning...\n");
  delay (200);

  return voltage;
}

I see what the problem is here. Youā€™re calling pinMode on an ADC channel variable, which doesnā€™t do what one would logically expect (Arduino pin mapping is an utter train wreck, as far as Iā€™m concerned).

Youā€™re setting pin 1 to open drain on a V2 module, which is the UART0 TXD line, and causes serial output to cease (although the program is still running). I think you want

pinmode (37, OPEN_DRAIN);

and

pinMode (37, INPUT);

for this to work as expected.

Thank you very much Jeff. I was able to get battery monitoring working on a wireless stick v2.1 and wifi lora v2.0 as well as a version 3 with some changes.

Your post is nearly exactly 3 years old, but the examples from heltec and the pinout documentation pdf has not improved at all. I was using an external battery monitoring solution for quite a while until getting a V3 device recently which got me into trying to use the internal circuits again. (Mostly because I had to rewrite my whole Sketch as moving from V2 to V3 changed about everything.

The heltec website outright lies about this: ā€œThe newly launched V3 version has the same pin sequence as the V2 versionā€ Then why did I have to change the oled settings, half of the pin definitions and cannot and a completely different lora library? (I understand its because of the different chip, but you do not offer a working example to communicate with your own older devices) Documentation, images and silkscreen do not fit at all.

Seeing other posts in the forum, especially the heltec nightmares thread, this will have been the last heltec device I will purchase. If the documentation would improve in the future I might think about it again, but this does not seem to be the case so far.

Again, thank you Jeff! You saved me time, code complexity and cables. I wish this wouldnt have been needed.

Can you share the code for wifi lora32 v3.1? I could not get it to read the battery.

I am almost new to these issues. Should I make my own voltage divider circuit to read the battery level or is it enough to just write code? If I need a voltage divider, can you share the wiring diagram for v3.1? Thank you.

Perhaps have a look at this discussion on the subject of battery voltage measurements.

Wow. Thank you. That is very useful.

I think there are some problems with my v3 device. for example: when only battery connected, the device always shows wakeup cause is ā€˜0ā€™ after waking up from deep sleep for 30 seconds and ā€˜RTC_DATA_ATTR int16_t n = 0;ā€™ this n variable is always ā€˜0ā€™ in RTC memory. However, the device always shows wakeup cause is ā€˜4ā€™ after waking up from deep sleep for 15~ and lower seconds and the variable ā€˜nā€™ can be changed. So the timer triggering works well but the rtc memory and wake up reason does not work well for more than 15 seconds. I think the device cuts power after a certain time when the battery is connected but everthing works well when the usb is connected.

RTC_DATA_ATTR int16_t n = 0;
void setup()
{
	esp_sleep_wakeup_cause_t wakeup_reason;
	wakeup_reason = esp_sleep_get_wakeup_cause();

	Serial.begin(115200);

	// Display
	pinMode(Vext, OUTPUT);	 // turn on external voltage
	digitalWrite(Vext, LOW); // turn on external voltage
	oled.init();

	spf("\nAwaking.. reason: %d  n: %d\n", wakeup_reason, n);

	oled.drawString(0, 0, "reason: " + String(wakeup_reason) + " n: " + String(n));
	oled.display();

	delay(2000);

	pinMode(Vext, OUTPUT);	  // turn on external voltage
	digitalWrite(Vext, HIGH); // turn on external voltage
	Serial.flush();

	n++;

	delay(500);
	esp_sleep_enable_timer_wakeup(30 * uS_TO_S_FACTOR);
	esp_deep_sleep_start();
}

void loop()
{
}

void VextON(void) {

pinMode(Vext, OUTPUT);

digitalWrite(Vext, LOW);

} Iā€™m not expert, but you are turning off the external voltage.

I have two same devices. One of them works great. Other one doesnā€™t work properly when the battery is connected only. I think some tiny components broken like capacitors.