Files
FacePlant/src/sensors/BatterySensor.cpp

119 lines
3.4 KiB
C++
Raw Normal View History

#include "BatterySensor.h"
void BatterySensor::begin() {
pinMode(PIN_BATTERY_ADC, INPUT);
pinMode(PIN_LBO, INPUT);
2026-02-10 21:31:36 -05:00
pinMode(PIN_CHG, INPUT_PULLUP); // CHG is LOW when charging
analogReadResolution(12); // 12-bit ADC (0-4095)
Serial.println("[Battery] Initialized");
2026-02-10 21:31:36 -05:00
Serial.println("[Battery] ADC on GPIO 2, LBO on GPIO 5, CHG on GPIO 4");
// Initial reading
_voltage = readBatteryVoltage();
_percent = voltageToPercent(_voltage);
_isLow = (_voltage < VOLTAGE_LOW);
Serial.print("[Battery] Initial voltage: ");
Serial.print(_voltage);
Serial.print("V, ");
Serial.print(_percent);
Serial.println("%");
}
void BatterySensor::loop() {
unsigned long now = millis();
if (now - _lastCheckMs < CHECK_INTERVAL_MS) return;
_lastCheckMs = now;
float prevVoltage = _voltage;
int prevPercent = _percent;
bool wasLow = _isLow;
2026-02-10 21:31:36 -05:00
bool wasCharging = _isCharging;
// Read battery voltage via ADC
_voltage = readBatteryVoltage();
_percent = voltageToPercent(_voltage);
2026-02-10 21:31:36 -05:00
// Check CHG pin (LOW when charging)
bool chgLow = !digitalRead(PIN_CHG);
_isCharging = chgLow;
// Check LBO pin as backup confirmation
bool lboHigh = digitalRead(PIN_LBO);
bool lboIndicatesLow = !lboHigh;
2026-02-10 21:31:36 -05:00
// Battery is low if either voltage is low OR LBO pin indicates low (and not charging)
_isLow = ((_voltage < VOLTAGE_LOW) || lboIndicatesLow) && !_isCharging;
// Log significant changes
2026-02-10 21:31:36 -05:00
if (abs(_percent - prevPercent) >= 5 || _isLow != wasLow || _isCharging != wasCharging) {
Serial.print("[Battery] Voltage: ");
Serial.print(_voltage, 2);
Serial.print("V (");
Serial.print(_percent);
2026-02-10 21:31:36 -05:00
Serial.print("%) ");
if (_isCharging) {
Serial.print("CHARGING ");
}
Serial.print("LBO: ");
Serial.println(lboHigh ? "OK" : "LOW");
2026-02-10 21:31:36 -05:00
if (_isLow && !wasLow && !_isCharging) {
Serial.println("[Battery] ⚠️ LOW BATTERY WARNING - Please recharge!");
}
2026-02-10 21:31:36 -05:00
if (_isCharging && !wasCharging) {
Serial.println("[Battery] 🔌 Charging started");
} else if (!_isCharging && wasCharging) {
Serial.println("[Battery] ✓ Charging complete or disconnected");
}
}
}
float BatterySensor::readBatteryVoltage() {
// Take multiple samples and average them for stability
long sum = 0;
for (int i = 0; i < SAMPLES; i++) {
sum += analogRead(PIN_BATTERY_ADC);
delay(5);
}
int avgRaw = sum / SAMPLES;
// Convert ADC value to voltage at the pin
// ESP32-C3 ADC: 12-bit (0-4095) maps to 0-3.3V
float adcVoltage = (avgRaw / 4095.0) * 3.3;
// Multiply by divider ratio to get actual battery voltage
float batteryVoltage = adcVoltage * DIVIDER_RATIO;
return batteryVoltage;
}
int BatterySensor::voltageToPercent(float voltage) {
// Clamp voltage to valid range
if (voltage >= VOLTAGE_MAX) return 100;
if (voltage <= VOLTAGE_MIN) return 0;
// Linear mapping from voltage to percentage
// This is a simplified model; LiPo discharge curves are non-linear
// For better accuracy, you could use a lookup table
float percent = ((voltage - VOLTAGE_MIN) / (VOLTAGE_MAX - VOLTAGE_MIN)) * 100.0;
return constrain((int)percent, 0, 100);
}
bool BatterySensor::shouldBlink() const {
// Blink every 500ms when battery is low (< 20%)
return (_percent < 20) && ((millis() / 500) % 2 == 0);
}
int BatterySensor::iconFillWidth(int maxWidth) const {
// Calculate fill width for battery icon
// Returns 0 to maxWidth based on percentage
return (_percent * maxWidth) / 100;
}