mirror of
https://github.com/open-x4-epaper/sample-firmware.git
synced 2026-04-29 10:24:26 -07:00
Custom battery monitoring using calibrated ADC values instead of pangodream library
This commit is contained in:
@@ -16,7 +16,6 @@ board_build.partitions = default_16MB.csv
|
||||
; Libraries
|
||||
lib_deps =
|
||||
zinggjm/GxEPD2@^1.5.9
|
||||
https://github.com/pangodream/18650CL
|
||||
|
||||
; Build flags
|
||||
build_flags =
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// BatteryMonitor.cpp
|
||||
#include "BatteryMonitor.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
BatteryMonitor::BatteryMonitor(uint8_t adcPin, float dividerMultiplier)
|
||||
: _adcPin(adcPin), _dividerMultiplier(dividerMultiplier)
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t BatteryMonitor::readPercentage() const
|
||||
{
|
||||
return percentageFromMillivolts(readMillivolts());
|
||||
}
|
||||
|
||||
uint16_t BatteryMonitor::readMillivolts() const
|
||||
{
|
||||
const uint16_t raw = readRawMillivolts();
|
||||
const uint32_t mv = millivoltsFromRawAdc(raw);
|
||||
return static_cast<uint32_t>(mv * _dividerMultiplier);
|
||||
}
|
||||
|
||||
uint16_t BatteryMonitor::readRawMillivolts() const
|
||||
{
|
||||
const uint16_t raw = analogRead(_adcPin);
|
||||
return raw;
|
||||
}
|
||||
|
||||
double BatteryMonitor::readVolts() const
|
||||
{
|
||||
return static_cast<double>(readMillivolts()) / 1000.0;
|
||||
}
|
||||
|
||||
uint16_t BatteryMonitor::percentageFromMillivolts(uint16_t millivolts)
|
||||
{
|
||||
double volts = millivolts / 1000.0;
|
||||
// Polynomial derived from LiPo samples
|
||||
double y = -144.9390 * volts * volts * volts +
|
||||
1655.8629 * volts * volts -
|
||||
6158.8520 * volts +
|
||||
7501.3202;
|
||||
|
||||
// Clamp to [0,100] and round
|
||||
y = max(y, 0.0);
|
||||
y = min(y, 100.0);
|
||||
y = round(y);
|
||||
return static_cast<int>(y);
|
||||
}
|
||||
|
||||
uint16_t BatteryMonitor::millivoltsFromRawAdc(uint16_t adc_raw)
|
||||
{
|
||||
esp_adc_cal_characteristics_t adc_chars;
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, 1100, &adc_chars);
|
||||
return esp_adc_cal_raw_to_voltage(adc_raw, &adc_chars);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// BatteryMonitor.h
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class BatteryMonitor
|
||||
{
|
||||
public:
|
||||
// Optional divider multiplier parameter defaults to 2.0
|
||||
explicit BatteryMonitor(uint8_t adcPin, float dividerMultiplier = 2.0f);
|
||||
|
||||
// Read voltage and return percentage (0-100)
|
||||
uint16_t readPercentage() const;
|
||||
|
||||
// Read the battery voltage in millivolts (accounts for divider)
|
||||
uint16_t readMillivolts() const;
|
||||
|
||||
// Read raw millivolts from ADC (doesn't account for divider)
|
||||
uint16_t readRawMillivolts() const;
|
||||
|
||||
// Read the battery voltage in volts (accounts for divider)
|
||||
double readVolts() const;
|
||||
|
||||
// Percentage (0-100) from a millivolt value
|
||||
static uint16_t percentageFromMillivolts(uint16_t millivolts);
|
||||
|
||||
// Calibrate a raw ADC reading and return millivolts
|
||||
static uint16_t millivoltsFromRawAdc(uint16_t adc_raw);
|
||||
|
||||
private:
|
||||
uint8_t _adcPin;
|
||||
float _dividerMultiplier;
|
||||
};
|
||||
+13
-15
@@ -4,7 +4,7 @@
|
||||
#include <GxEPD2_BW.h>
|
||||
#include <SPI.h>
|
||||
#include "image.h"
|
||||
#include "Pangodream_18650_CL.h"
|
||||
#include "BatteryMonitor.h"
|
||||
|
||||
// Display SPI pins (custom pins for XteinkX4, not hardware SPI defaults)
|
||||
#define EPD_SCLK 8 // SPI Clock
|
||||
@@ -20,12 +20,9 @@
|
||||
#define BTN_GPIO3 3 // Power button (digital)
|
||||
|
||||
#define UART0_RXD 20 // Used for USB connection detection
|
||||
|
||||
#define BAT_GPIO0 0 // Battery voltage
|
||||
#define READS 10
|
||||
#define CONV_FACTOR 1.5176
|
||||
|
||||
Pangodream_18650_CL BL(BAT_GPIO0, CONV_FACTOR, READS);
|
||||
static BatteryMonitor g_battery(BAT_GPIO0);
|
||||
|
||||
static int rawBat = 0;
|
||||
|
||||
@@ -44,7 +41,7 @@ volatile DisplayCommand displayCommand = DISPLAY_NONE;
|
||||
// GxEPD2 display - Using GxEPD2_426_GDEQ0426T82
|
||||
// Note: XteinkX4 has 4.26" 800x480 display
|
||||
GxEPD2_BW<GxEPD2_426_GDEQ0426T82, GxEPD2_426_GDEQ0426T82::HEIGHT> display(
|
||||
GxEPD2_426_GDEQ0426T82(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
|
||||
GxEPD2_426_GDEQ0426T82(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
|
||||
|
||||
// FreeRTOS task for non-blocking display updates
|
||||
TaskHandle_t displayTaskHandle = NULL;
|
||||
@@ -78,6 +75,7 @@ volatile Button currentPressedButton = NONE;
|
||||
const unsigned long POWER_BUTTON_WAKEUP_MS = 1000; // Time required to confirm boot from sleep
|
||||
const unsigned long POWER_BUTTON_SLEEP_MS = 1000; // Time required to enter sleep mode
|
||||
|
||||
|
||||
// Get button name as string
|
||||
const char *getButtonName(Button btn)
|
||||
{
|
||||
@@ -163,11 +161,11 @@ void drawBatteryInfo()
|
||||
display.printf("Power: %s", charging ? "Charging" : "Battery");
|
||||
|
||||
display.setCursor(40, 200);
|
||||
display.printf("Raw: %i", rawBat);
|
||||
display.printf("Raw: %i", g_battery.readRawMillivolts());
|
||||
display.setCursor(40, 240);
|
||||
display.printf("Volts: %.2f V", BL.getBatteryVolts());
|
||||
display.printf("Volts: %.2f V", g_battery.readVolts());
|
||||
display.setCursor(40, 280);
|
||||
display.printf("Charge: %i%%", BL.getBatteryChargeLevel());
|
||||
display.printf("Charge: %i%%", g_battery.readPercentage());
|
||||
}
|
||||
|
||||
// Display update task running on separate core
|
||||
@@ -410,14 +408,14 @@ void loop()
|
||||
|
||||
Serial.println("");
|
||||
|
||||
Serial.print("Value from pin: ");
|
||||
Serial.println(rawBat);
|
||||
Serial.print("Average value from pin: ");
|
||||
Serial.println(BL.pinRead());
|
||||
Serial.print("Value from pin (raw/calibrated): ");
|
||||
Serial.print(rawBat);
|
||||
Serial.print(" / ");
|
||||
Serial.println(BatteryMonitor::millivoltsFromRawAdc(rawBat));
|
||||
Serial.print("Volts: ");
|
||||
Serial.println(BL.getBatteryVolts());
|
||||
Serial.println(g_battery.readVolts());
|
||||
Serial.print("Charge level: ");
|
||||
Serial.println(BL.getBatteryChargeLevel());
|
||||
Serial.println(g_battery.readPercentage());
|
||||
Serial.println("");
|
||||
lastLogMs = now;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user