feat: ESP32 battery monitoring + adaptive screen brightness

Add battery voltage/level sensors (GPIO1 ADC) for the dock battery holder.
Screen now wakes at a configurable dim level on radar presence (default 30%)
and jumps to 100% for voice activity (listening, thinking, replying).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Aodhan Collins
2026-03-20 20:02:17 +00:00
parent ffc2407289
commit d5811e5b28
2 changed files with 59 additions and 13 deletions

View File

@@ -67,6 +67,7 @@ ESP32-S3-BOX-3
| Sensor dock I2C SCL | GPIO40 | sensor bus (AHT-30, AT581x radar) |
| Sensor dock I2C SDA | GPIO41 | sensor bus (AHT-30, AT581x radar) |
| Radar presence output | GPIO21 | AT581x digital detection pin |
| Battery voltage ADC | GPIO1 | dock battery holder, voltage divider (×2) |
---
@@ -117,6 +118,14 @@ Optional accessory dock connected via secondary I2C bus (GPIO40/41, 100kHz):
- **AT581x mmWave radar** — presence detection via GPIO21, I2C for settings config
- **Radar RF switch** — toggle radar on/off from HA
- Radar configured on boot: sensing_distance=600, trigger_keep=5s, hw_frontend_reset=true
- **Battery monitoring** — ADC on GPIO1 with voltage divider (×2), reports voltage + percentage (Li-ion 3.04.2V curve)
### Display Brightness
Screen brightness adapts to context:
- **Radar presence** → wakes at configurable dim level (default 30%, adjustable 5100% via "Radar brightness" entity in HA)
- **Voice activity** (listening, thinking, replying, error, timer) → full 100% brightness
- **Idle timeout** → screen off (configurable 160 min)
### Voice Assistant

View File

@@ -147,7 +147,9 @@ binary_sensor:
id: radar_presence
device_class: occupancy
on_press:
- script.execute: screen_wake
- script.execute:
id: screen_wake
brightness_pct: !lambda return id(radar_brightness).state;
- script.execute: screen_idle_timer
# --- Display backlight ---
@@ -371,22 +373,22 @@ script:
- lambda: |
switch(id(voice_assistant_phase)) {
case ${voice_assist_listening_phase_id}:
id(screen_wake).execute();
id(screen_wake).execute(100.0f);
id(s3_box_lcd).show_page(listening_page);
id(s3_box_lcd).update();
break;
case ${voice_assist_thinking_phase_id}:
id(screen_wake).execute();
id(screen_wake).execute(100.0f);
id(s3_box_lcd).show_page(thinking_page);
id(s3_box_lcd).update();
break;
case ${voice_assist_replying_phase_id}:
id(screen_wake).execute();
id(screen_wake).execute(100.0f);
id(s3_box_lcd).show_page(replying_page);
id(s3_box_lcd).update();
break;
case ${voice_assist_error_phase_id}:
id(screen_wake).execute();
id(screen_wake).execute(100.0f);
id(s3_box_lcd).show_page(error_page);
id(s3_box_lcd).update();
break;
@@ -400,7 +402,7 @@ script:
id(s3_box_lcd).update();
break;
case ${voice_assist_timer_finished_phase_id}:
id(screen_wake).execute();
id(screen_wake).execute(100.0f);
id(s3_box_lcd).show_page(timer_finished_page);
id(s3_box_lcd).update();
break;
@@ -560,14 +562,12 @@ script:
- id: screen_wake
mode: restart
parameters:
brightness_pct: float
then:
- if:
condition:
light.is_off: led
then:
- light.turn_on:
id: led
brightness: 100%
- light.turn_on:
id: led
brightness: !lambda return brightness_pct / 100.0f;
# --- Switches ---
@@ -689,6 +689,18 @@ number:
max_value: 60
step: 1
initial_value: 1
- platform: template
name: Radar brightness
id: radar_brightness
icon: "mdi:brightness-6"
entity_category: config
unit_of_measurement: "%"
optimistic: true
restore_value: true
min_value: 5
max_value: 100
step: 5
initial_value: 30
# --- Sensor dock (ESP32-S3-BOX-3-SENSOR) ---
@@ -709,6 +721,31 @@ sensor:
window_size: 5
send_every: 5
update_interval: 30s
# --- Battery voltage (dock battery holder, GPIO1 with voltage divider) ---
- platform: adc
pin: GPIO1
name: Battery Voltage
id: battery_voltage
attenuation: 12db
update_interval: 60s
filters:
- multiply: 2.0 # voltage divider ratio on dock
- sliding_window_moving_average:
window_size: 5
send_every: 5
- platform: template
name: Battery Level
id: battery_level
unit_of_measurement: "%"
device_class: battery
accuracy_decimals: 0
update_interval: 60s
lambda: |-
float v = id(battery_voltage).state;
if (v >= 4.2) return 100.0f;
if (v <= 3.0) return 0.0f;
// Simple linear approximation for Li-ion 3.0V4.2V
return (v - 3.0f) / 1.2f * 100.0f;
at581x:
i2c_id: sensor_bus