fix(battery): detect TP4056 charging and full states on new board

This commit is contained in:
chenjintao
2026-10-23 16:23:39 +08:00
parent 415c75b0e6
commit 6116a67d5f
13 changed files with 617 additions and 249 deletions
+6 -5
View File
@@ -51,14 +51,15 @@ not been enabled as a replacement.
| `CONFIG_TQ_POWER_HOLD_GPIO` | -1 | No MCU power-hold net on the new board |
| `CONFIG_TQ_RESET_BUTTON_ENABLE` | Disabled | The old optional reset default GPIO14 now belongs to stepper IN1; configure separate physical wiring before enabling |
| `CONFIG_TQ_BATTERY_SHUTDOWN_WAKE_BUTTON_GPIO` | -1 | No additional deep-sleep wake button |
| GPIO8 / 充满检测 | Not consumed | Full-charge input exists on hardware; no option/driver added |
| GPIO8 / 充满检测 | Input | `CONFIG_TQ_BATTERY_FULL_GPIO=8`, low-active TP4056 STDBY# via Q8 |
| GPIO10 / 马达控制 | Not consumed | Rocker-motor gate held off by external R30 pull-down; no new option/driver added |
| GPIO3 / 35 / 36 / 37 / 45 / 46 | NC on schematic | Do not infer arbitrary availability from NC |
Mechanical switches use pull-up only. PTT and charger active levels are retained
from the previous configuration and require actual idle/active measurements.
Battery full-charge prompts still use voltage/percentage/time inference rather
than GPIO8. ADC divider gain/offset remain unchanged pending VBAT measurements.
Battery charge/full state uses GPIO18/GPIO8 with 100ms polling and 1s sampled
stability confirmation. Both active means fault; both inactive means not charging.
Full prompts require a confirmed charging-to-full transition; no voltage inference. ADC divider gain/offset remain unchanged pending VBAT measurements.
## Boot Calibration And Sleep
@@ -66,8 +67,8 @@ than GPIO8. ADC divider gain/offset remain unchanged pending VBAT measurements.
switch 1 on GPIO11 with IN1/IN2/IN3/IN4 = 14/21/47/48. Verify motor direction,
mechanical limits and bounded stop on hardware.
Charge-state edge interrupts and low-active deep-sleep wake both follow
`CONFIG_TQ_BATTERY_CHARGE_GPIO=18`. Verify charger insertion/removal and wake
Charge inputs are polled without GPIO interrupts. Low-active deep-sleep wake follows
`CONFIG_TQ_BATTERY_CHARGE_GPIO=18`; the full input is not a wake source. Verify charger insertion/removal and wake
behavior after changing the board.
## System Interfaces
+20 -12
View File
@@ -1,6 +1,6 @@
# 新旧板 GPIO 对比与固件适配位置
核对日期:2026-10-23。初始对照保留在下文;当前已应用现有功能的新板引脚映射,新增功能仍未接入。验证结果见文末,未烧录或进行实机验收。
核对日期:2026-10-23。初始对照保留在下文;当前已应用新板引脚映射及GPIO8满电检测,GPIO10马达仍未接入。验证结果见文末,未烧录或进行实机验收。
## 对照基线
@@ -17,10 +17,10 @@
大部分引脚在 `sdkconfig.defaults` 和 `main/Kconfig.projbuild` 中修改即可;已有本地 `sdkconfig` 还须通过 `menuconfig` 同步,因为修改 defaults 不会覆盖已经保存的配置。不要手改 `build/config/sdkconfig.h`,也不要提交本地 `sdkconfig`。
后续菜单整理:现有 42 个 GPIO/电平/上下拉配置已集中到
菜单整理:GPIO/电平/上下拉配置已集中到
`TQ Cat Configuration -> Board Hardware Configuration (GPIO)` 单页,按 LCD、音频、
输入、步进、电源/电池分区。配置名及依赖保持原样;默认值及本地有效配置已更新为新板映射,
未新增 GPIO8 充满检测或 GPIO10 马达配置。旧硬编码 GPIO4/5 功能保留源码,
本次充电逻辑重写已新增 GPIO8 充满输入及有效电平配置,GPIO10 马达仍未接入。旧硬编码 GPIO4/5 功能保留源码,
平台初始化已移除其启动调用,不再创建这些任务。
下文 Kconfig 旧行号属于对照时快照,搬迁后应按配置名定位。
@@ -38,8 +38,8 @@
| LCD 时钟 CLK / 新板 SCL | 8 | 8 | **16** | `TQ_SCREEN_SPI_CLK_GPIO`;`lcd_direct.c` SPI bus |
| LCD MISO | 未接 | -1 | 未接 | `TQ_SCREEN_SPI_MISO_GPIO=-1` 保持 |
| 电池电压检测 Power_t / 电量检测 | 9 | 9 | **17** | `TQ_BATTERY_ADC_GPIO`;`platform_battery_driver.c` |
| 充电状态 Charge / 充电检测 | 10 | 10 | **18** | `TQ_BATTERY_CHARGE_GPIO`;电池驱动、充电边沿中断及深睡唤醒链路 |
| 独立充满检测 | 未接入 MCU | 无 | **8** | 当前无配置项;需新增采样配置和状态映射,见后文 |
| 充电状态 Charge / 充电检测 | 10 | 10 | **18** | `TQ_BATTERY_CHARGE_GPIO`;电池驱动、双路轮询及深睡唤醒链路 |
| 独立充满检测 | 未接入 MCU | 无 | **8** | `TQ_BATTERY_FULL_GPIO` / `TQ_BATTERY_FULL_ACTIVE_LEVEL`;见后文 |
| 功放 PA_CTRL | 11 | 11 | **9** | `MULTIMODAL_AUDIO_PA_GPIO`;音频 codec 初始化及运行时使能 |
| 开关1 / 原 SW1 | 12 | 校准输入 12 | **11** | 若保持开关1作校准:`TQ_CALIBRATION_SWITCH_GPIO` |
| 开关2 / 原 SW2 | 13 | 抽签输入 13 | **12** | 若保持开关2作抽签:`TQ_SLOT_SWITCH_GPIO` |
@@ -92,7 +92,7 @@
| [platform_battery_driver.c](../components/platform/src/platform_battery_driver.c) | 约 136 行状态输入;158 行 ADC 映射;296 行采样状态 | 迁移 ADC/充电输入;新增独立充满输入及原始样本处理 |
| [platform.h](../components/platform/include/platform.h) | 约 406 行电池硬件样本契约 | 如接入充满检测,扩展平台硬件样本,保留未知/无效状态 |
| [domain.h](../components/domain/include/domain.h) / [domain_battery_service.c](../components/domain/src/battery/domain_battery_service.c) | 领域电池语义;样本到领域状态映射;约 363 行深睡调用 | 领域层拥有充电/满电语义,不能由显示层直接读取 GPIO8 判断 |
| [control_plane_battery_service.c](../components/control_plane/src/runtime/control_plane_battery_service.c) | 104 行起充电中断;约 400 行后满电推断/提示 | 迁移充电引脚配置自动覆盖现有中断;若新增满电检测,调整确认/提示策略和相应事件来源 |
| [control_plane_battery_service.c](../components/control_plane/src/runtime/control_plane_battery_service.c) | 充电轮询、独立ADC定时及提示 | 不注册充电GPIO中断;只有领域确认充电→满电才提示 |
| [domain_runtime_adapters.c](../components/domain/src/runtime/domain_runtime_adapters.c) | 807 / 836 / 865 行三路数字输入映射 | 已读取配置,单纯迁脚通常无需改;核对 PTT 有效电平 |
| [control_plane_key_input.c](../components/control_plane/src/runtime/control_plane_key_input.c) | 158 行起 `s_key_configs` | 同步核对三路按键及可选 reset,不把两个功能配置到同一 GPIO |
| [audio_pipeline_codec_impl.c](../components/platform/src/multimodal/audio_pipeline/audio_pipeline_codec_impl.c) | 148 行 I2C;223 行 I2S;318 行 PA | I2C/I2S 不变,PA 配置迁移到 9 |
@@ -122,11 +122,19 @@ GPIO17 的“电量检测”来自下板 Q5/Q6 控制后的电池分压:R6、R
新下板正式电路使用 TP4056,CHRG#/STDBY# 经 Q7/Q8、3.3V 上拉后送至 GPIO18/GPIO8。按电路作用可预期状态拉低时对应输入低有效,但这属于图纸推断:首次上板应记录“未插电 / 正在充电 / 充满 / 无电池”的两路实际电平,再确定配置和异常组合处理。不能仅凭换了充电芯片就反转电平。
现有固件只有“未知 / 未充电 / 充电中”硬件充电状态,满电提示依赖电压、百分比、时间确认。`TQ_BATTERY_FULL_MIN_*` 是满电推断阈值,**不是 GPIO8 配置项**。
当前固件以两路输入生成“未知 / 未充电 / 充电中 / 满电 / 异常”状态。
每100ms轮询,采样电平组合稳定1秒才更新;采样间断超过250ms重新确认,
持续2秒未能确认稳定组合时退出旧状态并标记未知,避免旧“充电中”长期屏蔽低压保护。
两路同时有效为异常,两路均无效只代表未充电,不证明 USB 或电池是否存在。
ADC失败、负载抑制不阻塞数字输入更新。
最小迁移可以先只使用 GPIO18,保留旧满电推断,并明确 GPIO8 尚未使用。要利用独立充满检测,需增加配置、平台原始采样、领域状态解释及控制层提示策略;不在上层 facade 复制平台类型,也不在 LCD 内读取原始 GPIO。
满电提示要求本次运行先确认充电,再直接确认满电;启动已满不播、拔线/异常/读取失败
打断本轮、不用电压和百分比推断满电。旧 `TQ_BATTERY_FULL_MIN_*` 和
`TQ_BATTERY_FULL_CONFIRM_SEC` 已移除;新增两项仍放在 GPIO 单页。
详细触发规则、测试和实机检查见 [新板充电检测](新板充电检测.zh-CN.md)。
充电 GPIO 同时参与中断和深睡唤醒:`domain_battery_service.c` 将 `CONFIG_TQ_BATTERY_CHARGE_GPIO` 传给 `platform_power_enter_deep_sleep()`,实施时一并检查唤醒驱动对新引脚及有效电平的处理。
GPIO18仍为低有效深睡唤醒源,GPIO8不参与唤醒。唤醒保护先轮询两路约1.2秒再读取ADC,
避免尚未去抖就再次入睡;深睡接口仍要求板级低有效连接。
### 4. 两个机械开关与触摸 PTT
@@ -144,7 +152,7 @@ GPIO17 的“电量检测”来自下板 Q5/Q6 控制后的电池分压:R6、R
## 已应用的新板配置
以下已有配置项均已写入 Kconfig 默认值、sdkconfig.defaults 和本地 sdkconfig。PTT 有效电平仍待实测,新增 GPIO8/10 功能未接入。
以下已有配置项均已写入 Kconfig 默认值、sdkconfig.defaults 和本地 sdkconfig。PTT 有效电平仍待实测;GPIO8现已接入,GPIO10仍未接入。
```ini
CONFIG_TQ_SCREEN_BACKLIGHT_GPIO=4
@@ -171,7 +179,7 @@ CONFIG_TQ_STEPPER_IN3_GPIO=47
CONFIG_TQ_STEPPER_IN4_GPIO=48
```
平台初始化已停止调用旧 GPIO4/5 输出模块;GPIO8 满电和 GPIO10 马达没有新增配置项。音频 SDA=1、SCL=2、MCLK=38、BCLK=39、DOUT=40、WS=41、DIN=42 保持。
平台初始化已停止调用旧 GPIO4/5 输出模块;GPIO8满电输入已接入,GPIO10马达仍未接入。音频 SDA=1、SCL=2、MCLK=38、BCLK=39、DOUT=40、WS=41、DIN=42 保持。
## 实施顺序与验证边界
@@ -184,7 +192,7 @@ CONFIG_TQ_STEPPER_IN4_GPIO=48
本次证据层级:两份 PDF 文本提取及关键连线视觉核对、工作区配置和源码静态核对。新板配置的构建与回归记录见下方;没有设备验证结果。
### 2026-10-23 重新切换新板后的验证记录
### 2026-10-23 重新切换新板后的验证记录(充电逻辑重写前快照)
本次在保留 VAD 重复 PTT 修复和 kikivok.com 域名迁移的基础上重新应用;以下主机测试与构建均已重新执行。
+2 -2
View File
@@ -20,8 +20,8 @@ Configuration (GPIO)`; see [firmware usage](firmware-pin-usage.md).
| 8 | GPIO15 | SDA | Output | ST7789P3 SPI MOSI | SPI data, not I2C SDA |
| 9 | GPIO16 | SCL | Output | ST7789P3 SPI clock | SPI clock, not I2C SCL |
| 10 | GPIO17 | 电量检测 | Analog input | Battery voltage sense | Lower-board R6/R11=100 kOhm each, Q5/Q6 switching; upper-board C31 filter |
| 11 | GPIO18 | 充电检测 | Input | TP4056 CHRG# via Q7 | Low-active assumption requires hardware verification |
| 12 | GPIO8 | 充满检测 | Input | TP4056 STDBY# via Q8 | Not consumed by current firmware; no new option added |
| 11 | GPIO18 | 充电检测 | Input | TP4056 CHRG# via Q7 | Low-active; polled with GPIO8; hardware verification pending |
| 12 | GPIO8 | 充满检测 | Input | TP4056 STDBY# via Q8 | Low-active; CONFIG_TQ_BATTERY_FULL_GPIO; stable confirmation in domain |
| 13 | GPIO19 | ESP_D_N | Bidirectional | USB D- | Type-C |
| 14 | GPIO20 | ESP_D_P | Bidirectional | USB D+ | Type-C |
| 15 | GPIO3 | NC | N/A | No assigned net | Old touch input moved to GPIO13 |
+70
View File
@@ -0,0 +1,70 @@
# 新板 TP4056 充电检测
2026-10-23:本实现替换旧单路充电检测与满电电压推断。
## 接线与状态
新板正式 TP4056 电路的 CHRG# 经 Q7 接 GPIO18,STDBY# 经 Q8 接 GPIO8。
两路默认低有效,3.3V上拉。配置位于 `TQ Cat Configuration -> Board Hardware
Configuration (GPIO)`;GPIO10马达没有接入。
| GPIO18 | GPIO8 | 确认后的领域状态 |
| --- | --- | --- |
| 低 | 高 | charging,充电中 |
| 高 | 低 | full,充满信号有效 |
| 高 | 高 | not_charging,未充电 |
| 低 | 低 | fault,异常组合 |
原理图只能支持接线推断,仍须实测未插电、充电、充满、无电池的实际电平。
两个状态脚不能可靠确定USB存在或电池存在;`full`表示芯片输出的稳定充满信号,
不等于检测到了电池。百分比仍按电压估算,不因满电信号强制改为100%。
## 检测与提示
- 平台只读取原始数字电平和ADC,不解释充电语义。数字输入初始化不依赖ADC校准。
- 领域每100ms检查一次两路组合;连续采样稳定1秒才发布状态。超过250ms未轮询,
丢弃旧稳定假设并重新确认;持续抖动2秒则置未知。读取失败立即置未知。
这是采样去抖,不能证明两个采样点之间没有短脉冲。
- 控制层不注册GPIO边沿中断,复用原有电池任务,无新增任务或定时器。
领域快照同时保留最近读取的有效性和两路有效信号,供状态转换日志诊断;
最近原始输入可能与尚未改变的去抖状态不同。
- 本次运行先确认充电,再确认满电才播放一次满电提示。启动已满、充电后拔线、
异常或读取失败均不播放;后两类还会取消本轮提示资格。重新确认充电可开启下一轮。
- 移除旧的最低满电电压、百分比及30秒推断时间配置;满电不再靠电压推断。
GPIO页新增 `TQ_BATTERY_FULL_GPIO=8`、`TQ_BATTERY_FULL_ACTIVE_LEVEL=0`。
## ADC、低电量和深睡
ADC正常10秒一次,轻待机300秒一次,失败或负载抑制1秒后重试;进入或退出轻待机
立即安排新样本。低压关机确认期间1秒一次。数字信号抖动不加速ADC采样,也不重复
消费旧样本推进关机计数。ADC失败会清空控制层低压确认计数。
原有电量曲线、滤波、负载抑制及阈值保持:低电量≤20%确认3次,≥25%退出;
未判定充电时,电量≤5%且滤波电压≤3.45V确认3次,或最新有效电压≤3.35V确认2次,
进入受控关机。未知/异常不冒充充电,不用来长期屏蔽原有低压保护。
GPIO18仍是低有效深睡唤醒源;GPIO8不作为唤醒源。唤醒保护提供约1.2秒有界轮询窗口,
确认充电或满电,或有效电压≥3.55V后允许继续启动。窗口内调度中断或输入抖动可能
导致状态仍未知,此时按电压判定,不无限等待。
## 验证与实机验收
主机回归入口:
```sh
python3 tools/test_battery_adc_init.py
python3 tools/test_battery_charge_detection.py
```
第一项提取实际平台C函数,验证GPIO18/8联合输入初始化、独立数字读取、ADC1/ADC2、
锁失败、校准失败释放和重试。第二项编译实际领域代码,用可控时钟和GPIO/ADC验证
四种输入组合、启动未知、连续抖动、稳定确认、长采样间隔、读取失败、ADC失败及
负载抑制独立性;并提取实际控制层电池任务,验证ADC节奏、待机切换、启动已满、
充电→满电提示、拔线取消及ADC失败不累计关机确认。
使用AddressSanitizer和UndefinedBehaviorSanitizer。
本次上述两个电池测试与五个显示回归脚本已通过;ESP-IDF 5.5.4新板配置构建通过。
未烧录,尚无本次逻辑的实机电平、提示或深睡验收结果。
实机仍需验证:不插电静置、插拔充电、充满、无电池、扬声器/电机/Wi-Fi并行、低电量
保护、深睡插电唤醒。对照GPIO18/8电平和万用表VBAT;主机测试或构建不能代替这些测量。