Merge pull request #2287 from pelgraine/fix/techo-lite-battery

Fixes #1183 — T-Echo Lite incorrect battery voltage
This commit is contained in:
Liam Cottle
2026-04-22 20:23:21 +12:00
committed by GitHub
3 changed files with 53 additions and 30 deletions

View File

@@ -8,24 +8,47 @@
void TechoBoard::begin() { void TechoBoard::begin() {
NRF52Board::begin(); NRF52Board::begin();
// Configure battery measurement control BEFORE Wire.begin()
// to ensure P0.02 is not claimed by another peripheral
pinMode(PIN_VBAT_MEAS_EN, OUTPUT);
digitalWrite(PIN_VBAT_MEAS_EN, LOW);
pinMode(PIN_VBAT_READ, INPUT);
Wire.begin(); Wire.begin();
pinMode(SX126X_POWER_EN, OUTPUT); pinMode(SX126X_POWER_EN, OUTPUT);
digitalWrite(SX126X_POWER_EN, HIGH); digitalWrite(SX126X_POWER_EN, HIGH);
delay(10); // give sx1262 some time to power up delay(10);
} }
uint16_t TechoBoard::getBattMilliVolts() { uint16_t TechoBoard::getBattMilliVolts() {
int adcvalue = 0; // Use LilyGo's exact ADC configuration
analogReference(AR_INTERNAL_3_0); analogReference(AR_INTERNAL_3_0);
analogReadResolution(12); analogReadResolution(12);
delay(10);
// ADC range is 0..3000mV and resolution is 12-bit (0..4095) // Enable battery voltage divider (MOSFET gate on P0.31)
adcvalue = analogRead(PIN_VBAT_READ); pinMode(PIN_VBAT_MEAS_EN, OUTPUT);
// Convert the raw value to compensated mv, taking the resistor- digitalWrite(PIN_VBAT_MEAS_EN, HIGH);
// divider into account (providing the actual LIPO voltage)
return (uint16_t)((float)adcvalue * REAL_VBAT_MV_PER_LSB); // Reclaim P0.02 for analog input (in case another peripheral touched it)
pinMode(PIN_VBAT_READ, INPUT);
delay(10); // let divider + ADC settle
// Read and average (matching LilyGo's approach)
uint32_t sum = 0;
for (int i = 0; i < 8; i++) {
sum += analogRead(PIN_VBAT_READ);
delayMicroseconds(100);
}
uint16_t adc = sum / 8;
// Disable divider to save power
digitalWrite(PIN_VBAT_MEAS_EN, LOW);
// LilyGo's exact formula: adc * (3000.0 / 4096.0) * 2.0
// = adc * 0.73242188 * 2.0 = adc * 1.46484375
uint16_t millivolts = (uint16_t)((float)adc * (3000.0f / 4096.0f) * 2.0f);
return millivolts;
} }
#endif #endif

View File

@@ -4,14 +4,12 @@
#include <Arduino.h> #include <Arduino.h>
#include <helpers/NRF52Board.h> #include <helpers/NRF52Board.h>
// built-ins // ============================================================
#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 // T-Echo Lite battery pins — hardcoded from LilyGo t_echo_lite_config.h
// NOT using any defines from variant.h for battery measurement
#define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT // ============================================================
#define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider #define PIN_VBAT_READ _PINNUM(0, 2) // BATTERY_ADC_DATA
#define PIN_VBAT_MEAS_EN _PINNUM(0, 31) // BATTERY_MEASUREMENT_CONTROL
#define PIN_VBAT_READ (4)
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
class TechoBoard : public NRF52BoardDCDC { class TechoBoard : public NRF52BoardDCDC {
public: public:
@@ -20,10 +18,11 @@ public:
uint16_t getBattMilliVolts() override; uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override { const char* getManufacturerName() const override {
return "LilyGo T-Echo"; return "LilyGo T-Echo Lite";
} }
void powerOff() override { void powerOff() override {
digitalWrite(PIN_VBAT_MEAS_EN, LOW);
#ifdef LED_RED #ifdef LED_RED
digitalWrite(LED_RED, LOW); digitalWrite(LED_RED, LOW);
#endif #endif

View File

@@ -24,7 +24,7 @@
#define PIN_PWR_EN _PINNUM(0, 30) // RT9080_EN #define PIN_PWR_EN _PINNUM(0, 30) // RT9080_EN
#define BATTERY_PIN _PINNUM(0, 2) #define BATTERY_PIN _PINNUM(0, 2)
#define ADC_MULTIPLIER (4.90F) #define ADC_MULTIPLIER (2.0F)
#define ADC_RESOLUTION (14) #define ADC_RESOLUTION (14)
#define BATTERY_SENSE_RES (12) #define BATTERY_SENSE_RES (12)
@@ -47,13 +47,13 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// I2C pin definition // I2C pin definition
#define PIN_WIRE_SDA _PINNUM(0, 4) // (SDA) #define PIN_WIRE_SDA _PINNUM(1, 4) // (SDA) - per LilyGo IIC_1_SDA
#define PIN_WIRE_SCL _PINNUM(0, 2) // (SCL) #define PIN_WIRE_SCL _PINNUM(1, 2) // (SCL) - per LilyGo IIC_1_SCL
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// SPI pin definition // SPI pin definition
#define SPI_INTERFACES_COUNT _PINNUM(0, 2) #define SPI_INTERFACES_COUNT (2)
#define PIN_SPI_MISO _PINNUM(0, 17) // (MISO) #define PIN_SPI_MISO _PINNUM(0, 17) // (MISO)
#define PIN_SPI_MOSI _PINNUM(0, 15) // (MOSI) #define PIN_SPI_MOSI _PINNUM(0, 15) // (MOSI)
@@ -149,10 +149,11 @@ extern const int SCK;
#define PIN_DISPLAY_BUSY DISP_BUSY #define PIN_DISPLAY_BUSY DISP_BUSY
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// GPS // GPS — per LilyGo t_echo_lite_config.h
// PIN_GPS_TX/RX named from GPS module's perspective
#define PIN_GPS_RX _PINNUM(1, 13) // RXD #define PIN_GPS_TX _PINNUM(0, 29) // GPS UART TX → MCU RX
#define PIN_GPS_TX _PINNUM(1, 15) // TXD #define PIN_GPS_RX _PINNUM(1, 10) // GPS UART RX ← MCU TX
#define GPS_EN _PINNUM(1, 11) // POWER_RT9080_EN #define GPS_EN _PINNUM(1, 11) // GPS RT9080 power enable
#define PIN_GPS_STANDBY _PINNUM(1, 10) #define PIN_GPS_STANDBY _PINNUM(1, 13) // GPS wake-up
#define PIN_GPS_PPS _PINNUM(0, 29) // 1PPS #define PIN_GPS_PPS _PINNUM(1, 15) // GPS 1PPS