# M5Stack Unit ADC v1.1 / ADS1110 开发约定 本文供后续 Codex 或维护者读取。动手写驱动前,先确认实物是 `M5Stack Unit ADC v1.1`、SKU `U013-V11`、ADC 芯片 `ADS1110`。不要把旧版 Unit ADC、ADS1100 库或其他 ADS111x 芯片的寄存器接口混进来。 ## 1. 当前项目边界 - 主控:`WalnutPi ZeroW`(H618) - 目的:测量点阵屏输入端 5V 电压,作为供电压降的数字观测值 - I²C 总线:`/dev/i2c-1` - 7 位地址:`0x48` - GPIO:物理脚 3 / `PI8/SDA1`,物理脚 5 / `PI7/SCL1` - 供电假设:系统已经提供可靠、共地的 `5V/GND` - 当前交付:本地资料、独立脚本,以及主服务中的电压状态、校准和可选低电压亮度保护 - 明确不做:电流、功率、实际发光亮度识别、BMS、物理断电、充电管理或核桃派关机 测量端是并联采样。屏幕负载电流不得经过模块。v1.1 原理图中 P1 测量负端经 `0Ω` 电阻接模块 GND,因此不能把它当成与核桃派隔离的差分表使用。 ## 2. 资料优先级和已知冲突 遇到资料冲突时采用以下优先级: 1. 实物型号、v1.1 原理图和 TI ADS1110 数据手册 2. M5Stack Unit ADC v1.1 产品描述及管脚表 3. M5Stack 产品页中的规格汇总表 4. M5Stack 旧 Arduino 示例和 `M5-ADS1100` 仓库 当前 M5Stack 产品页存在混杂信息:正文把 v1.1 描述为 ADS1110,并给出 `15/30/60/240 SPS`;但部分规格/比较表仍显示 ADS1100 或 `8/16/32/128 SPS`,链接的旧 Arduino 例程也使用 `M5_ADS1100.h`。对 `U013-V11` 必须使用 ADS1110 的 `15/30/60/240 SPS` 位定义,不得照抄旧库常量。 本地官方文件、原始 URL、下载日期和 SHA-256 见 `官方资料/来源索引.md`。 ## 3. 板级模拟换算 v1.1 原理图在测量输入端使用 `510kΩ` 与 `100kΩ` 分压,并由 LM358 缓冲后送入 ADS1110。标称分压倍率为: ```text (510k + 100k) / 100k = 6.1 ``` ADS1110 在 PGA=1 时的差分满量程为 `±2.048V`。选择 15 SPS 时输出为 16 位二进制补码,因此: ```text ADC差分电压 = signed_raw × 2.048 / 32768 屏幕输入电压 = ADC差分电压 × 6.1 × calibration_factor ``` 默认 `calibration_factor = 1.0`。屏幕端每 LSB 的标称分辨率为: ```text 2.048 / 32768 × 6.1 = 0.00038125V ``` 快速合理性检查: | 屏幕输入端标称电压 | 预期 raw(约) | |---:|---:| | `0V` | `0` | | `4.5V` | `11803` | | `5.0V` | `13115` | | `5.3V` | `13902` | | `12.0V` | `31475` | `raw=32767` 对应标称约 `12.4924V`,但这只是数学满量程;模块官方输入范围仍按 `0V ~ 12V`,不能把多出的计算余量当成允许输入范围。 ## 4. ADS1110 配置字节 ADS1110 配置寄存器只有 1 字节: | 位 | 名称 | 本项目值 | 含义 | |---:|---|---:|---| | 7 | `ST/DRDY` | 写入时 `0` | 连续模式下写入值被忽略;读取时 `0` 表示本次结果是新数据 | | 6:5 | 保留 | `00` | 必须为 0 | | 4 | `SC` | `0` | 连续转换模式 | | 3:2 | `DR1:DR0` | `11` | 15 SPS、16 位 | | 1:0 | `PGA1:PGA0` | `00` | PGA=1 | 因此本项目写入: ```text 0b00001100 = 0x0C ``` ADS1110 上电默认配置读值通常为 `0x8C`;位 7 是读取状态,校验配置时只比较低 7 位是否等于 `0x0C`。不要把 ADS1100 的采样率名称套在相同位值上。 ## 5. I²C 读写顺序 ADS1110 没有常见的“寄存器地址指针”步骤: 1. 以 7 位地址 `0x48` 打开 I²C 从设备。 2. 写入单个配置字节 `0x0C`。 3. 至少等待一个 15 SPS 转换周期,约 `66.7ms`;实现可留少量余量。 4. 一次读取 3 字节: - 字节 0:输出寄存器高字节 - 字节 1:输出寄存器低字节 - 字节 2:配置/状态字节 5. 将前两个字节按大端、有符号 16 位二进制补码解析。 6. 检查配置低 7 位仍为 `0x0C`;位 7 为 `0` 时,本次结果为新数据。 不要使用会自动在事务前发送“寄存器编号”的 SMBus 便捷函数,除非确认它能发出 ADS1110 所需的原始事务。当前独立脚本直接操作 `/dev/i2c-1`,避免引入依赖或错误的寄存器前缀。 ## 6. 独立脚本接口 文件:`示例程序/read_unit_adc_v1_1.py` 默认行为: - 总线 `/dev/i2c-1` - 地址 `0x48` - 配置 `0x0C` - 每次取 5 个新样本的中位数 - 输出屏幕输入端电压、raw 中位数和配置字节 常用命令: ```bash # 本机纯计算/协议自测,不访问 I²C,Windows 也可以运行 python "硬件相关资料和硬件的连接/M5Stack Unit ADC v1.1相关内容/示例程序/read_unit_adc_v1_1.py" --self-test # 核桃派单次读数 python3 "硬件相关资料和硬件的连接/M5Stack Unit ADC v1.1相关内容/示例程序/read_unit_adc_v1_1.py" # 连续读数 python3 "硬件相关资料和硬件的连接/M5Stack Unit ADC v1.1相关内容/示例程序/read_unit_adc_v1_1.py" --watch # 使用一次比例校正 python3 "硬件相关资料和硬件的连接/M5Stack Unit ADC v1.1相关内容/示例程序/read_unit_adc_v1_1.py" --calibration-factor 1.00604 --watch ``` 额外参数通过 `--help` 查看。独立工具必须保持 Python 标准库实现并与主服务监测器分开;不能把独立无限循环直接放进 FastAPI 进程,也不能与主服务同时长期读取同一地址。 ## 7. 错误与排障语义 后续修改脚本时必须保留可区分的错误: - `/dev/i2c-1` 不存在:I²C 未启用或设备节点不同。 - 权限不足:用户没有访问 I²C 设备的权限。 - 地址无响应:`0x48` 没有 ACK,优先查接线、供电和型号。 - 地址被占用:内核驱动已经 claim 该地址。 - 短读取:没有取得完整 3 字节,结果不可用。 - 配置低 7 位不是 `0x0C`:设备/协议不符或配置被改变,不能继续按 15 SPS/PGA=1 换算。 - 负 raw:按二进制补码保留并报告,不要在协议层静默截成 0;对本项目的正电压输入,持续负值应视为接线或偏置异常。 - 读数超出 `0V ~ 12V`:报告异常并检查硬件,不能用软件裁剪后假装正常。 `i2cdetect` 只用于首次诊断,不要在长期读取过程中反复扫描总线。 ## 8. 主服务集成约束 主服务已经按 `WEB-SCREEN-VOLTAGE` / `CONFIG-SCREEN-VOLTAGE` 接入网页电压显示和每台设备独立的软件校准,并按 `WEB-LOW-VOLTAGE-PROTECTION`、`CONFIG-LOW-VOLTAGE-PROTECTION`、`DISPLAY-LOW-VOLTAGE-PROTECTION` 接入可选保护。实现必须继续满足: - ADC 缺失或读取失败不能拖垮显示服务。 - 只有一个组件负责持续读取设备,其他组件读取缓存值,避免并发争用 I²C。 - 原始电压、校正系数、采样时间和错误状态要可区分,不能把读取失败伪装成 `0V`。 - 低电压保护阈值来自本项目真实屏幕和供电试验:校准后、未舍入的组中位数严格大于 `4.8V` 不限制,`4.5..4.8V` 使用 `floor(50 + 50 × (V-4.5)/0.3)` 限制实际亮度,严格低于 `4.5V` 进入 35% 低电图标;不能从 ADC 量程另行推导或改写边界。35% 来自覆盖保护膜后的红色可视性复测。 - 电压正常不等于屏幕状态正常;界面文案必须称为“屏幕输入电压”,不能称为“屏幕亮度传感器”。 - 正常轮询与校准专用采样都必须经过同一个监测组件,不能让 API 请求和后台线程并发打开设备。 - 校准使用同一测量点的可靠万用表参考值,只做单点比例修正;更换 ADC、接线或测量点后恢复 `1.0` 并重新校准。 - 每组继续取 `5` 个 15 SPS 新样本中位数。保护关闭或稳定高于 `4.8V` 时组起始间隔为 `5s`;高于阈值但持续下降时按预计到达阈值缩短为 `1..5s`;限亮为 `1s`;首次临界为 `0.5s`,之后按 `clamp(0.5, 2.0, 0.02/max(|dV/dt|, 0.01))` 自适应,放慢每轮最多增加 `0.5s`、加速立即生效;错误按 `1/2/5s` 退避。 - 每次 I²C 尝试使用单调序号并拒绝晚到旧结果。更严格保护一组立即发布,任何放宽需连续两组成功样本;失败取消待放宽,首次尚无样本不锁屏,已有成功样本后保持最后保护并标记 stale。 - 保护回调必须在监测锁和 I²C 锁外执行;回调错误与 ADC 状态分开,不能污染样本或解除保护,并要在后续周期重试。完整网页、配置和显示契约以 `WEB-LOW-VOLTAGE-PROTECTION`、`CONFIG-LOW-VOLTAGE-PROTECTION`、`DISPLAY-LOW-VOLTAGE-PROTECTION` 为准。 ## 9. 浏览器救援条件 以下情况才进入浏览器: - 实物不是 `U013-V11` 或 PCB 修订发生变化。 - 地址不是 `0x48`。 - 本地 PDF 损坏或与实物丝印冲突。 - 需要确认 ADS1110 电气极限、时序或未在本文覆盖的模式。 优先访问官方来源: - M5Stack: - v1.1 原理图: - TI ADS1110: - 核桃派项目约定:使用系统已有的 `/dev/i2c-1`,不运行其他开发板专用配置工具 浏览时使用 `U013-V11 ADS1110` 作为组合关键词,并记录所用来源和日期。论坛、商家详情和旧 `M5-ADS1100` 代码只能作为线索,不能覆盖原理图与 TI 数据手册。