Updates
This commit is contained in:
@@ -10,6 +10,9 @@ lib_deps =
|
||||
adafruit/Adafruit SSD1306
|
||||
bblanchon/ArduinoJson
|
||||
|
||||
; board_build.filesystem = spiffs
|
||||
; board_build.partitions = default.csv
|
||||
|
||||
build_flags =
|
||||
-D PB_VERSION=\"1.0.0\"
|
||||
-D PB_HOSTNAME=\"faceplant\"
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
void BatterySensor::begin() {
|
||||
pinMode(PIN_BATTERY_ADC, INPUT);
|
||||
pinMode(PIN_LBO, INPUT);
|
||||
pinMode(PIN_CHG, INPUT_PULLUP); // CHG is LOW when charging
|
||||
|
||||
analogReadResolution(12); // 12-bit ADC (0-4095)
|
||||
|
||||
Serial.println("[Battery] Initialized");
|
||||
Serial.println("[Battery] ADC on GPIO 2, LBO on GPIO 5");
|
||||
Serial.println("[Battery] ADC on GPIO 2, LBO on GPIO 5, CHG on GPIO 4");
|
||||
|
||||
// Initial reading
|
||||
_voltage = readBatteryVoltage();
|
||||
@@ -29,30 +30,47 @@ void BatterySensor::loop() {
|
||||
float prevVoltage = _voltage;
|
||||
int prevPercent = _percent;
|
||||
bool wasLow = _isLow;
|
||||
bool wasCharging = _isCharging;
|
||||
|
||||
// Read battery voltage via ADC
|
||||
_voltage = readBatteryVoltage();
|
||||
_percent = voltageToPercent(_voltage);
|
||||
|
||||
// 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;
|
||||
|
||||
// Battery is low if either voltage is low OR LBO pin indicates low
|
||||
_isLow = (_voltage < VOLTAGE_LOW) || lboIndicatesLow;
|
||||
// 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
|
||||
if (abs(_percent - prevPercent) >= 5 || _isLow != wasLow) {
|
||||
if (abs(_percent - prevPercent) >= 5 || _isLow != wasLow || _isCharging != wasCharging) {
|
||||
Serial.print("[Battery] Voltage: ");
|
||||
Serial.print(_voltage, 2);
|
||||
Serial.print("V (");
|
||||
Serial.print(_percent);
|
||||
Serial.print("%) LBO: ");
|
||||
Serial.print("%) ");
|
||||
|
||||
if (_isCharging) {
|
||||
Serial.print("CHARGING ");
|
||||
}
|
||||
|
||||
Serial.print("LBO: ");
|
||||
Serial.println(lboHigh ? "OK" : "LOW");
|
||||
|
||||
if (_isLow && !wasLow) {
|
||||
if (_isLow && !wasLow && !_isCharging) {
|
||||
Serial.println("[Battery] ⚠️ LOW BATTERY WARNING - Please recharge!");
|
||||
}
|
||||
|
||||
if (_isCharging && !wasCharging) {
|
||||
Serial.println("[Battery] 🔌 Charging started");
|
||||
} else if (!_isCharging && wasCharging) {
|
||||
Serial.println("[Battery] ✓ Charging complete or disconnected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
int percent() const { return _percent; }
|
||||
float voltage() const { return _voltage; }
|
||||
bool isLow() const { return _isLow; }
|
||||
bool isCharging() const { return _isCharging; }
|
||||
bool shouldBlink() const;
|
||||
|
||||
// For display
|
||||
@@ -18,6 +19,7 @@ public:
|
||||
private:
|
||||
static constexpr int PIN_BATTERY_ADC = 2; // Voltage divider input
|
||||
static constexpr int PIN_LBO = 5; // PowerBoost LBO pin
|
||||
static constexpr int PIN_CHG = 4; // PowerBoost CHG pin (LOW when charging)
|
||||
|
||||
static constexpr unsigned long CHECK_INTERVAL_MS = 2000;
|
||||
static constexpr int SAMPLES = 10; // Number of ADC samples to average
|
||||
@@ -33,6 +35,7 @@ private:
|
||||
int _percent = 100;
|
||||
float _voltage = 3.7;
|
||||
bool _isLow = false;
|
||||
bool _isCharging = false;
|
||||
unsigned long _lastCheckMs = 0;
|
||||
|
||||
float readBatteryVoltage();
|
||||
|
||||
@@ -60,11 +60,11 @@ _oled.display();
|
||||
delay(2100);
|
||||
}
|
||||
|
||||
void Display::drawBatteryIcon(int x, int y, int percent, bool blink) {
|
||||
void Display::drawBatteryIcon(int x, int y, int percent, bool blink, bool charging) {
|
||||
if (!_ok) return;
|
||||
|
||||
// Skip if blinking and blink state is off
|
||||
if (blink && ((millis() / 500) % 2 == 1)) return;
|
||||
// Skip if blinking and blink state is off (unless charging)
|
||||
if (!charging && blink && ((millis() / 500) % 2 == 1)) return;
|
||||
|
||||
// Battery body: 14x7 rectangle
|
||||
_oled.drawRect(x, y, 14, 7, 1);
|
||||
@@ -74,13 +74,33 @@ void Display::drawBatteryIcon(int x, int y, int percent, bool blink) {
|
||||
|
||||
// Fill level: 12 pixels max width inside battery
|
||||
int fillWidth = (percent * 12) / 100;
|
||||
if (fillWidth > 0) {
|
||||
_oled.fillRect(x + 1, y + 1, fillWidth, 5, 1);
|
||||
}
|
||||
|
||||
// Low battery warning: blink outline
|
||||
if (percent < 20 && blink) {
|
||||
// Draw thicker outline for emphasis
|
||||
_oled.drawRect(x - 1, y - 1, 16, 9, 1);
|
||||
if (charging) {
|
||||
// Draw animated lightning bolt when charging
|
||||
bool phase = (millis() / 300) % 2 == 0;
|
||||
int color = phase ? 1 : 0; // Blink between white and inverted
|
||||
|
||||
// Lightning bolt shape (simple zigzag)
|
||||
_oled.drawLine(x + 7, y + 1, x + 5, y + 3, color); // Top diagonal
|
||||
_oled.drawLine(x + 5, y + 3, x + 9, y + 3, color); // Middle horizontal
|
||||
_oled.drawLine(x + 9, y + 3, x + 7, y + 5, color); // Bottom diagonal
|
||||
|
||||
// Always draw at least some fill when charging
|
||||
if (fillWidth == 0 && phase) {
|
||||
_oled.fillRect(x + 1, y + 1, 2, 5, 1); // Small pulse even at 0%
|
||||
} else if (fillWidth > 0) {
|
||||
_oled.fillRect(x + 1, y + 1, fillWidth, 5, 1);
|
||||
}
|
||||
} else {
|
||||
// Normal fill level
|
||||
if (fillWidth > 0) {
|
||||
_oled.fillRect(x + 1, y + 1, fillWidth, 5, 1);
|
||||
}
|
||||
|
||||
// Low battery warning: blink outline
|
||||
if (percent < 20 && blink) {
|
||||
// Draw thicker outline for emphasis
|
||||
_oled.drawRect(x - 1, y - 1, 16, 9, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
|
||||
void showStatus(const String& line1, const String& line2);
|
||||
void bootAnimation();
|
||||
void drawBatteryIcon(int x, int y, int percent, bool blink);
|
||||
void drawBatteryIcon(int x, int y, int percent, bool blink, bool charging);
|
||||
|
||||
private:
|
||||
static constexpr int PIN_SDA = 6;
|
||||
|
||||
@@ -157,7 +157,7 @@ void FaceRenderer::renderDead(unsigned long now, const BatterySensor& battery) {
|
||||
}
|
||||
|
||||
// Draw battery icon in top-right corner
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), battery.shouldBlink());
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), battery.shouldBlink(), battery.isCharging());
|
||||
|
||||
d.display();
|
||||
}
|
||||
@@ -199,7 +199,7 @@ void FaceRenderer::renderBatteryLow(unsigned long now, const BatterySensor& batt
|
||||
drawMouthNervous();
|
||||
|
||||
// Draw battery icon in top-right corner (blinking)
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), true);
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), true, battery.isCharging());
|
||||
|
||||
d.display();
|
||||
}
|
||||
@@ -230,7 +230,7 @@ void FaceRenderer::renderNormal(unsigned long now, const BatterySensor& battery)
|
||||
}
|
||||
|
||||
// Draw battery icon in top-right corner
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), battery.shouldBlink());
|
||||
_display->drawBatteryIcon(110, 2, battery.percent(), battery.shouldBlink(), battery.isCharging());
|
||||
|
||||
d.display();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user