WiFi LoRa 32 V3 Voltage read(use GPIO1[VBAT_READ]) question


This is a simple code created by looking at the post above.

#include <Arduino.h>

#define VBAT_PIN 1
#define ADC_CTRL_PIN 37
#define BATTERY_SAMPLES 20

void VBAT_Init() {
pinMode(VBAT_PIN, INPUT);
pinMode(ADC_CTRL_PIN, OUTPUT);
}

float readBattVoltage() {
digitalWrite(ADC_CTRL_PIN, LOW);

uint32_t raw = 0;
for (int i = 0; i < BATTERY_SAMPLES; i++) {
raw += analogRead(VBAT_PIN);
}
raw = raw / BATTERY_SAMPLES;
Serial.println(raw);
digitalWrite(ADC_CTRL_PIN, HIGH);
return 5.42 * (3.3 / 1024.0) * raw;
}

void setup() {
Serial.begin(9600);
VBAT_Init();
}

void loop() {
float voltage = readBattVoltage();
Serial.println("Battery voltage: " + String(voltage) + "V");
delay(1000);
}

Only Type C USB
nobat Serial monitor Output(GPIO1,the battery voltage.)

Type C USB +3.7 V Lithium-ion Battery
ybat Serial monitorOutput(GPIO1,the battery voltage.)

The article describes a battery voltage measurement code for a device called Stick Lite V3. The code takes multiple ADC readings of the battery voltage, averages the readings, and calculates the final voltage measurement using a constant factor of 5.42 * (3.3 / 1024.0). The code also outputs the results to the serial monitor.

The author is now looking to modify the code for the WiFi LoRa32 V3 device, and wants to change the constant factor used in the voltage measurement calculation. The author found the voltage measurement formula in the datasheet for the WiFi LoRa32 V3, which uses resistors R1 = 390 and R2 = 100.
(https://heltec.org/project/wifi-lora-32-v3/)image01

The author is asking for help to write a code for measuring voltage on the LoRa32V3 device, using the information from the datasheet.

void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  
  //set the resolution to 12 bits (0-4096)
  analogReadResolution(12);
}

void loop() {
  // read the analog / millivolts value for pin 2:
  int analogValue = analogRead(2);
  int analogVolts = analogReadMilliVolts(2);
  
  // print out the values you read:
  Serial.printf("ADC analog value = %d\n",analogValue);
  Serial.printf("ADC millivolts value = %d\n",analogVolts);
  
  delay(100);  // delay in between reads for clear read from serial
}

Try to modify it based on this example.

%EB%B2%A0%ED%84%B0%EB%A6%AC%20%EC%97%B0%EA%B2%B0%ED%9B%84%20800%20%EC%B4%88%EB%B0%98%EC%9C%A0%EC%A7%80
The picture above shows the serial monitor with the battery connected and the output value of the serial monitor without the battery below.
I think this direction is right, seeing that the value reacts slightly depending on the presence or absence of battery connection.


I changed the analogread pin number from the code you gave me to 1.

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  
 
  analogReadResolution(12);
}

void loop() {
  
  int analogValue = analogRead(1);
  int analogVolts = analogReadMilliVolts(1);
  
  // print out the values you read:
  Serial.printf("ADC analog value = %d\n",analogValue);
  Serial.printf("ADC millivolts value = %d\n mV",analogVolts);
  
  delay(1000); 

}

Here is my solution for the WiFi LoRa 32 (V3). I finetuned it with multimeter measurements. It works fine when the board is connected only to the LiPo.

#include <Wire.h>
#include “HT_SSD1306Wire.h”
SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED);

void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}

#define Read_VBAT_Voltage 1
#define ADC_CTRL 37 // Heltec GPIO to toggle VBatt read connection …
// Also, take care NOT to have ADC read connection
// in OPEN DRAIN when GPIO goes HIGH
#define ADC_READ_STABILIZE 10 // in ms (delay from GPIO control and ADC connections times)

float readBatLevel() {
pinMode(ADC_CTRL,OUTPUT);
digitalWrite(ADC_CTRL, LOW);
delay(ADC_READ_STABILIZE); // let GPIO stabilize
int analogValue = analogRead(Read_VBAT_Voltage);
float voltage = 0.00403532794741887 * analogValue;
return voltage;
}

void setup() {
Serial.begin(115200);

// initialize OLED
VextON();
delay(100);
display.init();
display.clear();
display.setFont(ArialMT_Plain_16);
display.drawString(0, 20, “Battery Test”);
display.display();
delay(2000);
}

void loop() {
float v;
v = readBatLevel();
display.clear();
display.drawString(0, 20, String(v) + " Volt");
display.display();
delay(5000);
}

1 Like

Thank you. It’s solved with the code I showed you

I can confirm that is the solution. I can’t find that documented absolutely anywhere that pin 37 needs to be pulled low to turn on vbat reading. That…really should be written down somewhere. This board seems so good and the documentation and software seems so lacking.

Here is my code. It’s fairly similar to the above but it cleans up some things and moves setting pin 37 into the setup function which I think makes more sense.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, RST_OLED);

#define VBAT_PIN 1
#define VBAT_READ_CNTRL_PIN 37 // Heltec GPIO to toggle VBatt read connection …
// Also, take care NOT to have ADC read connection
// in OPEN DRAIN when GPIO goes HIGH
#define ADC_READ_STABILIZE 10 // in ms (delay from GPIO control and ADC connections times)

float readBatLevel() {
  int analogValue = analogRead(VBAT_PIN);
  float voltage = 0.0041 * analogValue;
  return voltage;
}

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_OLED, SCL_OLED);

  // turn on vbat read
  pinMode(VBAT_READ_CNTRL_PIN,OUTPUT);
  digitalWrite(VBAT_READ_CNTRL_PIN, LOW);

  // initialize OLED
  delay(100);
  Serial.println("Awake");
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;);
  }
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  display.println("hello");
  display.display();
}

int count = 0;
void loop() {
  display.clearDisplay();
  display.setCursor(0, 0); 
  float v = readBatLevel();
  display.println(String(v) + " Volt");
  display.println(count++);
  display.display();
  delay(500);

}

Note that I also had to adjust the voltage multiplier slightly for my board.

2 Likes