v2 firmware: HA command channel, battery screen, dynamic Home buttons, tilt-dimmer
Watch-side features developed on the AMOLED-2.06 and shared across all boards:
- BLE command channel (…0005, notify watch→PC) via ble_send_command(); the
watch stays "dumb" and the daemon maps commands to Home Assistant.
- Battery detail screen + protective low-voltage cutoff; power HAL gains
battery_mv() / shutdown(), with battery_est.{h,cpp} for the time-left anchor.
- Home screen: dynamic 2-column button grid driven by the desktop config
(RX "btns" labels); tap notifies {"cmd":"btn","i":N}.
- Dimmer screen: IMU tilt-joystick over the light's brightness / color temp.
imu_hal_read_accel() added to the HAL (real on 2.06/2.16, no-op elsewhere);
streams absolute {"cmd":"bri"|"ct","v":..}; daemon seeds the dial via "dim".
Per-board tilt axis is calibrated with the DIM_CALIB overlay (off by default).
Multi-board fix: enable LV_FONT_MONTSERRAT_20/28 on the 2.16, 1.8 and C6 envs.
Shared ui.cpp uses these glyphs for the launcher tiles and back chevron, so
those three boards had failed to compile since the Phase-2 UI landed. All four
envs now build clean. README: correct the Windows pairing name to "Clawdmeter".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
#include "battery_est.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
// Anchor-based, not a ring buffer (cf. usage_rate.cpp): we remember (time, pct)
|
||||
// at the moment discharge began and project from the average rate since then.
|
||||
// rate = (anchor_pct - pct_now) / minutes_elapsed
|
||||
// minutes_left = pct_now / rate
|
||||
// A long baseline beats a short ring for a signal that only ticks every few
|
||||
// minutes — the estimate just keeps tightening as the session runs. We withhold
|
||||
// a number until the cell has dropped a meaningful amount over a few minutes, so
|
||||
// the first figure isn't built on fuel-gauge settling noise right after boot.
|
||||
#define EST_MIN_DROP_PCT 3 // need >= 3% drained since the anchor
|
||||
#define EST_MIN_ELAPSED_MS 300000UL // ...over at least 5 minutes
|
||||
#define EST_MAX_MINUTES (100 * 60)
|
||||
|
||||
static bool have_anchor = false;
|
||||
static uint32_t anchor_ms = 0;
|
||||
static int anchor_pct = -1;
|
||||
static int last_pct = -1;
|
||||
static bool last_charging = false;
|
||||
|
||||
void battery_est_update(int percent, bool charging) {
|
||||
last_charging = charging;
|
||||
last_pct = percent;
|
||||
|
||||
if (charging || percent < 0) {
|
||||
// On USB / charging / no reading the estimate is meaningless. Drop the
|
||||
// anchor so the next discharge starts from a fresh baseline.
|
||||
have_anchor = false;
|
||||
return;
|
||||
}
|
||||
// Discharging. Start an anchor, or re-anchor if the gauge ticked UP (it
|
||||
// relaxes upward when load drops) so we never compute a negative rate.
|
||||
if (!have_anchor || percent > anchor_pct) {
|
||||
have_anchor = true;
|
||||
anchor_ms = millis();
|
||||
anchor_pct = percent;
|
||||
}
|
||||
}
|
||||
|
||||
int battery_est_minutes(void) {
|
||||
if (last_charging || last_pct < 0) return -2;
|
||||
if (!have_anchor) return -1;
|
||||
|
||||
int drop = anchor_pct - last_pct;
|
||||
uint32_t dt = millis() - anchor_ms;
|
||||
if (drop < EST_MIN_DROP_PCT || dt < EST_MIN_ELAPSED_MS) return -1;
|
||||
|
||||
// Minutes each 1% has been taking, extrapolated across the remaining pct.
|
||||
float minutes_per_pct = (float)dt / 60000.0f / (float)drop;
|
||||
float mins = (float)last_pct * minutes_per_pct;
|
||||
if (mins < 0) return -1;
|
||||
if (mins > EST_MAX_MINUTES) mins = EST_MAX_MINUTES;
|
||||
return (int)(mins + 0.5f);
|
||||
}
|
||||
Reference in New Issue
Block a user