feat(travelers): TCA9535 充电检测 + 键盘背光 + isVbusIn 修复
- 新增 P1.1 CHARGE_DET 充电检测(高电平=充电中),轮询间隔 2s
- Power.cpp isCharging()/isVbusIn() 均使用 TCA9535_CHARGE_DET_PIN 分支
- 新增 P1.0 键盘背光(高电平点亮),按键时亮,5s 无操作自动熄灭
- 修复开机供电维持:POWER_EN 在 Wire.begin() 后立即锁定
- 修复 P1 config 寄存器值 0x0A(之前 0x8D 导致 P1.2 高阻断电)
- ⚠️ 已知问题:TP4057 电压反串导致未充电时 P1.1 仍读高,需硬件修改
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# 2026-03-29 工作日志
|
||||
|
||||
## 项目初始扫描
|
||||
- 首次读取 firmware-2.7.15.567b8ea 代码结构
|
||||
- 确认项目为 Meshtastic 官方固件的自定义 fork
|
||||
- 发现 4 个自研板卡变体:esp32c3_moonshine / moonshine(带ADC/USB CDC)/ moonshine_mv(全功能)/ moonshine_travelers
|
||||
- 详细记录写入 MEMORY.md
|
||||
|
||||
## TCA9535PWR 矩阵键盘驱动实现
|
||||
- 目标板卡:esp32c3_moonshine_travelers
|
||||
- 新建驱动文件:
|
||||
- `src/input/TCA9535ButtonThread.h` - 驱动类声明,含寄存器宏、extern 指针
|
||||
- `src/input/TCA9535ButtonThread.cpp` - 4×4 矩阵扫描实现
|
||||
- 修改 `variants/esp32c3/diy/esp32c3_moonshine_travelers/variant.h`:
|
||||
- 添加 `HAS_TCA9535_BUTTON` 宏
|
||||
- 添加 `TCA9535_KEY_MAP`(4×4 矩阵行优先映射)
|
||||
- `TCA9535_INT_PIN=5`(GPIO5,低电平有效,下降沿触发)
|
||||
- 修改 `src/main.cpp`:include TCA9535ButtonThread.h,在 setupModules() 后初始化线程
|
||||
- I²C 地址:0x20(A0=A1=A2=0),与 SH1106 屏幕共用 Wire(SDA=0, SCL=1)
|
||||
- 矩阵接法:P0.0~P0.3 行输出,P0.4~P0.7 列输入,逐行拉低扫描,50µs 行间延时
|
||||
|
||||
## LTO 链接错误修复
|
||||
- 编译报 `undefined reference to TCA9535ButtonThread::*`(LTO -flto 导致)
|
||||
- 原因:.h/.cpp 中的 `#if defined(HAS_TCA9535_BUTTON)` 守卫导致在部分编译单元中符号被丢弃
|
||||
- 修复:去掉 .h/.cpp 中的条件守卫,让类定义和实现始终编译
|
||||
- main.cpp 中的实例化和初始化仍由 `#ifdef HAS_TCA9535_BUTTON` 控制
|
||||
- extern 指针声明保留在 `#ifdef` 中,非目标板卡不会引用
|
||||
|
||||
## RadioLib LoRa RST 通过 TCA9535 P1.4 控制
|
||||
- 自定义 HAL 子类 `TCA9535GpioHal` 拦截虚拟引脚 200,转发到 I²C
|
||||
- `tca9535LoraReset(bool high)` 静态函数,read-modify-write P1.4
|
||||
|
||||
## 电源管理(P1.2 + P1.3)
|
||||
- P1.2 = POWER_EN 输出,高电平有效,驱动 MOS 管维持供电
|
||||
- P1.3 = POWER_BOOT 输入,低电平有效(按键按下接地)
|
||||
- 开机流程:物理按键 → MOS 导通 → ESP32 得电 → init() 等 P1.3 持续按住 2 秒 → POWER_EN 拉高
|
||||
- 未按够 2 秒松开 → 不拉高 POWER_EN → 断电
|
||||
- 关机流程:运行中 P1.3 持续按住 2 秒 → POWER_EN 拉低 → 断电
|
||||
- 电源状态机:BOOT_PENDING → RUNNING → SHUTDOWN_PENDING
|
||||
- init() 中 P1 config = 0xEB(P1.2=输出, P1.3=输入, P1.4=输出)
|
||||
- 新增 `tca9535ReadPowerBoot()` 静态函数,读取 P1.3 输入状态
|
||||
- 新增 `tca9535PowerEn(bool on)` 静态函数,read-modify-write P1.2
|
||||
|
||||
## GPS 启用(GP-02 模块)
|
||||
- 问题:`tca9535GpsEn(false)` 在 TCA9535 init 中关闭了 GPS 电源,而 GPS::setup()->probe() 时 powerState=GPS_OFF,writePinEN(true) 只在 GPS_ACTIVE 时才调用 → probe 时模块没电
|
||||
- 修复:在 main.cpp 的 `createGps()` + enablePin 桥接之后,立即 `tca9535GpsEn(true)` + `delay(1000)` 给 GP-02 冷启动上电时间
|
||||
- GP-02 接线:VCC→3.3V, GND→GND, TX→GPIO20(ESP RX), RX→GPIO21(ESP TX),EN/RST/PPS/VRTC 悬空即可
|
||||
- 编译验证通过(esp32c3_moonshine_travelers SUCCESS)
|
||||
|
||||
## GPS 修复:P1.6/P1.7 默认高电平 + RX/TX 交换
|
||||
- 用户要求 GPS_RST(P1.6) 和 GPS_EN(P1.7) 通电后直接设为高电平
|
||||
- TCA9535ButtonThread.cpp init() 中改为 `tca9535GpsEn(true)` 和 `tca9535GpsReset(true)`
|
||||
- 移除 main.cpp 中的 delay workaround
|
||||
- GPS 仍然检测不到 → 交换 GPS_RX_PIN(21→20) 和 GPS_TX_PIN(20→21)
|
||||
- 更新 CHANGELOG.md,提交 311232c,push
|
||||
|
||||
## 九宫格键盘映射
|
||||
- 添加 4×4 矩阵中的数字键:key0-2=1-3, key4-6=4-6, key8-10=7-9, key12=*, key13=0, key14=#
|
||||
- 方向键保留:key3=UP, key7=DOWN, key11=LEFT, key15=RIGHT
|
||||
- 新增 `TCA9535_KEY_CHAR_MAP` 数组,`dispatchEvent()` 传 `kbchar` 参数
|
||||
|
||||
## ⚠️ TCA9535 MATRIXKEY 崩溃修复 + 键盘输入修复
|
||||
- 崩溃现象:按下矩阵键后立即 Load access fault at 0x40058766
|
||||
- 根因:`TCA9535_KEY_CHAR_MAP` 传的是 ASCII 字符(如 '0'=0x30, '9'=0x39),但 `CannedMessageModule` 把 `kbchar` 当 1-based 索引用(`currentMessageIndex = event->kbchar - 1`)。ASCII '0'=48 → index=47 → 数组越界 → 野指针 → 崩溃
|
||||
- 参考 RAK14004 实现:`kbI2cBase.cpp` 中 `PrintDataBuf = aCount*4 + bCount + 1` 传的是 1-16 的索引
|
||||
- 第一版修复(错误方向):把 TCA9535_KEY_CHAR_MAP 改为传索引 1-12
|
||||
- 问题:这样矩阵键只能选 canned message,无法进入文本输入
|
||||
- 正确修复:
|
||||
1. `TCA9535_KEY_CHAR_MAP` 恢复为 ASCII 字符('0'-'9', '*', '#')
|
||||
2. `CannedMessageModule::handleInputEvent()` 修改 MATRIXKEY 拦截逻辑:
|
||||
- 如果 `kbchar` 是可打印 ASCII(32-126):不拦截,让事件 fall through 到正常输入路径
|
||||
→ INACTIVE 状态进入 FREETEXT,FREETEXT 状态追加字符
|
||||
- 如果 `kbchar` 是 1-based 索引(如 RAK14004):继续走 canned message 选择路径
|
||||
- 加边界检查 `idx < 0 || idx >= messagesCount` 防御性忽略
|
||||
|
||||
## P1.1 充电检测 (CHARGE_DET)
|
||||
- P1.1 = CHARGE_DET 输入,高电平=正在充电
|
||||
- P1 config 从 0x8B 改为 0x8D(P1.1 配置为输入)
|
||||
- variant.h 新增 `TCA9535_CHARGE_DET_PIN (1u << 1)`
|
||||
- TCA9535ButtonThread.h 新增 `tca9535ReadChargeDet()` 静态内联函数
|
||||
- TCA9535ButtonThread.cpp 的 runOnce() 每 2 秒轮询 P1.1,更新全局 `tca9535IsCharging`
|
||||
- Power.cpp 的 `AnalogBatteryLevel::isCharging()` 读取 `tca9535IsCharging`(`#ifdef TCA9535_CHARGE_DET_PIN`)
|
||||
- Power.cpp include 条件从 `TCA9535_LORA_RST_VIRTUAL_PIN` 改为 `HAS_TCA9535_BUTTON`
|
||||
Reference in New Issue
Block a user