meshtastic / firmware

Meshtastic device firmware
https://meshtastic.org
GNU General Public License v3.0
3.37k stars 825 forks source link

Support battery voltage level on Heltec Lora 32 boards #442

Closed Dafeman closed 2 years ago

Dafeman commented 4 years ago

I don't have this board but it appears to have the ability to measure battery voltage based on the schematic.

More information discussed here.

geeksville commented 4 years ago

This issue has been mentioned on Meshtastic. There might be relevant details there:

https://meshtastic.discourse.group/t/heltec-board-is-deep-discharging-batteries/1349/9

mc-hamster commented 3 years ago

Pin 13 is shared with the wifi radio. Reading battery voltage won't be possible while the wifi radio is powered on.

Dafeman commented 3 years ago

Hmm, yea it seems the whole set of ADC2 pins are unusable https://www.esp32.com/viewtopic.php?t=8728

mc-hamster commented 3 years ago

It is usable, but it would mean periodically turning off the radio to take an adc reading and then turning the radio back on.

superjasiek commented 3 years ago

Trying to solve it out and make battery monitoring to work with heltec. According to this discussion Manufacturer changed reading voltage pin to 37. I was trying to compile heltec firmware with added battery_pin 37 but unfortunately after upload with platformIO i get this error Guru Meditation Error: Core 1 panic'ed (LoadProhibited) and device is keep restarting in loop. Here is also example of voltage calculating for heltec. Anyway thanks in advance for any tips and thank you for your grate work! Take care!

geeksville commented 3 years ago

wow - just read that thread. they really messed that transition up didn't they!

re: guru medition Just to check: if you build and run a 'clean' version of the heltec code using your repo that installs and runs okay?

superjasiek commented 3 years ago

Yep I think there is something wrong with circuit of battery or documentation - many heltec users have problems with reading battery voltage. About making clean build - when i was trying to upload it I had same error (without changing pins), but i will confirm that in the afternoon. All best, Jan

superjasiek commented 3 years ago

ok so here are some test results:

    • makeing clean build works ok
    • when i change configuration.h and add #define BATTERY_PIN 13 no changes but also log shows that battery is not present
    • when i change configuration.h and add #define BATTERY_PIN 37 and gps #define GPS_TX_PIN 38 device is somehow geting into deep sleep (?) and the log (without battery) looks like this:
??:??:?? 0 Filesystem files:
??:??:?? 0   /prefs/db.proto      
??:??:?? 0   /prefs/radio.proto   
??:??:?? 0   /prefs/channels.proto
??:??:?? 0 I2C device found at address 0x3c
??:??:?? 0 ssd1306 display found
??:??:?? 0 done
??:??:?? 0 Meshtastic hwvendor=5, swver=1.2.11, hwver=unset
??:??:?? 0 Setting random seed 2378870289
??:??:?? 0 Total heap: 254332
??:??:?? 0 Free heap: 222076
??:??:?? 0 Total PSRAM: 0
??:??:?? 0 Free PSRAM: 0
??:??:?? 0 NVS: UsedEntries 101, FreeEntries 529, AllEntries 630
??:??:?? 0 Initial packet id 692095387, numPacketId 4294967295  
??:??:?? 0 Setting default channel and radio preferences!       
??:??:?? 0 Expanding short PSK #1
??:??:?? 0 Wanted region 0, using Unset
??:??:?? 0 Loading /prefs/db.proto
??:??:?? 0 Loaded saved preferences version 11
??:??:?? 0 Loading /prefs/radio.proto
??:??:?? 0 Loading /prefs/channels.proto      
??:??:?? 0 Expanding short PSK #1      
??:??:?? 0 Wanted region 2, using EU433
??:??:?? 0 region=2, NODENUM=0xd1dc6dc4, dbsize=2
??:??:?? 0 Using analog input for battery level
??:??:?? 0 Read RTC time as 0 (cur millis 180) quality=0
??:??:?? 0 WANT GPS=1
??:??:?? 0 Setting GPS power=1
??:??:?? 2 ERROR: No UBLOX GPS found
??:??:?? 2 Hoping that NMEA might work
??:??:?? 2 WANT GPS=1
??:??:?? 2 External Notification Plugin Disabled
??:??:?? 2 Initializing Store & Forward Plugin - Enabled as Router
??:??:?? 2 Device doesn't have PSRAM.
??:??:?? 2 Store & Forward Plugin - Aborting Startup.
??:??:?? 2 Turning on screen
??:??:?? 2 Starting meshradio init...
??:??:?? 2 (bw=125, sf=12, cr=4/8) packet symLen=32 ms, payloadSize=16, time 2269 ms
??:??:?? 2 Set radio: name=LongSlow, config=3, ch=2, power=0
??:??:?? 2 Radio myRegion->freq: 433.174988
??:??:?? 2 Radio myRegion->spacing: 0.200000
??:??:?? 2 Radio myRegion->numChannels: 8
??:??:?? 2 Radio channel_num: 2
??:??:?? 2 Radio frequency: 433.574982
??:??:?? 2 Short packet time: 2269 msec
??:??:?? 2 Set radio: final power level=17
??:??:?? 2 RF95 init result 0
??:??:?? 2 Radio init succeeded, using RF95 radio
??:??:?? 2 PowerFSM init, USB power=0
[D][esp32-hal-cpu.c:189] setCpuFrequencyMhz(): PLL: 320 / 4 = 80 Mhz, APB: 80000000 Hz
??:??:?? 2 [Power] Battery: usbPower=0, isCharging=0, batMv=0, batPct=0
??:??:?? 2 [Screen] Screen: Started...
??:??:?? 2 [GPS] publishing GPS lock=0
??:??:?? 2 [GPS] No GPS lock
??:??:?? 2 [GPS] got gps notify time=0, lat=0, bat=0
??:??:?? 2 [GPS] DB update position node=0xd1dc6dc4 time=0, latI=0, lonI=0
??:??:?? 2 [GPS] Node status update: 2 online, 2 total
??:??:?? 2 [SerialPlugin] Serial Plugin Disabled
??:??:?? 2 [StoreForwardPlugin] Iterating through the seen nodes in receivedRecord...
??:??:?? 2 [StoreForwardPlugin] Iterating through the message history...
??:??:?? 2 [StoreForwardPlugin] Message history contains 0 records
??:??:?? 2 [StoreForwardPlugin] StoreForwardPlugin::historyReport runtime - 0 ms
??:??:?? 2 [RangeTestPlugin] Range Test Plugin - Disabled
Transition powerFSM transition=boot timeout, from=BOOT to=ON
??:??:?? 5 [PowerFSM] Setting bluetooth enable=1
Pre BT: 211532 heap size
??:??:?? 5 [PowerFSM] Starting bluetooth
??:??:?? 5 [Screen] Done with boot screen...
??:??:?? 5 [Screen] showing standard frames
??:??:?? 5 [Screen] Showing 0 plugin frames
??:??:?? 5 [Screen] Total frame count: 35
??:??:?? 5 [Screen] Added plugins.  numframes: 0
??:??:?? 5 [Screen] Finished building frames. numframes: 4
??:??:?? 5 [Screen] Setting fast framerate
??:??:?? 6 [Screen] BLE task running
??:??:?? 6 [Screen] registered service 0x1800 with handle=1
??:??:?? 6 [Screen] registered service 0x1801 with handle=6
??:??:?? 6 [Screen] registered service 6ba1b218-15a8-461f-9fa8-5dcae273eafd with handle=10
??:??:?? 6 [Screen] registered service cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30 with handle=18
[D][esp32-hal-i2c.c:1345] i2cProcQueue():  Gross Timeout Dead start=0x180b, end=0x180b, =0, max=50 error=1
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbe2e8
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffbc240
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffbc2a0 bits=10
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffbc2d0
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffd8dcc
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=1
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=0
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=1
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x00000000
[I][esp32-hal-i2c.c:311] i2cDumpDqData(): Debug Buffer not Enabled
[I][esp32-hal-i2c.c:354] i2cDumpInts(): Debug Buffer not Enabled
??:??:?? 6 [Screen] BLE advertisting type=0, Private=0, Device Address: 69:f0:08:d1:dc:6d

??:??:?? 6 [Screen] Setting idle framerate
??:??:?? 12 [StoreForwardPlugin] Iterating through the seen nodes in receivedRecord...
??:??:?? 12 [StoreForwardPlugin] Iterating through the message history...
??:??:?? 12 [StoreForwardPlugin] Message history contains 0 records
??:??:?? 12 [StoreForwardPlugin] StoreForwardPlugin::historyReport runtime - 0 ms
??:??:?? 22 [Power] Battery: usbPower=0, isCharging=0, **batMv=2500**, batPct=0
Transition powerFSM transition=LowBat, from=ON to=SDS
??:??:?? 22 [Power] Entering deep sleep for 31536000 seconds
??:??:?? 22 [Power] Setting bluetooth enable=0
??:??:?? 22 [Power] advertise complete; reason=29error enabling advertisement; rc=30
??:??:?? 22 [Power] Done shutting down bluetooth
Shutdown BT: 225560 heap size
??:??:?? 22 [Power] GPS prepare sleep!
??:??:?? 22 [Power] GPS deep sleep!
??:??:?? 22 [Power] WANT GPS=0
??:??:?? 22 [Power] Turning off screen
??:??:?? 22 [Power] Saving /prefs/db.proto
??:??:?? 23 [Power] Saving /prefs/radio.proto
??:??:?? 23 [Power] Saving /prefs/channels.proto
??:??:?? 23 [Power] Setting GPS power=0

and log with baterry attached:

??:??:?? 0 Filesystem files:
??:??:?? 0   /prefs/db.proto
??:??:?? 0   /prefs/radio.proto
??:??:?? 0   /prefs/channels.proto
??:??:?? 0 I2C device found at address 0x3c
??:??:?? 0 ssd1306 display found
??:??:?? 0 done
??:??:?? 0 Meshtastic hwvendor=5, swver=1.2.11, hwver=unset
??:??:?? 0 Setting random seed 2668506085
??:??:?? 0 Total heap: 254332
??:??:?? 0 Free heap: 222076
??:??:?? 0 Total PSRAM: 0
??:??:?? 0 Free PSRAM: 0
??:??:?? 0 NVS: UsedEntries 101, FreeEntries 529, AllEntries 630
??:??:?? 0 Initial packet id 733692157, numPacketId 4294967295
??:??:?? 0 Setting default channel and radio preferences!
??:??:?? 0 Expanding short PSK #1
??:??:?? 0 Wanted region 0, using Unset
??:??:?? 0 Loading /prefs/db.proto
??:??:?? 0 Loaded saved preferences version 11
??:??:?? 0 Loading /prefs/radio.proto
??:??:?? 0 Loading /prefs/channels.proto
??:??:?? 0 Expanding short PSK #1
??:??:?? 0 Wanted region 2, using EU433
??:??:?? 0 region=2, NODENUM=0xd1dc6dc4, dbsize=2
??:??:?? 0 Using analog input for battery level
??:??:?? 0 Read RTC time as 0 (cur millis 181) quality=0
??:??:?? 0 WANT GPS=1
??:??:?? 0 Setting GPS power=1
??:??:?? 2 ERROR: No UBLOX GPS found
??:??:?? 2 Hoping that NMEA might work
??:??:?? 2 WANT GPS=1
??:??:?? 2 External Notification Plugin Disabled
??:??:?? 2 Initializing Store & Forward Plugin - Enabled as Router
??:??:?? 2 Device doesn't have PSRAM.
??:??:?? 2 Store & Forward Plugin - Aborting Startup.
??:??:?? 2 Turning on screen
??:??:?? 2 Starting meshradio init...
??:??:?? 2 (bw=125, sf=12, cr=4/8) packet symLen=32 ms, payloadSize=16, time 2269 ms
??:??:?? 2 Set radio: name=LongSlow, config=3, ch=2, power=0
??:??:?? 2 Radio myRegion->freq: 433.174988
??:??:?? 2 Radio myRegion->spacing: 0.200000
??:??:?? 2 Radio myRegion->numChannels: 8
??:??:?? 2 Radio channel_num: 2
??:??:?? 2 Radio frequency: 433.574982
??:??:?? 2 Short packet time: 2269 msec
??:??:?? 2 Set radio: final power level=17
??:??:?? 2 RF95 init result 0
??:??:?? 2 Radio init succeeded, using RF95 radio
??:??:?? 2 PowerFSM init, USB power=0
[D][esp32-hal-cpu.c:189] setCpuFrequencyMhz(): PLL: 320 / 4 = 80 Mhz, APB: 80000000 Hz
??:??:?? 2 [Power] Battery: usbPower=0, isCharging=0, batMv=0, batPct=0
??:??:?? 2 [Screen] Screen: Started...
??:??:?? 2 [GPS] publishing GPS lock=0
??:??:?? 2 [GPS] No GPS lock
??:??:?? 2 [GPS] got gps notify time=0, lat=0, bat=0
??:??:?? 2 [GPS] DB update position node=0xd1dc6dc4 time=0, latI=0, lonI=0
??:??:?? 2 [GPS] Node status update: 2 online, 2 total
??:??:?? 2 [SerialPlugin] Serial Plugin Disabled
??:??:?? 2 [StoreForwardPlugin] Iterating through the seen nodes in receivedRecord...
??:??:?? 2 [StoreForwardPlugin] Iterating through the message history...
??:??:?? 2 [StoreForwardPlugin] Message history contains 0 records
??:??:?? 2 [StoreForwardPlugin] StoreForwardPlugin::historyReport runtime - 0 ms
??:??:?? 2 [RangeTestPlugin] Range Test Plugin - Disabled
Transition powerFSM transition=boot timeout, from=BOOT to=ON
??:??:?? 5 [PowerFSM] Setting bluetooth enable=1
Pre BT: 211532 heap size
??:??:?? 5 [PowerFSM] Starting bluetooth
??:??:?? 5 [Screen] Done with boot screen...
??:??:?? 5 [Screen] showing standard frames
??:??:?? 5 [Screen] Showing 0 plugin frames
??:??:?? 5 [Screen] Total frame count: 35
??:??:?? 5 [Screen] Added plugins.  numframes: 0
??:??:?? 5 [Screen] Finished building frames. numframes: 4
??:??:?? 5 [Screen] Setting fast framerate
??:??:?? 6 [Screen] BLE task running
??:??:?? 6 [Screen] registered service 0x1800 with handle=1
??:??:?? 6 [Screen] registered service 0x1801 with handle=6
??:??:?? 6 [Screen] registered service 6ba1b218-15a8-461f-9fa8-5dcae273eafd with handle=10
??:??:?? 6 [Screen] registered service cb0b9a0b-a84c-4c0d-bdbb-442e3144ee30 with handle=18
??:??:?? 6 [Screen] BLE advertisting type=0, Private=0, Device Address: 69:f0:08:d1:dc:6d

??:??:?? 6 [Screen] Setting idle framerate
??:??:?? 12 [StoreForwardPlugin] Iterating through the seen nodes in receivedRecord...
??:??:?? 12 [StoreForwardPlugin] Iterating through the message history...
??:??:?? 12 [StoreForwardPlugin] Message history contains 0 records
??:??:?? 12 [StoreForwardPlugin] StoreForwardPlugin::historyReport runtime - 0 ms
??:??:?? 22 [Power] Battery: usbPower=0, isCharging=0, **batMv=2159**, batPct=0
Transition powerFSM transition=LowBat, from=ON to=SDS
??:??:?? 22 [Power] Entering deep sleep for 31536000 seconds
??:??:?? 22 [Power] Setting bluetooth enable=0
??:??:?? 22 [Power] advertise complete; reason=29error enabling advertisement; rc=30
??:??:?? 22 [Power] Done shutting down bluetooth
Shutdown BT: 225560 heap size
??:??:?? 22 [Power] GPS prepare sleep!
??:??:?? 22 [Power] GPS deep sleep!
??:??:?? 22 [Power] WANT GPS=0
??:??:?? 22 [Power] Turning off screen
??:??:?? 22 [Power] Saving /prefs/db.proto
??:??:?? 23 [Power] Saving /prefs/radio.proto
??:??:?? 23 [Power] Saving /prefs/channels.proto
??:??:?? 23 [Power] Setting GPS power=0

I've also noticed that when i flash precopiled version straight from new relese Light Sleep functions does not work - for example the screen is constatly on. Sleep function only works when i compile and upload software through platformIO

geeksville commented 3 years ago

ooh that helps! the reason it is entering SDS state is:

??:??:?? 22 [Power] Battery: usbPower=0, isCharging=0, batMv=2159, batPct=0 Transition powerFSM transition=LowBat, from=ON to=SDS

We have a threshold where if the battery drops below that level we consider the battery critically low and to prevent burning out batteries we try to shut everything down (inlcuding the main CPU).

I haven't followed the full thread that was linked on the heltec site, but can you add some debug printing in AnalogBatteryLevel:: getBattVoltage? And check those values against what you read with a multimeter? It sounds to me like either a) the battery sense on your heltec is probably not going to that pin.

(Alas - I don't think I remebered to bring a Heltec with me to taiwan - but if you can't debug this on your board I can ask around locally)

superjasiek commented 3 years ago

Sure i will try to do that but if you can point how to debug AnalogBatteryLevel? You mean python tool - meshtastic --debug AnalogBatteryLevel:: getBattVoltage or add some lines to code of Power.cpp? Threshold level is probably reason of going into sleep mode, but low battery level could be caused by different voltage divider in this case they use R1=100k, R2=220K. I will also try to compile an example script from heltec to measure batt to see if it measures anything ;-) - also noticed that in example script for measuring batt they use two pins - 36 and 37:

void loop()
{
   //WiFi LoRa 32        -- hardare versrion ≥ 2.3
   //WiFi Kit 32         -- hardare versrion ≥ 2
   //Wireless Stick      -- hardare versrion ≥ 2.3
   //Wireless Stick Lite -- hardare versrion ≥ 2.3
   //Battery voltage read pin changed from GPIO13 to GPI37
   adcStart(37);
   while(adcBusy(37));
   Serial.printf("Battery power in GPIO 37: ");
   Serial.println(analogRead(37));
   uint16_t c1  =  analogRead(37)*XS*MUL;
   adcEnd(37);

   delay(100);

   adcStart(36);
   while(adcBusy(36));
   Serial.printf("voltage input on GPIO 36: ");
   Serial.println(analogRead(36));
   uint16_t c2  =  analogRead(36)*0.769 + 150;
   adcEnd(36);
   Serial.println("-------------");

Report in about 8h but probably it's gonna be late in your place (midnight?) Thanks in advance for any advice!

superjasiek commented 3 years ago

Ok, unfortunately i did not know how to make a proper debug but after a loooong search i found sketch that reads voltage properly - of course it is not from manufacturer - all credits goes to JeffMcClain who included it here

// Heltec WiFi LoRa V2 battery read example 
// by Jeff McClain  jeff@themcclains.net
//
#include <Arduino.h>
#include <esp_adc_cal.h>
#include <driver/adc.h>
#include "heltec.h"

#define MAXBATT                 4200    // The default Lipo is 4200mv when the battery is fully charged.
#define LIGHT_SLEEP_VOLTAGE     3750    // Point where start light sleep
#define MINBATT                 3200    // The default Lipo is 3200mv when the battery is empty...this WILL be low on the 3.3v rail specs!!!

#define VOLTAGE_DIVIDER         3.20    // Lora has 220k/100k voltage divider so need to reverse that reduction via (220k+100k)/100k on vbat GPIO37 or ADC1_1 (early revs were GPIO13 or ADC2_4 but do NOT use with WiFi.begin())
#define DEFAULT_VREF            1100    // Default VREF use if no e-fuse calibration
#define VBATT_SAMPLE            500     // Battery sample rate in ms
#define VBATT_SMOOTH            50      // Number of averages in sample
#define ADC_READ_STABILIZE      5       // in ms (delay from GPIO control and ADC connections times)
#define LO_BATT_SLEEP_TIME      10*60*1000*1000     // How long when low batt to stay in sleep (us)
#define HELTEC_V2_1             1       // Set this to switch between GPIO13(V2.0) and GPIO37(V2.1) for VBatt ADC.
#define VBATT_GPIO              21      // Heltec GPIO to toggle VBatt read connection ... WARNING!!! This also connects VEXT to VCC=3.3v so be careful what is on header.  Also, take care NOT to have ADC read connection in OPEN DRAIN when GPIO goes HIGH
#define __DEBUG                 0       // DEBUG Serial output

uint16_t Sample();
void drawBattery(uint16_t, bool = false);

esp_adc_cal_characteristics_t *adc_chars;

void setup() {
  while (! Serial);
  delay(20);

  // Characterize ADC at particular atten
  #if (defined(HELTEC_V2_1))
  adc_chars = (esp_adc_cal_characteristics_t*)calloc(1, sizeof(esp_adc_cal_characteristics_t));
  esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
  adc1_config_width(ADC_WIDTH_BIT_12);
  adc1_config_channel_atten(ADC1_CHANNEL_1,ADC_ATTEN_DB_6);
  #else
  // Use this for older V2.0 with VBatt reading wired to GPIO13
  adc_chars = (esp_adc_cal_characteristics_t*)calloc(1, sizeof(esp_adc_cal_characteristics_t));
  esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
  adc2_config_channel_atten(ADC2_CHANNEL_4,ADC_ATTEN_DB_6);
  #endif

  #if defined(__DEBUG) && __DEBUG > 0
  Serial.printf("ADC Calibration: ");
  if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
      Serial.printf("eFuse Vref\n");
  } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
      Serial.printf("Two Point\n");
  } else {
      Serial.printf("Default[%dmV]\n",DEFAULT_VREF);
  }
  #else
  if (val_type);    // Suppress warning
  #endif

  Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Disable*/, true /*Serial Enable*/);
  Heltec.display->flipScreenVertically();
  Heltec.display->setFont(ArialMT_Plain_10);
  Heltec.display->clear();

  #if defined(__DEBUG) && __DEBUG >= 1
  Serial.printf("ADC Calibration: ");
  if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
      Serial.printf("eFuse Vref\n");
  } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
      Serial.printf("Two Point\n");
  } else {
      Serial.printf("Default[%dmV]\n",DEFAULT_VREF);
  }
  #else
  if (val_type);    // Suppress warning
  #endif

  // Prime the Sample register
  for (uint8_t i = 0;i < VBATT_SMOOTH;i++) {
    Sample();
  }

  pinMode(VBATT_GPIO,OUTPUT);
  digitalWrite(VBATT_GPIO, LOW);              // ESP32 Lora v2.1 reads on GPIO37 when GPIO21 is low
  delay(ADC_READ_STABILIZE);                  // let GPIO stabilize

}

void loop() {
  Heltec.display->clear();
  uint16_t voltage = Sample();
  drawBattery(voltage, voltage < LIGHT_SLEEP_VOLTAGE);
  Heltec.display->display();

  if (voltage < MINBATT) {                  // Low Voltage cut off shut down to protect battery as long as possible
    Heltec.display->setColor(WHITE);
    Heltec.display->setFont(ArialMT_Plain_10);
    Heltec.display->setTextAlignment(TEXT_ALIGN_CENTER);
    Heltec.display->drawString(64,24,"Shutdown!!");
    Heltec.display->display();
    delay(2000);
    #if defined(__DEBUG) && __DEBUG > 0
    Serial.printf(" !! Shutting down...low battery volotage: %dmV.\n",voltage);
    delay(10);
    #endif
    esp_sleep_enable_timer_wakeup(LO_BATT_SLEEP_TIME);
    esp_deep_sleep_start();
  } else if (voltage < LIGHT_SLEEP_VOLTAGE) {     // Use light sleep once on battery
    uint64_t s = VBATT_SAMPLE;
    #if defined(__DEBUG) && __DEBUG > 0
    Serial.printf(" - Light Sleep (%dms)...battery volotage: %dmV.\n",(int)s,voltage);
    delay(20);
    #endif
    esp_sleep_enable_timer_wakeup(s*1000);     // Light Sleep does not flush buffer
    esp_light_sleep_start();
  }
  delay(ADC_READ_STABILIZE);
}

// Poll the proper ADC for VBatt on Heltec Lora 32 with GPIO21 toggled
uint16_t ReadVBatt() {
  uint16_t reading = 666;

  digitalWrite(VBATT_GPIO, LOW);              // ESP32 Lora v2.1 reads on GPIO37 when GPIO21 is low
  delay(ADC_READ_STABILIZE);                  // let GPIO stabilize
  #if (defined(HELTEC_V2_1))
  pinMode(ADC1_CHANNEL_1, OPEN_DRAIN);        // ADC GPIO37
  reading = adc1_get_raw(ADC1_CHANNEL_1);
  pinMode(ADC1_CHANNEL_1, INPUT);             // Disconnect ADC before GPIO goes back high so we protect ADC from direct connect to VBATT (i.e. no divider)
  #else
  pinMode(ADC2_CHANNEL_4, OPEN_DRAIN);        // ADC GPIO13
  adc2_get_raw(ADC2_CHANNEL_4,ADC_WIDTH_BIT_12,&reading);
  pinMode(ADC2_CHANNEL_4, INPUT);             // Disconnect ADC before GPIO goes back high so we protect ADC from direct connect to VBATT (i.e. no divider
  #endif

  uint16_t voltage = esp_adc_cal_raw_to_voltage(reading, adc_chars);  
  voltage*=VOLTAGE_DIVIDER;

  return voltage;
}

//  Use a buffer to average/sample ADC
uint16_t Sample() {
  static uint8_t i = 0;
  static uint16_t samp[VBATT_SMOOTH];
  static int32_t t = 0;
  static bool f = true;
  if(f){ for(uint8_t c=0;c<VBATT_SMOOTH;c++){ samp[c]=0; } f=false; }   // Initialize the sample array first time
  t -= samp[i];   // doing a rolling recording, so remove the old rolled around value out of total and get ready to put new one in.
  if (t<0) {t = 0;}

  // ADC read
  uint16_t voltage = ReadVBatt();

  samp[i]=voltage;
  #if defined(__DEBUG) && __DEBUG > 0
  Serial.printf("ADC Raw Reading[%d]: %d", i, voltage);
  #endif
  t += samp[i];

  if(++i >= VBATT_SMOOTH) {i=0;}
  uint16_t s = round(((float)t / (float)VBATT_SMOOTH));
  #if defined(__DEBUG) && __DEBUG > 0
  Serial.printf("   Smoothed of %d/%d = %d\n",t,VBATT_SMOOTH,s); 
  #endif

  return s;
}

void drawBattery(uint16_t voltage, bool sleep) {
  Heltec.display->setColor(BLACK);
  Heltec.display->fillRect(99,0,29,24);

  Heltec.display->setColor(WHITE);
  Heltec.display->drawRect(104,0,12,6);
  Heltec.display->fillRect(116,2,1,2);

  uint16_t v = voltage;
  if (v < MINBATT) {v = MINBATT;}
  if (v > MAXBATT) {v = MAXBATT;}
  double pct = map(v,MINBATT,MAXBATT,0,100);
  uint8_t bars = round(pct / 10.0);
  Heltec.display->fillRect(105,1,bars,4);
  Heltec.display->setFont(ArialMT_Plain_10);
  Heltec.display->setTextAlignment(TEXT_ALIGN_RIGHT);
  // Draw small "z" when using sleep
  if (sleep > 0) {
    Heltec.display->drawHorizontalLine(121,0,4);
    Heltec.display->drawHorizontalLine(121,5,4);
    Heltec.display->setPixel(124,1);
    Heltec.display->setPixel(123,2);
    Heltec.display->setPixel(122,3);
    Heltec.display->setPixel(121,4);
  }
  Heltec.display->drawString(127,5,String((int)round(pct))+"%");
  Heltec.display->drawString(127,14,String(round(voltage/10.0)/100.0)+"V");
  #if defined(__DEBUG) && __DEBUG > 0
  static uint8_t c = 0;
  if ((c++ % 10) == 0) {
    c = 1;
    Serial.printf("VBAT: %dmV [%4.1f%%] %d bars\n", voltage, pct, bars);
  }
  #endif
}

I also attach three pictures: first one - when heltec is connected to usb port with battery (charging) image second - running only with battery (you can see "z" sign so it detects that battery is present) image third - running only with usb image

geeksville commented 3 years ago

This issue has been mentioned on Meshtastic. There might be relevant details there:

https://meshtastic.discourse.group/t/heltec-board-is-deep-discharging-batteries/1349/17

xorebxebx commented 3 years ago

Hi all! Today i was able to get voltage measurement and sleep mode working on heltec lora32 v2 by adding this 2 lines to heltec section of configuration.h.

#define BATTERY_PIN 37 #define ADC_MULTIPLIER 3.75

IMG_20210414_082348_850

mc-hamster commented 2 years ago

closed per previous comment.