From 3a5c48f440b0c7352ecbc78cdaab5fdcd0621d98 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Sat, 7 Feb 2026 16:20:33 +1100 Subject: [PATCH] "Battery UI changes - percentage display and icon size" --- examples/companion_radio/ui-new/UITask.cpp | 48 ++++++++++++++++------ src/helpers/ui/GxEPDDisplay.cpp | 4 ++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index d6264c6c..d32c5ab7 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -104,29 +104,53 @@ class HomeScreen : public UIScreen { void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts) { - // Convert millivolts to percentage - const int minMilliVolts = 3000; // Minimum voltage (e.g., 3.0V) - const int maxMilliVolts = 4200; // Maximum voltage (e.g., 4.2V) - int batteryPercentage = ((batteryMilliVolts - minMilliVolts) * 100) / (maxMilliVolts - minMilliVolts); - if (batteryPercentage < 0) batteryPercentage = 0; // Clamp to 0% - if (batteryPercentage > 100) batteryPercentage = 100; // Clamp to 100% + // Try to get accurate SOC from BQ27220 fuel gauge first + uint8_t batteryPercentage = board.getBatteryPercent(); + + // Fall back to voltage-based estimation if fuel gauge returns 0 + if (batteryPercentage == 0 && batteryMilliVolts > 0) { + const int minMilliVolts = 3000; + const int maxMilliVolts = 4200; + int pct = ((batteryMilliVolts - minMilliVolts) * 100) / (maxMilliVolts - minMilliVolts); + if (pct < 0) pct = 0; + if (pct > 100) pct = 100; + batteryPercentage = (uint8_t)pct; + } - // battery icon - int iconWidth = 22; - int iconHeight = 8; - int iconX = display.width() - iconWidth - 5; // Position the icon near the top-right corner - int iconY = 0; display.setColor(DisplayDriver::GREEN); + // battery icon dimensions (smaller to match tiny percentage text) + int iconWidth = 16; + int iconHeight = 6; + + // measure percentage text width to position icon + text together at right edge + display.setTextSize(0); + char pctStr[5]; + sprintf(pctStr, "%d%%", batteryPercentage); + uint16_t textWidth = display.getTextWidth(pctStr); + + // layout: [icon 16px][cap 2px][gap 2px][text][margin 2px] + int totalWidth = iconWidth + 2 + 2 + textWidth + 2; + int iconX = display.width() - totalWidth; + int iconY = 0; // vertically align with node name text + // battery outline display.drawRect(iconX, iconY, iconWidth, iconHeight); // battery "cap" - display.fillRect(iconX + iconWidth, iconY + (iconHeight / 4), 3, iconHeight / 2); + display.fillRect(iconX + iconWidth, iconY + (iconHeight / 4), 2, iconHeight / 2); // fill the battery based on the percentage int fillWidth = (batteryPercentage * (iconWidth - 4)) / 100; display.fillRect(iconX + 2, iconY + 2, fillWidth, iconHeight - 4); + + // draw percentage text after the battery cap, offset upward to center with icon + // (setCursor adds +5 internally for baseline, so compensate for the tiny font) + int textX = iconX + iconWidth + 2 + 2; // after cap + gap + int textY = iconY - 3; // offset up to vertically center with icon + display.setCursor(textX, textY); + display.print(pctStr); + display.setTextSize(1); // restore default text size } CayenneLPP sensors_lpp; diff --git a/src/helpers/ui/GxEPDDisplay.cpp b/src/helpers/ui/GxEPDDisplay.cpp index a1a598c2..6080e734 100644 --- a/src/helpers/ui/GxEPDDisplay.cpp +++ b/src/helpers/ui/GxEPDDisplay.cpp @@ -84,6 +84,10 @@ void GxEPDDisplay::startFrame(Color bkg) { void GxEPDDisplay::setTextSize(int sz) { display_crc.update(sz); switch(sz) { + case 0: // Tiny - built-in 6x8 pixel font + display.setFont(NULL); + display.setTextSize(1); + break; case 1: // Small - use 9pt (was 9pt) display.setFont(&FreeSans9pt7b); break;