Files
FacePlant/src/sensors/BatterySensor.cpp

101 lines
2.8 KiB
C++
Raw Normal View History

#include "BatterySensor.h"
void BatterySensor::begin() {
pinMode(PIN_BATTERY_ADC, INPUT);
pinMode(PIN_LBO, INPUT);
analogReadResolution(12); // 12-bit ADC (0-4095)
Serial.println("[Battery] Initialized");
Serial.println("[Battery] ADC on GPIO 2, LBO on GPIO 5");
// 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;
// Read battery voltage via ADC
_voltage = readBatteryVoltage();
_percent = voltageToPercent(_voltage);
// Check LBO pin as backup confirmation
bool lboHigh = digitalRead(PIN_LBO);
bool lboIndicatesLow = !lboHigh;
// Battery is low if either voltage is low OR LBO pin indicates low
_isLow = (_voltage < VOLTAGE_LOW) || lboIndicatesLow;
// Log significant changes
if (abs(_percent - prevPercent) >= 5 || _isLow != wasLow) {
Serial.print("[Battery] Voltage: ");
Serial.print(_voltage, 2);
Serial.print("V (");
Serial.print(_percent);
Serial.print("%) LBO: ");
Serial.println(lboHigh ? "OK" : "LOW");
if (_isLow && !wasLow) {
Serial.println("[Battery] ⚠️ LOW BATTERY WARNING - Please recharge!");
}
}
}
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;
}