KOEN中HI

软件结构 · 试验台

2026-10-11 设计记录 · 处理部 NXP i.MX 95 · ECG AFE159RP8 · SpO2 AFE4490 · 器件试验台 ESP32-S3 + ADS1293

标记:已确定 已作为规格确定的项目 · 默认值 设计文档所定的值(未确定) · 未确认 尚未通过原文·实测确认的值。通过算术得出的值标为「计算」。

目录

  1. 整体架构
  2. 内核分配与 M33
  3. 采样率与信号路径
  4. 内核间通信 (共享环形缓冲 · RPMsg)
  5. 延迟预算
  6. Holter 存储 · 趋势
  7. 报警引擎
  8. 状态机
  9. 启动自检
  10. 云 · 安全 · 更新
  11. 软件等级划分 · 模块
  12. 开发顺序 · 实测清单
  13. 试验台固件 (ESP32-S3 + ADS1293)
  14. 试验台验证结果

1. 整体架构

处理部为 NXP i.MX 95。接触患者的测量部(患者岛)是隔离的,经数字隔离器(ISO7762)与处理部相连。处理部芯片构成(i.MX 95 · AFE159RP8 · AFE4490 · 第 2 阶段 RM44L920)为 已确定 规格,下面的内核分配为 默认值。

 患者岛(隔离, CF)                       │ 非患者侧 (i.MX 95 SoM)
 ──────────────────────────────────────┼───────────────────────────────────────
 AFE159RP8 (ECG 8ch, 电极 10, 起搏芯片内) ─ISO7762#1─ LPSPI-A ┐
 AFE4490   (SpO2, PRF 500 Hz)            ─ISO7762#2─ LPSPI-B ├─► Cortex-M7 800 MHz (FreeRTOS)
 V1/V5 开关 · sim/signal 开关状态          ─(隔离 GPIO)────────┘   采集·滤波·QRS·起搏·SpO2
 (+选配) NIBP 模块 UART · Resp(AFE 内置)                            ·报警判定·报警音
                                                    │ 共享 DDR 环(波形) + RPMsg(命令·事件)
                                                    ▼
                         Cortex-A55 ×6 (Linux, Yocto)  屏幕(Qt)·Holter·趋势·云·OTA·日志·权限
                         Cortex-M33 (NXP SM)           电源·时钟·复位·PMIC·故障响应(以 LM 为单位复位)
 外部:TPS3430 窗口看门狗(由 M7 喂狗) → WDO → 备用蜂鸣器 + A55 GPIO   [第 2 阶段] RM44L920 安全 MCU (SPI)
 LTC1760 + 智能电池组 A/B (SMBus, 归 M7) · VSYS 欠压比较器 → M7 IRQ

内核分配原则三条 默认值

  1. 涉及患者安全的路径(采集 → 判定 → 报警音)由 M7 一颗内核闭环完成。 即使 Linux 崩溃,声音仍会响。
  2. Linux 只负责「显示·存储·发送」。 Linux 停止时,M7 会察觉并发出高优先级「显示故障」报警。
  3. M7 停止时,System Manager(SM)只复位 M7,在此期间 TPS3430 鸣响备用蜂鸣器,A55 将波形变为灰色。

2. 内核分配与 M33

设计审查中改变的一点 — M33 上不能放监视·报警备份。 i.MX 95 的 M33 是 NXP System Manager 专用内核。NXP imx-sm 文档(sm/doc/arch.md)原文:

  • 「SM owns the M33 core and does not support customers adding workloads to this core.」
  • 「the Cortex-M33 is not available to run customer applications. … additional customer functionality may interfere with the real-time response of the SM.」

因此 默认值 定为如下。M33 保持 NXP SM 原样(不改代码,只改配置文件),将 SM 的故障响应(FCCU·看门狗 → 只复位相应 LM)用作「第 1 层硬件监视」。SM 配置中已包含 M7_LOCKUP → M7(LM1) 复位、WDOG3/WDOG4 → AP(LM2) 复位 响应。监视·报警备份为 第 1 阶段:M7 ↔ A55 互相监视 + 外部窗口看门狗 TPS3430 + 备用蜂鸣器,第 2 阶段:由 RM44L920 接管。

各内核职责 默认值

内核OS职责
M7 (800 MHz,SoM 供应商标称)FreeRTOS + MCUXpresso SDK + RPMsg-Lite (备选方案 Zephyr)AFE159RP8·AFE4490 采集,公共时间轴,起搏检测,抽取,双重自适应陷波,HPF/LPF,QRS·HR,SpO2·PR·PI,(选配) 呼吸·NIBP,报警条件判定·优先级·报警音合成,导联脱落·传感器脱落,电源监视(LTC1760·电池组·VSYS),外部看门狗喂狗,A55 监视
M33NXP SM (裸机,无自有代码)电源·时钟·复位·PMIC,TRDC 资源隔离,FCCU 故障响应,复位原因记录
A55 ×6Linux (NXP 供应商内核)Qt 6 屏幕,Holter 记录,趋势 DB,报警显示·操作·日志,设置·权限,云同步,OTA·USB 更新,服务模式,安全
RM44L920 (第 2 阶段)TI HALCoGen + 自研 (未定)报警判定双重比对,备用报警音,外部看门狗管理,失效安全决策

资源归属 (由 SM 配置固定)

资源归属备注
LPSPI ×2 (ECG·PPG 专用总线)M7AFE4490 在未选中时不能进入三态,因此禁止共享总线
DRDY·ADC_RDY 中断 GPIO,开关状态 GPIOM7
通用时间戳定时器 1 个M7ECG·PPG 公共时间轴
SAI 或 PWM + 报警音放大器M7必须与 Linux 无关地发出声音
I²C(SMBus) → LTC1760·电池组 A/BM7因为电源报警由 M7 判定
(选配) NIBP UARTM7M7 需要知道泵工作期间的 ECG 噪声标示
WDOG5M7 (SM 故障响应)WDOG5 → LM_RESET lm 1
PMIC I²C,时钟,复位SM
显示(LVDS)·GPU·eMMC·USB·Wi-Fi/BT·GbE ×2·备用蜂鸣器 GPIOA55
ELE(EdgeLock Secure Enclave)启动链·A55

资源预算 (计算·默认值)

项目值备注
M7 ITCM / DTCM256 KB / 256 KB以 Zephyr dts 为准。NXP 参考手册原文 未确认
M7 代码位置ITCM (DSP·ISR),大表放 DDR默认值
M7 负载估算8 kHz 中断(每次 ≤ 5 µs → 4 %) + 抽取 FIR 约 0.75 M MAC/s + 陷波·QRS(500 SPS) → 低于 10 %计算。计划用 DWT 周期计数器实测
共享 DDR 保留区32 MiB (环约 23.2 MiB + 余量)计算

3. 采样率与信号路径

为什么是 8 kSPS

默认值 ECG 所有通道以 8 kSPS 24 位 采集。起搏采用 芯片内检测(第 1 级) + M7 软件检测(第 2 级确认)。若通过详细数据手册确认芯片内检测完全满足要求,再考虑降到 2 kSPS,在此之前固定为 8 kSPS。

M7 内部路径

AFE159RP8 8 kSPS × 8ch × 24bit ── DRDY ISR → LPSPI DMA ─┐
                                                         ├─ ① 打时间戳 (通用定时器 32bit, 样本号 u64)
AFE4490 500 SPS × 6 流 ── ADC_RDY ISR → LPSPI ───────────┘
   ├─ ② 起搏:芯片标志 + 8 kSPS 斜率·宽度确认 → 事件 {样本号, 导联, 宽度}
   ├─ ③ 起搏消隐:在 8 kSPS 下用直线插值填补脉冲区间
   ├─ ④ 抽取 8000 → 2000 → 500 SPS (线性相位 FIR 2 级, ÷4·÷4)
   │      群延迟估算:31 抽头(8k) 1.9 ms + 63 抽头(2k) 15.5 ms ≈ 17.4 ms (计算)
   ├─ ⑤ 「原始数据」分支 → Holter 存储(500 SPS 24bit, 陷波前·HPF 前) + calib 行
   ├─ ⑥ HPF → 双重自适应陷波(60·120 Hz) → LPF   (陷波前·后都保留 — 供比较画面用)
   ├─ ⑦ QRS 检测 (独立频带 5~15 Hz, 与陷波状态无关)
   │      起搏事件仅在「Paced=Yes」时才从 HR 中排除·打标记
   └─ ⑧ PPG:500 SPS → 5 样本平均 100 SPS → 带通滤波 → R·SpO2·PR·PI。1 秒周期

降到 500 SPS 的原因:之前设计的双重陷波系数以 fs = 500 Hz 为基准,可以直接沿用。消隐长度和 FIR 抽头数在信号处理设计中通过实测确定。

通道分配 默认值

AFE 通道基本 5 电极12 导联选配
CH1I (LA−RA)I
CH2II (LL−RA)II
CH3III (LL−LA) 直接 已确定V1
CH4V (V1/V5 开关)V2
CH5~8自诊断轮询(内部测试信号 → calib 行,电源·温度)V3~V6
12 导联选配与「III 直接测量」无法同时放入 8 通道(I·II·III·V1~V6 = 9 通道)。是仅在 12 导联时计算 III,还是使用两颗 AFE,尚未决定。软件按通过配置表接收通道映射来编写,因此无论哪种方案都无需改代码。AFE159RP8 是否具备 CH5~8 自诊断轮询功能 未确认。

显示用降采样

4. 内核间通信 — 共享内存环 + RPMsg

路径内容理由
共享 DDR 环 (SPSC,M7 写·A55 读)波形(原始数据·处理后·PPG)·心搏/起搏事件数据量大(每秒数十 kB)。零拷贝。A55 每个 vsync 轮询写索引 → 延迟 ≤ 1 帧
RPMsg命令·设置·报警状态·数值·心跳以消息为单位·保证顺序。Linux 默认缓冲区 512 B

RPMsg 公共头 (24 B,小端) 默认值

字段类型说明
magicu160xEC61
veru8协议版本 (在 HELLO 中比对,不同则为设备故障)
typeu8消息类型
lenu16正文长度 (≤ 472 B = 512 − RPMsg 头 16 − 24)
flagsu16bit0 要求应答,bit1 重发
sequ32发送方序列号。检测丢失·乱序
t_idxu64以 500 SPS 为基准的全局样本号 (公共时间轴)
crcu32CRC-32C (crc 字段置 0,对头+正文计算)

端点 2 个:ekg-ctrl (A55 → M7 命令,M7 应答) · ekg-evt (M7 → A55 事件·状态)。

主要消息 默认值

type名称方向 · 周期要点
0x01/0x02HELLO / HELLO_ACK启动时M7 固件版本·协议版本·环布局表 ↔ 发布版本号。不同则高优先级「软件不一致」
0x10HB_M7M7→A55 10 Hz运行时间,设备状态,环写索引,CPU 负载,样本丢失数,陷波状态
0x11HB_UIA55→M7 10 Hz实际翻转的帧计数器,当前屏幕上显示的报警 ID 列表
0x20~0x22CFG_SET / ACK / SNAPSHOT请求·应答·1 分钟发送安全设置并回读已生效的值进行确认。超出允许范围则拒绝
0x30~0x32ALARM_STATE / CMD / CMD_ACK变化时立即 + 1 Hz判定在 M7。A55 只做暂停(默认 2 分钟)·确认·解除闭锁操作
0x40NUMERICS1 HzHR(来源 ECG/PPG/SIM),PR,SpO2(「参考值·未校准」标志),PI,各参数有效/无效
0x50~0x52DEVICE_STATE · POWER_STATUS · SELFTEST变化时 · 1 Hz · POST设备状态,电池组 A/B 剩余电量·温度·SOH,自检结果
0x60LEAD_STATUS变化时各电极导联脱落,V1/V5 开关位置,sim/signal 位置,SpO2 传感器状态
0x70 · 0x80/0x81FAULT · SHUTDOWN_REQ/READY发生时故障代码 · 关机前确认 Holter 文件已关闭
0x90SERVICE_CMD仅服务模式测量模式下拒绝
0xA0TIME_SYNC1 分钟UTC ↔ t_idx 对应 (用于记录。报警判定只用 t_idx)

共享内存环 (计算·默认值)

所有环长度均为 2 的幂,索引为全局样本号 u64 掩码。M7 写完数据后 内存屏障 → 更新写索引。每个块(20 ms = 10 样本)附 CRC-32C。

环格式长度大小用途
R_RAWint32 × 8ch,500 SPS (陷波前·HPF 前)2¹⁹ = 17.5 分钟16 MiBHolter·calib。在 Linux 重新启动期间保住记录
R_PRE / R_POSTfloat32 × 8ch × 22¹⁶ = 131 s4 MiB屏幕,陷波比较画面,冻结
R_PPG{red, ir int32, pleth float},100 SPS2¹⁷ = 21.8 分钟2.5 MiB第 5·6 行,Holter
R_EVT32 B 事件2¹⁴512 KiB心形图标同步,注释
控制块布局表·写索引·覆盖计数器—4 KiB
合计约 23.2 MiB → 保留 32 MiB

保留区为 non-cacheable。仅 A55 复位时该 DDR 区域是否保持原样 未确认 — 实测项目 S-01。

5. 延迟预算

电极 → 屏幕 (计算·默认值)

阶段延迟
AFE159RP8 内部数字滤波器未确认
抽取 FIR 2 级≈ 17.4 ms
M7 块处理 (20 ms 块)≤ 20 ms
共享环 → A55 轮询≤ 16.7 ms
固定显示延迟 D (吸收 QRS 检测延迟,心形图标同步)初始值 300 ms
渲染 + 页面翻转 (双缓冲 2 帧)≤ 33 ms
合计约 390 ms + AFE 延迟

报警 默认值

路径预算
心率上·下限,心搏停止 (条件延迟 + 信号生成延迟)合计 ≤ 10 s (条件判定 ≤ 8 s + 声音开始 ≤ 1 s + 余量) — 主动采用对家用不适用的 IEC 60601-2-27 标准
导联脱落·饱和显示≤ 1 s (标准 ≤ 10 s)
SpO2 更新停止> 30 s 则低优先级
电池耗尽剩余 20 分钟时高优先级 (标准「至少提前 5 分钟」)
M7 判定 → A55 屏幕显示≤ 50 ms
M7 判定 → 云·监护人通知尽力而为(无保证) — 不算作报警系统的一部分

6. Holter 存储 · 趋势

原则

1 秒块 默认值

固定大小槽位:4 通道 8 KiB,8 通道 16 KiB (eMMC 4 KiB 对齐)。预先分配 1 小时 = 3600 个槽位的分段文件,使写入期间文件元数据不变。

位置字段大小
头部magic 'EKGB',格式版本,会话 UUID,块序列号,首个样本号,UTC + 单调时间,采样率(500),通道数·映射·刻度,滤波设置副本,陷波状态,标志(SIM·导联脱落·Paced·充电中)128 B
ECG500 × N 通道 × 3 B (24 位打包)6,000 B (4ch) / 12,000 B (8ch)
PPG100 × 2 × 3 B (red·IR)600 B
趋势这 1 秒的 HR·PR·SpO2·PI·(RR·NIBP) + 有效标志32 B
注释 TLV心搏(类型「仅供参考」),起搏时刻(8 kSPS 分辨率),导联变化,V1/V5 切换,报警开始·结束,患者按钮,时间校正可变
尾部CRC-32C + 包含前一块 SHA-256 的哈希链36 B

趋势 DB 默认值

7. 报警引擎 (IEC 60601-1-8 优先级)

优先级·信号 默认值

项目高中低
颜色#FF0000 填充黄色填充 + 黑色文字青绿色填充 + 黑色文字
闪烁维持现行 1 Hz (标准原文确认前)相同无
声音10 脉冲突发3 脉冲1~2 脉冲

报警列表 (摘录) 默认值

类别报警优先级
生理HR 上·下限 (默认 50~120,调整步长 ≤ 5 bpm)中
生理心搏停止高
生理SpO2 下限 (默认 90 %,禁止默认值低于 85 %) — 同时显示「参考值·未校准」中
生理PR 上·下限 (默认 50~120)中
技术导联脱落(显示电极名称) · 放大器饱和 · SpO2 传感器脱落中
技术AC 断开(进入停电模式) · SOC 10 % · Holter 记录失败中
技术剩余时间 ≤ 20 分钟 · 设备故障 · 显示故障(A55 停止)高
技术SpO2 更新停止 > 30 s · 存储空间 90 % · 云连接断开低
信息SIMULATION(全屏) · 充电中无法测量 · AC 恢复—

心律失常分类结果不用于报警,仅供记录·参考。

8. 状态机

三个维度叠加:设备状态(S) × 各参数信号有效性 × 电源状态(P)。

设备状态 默认值

状态进入条件屏幕声音
BOOT/POST开机,M7 启动白色启动画面 + 进度POST 结束时短促自检发声 1 次
S0 正常POST 通过6 行波形·数值生理报警时
S1 信号无效 (按参数)导联脱落·传感器脱落·饱和·NaN·自诊断偏离·环数据中断 0.5 s相应行显示虚线/灰色,数值「---」(不保留上次的值)技术报警 中/低
S2 设备故障POST 失败,看门狗复位记录,AFE 通信中断,版本不一致,心跳丢失「设备故障 — 无法测量」全屏高 (M7 扬声器或备用蜂鸣器)
S3 安全停止患者岛电源异常,电路板过热,剩余时间 ≤ 5 分钟「测量停止」+ 原因高
SERVICE未连接患者 + 服务权限服务画面—

两条原则:不显示冻结的正常波形 · 即使主处理部崩溃,报警音依然存活。

电源状态 默认值

状态条件动作
P0 AC有 AC充电。充电中测量遵循两级解除规则 — 第 1 级期间显示「充电中无法测量」+ 硬件联锁
P1 停电模式AC 断开中优先级报警 1 次,背光 30 %,DVFS,延长上传间隔。测量·记录·报警照常
P2 电量不足剩余 ≤ 20 分钟高优先级,Holter 维持 1 s 周期,停止上传
P3 关机序列剩余 ≤ 5 分钟或电芯阈值M7 → SHUTDOWN_REQ → A55 关闭 Holter·fsync·日志 → SHUTDOWN_READY → 关闭岛电源 → 依次关闭背光·面板·SoM
P4 突然断电VSYS 比较器中止写入。丢失 ≤ 1~2 s

9. 启动自检 (POST) · 周期性测试

顺序项目负责失败时
1AHAB 签名验证链 (ROM → 容器)ELE / ROM不启动
2读取 SM 复位原因 — 之前是否有看门狗·故障A55日志
3M7 自身:TCM 代码 CRC,RAM 模式,时钟比对(通用定时器 vs AFE DRDY 周期)M7S2
4AFE159RP8:芯片 ID,内部测试信号,输入短路噪声,电源·温度,导联脱落比较器 (功能列表 未确认)M7S2
5AFE4490:SPI 写读比对,ADC_RDY = PRF,LED·PD 诊断M7S2
6电池组 A/B 状态·SOH,LTC1760 状态M7按报警等级
7报警音短促 1 次M7S2
8DDR 内联 ECC,eMMC 寿命寄存器,数据分区挂载·Holter 恢复A55按报警等级
9设置 CRC,M7 ↔ A55 发布版本号比对A55·M7S2
10备用蜂鸣器路径 (仅在服务模式)——

周期性测试 (测量中):calib 行 = 内部测试信号兼作连续自诊断,幅度超出 ±2 % 则判为「AFE 增益异常」。电源·温度每隔数秒轮询空闲通道。

10. 云 · 安全 · 更新

云 — 离线存储后同步 默认值

启动链 (AHAB)

Boot ROM ─(ELE 验证)─► 启动容器 [SM(M33) · U-Boot SPL · ATF · OP-TEE · U-Boot]
         U-Boot ─(AHAB 认证)─► M7 固件容器 (位于 A/B 槽内) → M7 启动 → 开始采集
         U-Boot ─(签名 FIT)──► 内核 + DTB + initramfs (A/B 槽) → rootfs dm-verity

将 M7 固件放在 A/B 槽中,与 Linux 作为一个包一起更新·一起回滚。代价是 M7 启动推迟到 U-Boot 阶段(数秒,计划实测)。i.MX 95 用 AHAB 签名流程·回滚计数器 未确认。

OTA (RAUC A/B,必须签名) 默认值

用户权限 默认值

角色可执行操作认证
用户查看,事件按钮,声音暂停(2 分钟),亮度无
监护人+ 记录开始·停止,远程通知连接,导出PIN
医护人员+ 报警限值·延迟,滤波模式,Paced 设置,开启选配PIN
服务+ 服务模式,日志导出,更新,自诊断PIN + 已签名的服务令牌
制造序列号·密钥注入·校准值写入 → 出厂后锁定工厂专用

安全设置(报警限值·最小音量·Paced)须在 M7 完成 CFG_SET → 回读确认后才算「已生效」。M7 按最后确认的值持续运行。

11. 软件等级划分 (IEC 62304) · 模块

软件项等级 (默认值)划分依据
M7:采集·滤波·QRS·起搏·SpO2·AlarmCore·报警音·电源监视·A55 监视C直接关系到危害的判定在这里
A55:波形·数值显示(Qt)BM7 监视帧计数器·已显示报警列表 → 停止时由 M7 发出高优先级声音
A55:AlarmUIB判定·声音在 M7。暂停时间上限由 M7 强制
A55:Holter·趋势·云·OTA·权限·日志B失败会以技术报警体现或回滚。与报警路径无关
M33:NXP SMSOUP内核隔离的硬件依据
RM44L920 (第 2 阶段)C

划分依据:独立内核 + SM 的资源隔离(以 LM 为单位) + M7 不依赖 Linux 运行 + 外部窗口看门狗。该划分在标准上是否被认可需由检测机构判断,因此 未确认。

模块 (摘录)

模块位置输入 → 输出
acq_ecg · acq_ppgM7AFE 中断·SPI → 8 kSPS 帧 / 500 SPS 6 流 + 时间戳
pace · decim · notch2 · filtM78 kSPS → 起搏事件 · 500 SPS · 陷波状态
qrs · spo2M7心搏事件·HR / SpO2·PR·PI·质量
power · alarm_core · supervisorM7电源状态 · 报警状态·报警音 · 看门狗喂狗·显示故障
ipcM7·A55环·RPMsg (由单一定义自动生成 C/C++/Python 头文件)
ekg-ui · ekg-alarmuiA55环·数值·报警状态 → 屏幕,HB_UI,报警操作
ekg-recorder · ekg-trend · ekg-syncA551 秒块 · SQLite · MQTT·上传
ekg-config · ekg-update · ekg-serviceA55CFG_SET·审计日志 · RAUC · 服务命令

信号处理代码(dsp/)用与硬件无关的 C 编写,也可在 PC 上构建,并通过回放公开心电数据库进行单元测试。即使更换 RTOS,代价也很小。

12. 开发顺序 · 实测清单 默认值

阶段内容视为完成的标准
0 (无电路板)协议定义,在 PC 上做信号处理 — 用记录波形·模拟器波形验证抽取·陷波·QRS·报警判定输出检测性能数值,陷波测试,报警阶跃测试(80 → 40·120·0 bpm)
1直接从 i.MX 95 评估板开始。Yocto 基础镜像,SM 配置,M7 hello + RPMsg + 共享环HELLO/HB 往返,A55 强制复位实测 S-01
2连接 AFE,8 kSPS 采集,Qt 6 行屏幕样本丢失 0 (24 h),屏幕延迟实测
3AlarmCore + 报警音 + 状态机 + POST + 看门狗故障注入(M7 停止·A55 停止·拔出 AFE 线)
4Holter·趋势·电源联动反复强制断电 → 哈希链丢失 ≤ 1~2 s
5安全:AHAB 签名,dm-verity,RAUC,USB 更新拒绝错误签名,失败 3 次回滚
6云(国内区域测试服务器)通信中断 1 周后按顺序恢复,不删除未确认部分
7选配(12 导联·呼吸·NIBP),RM44L920 联动双重判定比对
实测 ID内容
S-01A55 复位时共享 DDR·M7 是否继续工作,Linux 重启时间
S-02M7 复位后重启时间 (期间记录中断的长度)
S-03M7 负载,8 kHz 中断抖动
S-04电极 → 屏幕延迟,AFE159RP8 滤波器延迟
S-05ext4 vs F2FS 断电测试,eMMC Reliable Write 行为
S-06从 U-Boot 到 M7 启动的时间

未决定事项:12 导联选配时 lead III 的处理(计算或 2 颗 AFE),V1/V5 波形在屏幕上的位置。

13. 试验台固件 — ESP32-S3 + ADS1293 + 心率·血氧模块

这是与本产品(AFE159RP8 · AFE4490 · i.MX 95)不同的试验台专用构成。目的是先用市售模块确认信号路径·帧·接收画面。

状态(截至 2026-10-11):器件未到货。仅编译通过,电路板上传·实测为 0 次。下面的「未确认」将在器件到货后测量并消除。

接线 (ESP32-S3 N16R8)

信号ESP32-S3备注
ADS1293 SCLK / SDI / SDO / CSBGPIO 12 / 11 / 13 / 10HSPI 总线 (与 2.0" 屏幕用总线·引脚分开)
ADS1293 DRDYBGPIO 2下降沿中断,内部上拉
ADS1293 ALARMBGPIO 1 (可选)仅在状态行显示
MAX30102 SDA / SCLGPIO 8 / 9400 kHz,不使用 INT · 10 ms 轮询
电源3V3 · GND禁止给 ADS1293 模块接 5 V — VDDIO 最大 3.6 V

避开的引脚:4·5·6·7·15(2.0" 屏幕) · 19·20(USB) · 43·44(UART0) · 26~32(闪存) · 33~37(OPI PSRAM) · 0·3·45·46(启动配置引脚) · 38·48(视电路板而定为 RGB LED)。

ADS1293 — lead I·II·III 全部直接测量

通道+−导联FLEX 值
CH1LA (IN2)RA (IN1)I0x11 (与数据手册示例相同)
CH2LL (IN3)RA (IN1)II0x19 (与示例相同)
CH3LL (IN3)LA (IN2)III (直接)0x1A — 示例中关闭 CH3,以 III = II − I 计算
LA 同时接在 CH1 的 + 和 CH3 的 − 上。同极性共用是数据手册示例的做法,但不同极性共用既没有禁止说明也没有允许说明 未确认。因此在接收画面上逐样本绘制爱因托芬残差 II − (I + III) 进行判定。ADS1293 只有 3 个通道,接上 V1/V5 就无法同时进行 III 直接测量 — 这是仅限试验台的限制。

电极分配默认:RA→IN1,LA→IN2,LL→IN3,RL←IN4(RLD 输出)。由于模块插孔接线未确认,可用命令 e 更改 IN 编号。

主要寄存器

地址值含义
0x06 · 0x07 · 0x080x00 · 0x07 · 0x01开启 DC 导联脱落,向 IN1~3 注入电流,8 nA。比较基准 VDD − 0.5 V。若没有 RL 回路,全部显示「脱落」属正常
0x0A · 0x0B · 0x0C0x07 · 0x00 · 0x04共模 = RA·LA·LL 平均 → RLD 输出 → IN4(RL)
0x11 · 0x13 · 0x140x00 · 0x07 · 0x00内部 2.4 V 基准,三个通道高分辨率,全部开启
0x27 · 0x2F0x08 · 0x71DRDYB = CH1 ECG,流式输出 = 状态 + 3 通道 (1+9 字节)
0x12 · 0x000x04 · 0x01外部 4.096 MHz 晶振 → 数字部分,等待 15 ms 后开始转换。模块上是否有晶振 未确认 — 若没有,固件每 1 秒发出警告

RL 脱落无法通过导联脱落检测到,因此另行输出 RLD 输出是否接近电源轨(RLDRAIL)。错误寄存器每 32 个样本读取一次,或在 ALARMB 位置位时立即读取。

采样率 (数据手册表 8,SDM 102.4 kHz,R1 = 4)

命令ODR带宽ADCMAX噪声 (µV rms,表中值)1 LSB每 1 mV 码值
r 533 默认533.33 Hz105 Hz0xF300002.070.0861 µV11,612
r 853853.33 Hz175 Hz0xB964F02.670.1129 µV8,859
r 400400 Hz80 Hz0x8000001.810.1635 µV6,117

以 533 为默认是因为它最接近以 500 SPS 为基准的陷波设计(陷波系数需按 533.33 Hz 重新计算)。覆盖诊断带宽 150 Hz 的只有 853,监护带宽 40 Hz 三者都能覆盖。输入范围为 INA 差分 ±400 mV。

内置测试信号

命令信号期望码值 (533 模式)
t ++VTEST = VREF/12 = +200 mV DC10,285,056
t -−200 mV DC5,640,192
t 0输入短路 (噪声测量)7,962,624 (= ADCMAX/2)
t x关闭 (电极)—

VTEST 与 VREF 来自同一基准,因此不是增益校准,而是用于自检·确认通道间增益差。1 mV 校准信号(calib)由外部电池模拟器承担。

心率·血氧模块 (推测为 MAX30102,I2C 0x57)

串口协议

533 SPS × 16 B + 100 × 12 B ≈ 9.7 kB/s (853 SPS 时为 14.9 kB/s)。二进制帧 + 以 # 开头的文本行(信息·1 秒状态·警告),也有 CSV 模式。

ECG 帧 16 B : A5 5A 'E' seq(u16 LE) CH1 CH2 CH3(u24, MSB 在前) flags crc8
PPG 帧 12 B : A5 5A 'P' seq(u16 LE) RED IR(u24)                 crc8
crc8 = 多项式 0x07, 初值 0, 从 'E'/'P' 到 flags

flags: 1 RA 脱落 · 2 LA 脱落 · 4 LL 脱落 · 8 RLD 电源轨 · 16 共模超范围
       32 输入超范围 · 64 合成 · 128 测试信号

CRC 计算部分摘录(固件与 PC 测试代码使用同一头文件):

static inline uint8_t ekg_crc8(const uint8_t *p, size_t n) {   // 多项式 0x07, 初值 0
  uint8_t c = 0;
  for (size_t i = 0; i < n; i++) {
    c ^= p[i];
    for (int b = 0; b < 8; b++) c = (c & 0x80) ? (uint8_t)((c << 1) ^ 0x07) : (uint8_t)(c << 1);
  }
  return c;
}

码值 → 电压转换采用数据手册式 13:V = (ADC_OUT/ADCMAX − ½)·2·VREF/3.5。

命令含义
m a / m sADS1293 实测 / 合成 (无模块时自动切换为合成)
o b / o c二进制 / CSV
r 533 · r 853 · r 400采样率
t + · t - · t 0 · t x内置测试信号
e 1 2 3 4RA LA LL RL 的 IN 编号
l 1 · g 1 / g 0导联脱落电流 ×8 nA (0 = 关) · RLD 开/关
h 72 · n 50 · w 2 · c 1合成:心率 · 60 Hz 注入 µV(RA 0 倍·LA 1 倍·LL 2 倍) · 白噪声 µV rms · calib 方波
dADS1293 寄存器转储

合成信号以与 ADS1293 相同的 ADC 码值形式输出,因此接收端无需区分实测与合成(只有 flags 64 不同)。合成模型将肢体电位设为 φRA=0,φLA=I,φLL=II,并以电位差重新计算导联,因此 III = II − I 按定义成立。电轴 50° 是合成用的任意值。

接收·显示脚本 (PC · 树莓派通用)

安全 — 接触人体之前

本试验台没有隔离。模块 → ESP32 → USB → 计算机在电气上连成一体。

  1. 笔记本电脑只用电池供电。拔掉充电器
  2. 笔记本电脑上不要插其他线缆(HDMI 显示器、以太网、使用电源适配器的外置硬盘、音频)
  3. 使用适配器供电的树莓派 + 屏幕不用于人体电极测试 — 仅用于合成·短路·模拟器阶段
  4. 不要直接插在接地的台式机上并在身体上贴电极
  5. 贴电极期间不要接触金属桌·暖气片·水管
  6. 不要贴在潮湿皮肤·伤口上。电极为一次性,只用 1 次
  7. 不要给使用心脏起搏器·植入式器械的人贴电极
  8. 不要用本装置的波形·数值判断健康状况 — 这是试验台
  9. 不要给模块接入 5 V (VDDIO 最大 3.6 V)

测试顺序

阶段内容通过标准
① 合成只将 ESP32 接 USB。不接模块,确认接收端全路径 (m s · n 50 · c 1)中断 0 · 残差 ≤ 2 LSB · 心率 72 · 60 Hz 幅度 I·III 相同,II 为其 2 倍
② 短路噪声连接模块,不接电极。确认 REVID=0x01 后 t 0 10 秒 · t + · t -,接着在插孔处将四个电极接到一点并执行 t xt 0 噪声 rms ≈ 表中值(533 模式 2.07 µV rms) · t ± 码值与期望值相同 · 无 DRDYB 警告 · 导联脱落位为 0
③ 模拟器外部电池模拟器(1 V p-p → 1000:1 → 1 mV)。尚未制作1 mV 测得 1 mV · 残差处于噪声水平(判定 III 直接测量成立) · 保存 60 Hz 陷波前/后原始数据 · 逐个拔下电极检查导联脱落响应
④ 人体电极在遵守上述全部安全事项后,接 RA·LA·LL·RL 4 个导联脱落 0 · RLD 电源轨 0 · 可见 QRS · 心率与手腕脉搏一致 · 记录 60 Hz 残留幅度

④ 之前必须经过 ②·③。若在 ② 中出现 DRDYB 警告(怀疑无晶振),就在此停止。

14. 试验台验证结果 (2026-10-11)

  • 编译通过 2 种,试验台源码警告 0 条 (--warnings all,arduino-cli 1.5.2-rc.1 · esp32 内核 3.3.12)
    • 基本 ESP32-S3 — 闪存 365,710 B (27 %) · RAM 24,336 B (7 %)
    • 原生 USB CDC + OPI PSRAM + 16 MB — 366,348 B (27 %) · 25,016 B (7 %)
  • 未进行电路板上传 (器件未到货)
  • 帧交叉验证:在 PC 上编译与固件相同的头文件(帧·合成信号),生成 20 秒数据流,并用 Python 接收端解析
    • ECG 10,666 帧中,准确丢弃了 1 个故意损坏 CRC 的帧(计为中断 1),PPG 2,000 帧丢失 0
    • 即使混入含有 0xA5 0xA5 字节的韩文文本行,也不会失去同步
    • 爱因托芬残差最大 0.086 µV = 1 LSB,rms 0.042 µV → 检查通过
    • 另行确认了 CSV 路径(行解析·seq 中断·flags)
合成信号回放接收画面:lead I、II、III、残差、脉搏波红光、脉搏波 IR 共 6 行
合成数据流回放画面。合成的 60 Hz 50 µV 注入在 I·II·III 上可见,残差 II−(I+III) 行接近 0。标题中的 R 比值为参考值,SpO2 数值未校准。这是合成信号,并非传感器实测。

剩余未确认事项 (器件到货后确认)

  1. ADS1293 模块的电源构成(VDD·VDDIO),有无 4.096 MHz 晶振,插孔引脚分配,输入保护·RLD 器件值
  2. 将一个输入引脚同时接到 CH1 + 和 CH3 − 是否允许 (以残差判定)
  3. 传感器模块是否为 MAX30102,红光·IR 是否调换
  4. 与 MAX30102 原文数据手册比对
  5. ESP32-S3 板的 RGB LED 引脚,USB 端口方式
  6. 导联脱落 8 nA 在电缆电容下需要几秒做出响应
  7. 医疗标准中电极 DC 电流限值的数值