跳转到内容

电量计与风扇

前提:已完成手动适配页里的 overlay 和 config.txt 配置块—— 其中已经包含本页用到的 stc3117-gauge 和 i2c-fan 那几行。

电池电量由一颗 STC3117 电量计(I2C 地址 0x70)测量,挂在计算模块的 SDA0/SCL0 上。它位于树莓派 / ESP32-S3 之间的 I2C 多路切换器后面,上电时切换给树莓派(也就是树莓派占用屏幕的时候)。

Raspberry Pi OS 没有编译 CONFIG_FUEL_GAUGE_STC3117,所以 TypixDeck 系统把驱动做成 DKMS 模块—— 每当安装了新内核及其 headers,它都会自动重新编译。

Terminal window
sudo apt install -y dkms linux-headers-rpi-v8 linux-headers-rpi-2712
# (the dwc2fix kernel from the USB audio page brings its own headers)
[ -d ~/typixdeck-pi-gen ] || git clone --depth 1 -b typixdeck https://github.com/TypixNode/pi-gen.git ~/typixdeck-pi-gen
SRC=/usr/src/stc3117-fuel-gauge-6.18
sudo mkdir -p $SRC
sudo cp ~/typixdeck-pi-gen/typixdeck-stage/03-battery-dkms/files/{stc3117_fuel_gauge.c,Makefile,dkms.conf} $SRC/
sudo dkms add -m stc3117-fuel-gauge -v 6.18
sudo dkms install -m stc3117-fuel-gauge -v 6.18
sudo reboot

检查:

Terminal window
dmesg | grep stc3117
cat /sys/class/power_supply/stc3117-battery/{capacity,voltage_now,current_now,status}
upower -d | grep -E 'percentage|state'

UPower 会自动接管这块电池,所以各个桌面(labwc 面板、Phosh、Plasma)的电池图标无需额外配置就能用。

stc3117-gauge 描述了这块板子:

属性 值 原因
shunt-resistor-micro-ohms 10000 10 mΩ 电流采样电阻
charge-full-design-microamp-hours 2400000 604070 锂聚合物电池,约 2400 mAh
voltage-min/max-design-microvolt 3.0 V / 4.2 V
factory-internal-resistance-micro-ohms 140000 电量计看到的整包内阻(电芯 + 保护板 + 线材),用 CPU 负载阶跃实测;驱动默认的 200 mΩ 会让初始电量估低约 15 个百分点

总线:CM4 默认目标是 i2c_csi_dsi(GPIO44/45,i2c-10);CM5 要传 i2c_csi_dsi0 参数 (RP1,GPIO38/39)——所以两者的 config.txt 写法不同。不要让 CM4 指向 i2c_csi_dsi0:在 CM4 上那是 GPIO0/1,属于 DPI 屏幕(会报 pin gpio0 already requested)。换用其他电池时,可以用 capacity-uah、 shunt-uohm、rint-uohm 参数覆盖对应数值。

不要在 TypixDeck 上直接加载主线的 stc3117_fuel_gauge。它把 16 × 16 位的 OCV 表当 16 个字节写进去, 把表写坏;把千分比当百分比上报(4.6% 显示成 46%);把电流按无符号读、正负号约定还是反的;还会把 ESP32-S3 已经启动的电量计复位。TypixDeck 版修掉了这些,并且增加了:

  • 每块电池只初始化一次,并与 ESP32-S3 协同。 电量计的状态由两颗处理器共享,所以它们通过电量计自身 带电池供电的 RAM 里的一个标记来协调:谁先拿到总线,谁就根据测得的电压设定初始电量并写入标记; 另一方只读不写。拔掉电池 RAM 会清空,下次重新初始化。没有这个机制时,刚装好的系统可能在满电时只显示 3–6%。
  • 4.2 V 放电曲线,适配 604070 电池,并与对应的电量断点表一起写入(主线的曲线属于 4.35 V 电芯,在这里 永远到不了 100%)。
  • 只有在连续一致的证据下才重新初始化——电压和电流不在同一个转换周期,负载变化时的单次读数不可信。
  • 提供 charge_now / charge_full,供自行计算百分比的面板插件使用;多路切换器把电量计交给 ESP32-S3 期间,电池不会被判定为“已拔出”。

config.txt 配置块里的 i2c-fan,emc2301 那几行,把 Raspberry Pi OS 自带的 i2c-fan overlay 绑定到板上 同一对 SDA0/SCL0 上的 EMC2301。不加的话,控制器一直停在上电默认的 100% 占空比,系统里也没有风扇传感器。

  • 这个 overlay 会自己启用那条总线——不要同时再加 dtparam=i2c_vc=on。
  • 如果要调参数,在 6.12 及更新的内核上 minpwm 必须 ≤ 51:更大的值会让驱动拒绝第一档冷却状态, 风扇 probe 静默失败。midtemp、maxtemp、maxpwm 可以放心调。

CM5 还驱动一个树莓派 5 式的四线 PWM 风扇(pwmfan)。原版曲线对封闭机壳来说太保守——50 °C 起只有 29%—— 所以 TypixDeck 系统保持触发温度不变,把每一档的占空比调高:

触发温度 原版 PWM TypixDeck PWM 实测
50 °C 75 130 3.6k → 6.5k RPM
60 °C 125 180
67.5 °C 175 220
75 °C 250 255 全速 10.0k RPM
[cm5]
dtparam=cooling_fan=on
dtparam=fan_temp0_speed=130
dtparam=fan_temp1_speed=180
dtparam=fan_temp2_speed=220
dtparam=fan_temp3_speed=255

这些参数名由 CM5 自己的设备树定义(fan_temp0..3、_hyst、_speed),所以是安全的;拼错一个 dtparam 正是“开机后风扇不转”的经典原因。查看当前实际生效的值:

Terminal window
od -An -t u1 /proc/device-tree/cooling_fan/cooling-levels # PWM per state
for d in /sys/class/hwmon/hwmon*; do [ -r $d/fan1_input ] && echo "$(cat $d/name) $(cat $d/fan1_input) rpm pwm=$(cat $d/pwm1)"; done

hwmon 编号每次开机可能不同——请按 name 查找风扇,不要写死 hwmonN。