日志口迁到 RS232#1/UART5 之后,台架那根线接在 CN1 的 RS-232 端子上,枚举 出来是 COM3;.serialtest/config.json 还写着 COM6,@test / @build / serial-assistant 不显式指端口时就会去开一个已经没人说话的口,抓到空日志。 - .serialtest/config.json:portName COM6 -> COM3。 - 产品需求 §9.13:物理前置改成已完成口径,写明台架口由 COM6 变 COM3。 - 数据可信:资源图例里的台架串口同步成 COM3。 docs/测试说明/m2_data/README.md 里的 COM6 是 2026-09-22 那次运行记录,按当时 事实保留不改。
41 KiB
数据可信(等待台架与外部资源)
这篇是什么:把"采集出来的数到底能不能信"一次讲完——已经证到哪一步、按构造还证不到什么、 下一跳怎么跨、哪些必须等外部资源。 它同时是设计约束的归属文件:§2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 被代码与测试头注释 当口径出处引用(
adc_cal.*/meas.*/cfg_file.*/prot_elm/protect_task.c/ui_data*/test/host/prot_dim/*),它们是现行规范,不是"已完成记录"。已完成的事项按"完成即销项"只删 §5 表里的行。 排序权威只有一处:docs/任务规划/README.md§2;后续事项索引在docs/任务规划/登记簿.md§7。
最该先知道的一条:保护判据现在处于未标定闭锁态。判据 =
App/algo/adc_cal.c的adc_cal_prot_blocked()——UA / UN / IA 的ADC_CAL_F_VALID全置位才放行,protect_task拿它的返回值 停走判据(判据已从protect_task.c搬进adc_cal.c,旧行号引用作废;只有DTU_BENCH构建旁路,且只旁路这一处)。 用户裁定(2026-10-25):保持闭锁到标准源到位,不缩短解锁路径(不用万用表走捷径)。
1. 三十秒看清全局
图由 tools/arch_diagram/gen_data_trust_ladder_svg.py 生成(改图改脚本重跑,勿手改 SVG)。
每升一级只多答一个问题,台阶之间的高度差就是"下游能多信多少":
| 台阶 | 多答的问题 | 状态 |
|---|---|---|
| 1 通路活 | 9 路都在转换、没串道、极性没反? | ✅ 2026-10-27 已证 |
| 2 静态引脚电压 | 注 1 V 直流,读数是不是 1 V? | ✅ 2026-10-27 已证(六项判据全 PASS,§2.6) |
| 3 动态引脚波形 | 注 1 V 正弦,算出来还是不是 1 V? | ⬜ 一次也没做过(§2.7 → 方案见 §4.6) |
| 4 端子二次值 | 引脚上这 1 V 对应端子侧几 V? | 🟡 等子板原理图或实物 |
| 5 精度等级验收 | 额定工况下整条链误差够几级? | 🟡 等标准源 |
三条结论:
- 第 1、2 级已闭环,证据与判据的属主是
docs/硬件平台/ADC通道映射说明.md§8.1,执行步骤属主是docs/测试说明/ADC前端注入验证流程.md——本文不重抄,只写"证到哪、为什么不能再往外推"。 - 第 3 级是当前唯一的空白,而且不需要任何外部资源:一台能出 50 Hz 正弦的交流信号发生器, 接在已经验证过的那个注入点上就行。它比第 4、5 级安全一个量级——只需 ±2 V 以内的正弦, 而端子级验证要上 100 V / 220 V 二次值。不用烧高压、不用标准源,这是把它排最前的理由(§4.6)。
- 第 4、5 级在等外部:④ 子板/端子板变比(仓库里没有原理图)与标准源两点标定,
两者完成前
eng保持 0,本波只承诺"ADC 引脚电压"。
本文怎么读:
| 你想做什么 | 直接看 |
|---|---|
| 判断现在这些数能信到什么程度 | §1 这张图 + §2.6(静态证到哪)+ §2.7(动态没证什么) |
| 改采集 / 算法 / 品质位相关代码 | §2.1 §2.2 §2.3(口径)+ §4.1~§4.5(设计依据) |
| 上台架做正弦验证 | §4.6(接法、判据 D1~D6、读数出口、坑)+ §5 的「信号发生器动态波形验证」卡 |
| 看还差谁、按什么顺序做 | §5 任务卡 + §6 顺序图 |
| 确认某件事是故意不做而不是漏了 | §9;有没有踩坑风险看 §8 |
2. 事实基线(2026-10-29 代码级核对;行号是核对时快照)
2.1 通道与量纲(锚点:adc_cal.* / meas.* / ui_data*)
已证的:9 路语义 ↔ 物理通道 ↔ 转换器这三者一一对应(k_adc_map 与 CubeMX 标签逐条对齐 + 开机自检)。
没证的:这张表的系数只到引脚,不到端子。
| 语义通道 | 转换器 | 码值格式 | LSB(@ 引脚) | 前端 | ROM 默认系数(@ 引脚) | 交流可用性 |
|---|---|---|---|---|---|---|
| UA | TPAFE5160 | 16 位双极性 ±5 V | 152.59 µV | 1k 串 + 滤波 C(③ = 1:1,无分压) | 152.59 µV/码 | ✅ 可用 |
| UN | TPAFE5160 | 同上 | 152.59 µV | 同上 | 152.59 µV/码 | ✅ 可用 |
| IA | TPAFE5160 | 同上 | 152.59 µV | 同上 | 152.59 µV/码 | ✅ 可用(缺 A/V 变比) |
| UB / UC | STM32 ADC1 | 12 位单极性 0~3.3 V | 805.66 µV | 同上 | 805.66 µV/码 | ❌ 削顶(无中点偏置) |
| IB / IC / IN | STM32 ADC1 | 同上 | 805.66 µV | 同上 | 805.66 µV/码 | ❌ 削顶 |
| TEMP | STM32 ADC1 | 同上 | 805.66 µV | 同上 | 热敏非线性 | — 不纳入线性标定 |
- 通道数
ADC_SEM_COUNT = 9(8 电气 + 温度),枚举定义App/algo/adc_input.h:38-49。 - 唯一折算点:
App/task/adc_task.c:382的frame[s] = adc_cal_apply((adc_semantic_t)s, code)—— 全仓只有这一处把码值变成工程量,现单位 = ADC 引脚电压 V(eng = 0)。 - 端到端链路分四段(① 语义↔网名↔通道、② 引脚电压↔码值、③
AINn↔ 引脚、④ 端子 ↔AINn), 属主docs/硬件平台/ADC通道映射说明.md§7.1:①②③ 已定死(③ 变比 1:1),只有 ④ 是缺口。
2.2 量纲错配与量纲回归(锚点:test/host/prot_dim/*;M4 退出判据⑥)
这一节为什么必须在:台架此前"通过",是因为没有一条判据检查"不该动作时不动作"。 "码值当工程量"的错配曾让 OC 拿 ~11000 码值去比 10 A 定值 → 恒假动作。这类错的可怕之处不是 "测不准",而是每次都跳,而且三处消费者(判据、104、UI)一起错、一处都不报错。
固化它的回归 = test/host/prot_dim/:从 ADC 码值出发、显式写出码值↔二次值换算,走真实的
折算 → 采样环 → 全周傅氏 → 元件判据链;任何一环把量纲弄丢(例如折算点被旁路),断言立刻翻转
(TC-PROTDIM-002 就是反错配对照,专门复现那次历史事故)。它用的是合成系数 10 mV/码,
不是板上 152.59 / 805.66 µV/码——它证的是"链条别丢量纲",不证"变比数值对不对"(后者归 §2.6 与 §4.6)。
| 量纲档 | 怎么进入这个档 | 现在的处置 |
|---|---|---|
eng = 0(ADC 引脚电压 V) |
VALID 未置位——当前产品构建恒此态 |
§4.3 闭锁停走整条判据链;UI 第 7 行显示"未标定"徽标 |
eng = 1(二次值 V / A) |
④ 变比到手 且 电气 8 路 adc_cal_flags() 的 VALID 全置位(App/app/ui_data_feed.c 的 feed_eng()) |
定值与工程量同域,判据才名副其实 |
| 混档(最坏情况) | 只改折算系数、不改下游常数 | §2.3 那三处必须跟着动,这正是 §2.3 存在的理由 |
2.3 三个必须同步重定的下游常数(锚点:freq.h / iec104_pts.* / prot_set.c)
这节的意义是**"动一处量纲要同步三处"**,不是待办清单——三行现在两行已落地。
| # | 位置 | 现值与语义 | 状态 |
|---|---|---|---|
| 1 | App/algo/freq.h:62 |
FREQ_AMP_MIN 50.0f——测频幅值门,已按二次值 V 口径重定(50 V = 0.5×Un,与 prot_set.c 头部量纲基准同源) |
✅ 已重定;⚠ 副作用:eng=0 期间帧值 ≤5 V < 50 V → 本门恒不过 → freq_valid() 恒 0(freq.h:58-60 自陈)。这条直接决定 §4.6 里测频腿怎么读、为什么 D4 的"过判据"是"如实报不可测" |
| 2 | App/protocol/iec104/iec104_pts.c:69-80 |
k_yc[].deadband 已按点重定:电压 0.5 V、电流 0.005 A、频率 0.5 Hz(真源在 run_par,UI 可改) |
✅ 已重定;④ 变比到手后需再复核一次量纲 |
| 3 | App/algo/prot_set.c:25-70 |
g_prot_set_meta[] 定值 = 二次值 A / V(基准 100 V / 1 A):OC1 10 A、OV 120 V、UV 20 V、3U0 15 V… |
🟡 口径对,但标定前无法在板上验真;§7 #1 定了精度目标后连同 min/max 复核 |
2.4 / 2.5 —— 2026-10-25 瘦身时删除,编号不复用(防止被重新取走)
2.6 静态验证:已知电压注入已于 2026-10-27 台架闭环(锚点:adc_cal.* / meas.* / ui_data*)
判据与实测记录的属主 = docs/硬件平台/ADC通道映射说明.md §8.1,执行步骤属主 =
docs/测试说明/ADC前端注入验证流程.md。一块万用表 + 一个电位器 + 串口 adc: 心跳行就够,
不需要示波器、信号源、标准源;注入点在串联电阻的端子侧 U5 排针(不碰 LQFP 引脚)。
| 项 | 实测 | 判据 |
|---|---|---|
| 零点(8 路逐路短接 AGND) | 0~5 码 | TPAFE ≤30 / STM32 ≤5 码 |
| 三点线性(UA 0.3 / 1.0 / 2.0 V) | R² = 0.9999997,截距 −7.2 码 | ≥0.999 |
| 斜率(UA,TPAFE) | 6544.2 码/V(理论 6553.6,偏差 −0.14 %) | 偏差 ≤2 % |
| 逐通道映射 | 8 路各自塌到本路 | 注入哪路只动哪路 |
| 极性(TPAFE 三路 −1.0 V) | −6566 / −6568 / −6566,对称性 ≤0.34 % | 落在 −6554 附近且 ≤2 % |
| 节奏 | Δ9998 / 10 s ≈ 1000 Hz,idle=0、adc1_err=0 |
注入期间仍 1000 Hz |
六项全 PASS ⇒ ③ 段(AINn ↔ 转换器引脚)变比 = 1:1(若存在 2:1 分压,斜率应约 3277)、
k_adc_map[] 逐路对应、TPAFE 补码符号位解释正确、§2.1 的 ROM 默认系数被实测支持。
空载浮空读数(TPAFE ~11450 / STM32 ~1000)是上电瞬态 + 输入悬空,不是零点,别拿首帧当零点用。
这一轮证到的是"一条水平线的高度":给定直流电压 → 码值 → 折算,斜率、零点、线性度、极性、
通道对位、节拍全在 ±2 % 内。直流信号在时间轴上没有形状,所以相位、频率、波形相关性、真实削顶、谐波
这五类按构造不在本节证据范围内——逐条列在 §2.7。另有两项本轮未覆盖:
串扰(零点步骤时其余七路浮空本身在漂)与"注入进行中"的节奏(只测了注入前后),口径同
docs/硬件平台/ADC通道映射说明.md §8.1 尾注。
一个必须记住的区分:CLIPPED 位是来源派生(App/algo/adc_cal.c:291-293:系数来自 STM32 就置位,
V0.1 恒命中 UB/UC/IB/IC/IN,位图 0xE6),它表示"这路不能测交流",不等于"这路此刻正在削顶"。真削顶的签名是
cal: 行的 rail= 位图与 rail: edge=… 那行 [ERR]——这条路径至今只在直流饱和里起过(§4.6 D5)。
M4 承诺边界:只到 ADC 引脚电压(
eng = 0)。"端子二次值"要等 §5「端子/子板变比确认」拿到变比、「两点标定与精度验收」用标准源写入[adc_cal]并置VALID;eng升 1 的条件是电气 8 路 VALID 全置位(App/app/ui_data_feed.c的feed_eng())。 本节编号与承诺边界口径勿删——adc_cal.*/meas.*/ui_data*/simulator/main.c的头注释都指到这里。
2.7 动态验证:正弦波一次也没采过
一句话:整条计算链现在只在PC 合成数据上验过,从没在真实交流波形上验过。 不是"精度差一点",是"这一档完全空白"。
证据(逐条可查,全部是各套件自己的自陈,不是推测):
| 出处 | 原话要点 |
|---|---|
test/host/phasor/run_unit_test.py |
「板端无信号源,无法注入已知幅值/相位/频率的标准波形,因而无法验证"读数 = 设定有效值"」 |
test/host/meas/run_unit_test.py |
「读数与注入源比对类判据仍归台架(实测采样类,本套件不覆盖)」 |
test/host/prot_dim/prot_dim_test.c |
系数是合成覆写的 10 mV/码,非板上 152.59 / 805.66 µV/码 |
App/algo/adc_cal.h |
adc_cal_two_point():「实测注入未做(台架待跑),本函数即"公式齐备"的交付物」 |
docs/测试说明/ADC前端注入验证流程.md |
「只验直流:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源」 |
App/task/adc_task.c 心跳块 |
adc: 是当拍瞬时码值、meas: 是 200 ms 快照——没有一行能给出波形形状 |
按下游列一遍"现在能不能信":
| 下游 | 现在 | 为什么 |
|---|---|---|
| 基波有效值(RMS) | 🟡 算法在 PC 上证过(幅值 ≤1 %、49/51 Hz 下 ≤1.5 %),经真 ADC 后一次没测 | 1 V 正弦进 ADC 后 fAmSQ 是否 = 1 V,无实测 |
| 相位 | ❌ 从未在真信号上比过;且代码里没有跨通道相位符号约定 | 只许比同片内通道(§9 的硬件限制) |
| 频率 | ❌ 恒不启动 | 幅值门 50 V 是二次值口径,引脚域 ≤5 V 恒不过(§2.3 #1)→ UI Hz 行恒 --、104 0x401D 恒 IV |
| 削顶 / 品质 | 🟡 位图逻辑对,真削顶路径没跑过 | rail: 那条 [ERR] 至今只在直流饱和里起过 |
| 谐波 C04 / C05 | ❌ 实例建了,无消费者、无出口 | prot_elm.c 无引用,meas 只算 harm=1 |
| 保护判据 | 🔒 闭锁中 | §4.3 |
→ 下一跳就是 §4.6:把一根真正的 50 Hz 正弦从已经验证过的那个注入点灌进去, 一次把上表里"手边设备能改"的几行改掉。
3. 目标与里程碑
波次目标:把"数"从原始码值推进到有物理含义、有品质、有死区、能上送的工程量。
M4 的六条退出判据(逐条对齐现状,别整格打勾):
| 退出判据 | 状态 | 证据 / 缺口 |
|---|---|---|
| ① 至少 1 路电压通道经已知电压注入验证,斜率与理论 LSB 偏差 ≤2 % | ✅ 2026-10-27 | UA 6544.2 vs 6553.6 码/V(−0.14 %),docs/硬件平台/ADC通道映射说明.md §8.1 |
② adc_cal 折算落地,采样环里是引脚电压 V 而非码值 |
✅ | App/task/adc_task.c:382(全仓唯一折算点) |
| ③ 8 通道系数 / 零点可落盘,加载失败回退 ROM 默认 | ✅ | [adc_cal] / [adc_cal_ofs],见 §4.4 |
| ④ 三处下游常数按工程量重定并注明依据 | ✅(有尾巴) | §2.3;#1 在 eng=0 恒失效已记因于 freq.h:58-60 |
| ⑤ "未标定 → 保护闭锁"生效 | 🟡 软件道 ✅;"解锁"这半程要等 VALID 置位才能上台架验 |
adc_cal_prot_blocked() + App/task/protect_task.c:245 |
| ⑥ 量纲回归用例(不该动作时不动作)通过 | ✅ | test/host/prot_dim/,见 §2.2 |
所以 M4 差的是"台架面",而且它分两半: 动态这半(§4.6)手边就能做、不要外部资源;端子与精度那半要等子板与标准源(§5 后两张卡)。
M5 遥测链 / M6 运行参数与点表:均已达成,口径沉淀在 App/algo/meas.h、App/algo/run_par.h
头注释与 §4.5;其中"104 上送值与工程量一致"仍挂在变比确认与两点标定上(注入验证只证到引脚电压口径)。
4. 设计要点
4.1 折算模型:板级事实进 ROM,现场标定进 cfg
工程量[V 或 A] = (code + b) × k_f
k_f = k[µV/码] × 1e-6 (float,init/load 时算一次)
| 符号 | 含义 | 存哪 | 定标 |
|---|---|---|---|
k |
µV/码(通道灵敏度) | cfg 段,int32 Q16(µV/码 × 65536) | 默认 = 板级理论系数(§2.1 表) |
b |
零点偏移(码值) | cfg 段,int32 | 默认 0 |
k_f |
V/码(运行时) | RAM,adc_cal_init/load 时由 k 派生 |
不落盘 |
- 为什么存 µV 而不是 V/码:
k在 V/码 量级是 3×10⁻⁴,Q16 只有 20 个刻度(5 % 分辨率); 换成 µV/码是 305,Q16 有 2000 万个刻度。 - 为什么 Q16 而不是参考项目的 Q10:TPAFE 通道 Q10 只能表达 312(+0.16 %),Q16 误差 < 0.001 %; 两者都占 4 字节,Q16 把"系数定点舍入"这一项从误差预算里直接抹掉。参考项目用 2^10 是因为定点 DSP 乘法成本,本机有 FPU、运行时本来就是 float。int32 上限可表达 32767 µV/码,远够。
- 运行时不走定点:
k预乘成float k_f,逐点只做一次浮点乘——1 kHz × 9 通道 = 9k 次/秒,可忽略。
4.2 三态可用性:标定 ≠ 可测
k 的默认值是板级理论系数,此时工程量单位是"ADC 引脚电压",不是二次值——还缺互感器/子板变比。
所以通道状态必须让消费者区分三档,不能把引脚电压当二次值用:
#define ADC_CAL_F_VALID 0x01u /* 该通道 k 已按变比标定 → 工程量为二次值 */
#define ADC_CAL_F_CLIPPED 0x02u /* 硬件削顶(单极性无偏置)→ 交流量不可信 */
| 通道 | VALID |
CLIPPED |
消费者应如何对待 |
|---|---|---|---|
| UA / UN / IA | 标定后置位 | 0 | 可用于保护、计量、上送 |
| UB / UC / IB / IC / IN | 永不置位(V0.2 硬件改版前) | 1,且是来源派生(不是实测削顶,见 §2.6 表) | 只作码值监视;点表已绑定,靠品质位把 104 侧驱动成 IV、值清零 |
| TEMP | 0 | 0 | 不参与线性标定,页面显示 -- |
adc_cal_flags(sem) 是三处(UI / 104 / 保护)唯一的可用性查询入口;adc_cal_apply() 不返回可用性,
所以"只看系数不看 flags"这种用法在接口层就被堵掉(对应 §8 的"削顶通道被当成可测"一行)。
4.3 未标定即闭锁(本波唯一的行为变更)
保护判据拿"ADC 引脚电压"跟"二次值定值"比必然误动作,所以 protect_task 多一个闭锁源:
UA / UN / IA 的 VALID 未全置位 → 判据停走(实现已搬进 App/algo/adc_cal.c 的
adc_cal_prot_blocked(),App/task/protect_task.c:245 消费并打 INFO + 记 SOE)。
- 与"自检失败 / 采样故障闭锁"同构(
PROT_HF_LOCK_MASK那一套),不新增机制。 - 现有台架
@test的期望会因此变化——这是有意的,任务卡里同步更新判据。 - 台架调试要旁路只能走编译期开关
DTU_BENCH,不进 cfg、不进 104。 ⚠DTU_BENCH只旁路这一处:它不旁路 §2.3 #1 的测频幅值门,也不产生任何读数出口。
4.4 落盘:拆两段,不碰引擎
CFG_FILE_MAX_KEYS = 16,8 通道 ×(k + b)= 16 正好顶格,将来加一个键就爆。故拆两段:
| 段名 | 键 | 字节 | 回调 |
|---|---|---|---|
[adc_cal] |
k_ua k_un k_ia k_ub k_uc k_ib k_ic k_in + valid(uint8 位图) |
8×4 + 1 = 33 | 不挂(RAM 副本即生效值) |
[adc_cal_ofs] |
b_ua … b_in |
8×4 = 32 | 不挂 |
段名 7 / 11 字符、键名 4 字符,均在 15 字符上限内;段数总计 5/8(含 [run_par] 9 键死区),未逼近上限。
- 系数唯一真源仍是这两段——104 写 k/b 经
adc_cal_set()代理,run_par不存第二份; 落盘链走SYS_EVT_RUN_PAR_SAVE(iec104Task peek 投递 → defaultTask 整档 save),p_cb依旧未用。 - ⚠ 负零点:引擎原本只有
CFG_VAL_UINT(strtoul+ 上界校验),负的零点偏移会落成4294967291这种现场看不懂的数——这就是补CFG_VAL_INT的动因(§7 #3)。 备选"零点存码值 + 32768 偏置的 uint16"已否决:绕开引擎却要每个读点记住减偏置,属于给未来埋坑。
4.5 遥测快照:让 104 与 UI 共用一份上游
104 的 s_src_yc_read() 自己遍历相量、UI 将来也要一份 → 两处各自决定"什么时候算新值""品质怎么判",
迟早打架。本波引入 App/algo/meas.c:每 200 ms 从相量使用区取一次,产出
typedef struct {
uint32_t seq; /* 只增;消费者据此判断是否换帧 */
uint32_t tick_ms;
uint8_t valid; /* 整帧有效 */
uint8_t rsv[3];
float yc[9]; /* 工程量(二次值或 ADC 引脚电压,由 flags 决定) */
uint16_t qds[9]; /* 每点品质:IV / NT / OV / CLIPPED */
uint8_t freq_valid;
float freq_hz;
} meas_snap_t; /* 72 B,双区共 ≈144 B;改字段 = 改协议,须同步 104 与 UI */
- 发布者 =
adc_task,在phasor_run()/freq_run()之后按 200 ms 分频发布;生产者在自己上下文里 发布,消费者不组装、不判断新旧。全仓meas_tick()调用点数 = 1 是评审判据(§8"快照双写")。 - 跨任务读沿用
phasor的双区原子交换(写侧填非使用区、末尾翻单字节索引;读侧先取索引再整体拷), 不是新机制、不引入锁。 - 104 与 UI 都读这份快照 → 同一份数据、两个消费者;104 侧值与品质整体透传,不做本地判断。
- 200 ms 是上送节拍,不是平均窗:相量本身已是 1 ms 刷新的基波有效值,再平均只会引入滞后。 ⚠ 这条在动态验证里有个可读的后果:注入非整 50 Hz 的正弦时,快照轨会呈现拍频式跳动,属预期(§8)。
4.6 动态波形验证:用信号发生器把整条计算链跑一遍
图由 tools/arch_diagram/gen_data_trust_dc_ac_svg.py 生成(改图改脚本重跑,勿手改 SVG)。
4.6.1 为什么这一跳既不用标准源、也不用烧高压
| 理由 | 依据 |
|---|---|
| 注入点已经验证过,且就在那儿 | docs/测试说明/ADC前端注入验证流程.md §3 的注入点清单(串联电阻端子侧 = U5 排针);③ 段 1:1 已拿到台架证据(§2.6) |
| 不知道 ④ 变比也能验算法 | 注入点在 ④ 之前,发生器给的电压就是引脚电压,算法链要证的正是"引脚域里算得对不对" |
| 幅度小两个数量级 | 只需 ±2 V 以内的正弦(TPAFE 侧判据上限);端子二次值验证要上 100 V / 220 V,风险与设备都在那一级 |
| 现有静态验证的读数出口可直接复用 | 串口心跳 + 104 YC,零固件改动(§4.6.3) |
这一跳证的是功能性(算得对不对、品质报得实不实、节拍稳不稳),不是计量(误差几级)—— 发生器不当"标准"的界线见 §4.6.5 与 §7 #9。
4.6.2 判据 D1~D6
| # | 验什么 | 接法 | 读哪 | 过判据 |
|---|---|---|---|---|
| D1 | 基波幅值计量 | UA(R31 / AIN1)注 1.000 Vrms、50.000 Hz 正弦 |
meas: 的 ua_mv;或 104 0x4011 |
读数 = 万用表 AC 档读数,偏差 ≤2 %(与静态同档)。⚠ 别用 phasor(hb) 行比幅值——那是 ×0.1 定点,注 1 V 只剩 10 格(§4.6.3) |
| D2 | 读数是否只跟基波走 | 同幅值改方波、三角 | 同上 | 期望值 = 基波分量有效值(方波基波 = 4/π × 峰值/√2 ≈ 0.90×峰值;三角 = 峰值/√6),不是真有效值;偏差 ≤2 %。顺带把"这台仪表读的是基波"这条口径钉进文档——用户拿真有效值表去对会以为差了 10 % |
| D3 | 相位 | UA 与 UN 两路同片(都走 TPAFE)注同幅、同相 | phasor(hb) 各行 Re= / Im= |
两路 atan2(fIm, fRe) 之差 ≤2°;改变发生器相位 90°,差值跟着走。只许比同片内——跨转换器无同刻性(§9),STM32 那五路还有 1 拍乒乓滞后 |
| D4 | 测频 | 同 D1 的 1 V/50 Hz | freq(hb): 与 104 0x401D |
预期就是"不出数"(幅值门 50 V 在引脚域恒不过,§2.3 #1)→ 这条的判据是"如实报不可测"(freq_valid=0、UI Hz 显示 --、104 上送 IV),不是报出一个错误的 50.00。想真验 45~55 Hz 精度(PC 侧判据 0.02 Hz)须临时把 FREQ_AMP_MIN 降到引脚域量级(如 0.5 V)单跑一轮 → §7 #8 + §8 风险行 |
| D5 | 削顶与品质路由(负向用例) | 给 UB(R52 / AIN2)注同幅正弦 |
cal: 行的 rail= / edge=;rail: edge=… 的 [ERR] 行;104 0x4012 |
负半周钉下轨 → 连续 20 拍(正好一个 50 Hz 周波)后该路贴轨位锁存、edge 起沿、104 上该路 IV 且值清零。⚠ 这条会故意造出 [ERR],而 @test 的 forbidden 标记含 [ERR] → 本轮要么人工判读、要么把这五路排在最后单独一轮(§8 第一行) |
| D6 | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注) | phasor(hb) C04-IA-F2 / C05-IA-F5 两行(log_phasors() 逐实例打印,实例表加行即自动覆盖) |
谐波轨读数 = 注入分量(±2 %)。⚠ 这两根轨目前没有任何下游消费者(prot_elm.c 无引用、meas 只算 harm=1),所以 D6 只证"算得对",不证"有人用"——出口归 §9 的谐波轨立项 |
先做 D1 / D2 / D5(纯读数、无跨通道约定),D3 / D6 次之,D4 视 §7 #8 的裁定。
4.6.3 读数出口(零固件改动)
| 出口 | 有什么 | 坑 |
|---|---|---|
串口每 10 s 心跳(App/task/adc_task.c 心跳块) |
adc:(9 路码值)、cal:(三路 mV + vl/cl/rail/edge 位图)、phasor(hb)(逐实例 Re / Im / rms)、freq(hb)、meas:(快照轨) |
MicroLIB 无 %f,全是定点:phasor ×0.1(1 V 注入只剩 10 格)、freq ×0.01 Hz、cal: / meas: ×1000(1 mV)。10 s 一行的单点瞬时值对 50 Hz 等价于随机相位抽样 |
104 YC(现成 PC 主站 test/host/iec104_master.py) |
0x4011~0x4018 八个电气量 + 0x401D 频率,浮点无量化,还带品质 |
UB/UC/IB/IC/IN 恒 IV、值清零 → 那五路只能回读串口码值域 |
| UI 交流量页 | Ua / U0 / Ia / Ia2 / Ia5 / Hz / 标定徽标 共 7 行 |
160×160 单色;-- 同时表示"没数"和"有数但不可信" → 不能当判据,只能当旁证 |
| 板上没有的(本波现状) | 把窗里 20 / 40 个点导出来的任何出口:无命令控制台、无 dump、当前还不落文件 | 所以现在只能靠派生标量证;要看形状就拿示波器直接看注入点(只对照发生器,别拿它当判据)。这条限制是临时的:故障录波已立项,段文件就是现成的样本出口,届时判据升级为「PC 独立重算 vs 板上读数」对表(见 docs/子系统设计/故障录波设计说明.md §11) |
4.6.4 接法与红线(照抄既有红线,不新发明)
- 注入点:串联电阻的端子侧焊盘(
U5排针),逐路清单见docs/测试说明/ADC前端注入验证流程.md§3; 引脚侧没有串阻保护,必须外串 10 k 限流。 - 幅度按峰值算,别看 Vrms 数字:1.000 Vrms 正弦峰值已 1.414 V;TPAFE 侧按判据只到 ±2 V(满量程 ±5 V), STM32 那五路是 0~3.3 V 单极性——给它们注交流只能是 D5 那种"故意削顶"的用例,峰值同样不得超 3.3 V。
- 发生器与板必须共地(否则量到的是两地之间的差),且不形成地环:优先单点共地、必要时发生器浮地。
- 不许因为"反正发生器便宜"就往端子侧上额定电压——那是 §5 第二张卡(要变比)与 §9(要标准源)的范围。
4.6.5 这台发生器证不到什么(别让读数长得像证据)
| 证不到 | 为什么 | 归属 |
|---|---|---|
| 端子二次值 | 注入点在 ④ 之前,算出来还是引脚域 | §5「端子/子板变比确认」 |
| 精度等级(0.5 级 / 1 级) | 发生器自己的幅值误差本身就是要被校的量,不能冒充标准源 | §5「两点标定与精度验收」+ §7 #1 |
| 跨转换器相位 / 功率 / 对称分量 | 两片转换器无共同采样触发(V0.1 硬件缺陷)+ STM32 侧 1 拍乒乓滞后。量纲链路口径见 docs/硬件平台/ADC通道映射说明.md §7;处置见 §9 |
|
| THD / 谐波方和根 | 固件里只有两根谐波轨,没有合成出口 | §9(挂谐波轨立项) |
| 温升、EMC、长时间漂移 | 单轮台架不覆盖 | 送检与型式试验 |
5. 任务卡(完成即销项删行;标识列用语义短语,不配编号)
资源图例:🔴 台架(COM3 / ST-LINK,
bench.lock独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。 状态:⬜ 未开始 · 🟦 进行中。已闭环 = 直接删行。 本表只写判据;执行步骤在docs/测试说明/ADC前端注入验证流程.md,实测结论在docs/硬件平台/ADC通道映射说明.md§8.1(动态实测结论开在其后)。
| 标识(任务名) | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|
| 信号发生器动态波形验证 | 按 §4.6.2 跑完 D1~D6(D4 允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表新增到 docs/测试说明/ADC前端注入验证流程.md(直流节之后开一节"交流"),实测结论在 docs/硬件平台/ADC通道映射说明.md §8.1 之后新开一节;证据(串口日志 + 104 落库)归档 docs/测试说明/boot_log_data/ |
静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 1 Vrms 的交流信号发生器(不需要标准源、不需要端子加压) | 🔴 台架 + 手边发生器 | docs/测试说明/、docs/硬件平台/ |
⬜ |
| 端子/子板变比确认 | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 docs/硬件平台/ADC通道映射说明.md;据此判定 eng 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 |
已知电压注入验证(✅);与动态验证无依赖关系,可并行 | 🟡 子板实物或原理图 | docs/硬件平台/ |
⬜ |
| 两点标定与精度验收 | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 [adc_cal] 并置 VALID;误差 ≤ 目标精度(待定:0.5 级 / 1 级 → §7 #1);证据归档 |
端子/子板变比确认;削顶五路的处置结论(D5) | 🟡 标准源 / 继保测试仪 | docs/算法/、docs/测试说明/boot_log_data/ |
⬜ |
为什么把动态验证排在第一(不是因为它最重要,而是因为它把后面两张卡踩实):
- 它不依赖任何外部资源,而另两张卡都在等东西;等待期正好做它。
- 它复用刚闭环的注入点与读数出口,边际成本几乎为零。
- 它会先把 D5 那类"预期内的
[ERR]"暴露在台架规程里并写清判读,避免第二、三张卡跑到一半 才发现"自动化测试把这轮读成 FAIL"。 - 它顺手把"发生器能证 / 不能证"的界线钉住,两点标定开跑时判据不会串档。
6. 并行与顺序
主干一条道,两处等外部资源(自环 = 等待),动态那一步不阻塞后面的卡:
flowchart TD
S([静态注入 2026-10-27 已闭环]) --> Q1{发生器在手?}
Q1 -- 否 --> W1[等待:发生器到位<br/>不动端子、不烧高压]
W1 --> Q1
Q1 -- 是 --> DYN[信号发生器动态波形验证<br/>D1 幅值 · D2 波形 · D5 削顶 先做]
DYN --> WB[回写:测试说明加「交流」一节<br/>通道映射补动态实测节]
WB --> Q2{变比到手?}
Q2 -- 否 --> W2[等待:子板实物或原理图]
W2 --> Q2
Q2 -- 是 --> CAL[两点标定与精度验收<br/>标准源 / 继保测试仪]
CAL --> V[电气 8 路 VALID 全置位]
V --> R[保护自动解卡<br/>闭锁 → 解锁台架验证]
R --> E([标准源送检 + 第三方 104 主站验收])
W1 -. 并行不阻塞 .-> ENG[eng 保持 0<br/>本波只承诺「ADC 引脚电压」]
ENG -.-> E
- 实测斜率偏差规则:实测斜率与理论 LSB 偏差 >2 % 时先查前端(分压 / 变比 / 焊接)再改系数—— 用系数凑斜率会把硬件的错固化成"标定值"。这条对动态同样成立(D1 偏差 >2 % 先查接线与共地)。
- 并行度规则见
docs/环境与部署/并行任务工作树方案.md§7.3。
7. 前置决策
一张表带状态列:🟡 是还没拍的(拍板前相应任务卡无法判定 DoD),✅ 是口径锚点,勿删—— 第 3 行是
CFG_VAL_INT,App/cfg/cfg_file.c:31引用的"§7 决策 3"就指它,勿改序。
| # | 问题 / 决策 | 备选 | 现状 / 建议 | 状态 |
|---|---|---|---|---|
| 1 | 精度目标 | 0.5 级 / 1 级 | 决定两点标定的判据。两点标定开跑前必须定,否则"误差 ≤ 目标精度"这条 DoD 无法判定。保护判据本身只需 3~5 %,0.5 级是计量口径 | 🟡 开放 |
| 2 | 端子 / 子板变比从哪来 | ① 有子板原理图(直接算)② 只有子板实物(万用表同时量端子与引脚)③ 都没有 | 决定 eng 能否置 1。② 同样可行且够用;③ 则本波只交付"ADC 引脚电压",二次值登记为缺口 |
🟡 开放 |
| 3 | CFG_VAL_INT(有符号零点) |
补引擎值类型 / 零点改 uint16 + 32768 偏置 | 已定案:补值类型(strtol + ERANGE + 宽度上下界,s_encode() 带负号)。偏置方案否决理由见 §4.4 尾注 |
✅ 已定案 |
| 4 | 未标定即闭锁 | 保持闭锁 / 用万用表走捷径提前解锁 | 已定案:用户裁定 2026-10-25 保持闭锁到标准源到位,不缩短解锁路径 | ✅ 已定案 |
| 5 | 遥测快照发布权 | adc_task 分频发布 / 消费者各自计时组装 |
已定案:adc_task 唯一发布者(§4.5),调用点数 = 1 由评审守 |
✅ 已定案 |
| 6 | 温度是否纳入线性标定 | 纳入 / 不纳入 | 已定案:不纳入,adc_cal_flags(TEMP) 恒 0,页面 -- |
✅ 已定案 |
| 7 | 注入层级与上限 | 引脚侧 / U5 排针端子侧 |
已定案:端子侧(③ 段的"端子侧"),≤2 V 直流——U5 排针是可安全接触的最低一级,引脚侧要拆子板 |
✅ 已定案 |
| 8 | eng = 0 期间的测频幅值门怎么处置 |
A 保持恒失效(现状,UI 恒 --)/ B 台架临时把 FREQ_AMP_MIN 降到引脚域量级跑一轮 D4 再还原 / C 换成"相对量"门限(如帧内最大值的一定时比例) |
建议 A 为常态 + B 为一次性台架,C 需要重新论证别在过渡期改。跑之前先定,还原由 §8 风险行盯 | 🟡 开放 |
| 9 | 动态验证的基准与发生器要求 | 万用表 AC 档 / 发生器自报刻度 / 借标准源 | 建议:以万用表 AC 档为基准,发生器只要求"波形干净、幅度稳定、频率能锁 50.000 Hz",不拿它的刻度当精度;判据档沿用静态 ±2 % | 🟡 开放 |
8. 风险
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| 削顶负向用例被当成固件 bug | 做 D5 时 STM32 那五路必然钉下轨 → rail: edge=… 是 [ERR] 行,而 @test 的 forbidden 标记含 [ERR] → 整轮被判 FAIL |
判读规则写进流程文档:"做 D5 的这一轮 [ERR] rail: 属预期,只人工判读、不计入 @test 结论",或把这五路排在最后单独一轮并事先声明。同时别忘 cl=0xE6 是来源派生(§2.6),不是本轮新削出来的 |
| 拿发生器的精度当标准用 | 用发生器自报 Vrms 当基准值去比 | 基准 = 万用表 AC 档实测(§7 #9);发生器只当"波形干净、频率可锁"的信号源,它自己的幅值误差正是要被校的量 |
临时改了 FREQ_AMP_MIN 忘了还原 |
走 §7 #8 的 B 方案 | 改动落在产品头文件里、会编进固件。单列一条收尾判据:还原后 @build 0 错误 0 警告 + git diff 里 App/algo/freq.h 必须为空;并在 §7 #8 那行留一句"本轮台架已还原" |
| 峰值当成有效值,顶到量程外 | 只看 Vrms 数字:1.000 Vrms 峰值已 1.414 V | 接线前按峰值核一遍:TPAFE 侧 ≤±2 V、STM32 侧峰值必须 <3.3 V(且负半周本就钉轨,只作 D5 用) |
| 发生器与板不共地 / 地环 | 两台设备各自接电网地 | 单点共地,必要时发生器浮地;读数漂或出现与幅度无关的偏置先查这里 |
非整 50 Hz 注入被当成 meas 抖动 bug |
注 49.5 / 50.5 Hz | meas 是瞬时基波有效值透传、200 ms 是上送节拍不是平均窗(§4.5)→ 快照轨会有拍频式周期间跳动,属预期。测频腿要扫频时读 freq(hb),别读 meas: |
cfg 键数顶格 |
后续给 [adc_cal] 加键 |
已按 8+1 / 8 拆段;加键前先看 CFG_FILE_MAX_KEYS,必要时再拆 |
| 标定值把保护"调坏" | 两点标定写入错误系数 | adc_cal_set() 校验范围(k 必须在板级系数 ×[0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 [ERR] |
| 削顶通道被当成可测 | 消费者只看 k 不看 flags |
adc_cal_flags() 是唯一查询入口,adc_cal_apply() 不返回可用性;单测覆盖"CLIPPED 通道 104 恒 IV" |
| 快照双写 | 104 或 UI 侧也加一个 200 ms 计时器 | 设计约定"唯一发布者 = adc_task";评审时数 meas_tick() 调用点 = 1 |
| 加压烧板 | 变比未确认就往端子加额定电压 | 端子级上额定值必须在变比确认之后,且先量"端子对地通断"确认无直流通路。动态验证只在 U5 排针侧 ≤±2 V 做,正就是为了绕开这条风险 |
9. 范围边界(本波不做)
| 不做 | 理由 / 归属 |
|---|---|
| THD / 谐波方和根真有效值、快照 4 点平均 | 挂 docs/算法/继电保护功能复现规划.md 的「遥测谐波轨(可选)」一起做;快照保持"基波有效值 + 直取相量"口径(§4.5) |
| 谐波轨的消费出口(C04 / C05 目前无人消费) | D6 只证"算得对";接线到判据或上送属谐波轨立项范围,本波不动 |
| 端子级额定电压、绝缘耐压、温升 | 要标准源 / 型式试验条件;本波所有注入都在 U5 排针侧 ±2 V 以内 |
| 录波(原始码值段文件) | 已独立立项(2026-10-29):docs/任务规划/故障录波.md;本卡「动态波形验证」的样本出口将改由录波段文件承担,排序也随之调整(docs/子系统设计/故障录波设计说明.md §11) |
| 104 文件传输(规约侧读文件) | 仍独立待排;现场与台架取回一律走现成 FTP(21 端口),规约侧文件服务等送检或第三方交接需求再议 |
| 等周波调频 | 与标定正交、无标准源时判据不可达,见 docs/算法/继电保护功能复现规划.md §3.1 |
| 功率 / 相位跨相比较 / 功率因数 / 对称分量 | V0.1 硬件禁止:跨转换器无同一时刻性,docs/硬件平台/ADC通道映射说明.md §7 通道归属行 |
| PT 断线判据 | 需要 flags 与遥信配合,而 V0.1 无开入硬件 → 归开入波次 |
| 开入 / 开出固件 | 固件里完全没有这两类代码(docs/问题记录/采集与数据处理短板评测.md 登记),是另一个波次的量级 |
| 温度非线性折算 | §7 已定案行"温度不纳入线性标定" |
| 端子二次值(一次/二次变比换算) | 条件项:变比确认拿到变比才做;拿不到则本波只到"ADC 引脚电压",eng 保持 0,缺口登记进 docs/任务规划/登记簿.md |
| UI 页面(含交流量回炉) | 归「UI 补齐」;本波只保证 meas_snap_t 与 adc_cal_flags() 可被其消费 |
10. 与其它工作的关系
| 工作 / 文档 | 关系 |
|---|---|
docs/测试说明/ADC前端注入验证流程.md |
执行步骤的属主。本文只写"证到哪、判据是什么、为什么这么排";怎么接表笔、读哪一行、填哪张表一律在那篇里。动态验证的步骤同样落那篇(新开"交流"节),本文 §4.6 只留判据 |
| 通道映射说明 | docs/硬件平台/ADC通道映射说明.md §7.1(①②③④ 链路分段)与 §8.1(静态六项实测)是量纲与实测记录的属主;本文 §2.1 / §2.6 是它的消费者,不另立口径,动态实测结论也回写该文件 |
docs/子系统设计/故障录波设计说明.md |
录波段文件是本卡「动态波形验证」的样本出口:录波落地后判据从「比对派生标量」升级为「PC 独立重算 vs 板上读数」对表,动态验证的排序也因此让位给录波数据面(用户裁定 2026-10-29,理由与三处口径变更见该文 §11) |
docs/算法/采集与算法层设计说明.md |
算法与判据正文(全周傅氏、测频、保护元件);本文只规定"这些算法的信度到什么程度" |
docs/子系统设计/IEC104上行设计说明.md |
动态验证的读数出口(0x4011~0x4018 + 0x401D);送检验收索引在 docs/任务规划/登记簿.md §7 |
| 送检验收 | 标准源送检依赖本文「两点标定与精度验收」;顺序不可倒(先变比 → 再标定 → 才解卡 → 才送检,§6) |
| UI 补齐 | 已交付的 meas_snap_t + adc_cal_flags() 供 ui_data_rt_t 填 eng:现为 0 = 引脚电压,变比确认拿到变比后才升 1 = 二次值。UI 不必等本文任何一张卡 |
| 双转换器无共同采样触发(V0.2 硬件改版) | 本波的 CLIPPED 位就是这条硬件缺陷在软件里的可见形态;V0.2 改版后该位恒 0,页面与 104 绑定零改动 |