2 Commits

Author SHA1 Message Date
wandering1 87fa0276ad docs: 六轮验证文档剔除104读数通道+字母编号黑话清扫
CI / 静态门禁 (pre-commit) (push) Failing after 3m46s
CI / 主机侧单测 (MSVC) (push) Successful in 29s
注入流程/数据可信/故障录波设计说明三份文档与速查图
全部剔除104作为量测工具(YC交叉、0x401D/0x4012观察项、
§8.6第7步整行;总耗时150改135 min);104仍是固件消费者
与送检参照,架构表述保留。

注入流程全文清扫:A档/B档/定量档/定性档/段档/标量档等
字母编号与黑话清零;波形轮注简化为三句;通用动作段重写
为编号四步。

数据可信属主同步:§4.6前提表、§4.6.2三行判据、§4.6.3
读数点对比表、DoD证据归档口径。

内存内容分配策略.md:22修复编号改名事故(STM32L4被误替换
成「出口与记录」),按git原文恢复。

速查图生成器gen_ac_rounds_svg.py三处文案+脚注同步改并重跑,
脚本与产物同笔提交。
2026-11-04 19:04:31 +08:00
wandering1 740bcbcc37 Merge pull request 'fix(nand-ftl): 传输失败不再误标坏块 + format 不再被脏缓存挡死(#79)' (#81) from fix/nand-ftl-format-deadlock into master
CI / 静态门禁 (pre-commit) (push) Has been cancelled
CI / 主机侧单测 (MSVC) (push) Has been cancelled
Reviewed-on: #81
2026-11-04 19:01:36 +08:00
6 changed files with 345 additions and 547 deletions
+33 -33
View File
@@ -1,24 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1060" height="680" viewBox="0 0 1060 680" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<rect x="46.0" y="106.0" width="314.0" height="246.0" rx="10" fill="#eff6ff" stroke="#2563eb" stroke-width="2"/>
<text x="58.0" y="132.0" font-size="15" font-weight="700" fill="#0f172a">幅值轮</text>
<text x="348.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#2563eb">先做 · 主用例</text>
<text x="348.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#2563eb">先做 · 三档幅度</text>
<rect x="58.0" y="142.0" width="290.0" height="86.0" rx="6" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="62.0" y1="185.0" x2="344.0" y2="185.0" stroke="#94a3b8" stroke-width="0.8" stroke-dasharray="3 3"/>
<line x1="68.0" y1="161.2" x2="338.0" y2="161.2" stroke="#2563eb" stroke-width="1" stroke-dasharray="5 4"/>
<line x1="68.0" y1="208.8" x2="338.0" y2="208.8" stroke="#2563eb" stroke-width="1" stroke-dasharray="5 4"/>
<polyline points="68.0,185.0 69.9,182.9 71.9,180.7 73.8,178.6 75.8,176.6 77.7,174.6 79.7,172.7 81.6,170.9 83.5,169.3 85.5,167.7 87.4,166.3 89.4,165.1 91.3,164.0 93.3,163.1 95.2,162.3 97.1,161.8 99.1,161.4 101.0,161.3 103.0,161.3 104.9,161.5 106.8,161.9 108.8,162.5 110.7,163.3 112.7,164.2 114.6,165.4 116.6,166.7 118.5,168.1 120.4,169.7 122.4,171.4 124.3,173.2 126.3,175.1 128.2,177.1 130.2,179.2 132.1,181.3 134.0,183.4 136.0,185.5 137.9,187.7 139.9,189.8 141.8,191.9 143.8,193.9 145.7,195.9 147.6,197.7 149.6,199.5 151.5,201.1 153.5,202.6 155.4,204.0 157.4,205.2 159.3,206.3 161.2,207.1 163.2,207.8 165.1,208.3 167.1,208.6 169.0,208.8 170.9,208.7 172.9,208.4 174.8,208.0 176.8,207.3 178.7,206.5 180.7,205.5 182.6,204.3 184.5,203.0 186.5,201.5 188.4,199.9 190.4,198.2 192.3,196.3 194.3,194.4 196.2,192.4 198.1,190.3 200.1,188.2 202.0,186.1 204.0,183.9 205.9,181.8 207.9,179.7 209.8,177.6 211.7,175.6 213.7,173.7 215.6,171.8 217.6,170.1 219.5,168.5 221.5,167.0 223.4,165.7 225.3,164.5 227.3,163.5 229.2,162.7 231.2,162.0 233.1,161.6 235.1,161.3 237.0,161.2 238.9,161.4 240.9,161.7 242.8,162.2 244.8,162.9 246.7,163.7 248.6,164.8 250.6,166.0 252.5,167.4 254.5,168.9 256.4,170.5 258.4,172.3 260.3,174.1 262.2,176.1 264.2,178.1 266.1,180.2 268.1,182.3 270.0,184.5 272.0,186.6 273.9,188.7 275.8,190.8 277.8,192.9 279.7,194.9 281.7,196.8 283.6,198.6 285.6,200.3 287.5,201.9 289.4,203.3 291.4,204.6 293.3,205.8 295.3,206.7 297.2,207.5 299.2,208.1 301.1,208.5 303.0,208.7 305.0,208.7 306.9,208.6 308.9,208.2 310.8,207.7 312.7,206.9 314.7,206.0 316.6,204.9 318.6,203.7 320.5,202.3 322.5,200.7 324.4,199.1 326.3,197.3 328.3,195.4 330.2,193.4 332.2,191.4 334.1,189.3 336.1,187.1 338.0,185.0" fill="none" stroke="#2563eb" stroke-width="2" stroke-linejoin="round"/>
<text x="68.0" y="151.0" font-size="10.5" fill="#64748b">峰 ±1.414 V · 基波 RMS 1.000 V</text>
<text x="68.0" y="151.0" font-size="10.5" fill="#64748b">峰 ±1.414 V · 基波有效值 1.000 V</text>
<text x="58.0" y="244.0" font-size="11" font-weight="700" fill="#2563eb">注入</text>
<text x="94.0" y="244.0" font-size="11.5" fill="#64748b">UA(R31)端子侧,正弦 50.000 Hz、1.000 V</text>
<text x="94.0" y="260.0" font-size="11.5" fill="#64748b">rms</text>
<text x="94.0" y="244.0" font-size="11.5" fill="#64748b">UA(R31)端子侧,正弦 50.000 Hz,三档 Vpp</text>
<text x="94.0" y="260.0" font-size="11.5" fill="#64748b"> 2.828 / 1.414 / 0.566</text>
<text x="58.0" y="280.0" font-size="11" font-weight="700" fill="#2563eb">判据</text>
<text x="94.0" y="280.0" font-size="11.5" fill="#0f172a">ua_mv 中位数 ≈ 万用表 × 1000,偏差 ≤2 %</text>
<text x="58.0" y="300.0" font-size="11" font-weight="700" fill="#2563eb">出口</text>
<text x="94.0" y="300.0" font-size="11.5" fill="#64748b">meas: ua_mv 为主;104 0x4011 只作交叉读</text>
<text x="94.0" y="316.0" font-size="11.5" fill="#64748b">数</text>
<text x="94.0" y="280.0" font-size="11.5" fill="#0f172a">每档 ua_mv ≈ 万用表 × 1000,偏差 ≤2 %</text>
<text x="58.0" y="300.0" font-size="11" font-weight="700" fill="#2563eb">读数</text>
<text x="94.0" y="300.0" font-size="11.5" fill="#64748b">meas: ua_mv 为主(1 mV 分辨率)</text>
<rect x="372.0" y="106.0" width="314.0" height="246.0" rx="10" fill="#f0fdfa" stroke="#0d9488" stroke-width="2"/>
<text x="384.0" y="132.0" font-size="15" font-weight="700" fill="#0f172a">波形轮</text>
<text x="674.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#0d9488">真 RMS ≠ 基波</text>
<text x="674.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#0d9488">真有效值 ≠ 基波</text>
<rect x="384.0" y="142.0" width="290.0" height="86.0" rx="6" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="394.0" y1="161.2" x2="664.0" y2="161.2" stroke="#94a3b8" stroke-width="0.9" stroke-dasharray="5 4"/>
<polyline points="400.0,185.0 400.7,182.5 401.3,180.0 402.0,177.6 402.6,175.3 403.3,173.0 403.9,170.9 404.6,169.0 405.2,167.2 405.9,165.7 406.6,164.3 407.2,163.2 407.9,162.3 408.5,161.7 409.2,161.3 409.8,161.2 410.5,161.4 411.1,161.8 411.8,162.5 412.5,163.5 413.1,164.6 413.8,166.0 414.4,167.7 415.1,169.5 415.7,171.4 416.4,173.6 417.0,175.8 417.7,178.2 418.4,180.6 419.0,183.1 419.7,185.6 420.3,188.1 421.0,190.6 421.6,193.0 422.3,195.3 422.9,197.5 423.6,199.6 424.3,201.5 424.9,203.2 425.6,204.7 426.2,206.0 426.9,207.0 427.5,207.9 428.2,208.4 428.8,208.7 429.5,208.7 430.2,208.5 430.8,208.0 431.5,207.3 432.1,206.3 432.8,205.0 433.4,203.6 434.1,201.9 434.7,200.1 435.4,198.0 436.1,195.9 436.7,193.6 437.4,191.2 438.0,188.7 438.7,186.3 439.3,183.7 440.0,181.3 440.6,178.8 441.3,176.4 441.9,174.1 442.6,172.0 443.3,169.9 443.9,168.1 444.6,166.4 445.2,165.0 445.9,163.7 446.5,162.7 447.2,162.0 447.8,161.5 448.5,161.3 449.2,161.3 449.8,161.6 450.5,162.1 451.1,163.0 451.8,164.0 452.4,165.3 453.1,166.8 453.7,168.5 454.4,170.4 455.1,172.5 455.7,174.7 456.4,177.0 457.0,179.4 457.7,181.9 458.3,184.4 459.0,186.9 459.6,189.4 460.3,191.8 461.0,194.2 461.6,196.4 462.3,198.6 462.9,200.5 463.6,202.3 464.2,204.0 464.9,205.4 465.5,206.5 466.2,207.5 466.9,208.2 467.5,208.6 468.2,208.8 468.8,208.7 469.5,208.3 470.1,207.7 470.8,206.8 471.4,205.7 472.1,204.3 472.8,202.8 473.4,201.0 474.1,199.1 474.7,197.0 475.4,194.7 476.0,192.4 476.7,190.0 477.3,187.5 478.0,185.0" fill="none" stroke="#0d9488" stroke-width="1.8" stroke-linejoin="round"/>
@@ -27,17 +26,17 @@
<text x="529.0" y="226.0" font-size="10.5" text-anchor="middle" fill="#64748b">方波</text>
<polyline points="580.0,185.0 580.7,183.4 581.3,181.8 582.0,180.2 582.6,178.6 583.3,177.0 583.9,175.4 584.6,173.8 585.2,172.2 585.9,170.6 586.6,169.0 587.2,167.4 587.9,165.8 588.5,164.2 589.2,162.6 589.8,161.4 590.5,163.0 591.1,164.6 591.8,166.2 592.5,167.8 593.1,169.4 593.8,171.0 594.4,172.6 595.1,174.2 595.7,175.8 596.4,177.4 597.0,179.0 597.7,180.6 598.4,182.2 599.0,183.8 599.7,185.4 600.3,187.0 601.0,188.6 601.6,190.2 602.3,191.8 602.9,193.4 603.6,195.0 604.3,196.6 604.9,198.2 605.6,199.8 606.2,201.4 606.9,203.0 607.5,204.6 608.2,206.2 608.8,207.8 609.5,208.2 610.2,206.6 610.8,205.0 611.5,203.4 612.1,201.8 612.8,200.2 613.4,198.6 614.1,197.0 614.7,195.4 615.4,193.8 616.1,192.2 616.7,190.6 617.4,189.0 618.0,187.4 618.7,185.8 619.3,184.2 620.0,182.6 620.6,181.0 621.3,179.4 621.9,177.8 622.6,176.2 623.3,174.6 623.9,173.0 624.6,171.4 625.2,169.8 625.9,168.2 626.5,166.6 627.2,165.0 627.8,163.4 628.5,161.8 629.2,162.2 629.8,163.8 630.5,165.4 631.1,167.0 631.8,168.6 632.4,170.2 633.1,171.8 633.7,173.4 634.4,175.0 635.1,176.6 635.7,178.2 636.4,179.8 637.0,181.4 637.7,183.0 638.3,184.6 639.0,186.2 639.6,187.8 640.3,189.4 641.0,191.0 641.6,192.6 642.3,194.2 642.9,195.8 643.6,197.4 644.2,199.0 644.9,200.6 645.5,202.2 646.2,203.8 646.9,205.4 647.5,207.0 648.2,208.6 648.8,207.4 649.5,205.8 650.1,204.2 650.8,202.6 651.4,201.0 652.1,199.4 652.8,197.8 653.4,196.2 654.1,194.6 654.7,193.0 655.4,191.4 656.0,189.8 656.7,188.2 657.3,186.6 658.0,185.0" fill="none" stroke="#0d9488" stroke-width="1.8" stroke-linejoin="round"/>
<text x="619.0" y="226.0" font-size="10.5" text-anchor="middle" fill="#64748b">三角</text>
<text x="394.0" y="151.0" font-size="10.5" fill="#64748b">同峰值对齐(不是同 Vrms)</text>
<text x="394.0" y="151.0" font-size="10.5" fill="#64748b">同设 Vpp 2.828 V(不是同有效值)</text>
<text x="384.0" y="244.0" font-size="11" font-weight="700" fill="#0d9488">注入</text>
<text x="420.0" y="244.0" font-size="11.5" fill="#64748b">同峰值 1.414 V 改方波 / 三角(面板有效值各</text>
<text x="420.0" y="260.0" font-size="11.5" fill="#64748b">异)</text>
<text x="420.0" y="244.0" font-size="11.5" fill="#64748b">同设 Vpp 2.828 V 改方波 / 三角(面板有效</text>
<text x="420.0" y="260.0" font-size="11.5" fill="#64748b">值各异)</text>
<text x="384.0" y="280.0" font-size="11" font-weight="700" fill="#0d9488">判据</text>
<text x="420.0" y="280.0" font-size="11.5" fill="#0f172a">读数只跟基波:方波 ≈1278、三角 ≈817,±2 %</text>
<text x="384.0" y="300.0" font-size="11" font-weight="700" fill="#0d9488">出口</text>
<text x="384.0" y="300.0" font-size="11" font-weight="700" fill="#0d9488">读数</text>
<text x="420.0" y="300.0" font-size="11.5" fill="#64748b">meas: ua_mv;抬头记万用表响应类型</text>
<rect x="698.0" y="106.0" width="314.0" height="246.0" rx="10" fill="#f0fdf4" stroke="#16a34a" stroke-width="2"/>
<text x="710.0" y="132.0" font-size="15" font-weight="700" fill="#0f172a">相位轮</text>
<text x="1000.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#16a34a">定量 · 取段</text>
<text x="1000.0" y="132.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#16a34a">定量 · 录波</text>
<rect x="710.0" y="142.0" width="290.0" height="86.0" rx="6" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="714.0" y1="185.0" x2="996.0" y2="185.0" stroke="#94a3b8" stroke-width="0.8" stroke-dasharray="3 3"/>
<polyline points="720.0,185.0 721.9,183.4 723.9,181.8 725.8,180.2 727.8,178.6 729.7,177.1 731.7,175.6 733.6,174.1 735.5,172.7 737.5,171.4 739.4,170.1 741.4,168.9 743.3,167.7 745.3,166.7 747.2,165.7 749.1,164.8 751.1,164.0 753.0,163.3 755.0,162.7 756.9,162.2 758.8,161.8 760.8,161.5 762.7,161.3 764.7,161.2 766.6,161.3 768.6,161.4 770.5,161.7 772.4,162.0 774.4,162.5 776.3,163.1 778.3,163.7 780.2,164.5 782.2,165.4 784.1,166.3 786.0,167.4 788.0,168.5 789.9,169.7 791.9,170.9 793.8,172.3 795.8,173.7 797.7,175.1 799.6,176.6 801.6,178.1 803.5,179.7 805.5,181.3 807.4,182.9 809.4,184.5 811.3,186.1 813.2,187.7 815.2,189.3 817.1,190.8 819.1,192.4 821.0,193.9 822.9,195.4 824.9,196.8 826.8,198.2 828.8,199.5 830.7,200.7 832.7,201.9 834.6,203.0 836.5,204.0 838.5,204.9 840.4,205.8 842.4,206.5 844.3,207.1 846.3,207.7 848.2,208.1 850.1,208.4 852.1,208.6 854.0,208.7 856.0,208.7 857.9,208.6 859.9,208.4 861.8,208.1 863.7,207.7 865.7,207.1 867.6,206.5 869.6,205.8 871.5,204.9 873.5,204.0 875.4,203.0 877.3,201.9 879.3,200.7 881.2,199.5 883.2,198.2 885.1,196.8 887.1,195.4 889.0,193.9 890.9,192.4 892.9,190.8 894.8,189.3 896.8,187.7 898.7,186.1 900.6,184.5 902.6,182.9 904.5,181.3 906.5,179.7 908.4,178.1 910.4,176.6 912.3,175.1 914.2,173.7 916.2,172.3 918.1,170.9 920.1,169.7 922.0,168.5 924.0,167.4 925.9,166.3 927.8,165.4 929.8,164.5 931.7,163.7 933.7,163.1 935.6,162.5 937.6,162.0 939.5,161.7 941.4,161.4 943.4,161.3 945.3,161.2 947.3,161.3 949.2,161.5 951.2,161.8 953.1,162.2 955.0,162.7 957.0,163.3 958.9,164.0 960.9,164.8 962.8,165.7 964.7,166.7 966.7,167.7 968.6,168.9 970.6,170.1 972.5,171.4 974.5,172.7 976.4,174.1 978.3,175.6 980.3,177.1 982.2,178.6 984.2,180.2 986.1,181.8 988.1,183.4 990.0,185.0" fill="none" stroke="#16a34a" stroke-width="2" stroke-linejoin="round"/>
@@ -45,13 +44,14 @@
<text x="720.0" y="226.0" font-size="10.5" font-weight="700" fill="#16a34a">UA 0° 实线</text>
<text x="798.0" y="226.0" font-size="10.5" font-weight="700" fill="#e11d48">UN +90° 红虚线</text>
<text x="710.0" y="244.0" font-size="11" font-weight="700" fill="#16a34a">注入</text>
<text x="746.0" y="244.0" font-size="11.5" fill="#64748b">UA(R31)与 UN(R28)同源同幅 1.000 Vrms</text>
<text x="710.0" y="264.0" font-size="11" font-weight="700" fill="#16a34a">判据</text>
<text x="746.0" y="264.0" font-size="11.5" fill="#0f172a">同段内相位差 ≈0°,B 通道改 90° 应跟到 ≈90</text>
<text x="746.0" y="280.0" font-size="11.5" fill="#0f172a">°,±2°</text>
<text x="710.0" y="300.0" font-size="11" font-weight="700" fill="#16a34a">出口</text>
<text x="746.0" y="300.0" font-size="11.5" fill="#64748b">wave_read.py fft 定量;phasor(hb) 只核</text>
<text x="746.0" y="316.0" font-size="11.5" fill="#64748b">象限</text>
<text x="746.0" y="244.0" font-size="11.5" fill="#64748b">UA(R31)与 UN(R28)同源同幅 Vpp 2.828 </text>
<text x="746.0" y="260.0" font-size="11.5" fill="#64748b">V</text>
<text x="710.0" y="280.0" font-size="11" font-weight="700" fill="#16a34a">判据</text>
<text x="746.0" y="280.0" font-size="11.5" fill="#0f172a">同段内相位差 ≈0°,B 通道改 90° 应跟到 ≈90</text>
<text x="746.0" y="296.0" font-size="11.5" fill="#0f172a">°,±2°</text>
<text x="710.0" y="316.0" font-size="11" font-weight="700" fill="#16a34a">读数</text>
<text x="746.0" y="316.0" font-size="11.5" fill="#64748b">wave_read.py fft 定量;phasor(hb) 只核</text>
<text x="746.0" y="332.0" font-size="11.5" fill="#64748b">象限</text>
<rect x="46.0" y="366.0" width="314.0" height="246.0" rx="10" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
<text x="58.0" y="392.0" font-size="15" font-weight="700" fill="#0f172a">测频轮</text>
<text x="348.0" y="392.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#d97706">A 档无数 = 过</text>
@@ -68,8 +68,8 @@
<text x="58.0" y="524.0" font-size="11" font-weight="700" fill="#d97706">判据</text>
<text x="94.0" y="524.0" font-size="11.5" fill="#0f172a">A 档如实报不可测:valid=0、UI 显 --;报 5</text>
<text x="94.0" y="540.0" font-size="11.5" fill="#0f172a">0.00 反而是 bug</text>
<text x="58.0" y="560.0" font-size="11" font-weight="700" fill="#d97706">出口</text>
<text x="94.0" y="560.0" font-size="11.5" fill="#64748b">freq(hb) 0.01 Hz;UI Hz、104 0x401D</text>
<text x="58.0" y="560.0" font-size="11" font-weight="700" fill="#d97706">读数</text>
<text x="94.0" y="560.0" font-size="11.5" fill="#64748b">freq(hb) 0.01 Hz;UI Hz</text>
<rect x="372.0" y="366.0" width="314.0" height="246.0" rx="10" fill="#fff1f2" stroke="#e11d48" stroke-width="2"/>
<text x="384.0" y="392.0" font-size="15" font-weight="700" fill="#0f172a">削顶轮</text>
<text x="674.0" y="392.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#e11d48">负向 · 单独日志</text>
@@ -81,24 +81,24 @@
<text x="420.0" y="504.0" font-size="11.5" fill="#64748b">UB(R52):DC −1.00 V 保持 ≥5 s,或 2.0 </text>
<text x="420.0" y="520.0" font-size="11.5" fill="#64748b">Hz 正弦</text>
<text x="384.0" y="540.0" font-size="11" font-weight="700" fill="#e11d48">判据</text>
<text x="420.0" y="540.0" font-size="11.5" fill="#0f172a">连续 20 拍贴底 → rail / edge 锁存 + 104 </text>
<text x="420.0" y="556.0" font-size="11.5" fill="#0f172a">该路 IV 清零;50 Hz 正弦不锁存 = 预期</text>
<text x="384.0" y="576.0" font-size="11" font-weight="700" fill="#e11d48">出口</text>
<text x="420.0" y="576.0" font-size="11.5" fill="#64748b">cal: rail / edge;取段再跑 shape 对表</text>
<text x="420.0" y="540.0" font-size="11.5" fill="#0f172a">连续 20 拍贴底 → rail / edge 锁存;50 Hz</text>
<text x="420.0" y="556.0" font-size="11.5" fill="#0f172a"> 正弦不锁存 = 预期</text>
<text x="384.0" y="576.0" font-size="11" font-weight="700" fill="#e11d48">读数</text>
<text x="420.0" y="576.0" font-size="11.5" fill="#64748b">cal: rail / edge;录波再跑 shape 对表</text>
<rect x="698.0" y="366.0" width="314.0" height="246.0" rx="10" fill="#f5f3ff" stroke="#7c3aed" stroke-width="2"/>
<text x="710.0" y="392.0" font-size="15" font-weight="700" fill="#0f172a">谐波轮</text>
<text x="1000.0" y="392.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#7c3aed">定量 · 取段</text>
<text x="1000.0" y="392.0" font-size="10.5" text-anchor="end" font-weight="700" fill="#7c3aed">定量 · 录波</text>
<rect x="710.0" y="402.0" width="290.0" height="86.0" rx="6" fill="#ffffff" stroke="#cbd5e1" stroke-width="1"/>
<line x1="714.0" y1="445.0" x2="996.0" y2="445.0" stroke="#94a3b8" stroke-width="0.8" stroke-dasharray="3 3"/>
<polyline points="720.0,445.0 721.9,442.2 723.9,439.5 725.8,437.1 727.8,435.0 729.7,433.4 731.7,432.3 733.6,431.6 735.5,431.3 737.5,431.3 739.4,431.4 741.4,431.5 743.3,431.5 745.3,431.3 747.2,430.9 749.1,430.2 751.1,429.2 753.0,428.1 755.0,426.8 756.9,425.7 758.8,424.7 760.8,424.0 762.7,423.7 764.7,423.8 766.6,424.4 768.6,425.5 770.5,427.0 772.4,428.8 774.4,430.7 776.3,432.7 778.3,434.5 780.2,436.0 782.2,437.2 784.1,438.0 786.0,438.5 788.0,438.6 789.9,438.4 791.9,438.0 793.8,437.7 795.8,437.4 797.7,437.4 799.6,437.7 801.6,438.4 803.5,439.4 805.5,440.8 807.4,442.5 809.4,444.4 811.3,446.3 813.2,448.1 815.2,449.7 817.1,451.0 819.1,451.9 821.0,452.5 822.9,452.6 824.9,452.5 826.8,452.2 828.8,451.8 830.7,451.5 832.7,451.4 834.6,451.6 836.5,452.2 838.5,453.1 840.4,454.5 842.4,456.1 844.3,458.0 846.3,459.9 848.2,461.8 850.1,463.5 852.1,464.9 854.0,465.8 856.0,466.3 857.9,466.3 859.9,465.8 861.8,465.0 863.7,464.0 865.7,462.8 867.6,461.6 869.6,460.5 871.5,459.6 873.5,458.9 875.4,458.6 877.3,458.5 879.3,458.5 881.2,458.7 883.2,458.7 885.1,458.6 887.1,458.2 889.0,457.3 890.9,456.1 892.9,454.3 894.8,452.2 896.8,449.7 898.7,446.9 900.6,444.0 902.6,441.2 904.5,438.6 906.5,436.3 908.4,434.4 910.4,433.0 912.3,432.1 914.2,431.5 916.2,431.3 918.1,431.3 920.1,431.4 922.0,431.5 924.0,431.5 925.9,431.2 927.8,430.7 929.8,429.9 931.7,428.8 933.7,427.6 935.6,426.4 937.6,425.3 939.5,424.4 941.4,423.8 943.4,423.7 945.3,424.0 947.3,424.8 949.2,426.0 951.2,427.6 953.1,429.4 955.0,431.4 957.0,433.3 958.9,435.0 960.9,436.5 962.8,437.5 964.7,438.2 966.7,438.5 968.6,438.5 970.6,438.3 972.5,437.9 974.5,437.6 976.4,437.4 978.3,437.4 980.3,437.9 982.2,438.7 984.2,439.8 986.1,441.4 988.1,443.1 990.0,445.0" fill="none" stroke="#7c3aed" stroke-width="2" stroke-linejoin="round"/>
<text x="720.0" y="411.0" font-size="10.5" fill="#64748b">基波 + 2 次 + 5 次</text>
<text x="710.0" y="504.0" font-size="11" font-weight="700" fill="#7c3aed">注入</text>
<text x="746.0" y="504.0" font-size="11.5" fill="#64748b">IA(R19):基波 0.800 + 二次 0.160 + 五</text>
<text x="746.0" y="520.0" font-size="11.5" fill="#64748b">次 0.160 Vrms</text>
<text x="746.0" y="504.0" font-size="11.5" fill="#64748b">IA(R19):分三注,基波 Vpp 2.263、二五次</text>
<text x="746.0" y="520.0" font-size="11.5" fill="#64748b">各 Vpp 0.453</text>
<text x="710.0" y="540.0" font-size="11" font-weight="700" fill="#7c3aed">判据</text>
<text x="746.0" y="540.0" font-size="11.5" fill="#0f172a">Ia2 / Ia5 各 ≈0.160 Vrms,±2 %(最坏峰值</text>
<text x="746.0" y="556.0" font-size="11.5" fill="#0f172a"> 1.58 V 留余量)</text>
<text x="710.0" y="576.0" font-size="11" font-weight="700" fill="#7c3aed">出口</text>
<text x="746.0" y="540.0" font-size="11.5" fill="#0f172a">Ia2 / Ia5 各读数 ≈0.160 V,±2 %(最坏峰</text>
<text x="746.0" y="556.0" font-size="11.5" fill="#0f172a">值 1.58 V 留余量)</text>
<text x="710.0" y="576.0" font-size="11" font-weight="700" fill="#7c3aed">读数</text>
<text x="746.0" y="576.0" font-size="11.5" fill="#64748b">wave_read.py fft --ch 4;UI Ia2 / Ia5 </text>
<text x="746.0" y="592.0" font-size="11.5" fill="#64748b">目检旁证</text>
<line x1="46.0" y1="634.0" x2="1014.0" y2="634.0" stroke="#cbd5e1" stroke-width="1"/>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

+28 -25
View File
@@ -46,7 +46,7 @@
|---|---|
| 判断现在这些数能信到什么程度 | §1 这张图 + §2.6(静态证到哪)+ §2.7(动态没证什么) |
| 改采集 / 算法 / 品质位相关代码 | §2.1 §2.2 §2.3(口径)+ §4.1~§4.5(设计依据) |
| 上台架做正弦验证 | §4.6(接法、六轮判据、读数出口、坑)+ §5 的「信号发生器动态波形验证」卡 |
| 上台架做正弦验证 | §4.6(接法、六轮判据、数字从哪儿读、坑)+ §5 的「信号发生器动态波形验证」卡 |
| 看还差谁、按什么顺序做 | §5 任务卡 + §6 顺序图 |
| 确认某件事是**故意不做**而不是漏了 | §9;有没有踩坑风险看 §8 |
@@ -157,11 +157,11 @@ V0.1 恒命中 UB/UC/IB/IC/IN,位图 `0xE6`),它表示"这路不能测交
| 下游 | 现在 | 为什么 |
|---|---|---|
| 基波有效值(RMS) | 🟡 算法在 PC 上证过(幅值 ≤1 %、49/51 Hz 下 ≤1.5 %),**经真 ADC 后一次没测** | 1 V 正弦进 ADC 后 `fAmSQ` 是否 = 1 V,无实测 |
| 基波有效值 | 🟡 算法在 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` |
| 谐波 C04 / C05 | ❌ 实例建了,**无消费者、无处上送** | `prot_elm.c` 无引用,`meas` 只算 `harm=1` |
| 保护判据 | 🔒 闭锁中 | §4.3 |
→ **下一跳就是 §4.6**:把一根真正的 50 Hz 正弦从**已经验证过的那个注入点**灌进去,
@@ -242,7 +242,7 @@ M4 的六条退出判据(逐条对齐现状,别整格打勾):
- 与"自检失败 / 采样故障闭锁"同构(`PROT_HF_LOCK_MASK` 那一套),**不新增机制**。
- 现有台架 `/serial-boot-test` 的期望会因此变化——**这是有意的**,任务卡里同步更新判据。
- 台架调试要旁路只能走编译期开关 `DTU_BENCH`,不进 cfg、不进 104。
⚠ **`DTU_BENCH` 只旁路这一处**:它**不**旁路 §2.3 #1 的测频幅值门,也不产生任何读数出口。
⚠ **`DTU_BENCH` 只旁路这一处**:它**不**旁路 §2.3 #1 的测频幅值门,也不产生任何新的读数通道。
### 4.4 落盘:拆两段,不碰引擎
@@ -300,7 +300,7 @@ typedef struct {
| 注入点已经验证过,且就在那儿 | `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3 的注入点清单(串联电阻端子侧 = `U5` 排针);③ 段 1:1 已拿到台架证据(§2.6) |
| **不知道 ④ 变比也能验算法** | 注入点在 ④ **之前**,发生器给的电压就是引脚电压,算法链要证的正是"引脚域里算得对不对" |
| 幅度小两个数量级 | 只需 ±2 V 以内的正弦(TPAFE 侧判据上限);端子二次值验证要上 100 V / 220 V,风险与设备都在那一级 |
| 现有静态验证的读数出口可直接复用 | 串口心跳 + 104 YC,零固件改动(§4.6.3) |
| 现有静态验证的读数的地方可直接复用 | 串口心跳,零固件改动(§4.6.3) |
**这一跳证的是功能性**(算得对不对、品质报得实不实、节拍稳不稳),**不是计量**(误差几级)——
发生器不当"标准"的界线见 §4.6.5 与 §7 #9。
@@ -313,34 +313,37 @@ typedef struct {
> **轮次名一律用语义短语(用户裁定 2026-10-30:清退"字母+数字"判据号)**:D1 → 幅值轮、D2 → 波形轮、
> D3 → 相位轮、D4 → 测频轮、D5 → 削顶轮、D6 → 谐波轮;本族旧号作废不得再取走
> (与二极管位号、网络自愈决策记录、链路延迟缺陷编号只是同形,各不相干)。
>
> **注入幅度一律按峰峰值 Vpp 设定(用户裁定 2026-11-04)**:发生器面板的有效值显示不当设定基准
> (同一个 Vpp 换波形后有效值显示跟着变,切波形瞬间还残留上一波形的值);万用表 AC 档与板上读数
> 天然是有效值刻度,正弦下 有效值 = Vpp ÷ 2.828,换算着比。
| 轮次 | 验什么 | 接法 | 读哪 | 过判据 |
|---|---|---|---|---|
| **幅值轮** | 基波幅值计量 | 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) |
| **幅值轮** | 基波幅值计量 | UA(R31 / `AIN1`)注 Vpp 2.828 V(= 峰值 ±1.414 V)、50.000 Hz 正弦 | `meas:` 的 `ua_mv` | 读数 = 万用表 AC 档读数,偏差 ≤2 %(与静态同档)。⚠ 别用 `phasor(hb)` 行比幅值——那是 ×0.1 定点,注 1 V 只剩 10 格(§4.6.3) |
| **波形轮** | 读数是否只跟基波走 | 同幅值改方波、三角 | 同上 | 期望值 = **基波分量有效值**(同峰值下的基波 / 峰值比:方波 ≈ **0.90**,闭式 4/π ÷ √2 = 0.900、20 点整周期 DFT 实算 0.904;三角 ≈ **0.573**,闭式 8/π² ÷ √2 = 0.573、实算 0.578),**不是**真有效值(方波 = 1.000、三角 = 0.583 峰值);偏差 ≤2 %。算术与逐波形对照表见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的波形卡。顺带把"这台仪表读的是基波"这条口径钉进文档——用户拿真有效值表去对会以为差了 10 % |
| **相位轮** | 相位 | UA 与 UN 两路**同片**(都走 TPAFE)注同幅、同相 | **定量档**:录波段文件 `test/host/wave_read.py fft`(浮点重算基波相位;段内表序 `UA` = 0、`UN` = 3);**定性档**:`phasor(hb)` 各行 `Re=` / `Im=` | **定量档**:同段内两路相位差 ≤2°,把发生器相位改 90° 后差值跟到 ≈90°。**定性档只判"跟随"**(差值落进 80°~100°)——`phasor` 出口是 ×0.1 定点,1.000 Vrms 时每格 0.1 V,角度量化最坏 ≈ atan(0.1 / 0.707) ≈ 8°,判不动 2°(§4.6.3)。⚠ 段与发生器**无绝对相位锁定**(触发瞬间钉在段内点 159),只能比**同段内两路**的相对差,跨段比相位或拿发生器相位当绝对基准都不成立。**只许比同片内**——跨转换器无同刻性(§9),STM32 那五路还有 1 拍乒乓滞后 |
| **测频轮** | 测频 | 同幅值轮的 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 风险行 |
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 1.000 Vrms 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;104 `0x4012`;段文件档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿、104 上该路 IV 且值清零。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮(§8 第一行) |
| **谐波轮** | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注)。⚠ 峰值预算:1.000 Vrms 基波 + 两个 20 % 分量的最坏对齐 ≈ 1.98 V 已顶 ±2 V 红线 → 基波用 **0.800 Vrms**、二次与五次各 0.160 Vrms | **定量档**:段文件 `test/host/wave_read.py fft --ch 4 --all`(`IA` = 段内表序 4,直接给基波与 2 / 5 次谐波 RMS,单位 mV);**旁证**:UI 交流量页 `Ia2` / `Ia5`(1 mV)与 `phasor(hb) C04-IA-F2` / `C05-IA-F5`(×0.1 定点,只证这根轨不是恒 0) | 谐波轨读数 = 注入分量(**±2 %,走定量档**;周期行档判不动:0.160 Vrms 在 ×0.1 出口只有 1~2 格)。⚠ 这两根轨**目前没有任何下游消费者**(`prot_elm.c` 无引用、`meas` 只算 `harm=1`),所以谐波轮只证"算得对",**不证"有人用"**——出口归 §9 的谐波轨立项 |
| **相位轮** | 相位 | UA 与 UN 两路**同片**(都走 TPAFE)注同幅、同相 | **定量档**:录波段文件 `test/host/wave_read.py fft`(浮点重算基波相位;段内表序 `UA` = 0、`UN` = 3);**定性档**:`phasor(hb)` 各行 `Re=` / `Im=` | **定量档**:同段内两路相位差 ≤2°,把发生器相位改 90° 后差值跟到 ≈90°。**定性档只判"跟随"**(差值落进 80°~100°)——`phasor` 串口行是 ×0.1 定点,Vpp 2.828 V(板上读数 ≈1000 mV)时每格 0.1 V,角度量化最坏 ≈ atan(0.1 / 0.707) ≈ 8°,判不动 2°(§4.6.3)。⚠ 段与发生器**无绝对相位锁定**(触发瞬间钉在段内点 159),只能比**同段内两路**的相对差,跨段比相位或拿发生器相位当绝对基准都不成立。**只许比同片内**——跨转换器无同刻性(§9),STM32 那五路还有 1 拍乒乓滞后 |
| **测频轮** | 测频 | 同幅值轮的 1 V/50 Hz | `freq(hb):` | **预期就是"不出数"**(幅值门 50 V 在引脚域恒不过,§2.3 #1)→ 这条的判据是"如实报不可测"(`freq_valid=0`、UI `Hz` 显示 `--`),**不是**报出一个错误的 50.00。想真验 45~55 Hz 精度(PC 侧判据 0.02 Hz)须临时把 `FREQ_AMP_MIN` 降到引脚域量级(如 0.5 V)单跑一轮 → §7 #8 + §8 风险行 |
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 Vpp 2.828 V 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;段文件档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮(§8 第一行) |
| **谐波轮** | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注)。⚠ 峰值预算:Vpp 2.828 V 基波 + 两个 20 % 分量的最坏对齐峰值 ≈ 1.98 V 已顶 ±2 V 红线 → 基波用 **Vpp 2.263 V**、二次与五次各 Vpp 0.453 V | **定量档**:段文件 `test/host/wave_read.py fft --ch 4 --all`(`IA` = 段内表序 4,直接给基波与 2 / 5 次谐波有效值,单位 mV);**旁证**:UI 交流量页 `Ia2` / `Ia5`(1 mV)与 `phasor(hb) C04-IA-F2` / `C05-IA-F5`(×0.1 定点,只证这根轨不是恒 0) | 谐波轨读数 = 注入分量(**±2 %,走定量档**;周期行档判不动:读数 0.160 V 在 ×0.1 串口行上只有 1~2 格)。⚠ 这两根轨**目前没有任何下游消费者**(`prot_elm.c` 无引用、`meas` 只算 `harm=1`),所以谐波轮只证"算得对",**不证"有人用"**——接到哪、给谁用,归 §9 的谐波轨立项 |
**先做幅值 / 波形 / 削顶三轮**(纯读数、无跨通道约定),相位 / 谐波次之,测频轮视 §7 #8 的裁定。每条的两档跑法(周期行标量档 /
录波段文件定量档)、触发动作、耗时排布与失败分诊在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.6。
#### 4.6.3 读数出口(零固件改动)
#### 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 单色;`--` **同时**表示"没数"和"有数但不可信" → 不能当判据,只能当旁证 |
| **段文件样本出口(代码侧已落地,2026-10-29)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 「比对派生标量」已可升级成「PC 独立重算 vs 板上读数」对表(判据与执行步骤见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**但板级那一轮还没跑**(注 1 V / 50 Hz、与 `meas:` 与 104 YC 对表、CRC 不符必须拒收的实测,见 `docs/子系统设计/故障录波设计说明.md` §10);示波器仍旧只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
| **仍然没有的(2026-10-29 更新)** | 没有命令控制台、也没有「把窗里 20 / 40 个点导出来」的定点 dump 子命令——**但样本出口本身已成立**(上一行的段文件:一次 320 点 / 8 路,比原来规划的 20 / 40 点窗更宽) | 现场取回一律走现成 FTP(21 端口),形状就地看回放页单通道、或在 PC 侧用同一脚本出图;示波器只对照发生器、不当判据。**判据已升级为「PC 独立重算 vs 板上读数」对表**,对表的执行轮次待台架(见 `docs/子系统设计/故障录波设计说明.md` §11) |
| **段文件(原始样本,代码侧已落地,2026-10-29)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 「比对派生标量」已可升级成「PC 独立重算 vs 板上读数」对表(判据与执行步骤见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**但板级那一轮还没跑**(注 1 V / 50 Hz、与 `meas:` 对表、CRC 不符必须拒收的实测,见 `docs/子系统设计/故障录波设计说明.md` §10);示波器仍旧只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
| **仍然没有的(2026-10-29 更新)** | 没有命令控制台、也没有「把窗里 20 / 40 个点导出来」的定点 dump 子命令——**但原始样本这条通道本身已成立**(上一行的段文件:一次 320 点 / 8 路,比原来规划的 20 / 40 点窗更宽) | 现场取回一律走现成 FTP(21 端口),形状就地看回放页单通道、或在 PC 侧用同一脚本出图;示波器只对照发生器、不当判据。**判据已升级为「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),
- 幅度按**峰峰值 / 峰值**核,别看有效值数字:Vpp 2.828 V 正弦峰值已 ±1.414 V;TPAFE 侧按判据只到 **±2 V 峰值(= Vpp 4 V)**(满量程 ±5 V),
STM32 那五路是 **0~3.3 V 单极性**——给它们注交流只能是削顶轮那种"故意削顶"的用例,峰值同样不得超 3.3 V。
- 发生器与板**必须共地**(否则量到的是两地之间的差),且不形成地环:优先单点共地、必要时发生器浮地。
- **不许**因为"反正发生器便宜"就往端子侧上额定电压——那是 §5 第二张卡(要变比)与 §9(要标准源)的范围。
@@ -352,7 +355,7 @@ typedef struct {
| 端子二次值 | 注入点在 ④ 之前,算出来还是引脚域 | §5「端子/子板变比确认」 |
| 精度等级(0.5 级 / 1 级) | 发生器自己的幅值误差本身就是要被校的量,不能冒充标准源 | §5「两点标定与精度验收」+ §7 #1 |
| 跨转换器相位 / 功率 / 对称分量 | 两片转换器无共同采样触发(V0.1 硬件缺陷)+ STM32 侧 1 拍乒乓滞后;量纲链路口径见通道映射说明的链路分段一节 | §9(本波不做矢量类运算) |
| THD / 谐波方和根 | 固件里只有两根谐波轨,没有合成出口 | §9(挂谐波轨立项) |
| THD / 谐波方和根 | 固件里只有两根谐波轨,没有合成后的数送出去 | §9(挂谐波轨立项) |
| 温升、EMC、长时间漂移 | 单轮台架不覆盖 | 送检与型式试验 |
---
@@ -366,14 +369,14 @@ typedef struct {
| 标识(任务名)| DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表**新增到** `docs/测试说明/专项验证/ADC前端注入验证流程.md`(直流节之后开一节"交流"),实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1 之后新开一节;证据(串口日志 + 104 落库)归档 `docs/测试说明/测试数据/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 1 Vrms 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `docs/测试说明/`、`docs/硬件平台/` | ⬜ |
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表**新增到** `docs/测试说明/专项验证/ADC前端注入验证流程.md`(直流节之后开一节"交流"),实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1 之后新开一节;证据(串口日志 + 录波段文件)归档 `docs/测试说明/测试数据/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 Vpp 2.828 V 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `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);证据归档 | 端子/子板变比确认;削顶五路的处置结论(削顶轮) | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/测试数据/boot_log_data/` | ⬜ |
**为什么把动态验证排在第一**(不是因为它最重要,而是因为它把后面两张卡踩实):
1. 它**不依赖任何外部资源**,而另两张卡都在等东西;等待期正好做它。
2. 它复用刚闭环的注入点与读数出口,**边际成本几乎为零**。
2. 它复用刚闭环的注入点与读数的地方,**边际成本几乎为零**。
3. 它会先把削顶轮那类"预期内的 `[ERR]`"暴露在台架规程里并写清判读,避免第二、三张卡跑到一半
才发现"自动化测试把这轮读成 FAIL"。
4. 它顺手把"发生器能证 / 不能证"的界线钉住,两点标定开跑时判据不会串档。
@@ -434,9 +437,9 @@ flowchart TD
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| **削顶负向用例被当成固件 bug** | 做削顶轮时 STM32 那五路必然钉下轨 → `rail: edge=…` 是 `[ERR]` 行,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 整轮被判 FAIL | 判读规则写进流程文档:"做削顶轮的这一轮 `[ERR] rail:` 属预期,只人工判读、不计入 `/serial-boot-test` 结论",或把这五路排在最后单独一轮并事先声明。同时别忘 `cl=0xE6` 是**来源派生**(§2.6),不是本轮新削出来的 |
| **拿发生器的精度当标准用** | 用发生器自报 Vrms 当基准值去比 | 基准 = 万用表 AC 档实测(§7 #9);发生器只当"波形干净、频率可锁"的信号源,它自己的幅值误差正是要被校的量 |
| **拿发生器的精度当标准用** | 用发生器自报的有效值数字当基准值去比 | 基准 = 万用表 AC 档实测(§7 #9);发生器只当"波形干净、频率可锁"的信号源,它自己的幅值误差正是要被校的量 |
| **临时改了 `FREQ_AMP_MIN` 忘了还原** | 走 §7 #8 的 B 方案 | 改动落在产品头文件里、会编进固件。单列一条收尾判据:还原后 `/keil-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(且负半周本就钉轨,只作削顶轮用) |
| **峰值当成有效值,顶到量程外** | 只看面板有效值数字:正弦有效值 1.000 V = Vpp 2.828 V,峰值已 ±1.414 V | 接线前按**峰值**核一遍:TPAFE 侧 ≤±2 V、STM32 侧峰值必须 <3.3 V(且负半周本就钉轨,只作削顶轮用) |
| **发生器与板不共地 / 地环** | 两台设备各自接电网地 | 单点共地,必要时发生器浮地;读数漂或出现与幅度无关的偏置先查这里 |
| **非整 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`,必要时再拆 |
@@ -452,9 +455,9 @@ flowchart TD
| 不做 | 理由 / 归属 |
|---|---|
| THD / 谐波方和根真有效值、快照 4 点平均 | 挂 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」一起做;快照保持"基波有效值 + 直取相量"口径(§4.5) |
| **谐波轨的消费出口**(C04 / C05 目前无人消费) | 谐波轮只证"算得对";接线到判据或上送属谐波轨立项范围,本波不动 |
| **谐波轨被谁消费**(C04 / C05 目前无人消费) | 谐波轮只证"算得对";接线到判据或上送属谐波轨立项范围,本波不动 |
| 端子级额定电压、绝缘耐压、温升 | 要标准源 / 型式试验条件;本波所有注入都在 `U5` 排针侧 ±2 V 以内 |
| 录波(原始码值段文件) | **已交付代码面**(2026-10-29 立项并当日落地;判据属主 `docs/子系统设计/故障录波设计说明.md` §10,原卡片登记簿 2026-10-30 销项并入)本卡「动态波形验证」的样本出口**已**由录波段文件承担(§4.6.3 出口表已改),排序也随之调整(`docs/子系统设计/故障录波设计说明.md` §11);**没跑的是板级那一轮**(§10) |
| 录波(原始码值段文件) | **已交付代码面**(2026-10-29 立项并当日落地;判据属主 `docs/子系统设计/故障录波设计说明.md` §10,原卡片登记簿 2026-10-30 销项并入)本卡「动态波形验证」的原始样本**已**由录波段文件承担(§4.6.3 读数地点表已改),排序也随之调整(`docs/子系统设计/故障录波设计说明.md` §11);**没跑的是板级那一轮**(§10) |
| 104 文件传输(规约侧读文件) | 仍独立待排;现场与台架取回一律走现成 FTP(21 端口),规约侧文件服务等送检或第三方交接需求再议 |
| 等周波调频 | 与标定正交、无标准源时判据不可达,见 `docs/算法/继电保护功能复现规划.md` §3.1 |
| 功率 / 相位跨相比较 / 功率因数 / 对称分量 | **V0.1 硬件禁止**:跨转换器无同一时刻性,`docs/硬件平台/ADC通道映射说明.md` §7 通道归属行 |
@@ -472,9 +475,9 @@ flowchart TD
|---|---|
| **`docs/测试说明/专项验证/ADC前端注入验证流程.md`** | **执行步骤的属主**。本文只写"证到哪、判据是什么、为什么这么排";怎么接表笔、读哪一行、填哪张表一律在那篇里。动态验证的**步骤**同样落那篇(新开"交流"节),本文 §4.6 只留判据 |
| **通道映射说明** | `docs/硬件平台/ADC通道映射说明.md` §7.1(①②③④ 链路分段)与 §8.1(静态六项实测)是**量纲与实测记录的属主**;本文 §2.1 / §2.6 是它的**消费者**,不另立口径,动态实测结论也回写该文件 |
| **`docs/子系统设计/故障录波设计说明.md`** | 录波段文件是本卡「动态波形验证」的**样本出口**,数据面代码侧已落地(2026-10-29:环与段格式在 `App/algo/wave_ring.c` / `App/algo/wave_store.c`,PC 侧 `test/host/wave_read.py`);判据从「比对派生标量」升级为「PC 独立重算 vs 板上读数」对表的**执行轮次待台架**,动态验证的排序已因此让位给录波数据面(用户裁定 2026-10-29,理由与三处口径变更见 docs/子系统设计/故障录波设计说明.md §11) |
| **`docs/子系统设计/故障录波设计说明.md`** | 录波段文件是本卡「动态波形验证」的**原始样本来源**,数据面代码侧已落地(2026-10-29:环与段格式在 `App/algo/wave_ring.c` / `App/algo/wave_store.c`,PC 侧 `test/host/wave_read.py`);判据从「比对派生标量」升级为「PC 独立重算 vs 板上读数」对表的**执行轮次待台架**,动态验证的排序已因此让位给录波数据面(用户裁定 2026-10-29,理由与三处口径变更见 docs/子系统设计/故障录波设计说明.md §11) |
| **`docs/算法/采集与算法层设计说明.md`** | 算法与判据正文(全周傅氏、测频、保护元件);本文只规定"这些算法的信度到什么程度" |
| **`docs/子系统设计/IEC104上行设计说明.md`** | 动态验证的**读数出口**(`0x4011`~`0x4018` + `0x401D`);送检验收索引在 `docs/任务规划/登记簿.md` §7 |
| **`docs/子系统设计/IEC104上行设计说明.md`** | 104 上行协议本体(点表 `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 绑定零改动 |
@@ -19,7 +19,7 @@
关键事实:
1. **CCM 对 CPU 是全速内存**。Cortex-M4 无 语义取数与有效性 cache,"CCM 是慢内存"的直觉只适用于带 cache 的核(M7/出口与记录/H7 的非 cacheable 旁路),**在本芯片上不成立**——任何"按速度分配区域"的论证对本文档无效。
1. **CCM 对 CPU 是全速内存**。Cortex-M4 无 L1 cache,"CCM 是慢内存"的直觉只适用于带 cache 的核(M7/L4/H7 的非 cacheable 旁路),**在本芯片上不成立**——任何"按速度分配区域"的论证对本文档无效。
2. **DMA 对 CCM 地址的传输静默不落地**。2026-09-21 首轮 CCM 实验实证:以 CCM 上栈缓冲(dhara meta 132B / is_free 64B)为 DMA 源/目的时传输不生效,引发 FTL 重格式化循环与幻影坏块。此后 DMA 阈值提至 1024B 消除。**工程规则按"DMA 不可达 CCM"执行,不论数据手册如何表述。**
3. CCM 存在性已用 `ST-LINK_CLI -r32 0x10000000` 本机实测可读写;**克隆片可能缺 SRAM3,换料必须重测并回退布局**。
4. 工程不进入 Stop/Standby 低功耗模式,两区域掉电保留行为无差异,不构成分配判据。
@@ -2,11 +2,11 @@
> **模块名称**:故障录波——采样源沿用 TIM3 1 kHz 节拍,专用录波环(`App/algo/wave_ring.c`,已落地)、触发、落盘(defaultTask 是文件系统唯一写者)、取回(FTP 21 端口)、现场回放(UI 单通道页)。
> **文档定位**:本波的**设计属主**——口径、通道集、数据形态、触发模型、文件格式、预算与所有权边界、显示契约、二期不返工的结构约束在此定稿。**板级判据与本波执行顺序的属主即本文 §9 与 §10**——原任务规划下的《故障录波》卡片登记簿已于 2026-10-30 随销项并入本文后删除(沿革见 §14);排期顺位在 `docs/任务规划/README.md` §2.0「独立」行。
> **状态**:设计已定稿,**数据面 + 触发与落盘接线 + UI 两个页面(手动录波、录波回放)的代码面已交付(2026-10-29)**——主机单测 113 / 170 / 110 全 rc=0、双端编译 0 错误 0 警告、板端编码器与 PC 侧解码器两份独立实现字节级互验通过。**没做完的只有板级判据那一轮**(注量对表、FTP 拉回、与 `meas:` 和 104 浮点 YC 对表、CRC 不符必须拒收的实测、回放页放一段真波、两个待台架核数值),逐条列在本文 §10 板级各行。三条已裁定口径见 §1.2。**2026-10-31 远程半轮**已把其中不需要到场与注入的六样跑过(落盘道、触发时序、冷却恢复、轮转、PC 侧坏段拒收、104 并发)——结果与回放页新缺陷「段表枚举恒空」全在 §10「板级远程半轮记录」小节;**该缺陷已于 2026-11-02 远程修复并板级闭环**(根因 = 读侧 `wave_store_seg_path()` 返回值判错 + 键处理缺失效,证据与前后对拍见 §10「回放页枚举恒空缺陷修复记录」)。
> **状态**:设计已定稿,**数据面 + 触发与落盘接线 + UI 两个页面(手动录波、录波回放)的代码面已交付(2026-10-29)**——主机单测 113 / 170 / 110 全 rc=0、双端编译 0 错误 0 警告、板端编码器与 PC 侧解码器两份独立实现字节级互验通过。**没做完的只有板级判据那一轮**(注量对表、FTP 拉回、与 `meas:` 对表、CRC 不符必须拒收的实测、回放页放一段真波、两个待台架核数值),逐条列在本文 §10 板级各行。三条已裁定口径见 §1.2。**2026-10-31 远程半轮**已把其中不需要到场与注入的六样跑过(落盘道、触发时序、冷却恢复、轮转、PC 侧坏段拒收、104 并发)——结果与回放页新缺陷「段表枚举恒空」全在 §10「板级远程半轮记录」小节;**该缺陷已于 2026-11-02 远程修复并板级闭环**(根因 = 读侧 `wave_store_seg_path()` 返回值判错 + 键处理缺失效,证据与前后对拍见 §10「回放页枚举恒空缺陷修复记录」)。
> **相关文档**:
> `docs/子系统设计/ADC采样节拍设计说明.md`(节拍与时序账的属主;本文 §3 的数据源就是它)
> `docs/硬件平台/ADC通道映射说明.md`(网名 `AINn` 不等于板级 `ADCn`,也不等于转换器通道号;链路分段与削顶归属)
> `docs/任务规划/数据可信.md` §4.6(动态波形验证判据;录波落地后它的读数出口升级,见 §11)
> `docs/任务规划/数据可信.md` §4.6(动态波形验证判据;录波落地后它的读数通路升级,见 §11)
> `docs/架构设计/STM32F4-Base存储架构说明.md` §10.1(FatFs 两条实证陷阱与 8.3 短名限制)
> `docs/内存管理/内存内容分配策略.md` §6 与 R6 规则(新增静态缓冲大于 4 KB 的前置动作)
> `docs/UI设计/内容页架构.md`、`docs/UI设计/RemoDispBus协议与接收设计说明.md`(回放页与远端看图的能力边界)
@@ -311,7 +311,7 @@ flowchart TD
- **实际落地形态(逐字)**:打印点在 `App/task/adc_task.c`:782 行,格式串 `"wave: seg=%lu armed=%u src=%s pts=%u err=%lu ovf=%lu drop=%lu"`——**字段名与顺序就是上面的模板**(台架与 PC 脚本按行名 grep,动它就断脚本);`src` 取 M(手动)/ P(保护)/ T(定时自抓)/ `-`(本次上电还没触发过);`armed` 只在 FREEZE 与 SEALED 为 1(COOL 期只挡新触发不录新段,画进 armed 会被台架误读);`seg` 是累计**成功回执**的段数、不是轮转号;`err` = 落盘失败 + SEALED 滞留超时自弃(含 §5.2 第四条的 ring abandoned 判废),由环内计数收口,落盘道不数第二份账。`err` 与 `ovf` 的**已知容差**(lead 裁定 2026-10-29,不修只入档):这两个计数是跨上下文的读-改-自增(`ovf` 由任意上下文的拒绝路径加、`err` 由 adcTask 的滞留自弃与 defaultTask 的落盘失败分别加),本层双端编译、不许引 FreeRTOS / CMSIS 的临界区内在函数,所以并发拒绝或并发失败时**理论上可能少计一次**。定性为**观测计数的已知容差**:只用于趋势与判读,**不作为任何判据的唯一依据**——要坐实「冷却期内确实来了第二次触发」,同时看 `armed` 与那一刻 `/log/start.log` 的时刻。契约原文见 `App/algo/wave_ring.h` 文件头「观测计数的已知容差」段;
- **落盘道失败留痕名清单(2026-10-30 并入原卡片登记簿;台架判读按名索引,不新增第二种形态)**:单板上一律一行 `[WAVE] seg drop: <原因> (idx=… written=…)`,统一打印点 `App/task/default_task.c`:816——`crc selftest FAIL` / `mkdir /wave` / `opendir /wave` / `readdir /wave` / `seg_path` / `pack_start` / `f_open` / `pack_next` / `f_write short` / `pack stall` / `f_close` / `len mismatch` / **`ring abandoned`**(最后一条即 §5.2 第四条陷阱的处置留痕,代码与主机单测面已有、板级未测,观察项见 §10);另有一条非失败的慢段留痕 `[WAVE][WARN] seg held <毫秒> ms (idx=…)`(`App/task/default_task.c`:831)——搬得慢不是错,真失败才走 `seg drop`。
- 只在原先静默的黑洞处补锚点,别重复已有步骤——每条 DBG 日志约 90 B Flash 加 216 B 栈(`AGENTS.md` 的日志与工具链节);
- 该行已同步进 `docs/测试说明/专项验证/ADC前端注入验证流程.md` 的读数出口表(2026-10-29;同一张表还登记了段文件出口与 PC 侧读段工具)。
- 该行已同步进 `docs/测试说明/专项验证/ADC前端注入验证流程.md` 的读数地点表(2026-10-29;同一张表还登记了录波段文件与 PC 侧读段工具)。
---
@@ -322,7 +322,7 @@ flowchart TD
| 主机侧纯逻辑单测(新增,进 `test/host/`) | ① 环:预触发与后触发点数、冻结与解冻、冷却丢弃计数;② 段格式编解码往返,含 CRC 不符、零长度、字节数不符三条失败路径;③ 触发状态机三条来路(手动 / 保护 / bench)。**环与格式必须是纯逻辑**(不碰寄存器、不碰 RTOS)才能这样测——这是 `App/algo/` 既有分层纪律 |
| PC 侧工具的定性 | `test/host/wave_read.py` 是 **bench 工具**(`test/host/` 下的 loose .py,先例 `test/host/ftp_capture.py`),**不是**主机单测套件 → 不建 `run_unit_test.py`、不加 pre-commit 专属钩子(专属钩子默认不补,按 Lead 裁定 2026-10-27);它自带 `--selftest` 就是它的自带回归,跑法与四个子命令见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4 |
| 跨工具链分叉(实证,写进来是为了下一个模块别重踩) | 两份录波 .c 只 include 自身头(链上只有 stdint.h)时,ARMCC 报 22 条 identifier "NULL" is undefined;而主机 MSVC / gcc 会传递性把 stddef.h 拉进来,**主机单测完全照不出这个分叉** → 新增模块需要用 NULL 就自己 include stddef.h(与 `App/algo/sample_ring.c` 同口径,别塞公共头) |
| 板级 | 信号发生器注 1 V / 50 Hz → 手动一段 → FTP 拉回 → PC 脚本量出周波数、幅值、极性与注入一致;再把 PC 重算的基波有效值与板上 `meas:` 与 104 浮点 YC 对表。**判据只量四样:周波数、幅值、极性、钉轨路数——不比绝对相位**(理由见 §4.2「段内点序」:触发瞬间在工频周期内任意落点,段字节里没有绝对时间参考;真要比相位必须让发生器给同步触发,本波不做)。**钉轨对表的合格判据 = 头位图 ⊇ 实测钉轨路数,且差异必须能由注入条件解释**——因为 `clip_mask` 是按来源派生的链路可信性标记(§6.2 偏移 24 行),不是本段实测值:只加直流或小幅注入时那五路本就不该钉轨,硬取等式会假红。**同段另起一条强观察项**:V0.1 下这五路若在做**交流注入**时反而没钉轨,先怀疑接线或该路根本没被驱动——这是告警面,不是失败面(等式仍作为默认尺子留在 PC 侧 `shape --strict` 里,因为它有这个信号价值;要放行差异用那条判据的解释权,不靠改尺子)。**§5.2 第四条的板级观察项(代码与单测面已有、板级未测)**:bench 连续自抓期间人为把卷占住 2 s 以上(例如同一段跑 FTP 大文件读),看串口 `wave:` 行的 `err` 是否加一、是否只出现**一条** `[ERR] … seg drop: ring abandoned` 留痕(不是每拍刷屏)、且段号不推进(下一段仍写同号文件) |
| 板级 | 信号发生器注 1 V / 50 Hz → 手动一段 → FTP 拉回 → PC 脚本量出周波数、幅值、极性与注入一致;再把 PC 重算的基波有效值与板上 `meas:` 对表。**判据只量四样:周波数、幅值、极性、钉轨路数——不比绝对相位**(理由见 §4.2「段内点序」:触发瞬间在工频周期内任意落点,段字节里没有绝对时间参考;真要比相位必须让发生器给同步触发,本波不做)。**钉轨对表的合格判据 = 头位图 ⊇ 实测钉轨路数,且差异必须能由注入条件解释**——因为 `clip_mask` 是按来源派生的链路可信性标记(§6.2 偏移 24 行),不是本段实测值:只加直流或小幅注入时那五路本就不该钉轨,硬取等式会假红。**同段另起一条强观察项**:V0.1 下这五路若在做**交流注入**时反而没钉轨,先怀疑接线或该路根本没被驱动——这是告警面,不是失败面(等式仍作为默认尺子留在 PC 侧 `shape --strict` 里,因为它有这个信号价值;要放行差异用那条判据的解释权,不靠改尺子)。**§5.2 第四条的板级观察项(代码与单测面已有、板级未测)**:bench 连续自抓期间人为把卷占住 2 s 以上(例如同一段跑 FTP 大文件读),看串口 `wave:` 行的 `err` 是否加一、是否只出现**一条** `[ERR] … seg drop: ring abandoned` 留痕(不是每拍刷屏)、且段号不推进(下一段仍写同号文件) |
| 板级·触发来路(2026-10-30 并入原卡「手动触发与保护启动接线」板级段) | 真机面板按一次「手动录波」出一段;造一次过流,段号与该时刻 `/log/start.log` 事件对齐;冷却期内二次触发只加 `ovf` 不重录(**同时看 `armed` 与那一刻 start.log 的时刻,不要只盯 `ovf` 数字**——容差见 §9);冻结窗口内 104 上送与保护判据不受影响(这条是「丢录波样本不丢采集」的验收) |
| 板级·回放页(2026-10-30 并入原卡「现场单通道回放页」板级段) | 真机上放一段真波(不是模拟器合成节拍);远端看图能拍到该页做留证(只作留证,不是波形通路,§8.4);**空态与 CRC 失败态绝不允许画成一条直线**——用坏段在真机复现一次。**2026-10-31 远程半轮进展见下「板级远程半轮记录」小节**:PC 侧坏段拒收已过;回放页坏段/空态画面的测试面**已于 2026-11-02 枚举缺陷修复后打开**(真机已验证真段显示 + 切段切道,见下「回放页枚举恒空缺陷修复记录」小节),坏段/空态两画面本身仍是到场轮要拍的项 |
| UI | `ui-verify` 五步;回放页入 `ui-golden` 黄金参考(**参考图一旦入库只能改代码对齐,禁止刷参考掩盖**);新叶走 `gen_menu.py` 重生成 + 字库链 |
@@ -380,8 +380,8 @@ try 锁纪律)照常读出并显示 ⇒ try 锁读径正常;`manual_req` 作
「0 段缓存」,回放页从此假显「无录波段」、直到下一次 `manual_req` 才重试;失败应不钉表、
下键重试,与 soe_store 读者同纪律。
**本半轮没跑的(人到场轮清单)**:注量对表(周波数 / 幅值 / 极性 / 钉轨路数)、`meas:` 与 104
浮点 YC 数值对表、两个待台架核数值(封存超时窗 §4.2 兜底行与冷却时长 `App/algo/wave_ring.h`)、P 触发与 start.log 对齐(还得先解标定闭锁)、
**本半轮没跑的(人到场轮清单)**:注量对表(周波数 / 幅值 / 极性 / 钉轨路数)、`meas:`
浮点数值对表、两个待台架核数值(封存超时窗 §4.2 兜底行与冷却时长 `App/algo/wave_ring.h`)、P 触发与 start.log 对齐(还得先解标定闭锁)、
bench T 源与卷占用 2 s 的 `ring abandoned` 观察(需 bench 构建)、~~回放页坏段画面与空态画面
(等枚举缺陷修复后才有测试面)~~ **(2026-11-02 枚举缺陷修复后测试面已开,见下小节)**、
`task_prof` 读路径耗时峰值。**执行动作侧**(到场的人做什么、
@@ -447,7 +447,7 @@ bench 锁全程持有;三次烧录(埋点 / 诊断加强 / 根因修复)
| 旧口径 | 新口径 | 原因 |
|---|---|---|
| 「录波通道必须先有工程量,排在本波之后」 | 录波录**原始码值**,不等工程量;解释靠头里的系数快照 | §3.2:现在根本没有工程量,等下去等于永远不动 |
| 动态波形验证的读数出口 = 派生标量(`meas:` / 104 / `phasor(hb)`) | 派生标量仍是**判据**,但样本改从录波段导出 → 判据升级为「PC 独立重算 vs 板上读数」对表 | 录波段就是现成的样本出口,不必再造一条串口通路 |
| 动态波形验证读数的地方 = 派生标量(`meas:` / 104 / `phasor(hb)`) | 派生标量仍是**判据**,但样本改从录波段导出 → 判据升级为「PC 独立重算 vs 板上读数」对表 | 录波段就是现成的样本来源,不必再造一条串口通路 |
| 动态波形验证「手边可做、排在最前」 | 排在录波 P1 之后(用户裁定 2026-10-29:录波先行) | 先有样本通路,验证才不留遗憾 |
(2026-10-30 更新:原卡片登记簿已销项并入本文,§10 尾有本波执行顺序图;排期顺位在 `docs/任务规划/README.md` §2.0「独立」行。)
@@ -1,49 +1,22 @@
# ADC 前端注入验证流程(台架)
> **这篇是什么**:已知电压注入验证的**执行侧**——判据与实测记录在 `docs/硬件平台/ADC通道映射说明.md` §8.1,
> 这边写怎么接表笔、读哪一行日志、填哪张表、结果往哪回写。
> **这篇是什么**:已知电压注入验证的**执行侧**——怎么写表笔、读哪行日志、填哪张表、结果往哪回写。判据与实测记录在属主文档:直流轮 `docs/硬件平台/ADC通道映射说明.md` §8.1、交流轮 `docs/任务规划/数据可信.md` §4.6.2;**本文只写怎么跑**,分叉时判据从属主。证不到什么见 `docs/任务规划/数据可信.md` §4.6.1 与 §4.6.5,本文不重抄。
>
> **本文分两个轮次**:§1~§7 = **直流轮次**(零点 / 线性 / 通道映射 / 极性,2026-10-27 六项 PASS,
> 证的是"一条水平线的高度";**不需要**示波器、信号源、标准源,**只需要**一块万用表 + 一个电位器 + 串口日志)。
> §8 = **交流(正弦)动态验证轮次**(六轮:幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波,证的是"给定电压算得对不对、品质报得实不实、节拍稳不稳")——
> 一台信号发生器接在本文 §3 的同一批注入点上就能跑,**同样不用等标准源**;
> 等标准源的只是**精度等级**那一步(`docs/任务规划/数据可信.md` §5 的「两点标定与精度验收」)。
> V0.1 有五路单极性削顶(`UB/UC/IB/IC/IN`),它们在交流轮次里只能作"预期削顶"的负向用例。
>
> **判据的属主是 `docs/任务规划/数据可信.md` §4.6.2**(六轮各验什么、过判据是多少),本文 §8 只写**怎么跑**。
> 两边于 2026-10-29 对齐;若将来再分叉,分两类裁定:**「验什么、算不算过」从
> `docs/任务规划/数据可信.md` §4.6.2**,**「期望值怎么算、怎么接线怎么跑」从本文 §8**。
> 这一跳为什么不用等标准源、又证不到什么,见其 §4.6.1 与 §4.6.5,本文不重抄。
---
> **两个轮次**:§1~§7 = **直流轮次**(2026-10-27 六项 PASS,只需万用表 + 电位器 + 串口日志);§8 = **交流轮次**(幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波),一台信号发生器接 §3 同一批注入点就能跑,等标准源的只有**精度等级**。V0.1 五路单极性削顶(`UB/UC/IB/IC/IN`)在交流轮次只作"预期削顶"负向用例。
## 1. 为什么非做不可
下游已经全部按"工程量"消费:保护判据、104 遥测、UI 交流量页读的都是 `adc_cal_apply()` 的输出。系数错
一倍,三处一起错,且**没有任何一处会报错**。"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机
读数不同)不证明读数对。所以这一步的性质是**给整条链路的量纲盖章**,不是"补充测试"。
下游全部按"工程量"消费(保护判据、104 遥测、UI 交流量页读 `adc_cal_apply()` 输出)。系数错一倍,三处一起错,**没有任何一处会报错**。这一步是**给整条链路量纲盖章**,不是"补充测试"。
## 2. 前置事实:这个前端不是分压器
2026-10-27 按 `docs/硬件平台/V0.1.tel` 逐通道追线,以 UA 为例(图由
`tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG):
2026-10-27 按 `docs/硬件平台/V0.1.tel` 逐通道追线(图由 `tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图改脚本重跑):
![UA 通道前端:端子 → R31 → ADC7 → TPAFE AIN_7P;C44 / R32 在差分负端,不在信号通路上](../../images/ADC前端电路.svg)
`ADC7` 这个节点上**只有** R31、C44、U3.61 三样东西,**没有对地电阻**。所谓"1k 到地"是 R32,
它接在 TPAFE 的**负输入脚 AIN_7GND**(芯片手册 pin62)上,是把差分负端经 1k 拴到 AGND,
属于差分滤波,不是信号分压。STM32 侧更直接(图 B):`AIN2 —[R52 1k]— ADC17 —[C111]— AGND`,
同样没有分流电阻,连 R32 那个接地电阻都没有。
`ADC7` 节点只有 R31、C44、U3.61,**无对地电阻**;"1k 到地"是 R32 接 TPAFE 负输入脚 AIN_7GND,属差分滤波非信号分压。STM32 侧同样无分流电阻。结论:① **不存在 2:1 分压**(`docs/任务规划/数据可信.md` §2.1 已改引脚侧系数 152.59 / 805.66),只需确认转换器 LSB 与逐通道映射;② **端子侧斜率 = 引脚侧斜率**,端子侧注入安全且能直接验 LSB。
**由此得到两条可直接用的结论**:
1. **不存在 2:1 分压**。旧口径"板级系数 305.18 / 1611.3 µV/码"(按 2:1 折算到 `AINn` 侧的条件值)
在本板上不成立;`docs/任务规划/数据可信.md` §2.1 已于 2026-10-27 改为引脚侧系数(152.59 / 805.66)。
所以已知电压注入验证只需**确认转换器 LSB 与逐通道映射**,不必再判别两种读法。
2. **端子侧斜率 = 引脚侧斜率**。所以在**端子侧**注入既安全(有 1k 串阻护着芯片)又能直接验 LSB,
不必去碰 LQFP 引脚。
期望斜率(由转换器满量程事实推出,与前端无关):
期望斜率(由转换器满量程推出):
| 转换器 | 满量程 | LSB | **期望斜率** |
| ---------- | ----------------------- | ---------------- | -------------- |
@@ -52,7 +25,7 @@
## 3. 注入点清单
串联电阻的两只焊盘就是两个注入层级:**1 脚 = 端子侧(靠 U5)**,**2 脚 = 引脚侧(靠转换器)**。
串阻两只焊盘 = 两个注入层级:**1 脚 = 端子侧(靠 U5)**,**2 脚 = 引脚侧(靠转换器)**。
| 语义 | 串阻 | 端子侧节点 | 引脚侧节点 | 转换器脚 | 期望斜率 |
| -- | --- | --------------- | ------- | ----------- | ------------- |
@@ -66,60 +39,41 @@
| IN | R48 | `AIN11`(U5.C10) | `ADC11` | U17.36(PA2) | 1241.2 |
| 温度 | R47 | `V_ZL2`(U5.C11) | `ADC14` | U17.41(PA5) | 不验(非线性,不参与标定) |
> 引脚侧没有串阻保护,注入前**必须外串 10 k 限流**。除非端子侧结果对不上、需要分离
> "转换器的错"和"前端的错",否则不要用引脚侧。
> 引脚侧无串阻保护,注入前**必须外串 10 k 限流**;除非端子侧对不上需分离"转换器的错"和"前端的错",否则不用引脚侧。
## 4. 读数出口(固件只有下面这些周期行,没有命令控制台)
## 4. 数字能从哪儿读(固件只有下面这些周期行,没有命令控制台)
> **样本出口已落地(代码侧,2026-10-29)**:故障录波的数据面已进仓(格式与判据属主见 docs/子系统设计/故障录波设计说明.md §6.2 与 §6.3、板级判据见 §10、口径变更见该文 §11;原卡片登记簿 2026-10-30 销项并入后删除)——每次触发一段,段文件直接给出 8 路 × 320 点原始码值,动态验证的判据因此**可以**从「比对下表这些派生标量」升级为「PC 独立重算 vs 板上读数」对表。下表仍是固件唯一的**周期行**出口(段文件不是周期行,只在触发时产生),两种出口对表用。
> **录波段文件能力已落地(2026-10-29)**:故障录波数据面进仓(格式属主 `docs/子系统设计/故障录波设计说明.md` §6.2/§6.3、板级判据 §10;口径变更 2026-10-30 并入该文 §11,原卡片登记簿销项后删除)——每次触发一段,段文件直接给 8 路 × 320 点原始码值,判据可从「比对派生标量」升级为「PC 独立重算 vs 板上读数」互相对表。下表是固件**周期性**打印的全部输出行(段文件只在触发时产生,不在其中),两类数字互为对照。
| 日志行 | 频率 | 内容 | 用途 |
| ----------------------------------------------------------- | ------ | ------------------------ | ------------------- |
| `adc: UA=.. UB=.. UC=.. UN=.. IA=.. IB=.. IC=.. IN=.. T=..` | 每 10 s | **9 路原始码值** | 本次验证的主读数 |
| `cal: ua_mv=.. un_mv=.. ia_mv=.. vl=.. cl=..` | 每 10 s | UA/UN/IA 折算后毫伏 + 标定/削顶位图 | 旁证:码值 → 电压是否自洽 |
| `first: UA=.. … T=..` | 每次开机一次 | 9 路原始码值 | 与 `adc:` 行互校(同序同格式) |
| `frames=.. idle=.. adc1_err=.. tgap=..` | 每 10 s | 采集健康计数 | 步骤 4 的节奏判据 |
| `phasor(hb) C0x-…: Re=.. Im=.. rms=..`(逐实例)、`freq(hb): f=.. valid=..` | 每 10 s | 基波相量分量与测频读数(×0.1 / ×0.01 定点) | **交流轮次的主读数**(直流轮次只作旁证) |
| `meas: seq=.. v=.. ua_mv=.. un_mv=.. ia_mv=.. f=.. fv=..` | 每 10 s | 200 ms 遥测快照轨(基波有效值 mV) | 交流轮次的幅值比对(1 mV 分辨率,比 phasor 行细) |
| **段文件** `/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见,与 /log 平级) | 每次触发一段(手动 / 保护启动 / bench 定时) | 8 路 × 320 点原始码值 + 封存瞬间的标定与品质快照(布局见 docs/子系统设计/故障录波设计说明.md §6.2) | **样本出口**:交流轮次的主对表源——预触发 160 点 + 后触发 160 点,触发瞬间落在段内点 159 |
| PC 侧脚本 `test/host/wave_read.py`(不是固件日志,bench 工具,纯标准库) | 手动跑;`--selftest` 是它的自带回归 | 四个子命令:dump(逐字段与双 CRC)/ fft(全周傅氏重算基波有效值与相位)/ shape(削顶与形态判定,可 `--strict`)/ plot(出 SVG 或 PNG,PNG 用 `-o` 落文件) | 把段文件还原成周波数、幅值、相位、削顶判定与图 = 「PC 独立重算」这条判据的执行体;CRC 不符或零长度它必须**拒绝**而不是画出东西 |
| 日志行 | 频率 | 内容 | 用途 |
|---|---|---|---|
| `adc: UA=.. UB=.. UC=.. UN=.. IA=.. IB=.. IC=.. IN=.. T=..` | 每 10 s | **9 路原始码值** | **直流轮(§1~§7)主要读的数** |
| `cal: ua_mv=.. un_mv=.. ia_mv=.. vl=.. cl=..` | 每 10 s | UA/UN/IA 毫伏 + 标定/削顶位图 | 旁证:码值→电压自洽 |
| `first: UA=.. … T=..` | 每次开机一次 | 9 路原始码值 | 与 `adc:` 互校(同序同格式) |
| `frames=.. idle=.. adc1_err=.. tgap=..` | 每 10 s | 采集健康计数 | 判节奏用(判据在 §5.5,即步骤 4) |
| `phasor(hb) C0x-…: Re=.. Im=.. rms=..`、`freq(hb): f=.. valid=..` | 每 10 s | 基波相量与测频(×0.1 / ×0.01 定点) | **交流轮(§8)主要读的数**(直流轮只旁证) |
| `meas: seq=.. v=.. ua_mv=.. un_mv=.. ia_mv=.. f=.. fv=..` | 每 10 s | 200 ms 遥测快照轨(基波有效值 mV) | 交流幅值比对(1 mV 分辨率) |
| **段文件** `/wave/WAVE00.BIN` 起 100 号轮转(FTP 根下,与 /log 平级) | 每次触发一段 | 8 路 × 320 点 + 封存瞬间标定与品质快照(`docs/子系统设计/故障录波设计说明.md` §6.2) | **录波档要用的原始样本**:预触发 160 + 后触发 160 点,触发瞬间在段内点 159 |
| PC 侧 `test/host/wave_read.py`(纯标准库) | 手动跑;`--selftest` 自带回归 | 四子命令:dump(逐字段双 CRC)/ fft(全周傅氏重算基波有效值与相位)/ shape(削顶与形态,可 `--strict`)/ plot(SVG/PNG,PNG 用 `-o`) | 「PC 独立重算」执行体;CRC 不符或零长度必须**拒绝** |
> ⚠ 直流轮次用不到后两行,但**它们一直都在**。交流轮次(判据见 `docs/任务规划/数据可信.md` §4.6)
> 必须用 `meas:` 或 104 YC 比幅值,别用 `phasor(hb)` 行——那行是 ×0.1 定点,注 1 V 只剩 10 格。
> ⚠ 交流轮次(判据 `docs/任务规划/数据可信.md` §4.6)必须用 `meas:` 比幅值,别用 `phasor(hb)`——那行 ×0.1 定点,注 1 V 只剩 10 格。
`adc:` 行是 2026-10-27 新增的(`App/task/adc_task.c` 心跳块),此前只有 `cal:` 的三路,
验 8 个通道要复位二十余次。现在**全程不必复位**。
`adc:` 行 2026-10-27 新增(`App/task/adc_task.c` 心跳块),此前验 8 通道要复位二十余次,现在**全程不必复位**。
**「码」是什么**:ADC 输出的**原始整数**,中文常写「码值」/「AD 码」,英文对应 raw code / counts。
它表示"多少个最小刻度(LSB)",**本身不是物理量**——电压 = 码 × LSB,而两片转换器的 LSB 不同:
**「码」是什么**:ADC 原始整数,**不是物理量**——电压 = 码 × LSB:
| 转换器 | 位数与极性 | 码的范围 | 1 码 = | 换算示例 |
| 转换器 | 位数与极性 | 码范围 | 1 码 | 示例 |
|---|---|---|---|---|
| TPAFE5160 | 16 位双极性 | −32768 ~ +32767(共 65536 码 = 10 V 跨度) | 152.59 µV | 11430 码 × 152.59 µV ≈ **1.744 V** |
| STM32 ADC1 | 12 位单极性 | 0 ~ 4095(共 4096 码 = 3.3 V 跨度) | 805.66 µV | 1000 码 × 805.66 µV ≈ **0.806 V** |
| TPAFE5160 | 16 位双极性 | −32768~+32767(65536 码 = 10 V) | 152.59 µV | 11430 码 ≈ **1.744 V** |
| STM32 ADC1 | 12 位单极性 | 0~4095(4096 码 = 3.3 V) | 805.66 µV | 1000 码 ≈ **0.806 V** |
同一个整数落在两把刻度尺上代表不同电压(图由 `tools/arch_diagram/gen_adc_code_scale_svg.py`
生成,改图请改脚本重跑,勿手改 SVG):
![两把刻度尺:TPAFE 16 位双极性 1 码 152.59 µV;STM32 12 位单极性 1 码 805.66 µV](../../images/ADC码值刻度.svg)
![两把刻度尺:TPAFE5160 16 位双极性 −32768~+32767、1 码 152.59 µV、11430 码≈1.744 V;STM32 ADC1 12 位单极性 0~4095、1 码 805.66 µV、1000 码≈0.806 V](../../images/ADC码值刻度.svg)
**两把尺子不能混用**(同样"1000"差 5.3 倍)。§5 各表每格必须写明哪一路(UA/UB/… 属 TPAFE,T 属 STM32),抄错一行全盘作废。本文一律用"码"不用"伏":固件 `adc:` 行打印的就是码;**标定还没做,把码换成伏正是本次要验证的事**。判据:**TPAFE ≤ 30 码、STM32 ≤ 5 码**(≈4.6 mV / ≈4.0 mV)。
**两把尺子不能混用**:同样是"1000",在 TPAFE 上是 0.153 V,在 STM32 上是 0.806 V,差 5.3 倍。
所以 §5 各步的记录表里每一格都必须写明是哪一路(UA/UB/… 属 TPAFE,T 属 STM32),
抄错一行全盘结论作废。
⚠ **TPAFE 档 2026-10-27 由 ≤10 放宽到 ≤30**:首次实测残差 UA −14 / UN −15 / IA −13(≈2 mV)。原 ≤10 比实测噪声还紧,必然误判。残差若 >30 码 → 前端有真实失调,回前端查,不得再放宽。
本文一律用"码"而不是"伏",有两个理由:① 固件 `adc:` 行打印的就是码,抄数不用心算;
② **标定还没做,把码换成伏正是本次要验证的事**——先换算再用,等于默认了尚未验证的系数。
判据按转换器分两档:**TPAFE 侧 ≤ 30 码、STM32 侧 ≤ 5 码**——即短接后读数离 0 不超过
30 / 5 个刻度,折算 **≈4.6 mV / ≈4.0 mV**。两档数值差 6 倍是因为两种刻度差 5.3 倍
(TPAFE 152.59 µV/码、STM32 805.66 µV/码),统一到物理量后都在 4~5 mV 量级。
⚠ **TPAFE 档于 2026-10-27 由 ≤10 放宽到 ≤30**:首次实测三路残差 UA −14 / UN −15 / IA −13
(≈2 mV),按 16 位 /10 V 跨度算只有 0.02% FS。原来的 ≤10(≈1.5 mV)定判据时**没有实测依据**,
比实测噪声还紧,必然误判失败。**这不是"把判据改成能过"**——若残差继续增大(>30 码 / ≈4.6 mV),
说明前端确有真实失调(R32 侧接地断、TPAFE 失调),那时必须回前端查,不得再放宽。
⚠ `adc:` 行某路取数失败时该槽打 0,所以"9 路全 0"要读作"没数据",判据是同一份心跳里
`frames` 是否还在涨。
⚠ `adc:` 行某路取数失败时该槽打 0,"9 路全 0"读作"没数据",判据看同一心跳 `frames` 是否还在涨。
## 5. 步骤
@@ -129,25 +83,17 @@
| 量哪里 | 期望 | 验的是什么 |
|---|---|---|
| **串阻两端**(1 脚 ↔ 2 脚,即端子侧焊盘 ↔ 引脚侧焊盘) | **≈ 1 kΩ** | 串阻焊好、没虚焊 |
| **注入点 ↔ AGND**(TPAFE 侧,UA/UN/IA) | **≈ 1 MΩ 量级** | 无意外短路;**不是 1 kΩ** |
| **注入点 ↔ AGND**(STM32 侧,UB/UC/IB/IC/IN) | 高阻,不定量 | 无设计直流通路,只作短路排查 |
| **串阻两端**(1 脚 ↔ 2 脚) | **≈ 1 kΩ** | 串阻焊好、没虚焊 |
| **注入点 ↔ AGND**(TPAFE 侧 UA/UN/IA) | **≈ 1 MΩ 量级** | 无意外短路;**不是 1 kΩ** |
| **注入点 ↔ AGND**(STM32 侧 UB/UC/IB/IC/IN) | 高阻,不定量 | 无设计直流通路,只作短路排查 |
### 5.2 步骤 1:零点(这一步是整套测试的分水岭)
### 5.2 步骤 1:零点(这一关先过:零点都不干净,后面每一步的数都不可信)
**做什么**(8 路逐个重复,每路约 1 分钟):
**做什么**(8 路逐个,每路约 1 min):断电把该路**注入点短接 AGND**(短接线先 0 Ω 档确认直通)→ 上电等 `adc:` 行 → 抄进下表 → 断电拆线换下一路。
1. 断电,把该路**注入点短接到 AGND**(短接线之前先用 0 Ω 档确认该点与 AGND 直通);
2. 上电,等 `adc:` 行出现(每 10 s 一行,9 路码值都在里面);
3. 把该路码值抄进**下面的零点记录表**;
4. 断电拆短接线,换下一路。
**记录**(现场填;判据只看"短接后"列,"空载"列留证):
**记录**(现场填;判据只看"短接后"那一列,"空载"列是留证用):
> ⚠ **本表行序 = `adc:` 日志的列序**(UA UB UC UN IA IB IC IN),照着日志**从左往右**抄,
> 不要按"TPAFE 三路 / STM32 五路"重新分组。2026-10-27 现场实测就栽在这里:按语义分组抄,
> 结果 UN/IA 填成了 STM32 的 ~1000、UB/UC 填成了 TPAFE 的 ~11450——而 UN/IA 属 TPAFE、
> UB/UC 属 STM32,这两个量级在物理上不可能。**"转换器"列就是给这一眼准备的**。
> ⚠ **本表行序 = `adc:` 日志列序**(UA UB UC UN IA IB IC IN),照日志**从左往右**抄,别按"TPAFE 三路 / STM32 五路"分组。2026-10-27 就栽在这里:按语义分组抄,UN/IA 填成 STM32 ~1000、UB/UC 填成 TPAFE ~11450——量级物理上不可能。**"转换器"列就是给这一眼准备的**。
| 通道 | 转换器 | 端子侧节点 | 空载码值(浮空) | 短接 AGND 后码值 | 判据 |
| --- | --- | --- | --- | --- | --- |
@@ -160,26 +106,15 @@
| IC | STM32 | `AIN10`(U5.C9) | 991~1092 | 0 | ≤ 5 |
| IN | STM32 | `AIN11`(U5.C10) | 979~1065 |1~2 | ≤ 5 |
**为什么这一步最关键**:空载(输入浮空)读数比判据高两个数量级,最可能的解释是输入悬空后
漏电流在滤波电容上建立的平衡点——短接 AGND 后应塌回 0。但如果**短接后仍读 11430**,那就是
真实偏置,且超过零点补偿上限 `ADC_CAL_B_MAX`(8192 码)——`adc_cal_set()` 会直接拒掉、
回退 ROM 系数、永远置不了 `VALID`,保护也就永远解不了锁。**那种情况必须回前端查**
(R32 那侧接地是否断、TPAFE 是否失调),不能靠软件补偿。
**2026-10-27 实测:8 路全部 PASS。** 短接后 **0~5 码**(TPAFE ≤4.6 mV、STM32 ≤4.0 mV),远小于零点补偿上限 `ADC_CAL_B_MAX`(8192 码),**可正常标定、不触发回退**。
**2026-10-27 实测结论:8 路全部 PASS。** 短接后落在 **0~5 码**(TPAFE ≤4.6 mV、STM32 ≤4.0 mV),
全部远小于零点补偿上限 `ADC_CAL_B_MAX`(8192 码),**可以正常标定、不会触发回退**。
空载 → 短接的塌陷幅度:TPAFE 约 11430 → 0~4(三个数量级),STM32 约 1000 → 0~5(两个数量级),
两者都证明短接真实到位、输入前端没有意外直流通路。
⚠ **IB 最贴边**:2~5 码正好触上限(1.6~4.0 mV,物理没问题),**八路里余量最小**;日后 IB 零点变大第一个查 R49 那侧(`AIN9` / U5.A8)。
⚠ **IB 最贴边**:2~5 码,上限 5 码正好触到。折算 1.6~4.0 mV,物理上没问题,但**它是八路里
余量最小的一路**;若日后 IB 零点继续变大,第一个该查的是 R49 那侧(`AIN9` / U5.A8)。
### 5.3 步骤 2:三点线性(用 UA,免复位)
### 5.3 步骤 2:三点线性(用 UA 做,免复位)
3.3 V 轨经 10 k 电位器分压作源,逐点注入,**每点同时记两个数**:万用表读注入点电压、`adc:` 行读码值。
3.3 V 轨经 10 k 电位器分压作源,逐点注入。**每点同时记两个数**:万用表读注入点实际电压、
`adc:` 行读对应码值。
**记录**(UA 一路,三点;"目标"列是调电位器的靶子,"实测"列填万用表读数):
**记录**(UA 三点;"目标"列是靶子,"实测"列填万用表):
| 目标注入 | 实测电压(万用表) | 码值 | 反算 µV/码 | TPAFE 期望码 | STM32 期望码 |
| -------- | --------- | -- | ------- | --------- | --------- |
@@ -189,26 +124,17 @@
拟合 R² = 0.9999997 斜率 = 6544.2 码/V 偏差 = −0.14 % 截距 = −7.2 码(≈ −1.1 mV)
反算 LSB = 152.81 µV/码,与 TPAFE 期望 152.59 差 0.14 %——**与斜率偏差同源,是同一个数**。
反算 LSB = 152.81 µV/码,与 TPAFE 期望 152.59 差 0.14 %——**与斜率偏差同源**。期望码两列并列:同样三点也可复验 STM32 侧某路,两列差 5.3 倍,一眼确认表笔接的是哪片转换器。
期望码两列并列,是因为同样的三个注入点也可能拿去复验 STM32 侧某一路(UA 对不上时换路交叉验证);
两列数值差 5.3 倍,一眼能确认手上这支表笔当前接的是哪一片转换器。
判据:三点拟合 **R² ≥ 0.999**、斜率偏差 **≤ 2 %**。偏差 > 2 % **先查前端**(焊点、串阻实际值、电位器负载效应),不要用系数凑。
判据:三点线性拟合 **R² ≥ 0.999**,斜率与期望值偏差 **≤ 2 %**。
偏差 > 2 % 时**先查前端**(焊点、串阻实际值、电位器负载效应),不要用系数去凑——
把硬件的错固化成"标定值"是最坏的结果。
**2026-10-27 实测结论:PASS。** R² = 0.9999997(判据 ≥0.999)、斜率偏差 −0.14 %(判据 ≤2 %)。
三条残差 −2.0 / +3.5 / −1.4 码,落在读数噪声内,**无系统性弯曲**——即前端在这三个点上确实是
线性的,不存在未识别的分压元件。这是"③ 段变比 = 1:1"在台架上的第一次直接证据。
**2026-10-27 实测:PASS。** R² = 0.9999997、斜率偏差 −0.14 %。
### 5.4 步骤 3:极性(只 TPAFE 三路)
TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,负半周测不了。给 UA/UN/IA 各加一个
**−1.0 V** 点。
TPAFE 双极性补码可注负压;STM32 单极性负半周测不了。UA/UN/IA 各加 **−1.0 V** 点。
**记录**(三路各两个点):
**记录**(三路各两点):
| 通道 | +1.0 V 码值 | −1.0 V 码值 | 对称性偏差 |
| -- | --------- | --------- | ----- |
@@ -216,40 +142,26 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
| UN | 6549 | −6568 | 0.29 % |
| IA | 6548 | −6566 | 0.27 % |
判据:−1.0 V 点码值为**负**且落在 **−6554** 附近,幅值与 +1.0 V 点对称(差值 ≤ 2 %)
→ 符号位与补码解释正确。这一步专门补"连极性都没证过"这个缺口。
判据:−1.0 V 点码值**为负**且落在 **−6554** 附近,与 +1.0 V 对称(差 ≤ 2 %)→ 符号位与补码解释正确。
**2026-10-27 实测结论:PASS。** 三路 −1.0 V 点全部为负,落在 −6566~−6568(相对 −6554 偏
−0.18 %~−0.21 %);对称性偏差 0.27 %~0.34 %,远小于 2 % 判据。**补码符号位解释正确**。
**2026-10-27 实测:PASS。** 三路 −1.0 V 全负,落在 −6566~−6568;对称性 0.27 %~0.34 %,远小于 2 %。
### 5.5 步骤 4:节奏(注入期间顺带看)
注入期间 `frames=` 应仍**严格 1000 Hz 递增**(10 s 间隔 +10000 左右),`idle=0`,
`adc1_err=0`。这一条替代了原方案里"用示波器看 U3.14 BUSY 有脉冲"的判据——不需要示波器。
注入期间 `frames=` 应仍**严格 1000 Hz 递增**(10 s +10000 左右),`idle=0`、`adc1_err=0`。
**2026-10-27 实测结论:PASS。** 注入**前**(20:58 那次开机)与注入**后**(21:29)各取两行相隔
10 s 的心跳,两边都是 **Δ9998 码 / ≈10.0 s ≈ 1000.1 Hz**,`idle=0`、`adc1_rc=0`、`adc1_err=0`:
**2026-10-27 实测:PASS。** 注入**前**(20:58)与**后**(21:29)各取两行相隔 10 s 心跳,两边都是 **Δ9998 码 / ≈10.0 s ≈ 1000.1 Hz**,`idle=0`、`adc1_rc=0`、`adc1_err=0`:
| 时点 | `frames=` 两行 | Δ | 折算 |
|---|---|---|---|
| 注入前(20:58) | 29997 → 39995 | 9998 | 1000.5 Hz |
| 注入后(21:29) | 1819639 → 1829637 | 9998 | 1000.1 Hz |
⚠ **口径说明**:这两次是"注入**前后**",不是"注入**进行中**"——已知电压注入验证判据 ⑤ 要的正是"注入前后
`tpafe5160_frame_seq()` 仍严格 1000 Hz 递增",故按此口径已达标。若日后要连"进行中"也钉住,
在任一注入过程里再抓两行即可(注入不改变 TIM3 硬件触发,理论上无影响,但没测过就不算证过)。
`adc1_gap` / `tgap` / `skip` 是**本次开机以来的累计值**(548 / 363 / 183),10 s 内只增 3 / 2 / 1,
占比约 0.03 %,属正常漏检量级,不是停摆。
### 5.6 步骤 5:回写
1. 把实测斜率、零点、映射结果写进 `docs/硬件平台/ADC通道映射说明.md` §8,把"尚未执行"改成
实测值 + 日期;
2. 若实测确认无分压,同步在 `docs/硬件平台/ADC通道映射说明.md` §7.1 的链路分段表把第 ③ 段
(`AINn` ↔ 转换器引脚)从"待台架实测"改为实测结论;
3. `docs/任务规划/数据可信.md` 的已知电压注入验证行按"完成即删"销项;判据与实测证据的属主是
`docs/硬件平台/ADC通道映射说明.md` §8.1。
1. 实测斜率、零点、映射写进 `docs/硬件平台/ADC通道映射说明.md` §8("尚未执行"改实测值 + 日期);
2. 确认无分压后,把 `docs/硬件平台/ADC通道映射说明.md` §7.1 量纲链路的第 3 段(`AINn` 焊盘 ↔ 转换器引脚)改成实测结论;
3. `docs/任务规划/数据可信.md` 已知电压注入行按"完成即删"销项;判据与证据属主 `docs/硬件平台/ADC通道映射说明.md` §8.1。
## 6. 判据汇总
@@ -262,438 +174,321 @@ TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,
| 极性 | −1.0 V → −6554 码 | −6566 / −6568 / −6566,对称性 ≤0.34 % | PASS | 补码符号处理错 |
| 节奏 | 注入期间仍 1000 Hz | 注入前/后各 **Δ9998 / 10 s ≈ 1000 Hz**,`idle=0`、`adc1_err=0` | PASS | 注入改变了输入共模,触发转换异常 |
**总体结论(2026-10-27)**:**六项全部 PASS**。合起来证明了三件事:
① ③ 段(`AINn` ↔ 转换器引脚)**变比确为 1:1**,无隐藏分压(斜率偏差 −0.14 %);
② 8 路语义 ↔ 物理端子**一一对应**(零点步骤逐路代偿);
③ TPAFE 补码符号位解释正确(对称性 ≤0.34 %)。
已知电压注入验证的判据 ①②③④⑤⑥ 至此全部闭环(判据与实测记录 → `docs/硬件平台/ADC通道映射说明.md` §8.1)。
⚠ **两项残留口径**(不影响本轮 PASS,但别当成已验证):**串扰**未单独证(见上表"映射"行);
**节奏**只测了注入前后、没测注入进行中。两项若日后怀疑,各自的补做方法已写在对应小节。
**总体结论(2026-10-27)**:**六项全部 PASS**——结论一:从焊盘到转换器引脚那一段变比 1:1、无隐藏分压;结论二:8 路语义 ↔ 物理端子一一对应;结论三:TPAFE 补码符号位正确。全部闭环(→ `docs/硬件平台/ADC通道映射说明.md` §8.1)。⚠ **两项残留**(不影响 PASS):**串扰**未单独证;**节奏**只测注入前后。
## 7. 安全红线
1. **STM32 侧严禁超过 3.3 V**(VDDA + 0.3 V 即击穿),电位器上限就接 3.3 V 轨,不要接 5 V。
2. **TPAFE 侧按判据只到 ±2 V**,虽芯片容 ±5 V,但判据不需要更大。
3. **端子侧不许直接上额定电压**(220 V / 100 V 二次值)。本次是直流低压注入,
与"加压试保护"是两件事,后者要等端子/子板变比确认(`docs/硬件平台/ADC通道映射说明.md` §7.1 链路分段表 ④ 行)之后单独排。
4. **引脚侧注入必须外串 10 k**,且先接线后上电、先断电后拆线。
5. 注入源与板子**共地**;电位器一端接 3.3 V、一端接 AGND、中间抽头串 10 k 到注入点。
1. **STM32 侧严禁超过 3.3 V**(VDDA + 0.3 V 即击穿),电位器上限接 3.3 V 轨。
2. **TPAFE 侧按判据只到 ±2 V**(芯片容 ±5 V 但判据不需要更大)。
3. **端子侧不许直接上额定电压**(220 V / 100 V 二次值);"加压试保护"另排(`docs/硬件平台/ADC通道映射说明.md` §7.1 ④ 行)。
4. **引脚侧注入必须外串 10 k**,先接线后上电、先断电后拆线。
5. 注入源与板子**共地**;电位器一端 3.3 V、一端 AGND、抽头串 10 k 到注入点。
---
## 8. 交流(正弦)动态验证轮次(六轮:幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波)
> **判据的属主是 `docs/任务规划/数据可信.md` §4.6.2**(六轮各验什么、过判据是多少),本节只写**怎么跑**:
> 接哪个点、发生器怎么设、读哪一行的哪个字段、期望值怎么算、结果往哪回写。两边于 2026-10-29 对齐;将来
> 若再分叉,按两类裁定——**「验什么、算不算过」从 `docs/任务规划/数据可信.md` §4.6.2,「期望值怎么算、
> 怎么接线怎么跑」从本节**。为什么这一跳不用等标准源、以及它证不到什么,看其 §4.6.1 与 §4.6.5,本节不重抄。
>
> **引用写法**:本节凡引用判据文档的小节,一律写成「文件名 + 小节号」的紧邻形式;只写 §8.x 的是本文自己的节。
> **引用写法**:引用判据文档小节一律「路径 + 小节号」紧邻;只写 §8.x 的是本文自己的节。本节只写**怎么跑**(接哪个点、发生器怎么设、读哪行哪个字段、期望值怎么算、结果往哪回写)。
先下图建立全局轮廓——每一轮注什么波形、验什么、读哪个出口,再进 §8.5 逐轮执行卡:
![六轮一图速查:注入信号形状 → 接法与设定 → 判据一句话 → 数字从哪儿读;过判据属主在 数据可信.md §4.6.2](../../images/交流六轮速查.svg)
![六轮一图速查:注入信号形状 → 接法与设定 → 判据一句话 → 主读数出口;过判据属主在 数据可信.md §4.6.2](../../images/交流六轮速查.svg)
### 8.1 动手前先弄清楚:数字从哪儿读、能读到多细(决定今天判得动哪几轮)
### 8.1 动手前先把出口分辨率算清楚(决定今天能判到哪一档)
这轮能读到数字的地方共 5 处——3 处是**串口周期打印的日志行**、1 处是**板子屏幕**、1 处是**触发录波段文件后在 PC 上重算**。分辨率天差地别,各自判得动的轮次也不同,下表逐处列清:
这一轮和直流轮次**不一样:样本出口已经有了**。2026-10-29 故障录波的数据面并入主干,一次触发就是一段
`/wave/WAVE<NN>.BIN`(`NN` = 00~99 轮转号;8 路 × 320 点原始码值 + 封存瞬间的标定与品质快照),PC 侧 `test/host/wave_read.py` 把它还原成
周波数、幅值、**相位**、谐波与削顶判定。所以本轮每条用例都有两个档:**周期行标量档**(只读串口 / 104 / UI,
快,不用 FTP)与**段文件对表档**(多一次触发 + 一次取段 + 跑脚本,判得到位)。各出口的实际分辨率如下——
这张表决定每条用例走哪个档:
| 出口 | 打印处 | 分辨率 | 能判 | 判不动 |
| 在哪儿读 | 看到的形态 | 数字精度 | 判得动什么 | 判不动什么(为什么) |
|---|---|---|---|---|
| `meas: seq=.. v=.. ua_mv=.. un_mv=.. ia_mv=.. f=.. fv=..` | `App/task/adc_task.c:605` | **1 mV**(整数毫伏,只发 UA/UN/IA) | 幅值轮、波形轮的幅值 ≤2 % | 相位、谐波、其余五路 |
| 104 YC `0x4011`~`0x4018` + `0x401D`(短浮点 + 品质) | `App/protocol/iec104/iec104_pts.c:70` | 3 位有效数字 ≈ 0.01 V | 单个静态工作点的幅值交叉读数、品质 IV | **小步进**(每点 0.5 V / 0.005 A 变化死区)、相位、谐波 |
| `phasor(hb) C0x-…-F1: Re=.. Im=.. rms=.. (x0.1)` | `App/task/adc_task.c:209` | **0.1 V,且向下截断** | 有数没数、量级、象限 | ⚠ **相位轮的 ≤2° 与谐波轮的 ±2 %**:注 1.000 Vrms 时 `rms` 只有 10 格,20 % 的谐波只有 2 格 |
| `freq(hb): f=.. valid=.. (x0.01)` | `App/task/adc_task.c:224` | 0.01 Hz | 测频轮的读数与新鲜度 | — |
| UI 交流量页 `Ua/U0/Ia/Ia2/Ia5`(3 位小数)、`Hz`(2 位) | `Drivers/BSP/UI/ui_page_ac.c:47` | **1 mV**(人工目检 + 拍照留证) | 谐波轮谐波幅值、幅值轮交叉旁证、测频轮的 `Hz` 显 `--` | 相位(页面上没有角度) |
| 录波段文件 `/wave/WAVE<NN>.BIN`(`NN` = 00~99,100 个号轮转;FTP 根下,与 `/log` 平级)+ `test/host/wave_read.py`(`dump` / `fft` / `shape` / `plot`,纯标准库) | **已落地**(2026-10-29 并入 `v2-on-ui`;格式属主 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3) | 一次触发 8 路 × 320 点原始码值;`fft` 给基波 RMS、相位、2 次与 5 次谐波 RMS(mV) | **相位轮的 ≤2° 与谐波轮的 ±2 % 现在判得动**:PC 独立重算 vs 板上读数对表 | 段与发生器**无绝对相位锁定**(触发点在段内点 159)→ 只能比同段内相对相位;320 ms 快照不等于长时间稳定性 |
| **串口心跳行** `meas:`(打印处 `App/task/adc_task.c:605`,200 ms 一行) | `meas: seq=.. v=.. ua_mv=.. un_mv=.. ia_mv=.. f=.. fv=..` | **1 mV**(整数毫伏;电气量只发 UA/UN/IA 三路) | 幅值轮、波形轮的幅值 ≤2 % | 相位、谐波(这行没这两个数);其余五路(这行不发) |
| **串口心跳行** `phasor(hb)`(打印处 `App/task/adc_task.c:209`) | `phasor(hb) C0x-…-F1: Re=.. Im=.. rms=.. (x0.1)` | **0.1 V、向下截断**(×0.1 定点) | 有数没数、量级、象限 | ⚠ 相位 ≤2°、谐波 ±2 % 想都别想:注 Vpp 2.828 V(板上 ≈1000 mV)时 `rms` 满打满算 10 格,20 % 谐波只占 2 格 |
| **串口心跳行** `freq(hb)`(打印处 `App/task/adc_task.c:224`) | `freq(hb): f=.. valid=.. (x0.01)` | 0.01 Hz | 测频轮的读数和新鲜度(`valid`) | — |
| **板子屏幕** 主界面→实时数据→交流量(代码 `Drivers/BSP/UI/ui_page_ac.c:47`) | 页 7 行 `Ua/U0/Ia/Ia2/Ia5/Hz/量纲`;量值行 3 位小数、Hz 行 2 位 | **1 mV**(靠人眼看屏 + 拍照留证) | 谐波轮 `Ia2`/`Ia5` 幅值;幅值轮交叉旁证;测频轮 `Hz` 显 `--` | 相位(页面上没有角度) |
| **录波段文件 + PC 重算**:一次触发写一段 `/wave/WAVE<NN>.BIN` 到板 FTP 根目录(`NN` = 00~99 轮转),取回本机用 `test/host/wave_read.py` 算(`dump`/`fft`/`shape`/`plot`,纯标准库;格式属主 `docs/子系统设计/故障录波设计说明.md` §6.2/§6.3,2026-10-29 并入主干) | 段内 8 路 × 320 点原始码 + 封存瞬间的标定与品质快照 | `fft` 浮点重算:基波有效值、相位、2 次与 5 次谐波有效值(mV) | 相位 ≤2°、谐波 ±2 %——**只有这条路判得动**;顺带 PC 独立重算与板上数字互相对表 | 段与发生器**没有绝对相位锁**(触发点固定在段内点 159)→ 只能比同一段内的相对相位;一段 320 ms,不代表长时间稳定 |
**所以每条用例按两个档摆**(出口从"缺样本"变成"有段文件"的经过与口径变更,见 `docs/子系统设计/故障录波设计说明.md` §11;原卡片登记簿 2026-10-30 销项并入该文 §10):
**六轮用例先定「什么证据才算过」——这张快查表逐轮指定证据档**(背景:2026-10-29 录波段文件能力落地后,判据档位跟着重划过一次,经过见 `docs/子系统设计/故障录波设计说明.md` §11):
| 档 | 条目 | 说明 |
|---|---|---|
| **周期行就判得动** | 幅值、波形、测频、削顶四轮(削顶轮的接法要按 §8.5 改,原因写在那张卡里) | 判据在 `meas:` / 104 / `freq(hb)` / `rail:` 上分辨率都够,不取段也能收工 |
| **段文件档才判到位** | 相位轮、谐波轮 | 段文件已落地 → 浮点重算,≤2° 与 ±2 % 都是**定量**判据;周期行退为旁证,只在没取到段时走定性档。触发动作与命令写在 §8.5 的相位卡 / 谐波卡 |
| **要改代码的退路** | 相位轮抬倍数、测频轮 B 档 | 段文件落地后相位轮这条基本不必走;测频轮 B 档(放宽 `FREQ_AMP_MIN`)仍是唯一路子。两者都要重编 + 烧录 + 按 §8.9 还原,**动手前先问用户** |
| 证据档 | 哪些轮用 | 过关要求 | 定这个档的原因 |
|---|---|---|---|
| **心跳档**——串口周期行看够,**不用录波** | 幅值、波形、测频、削顶(削顶的接法以 §8.5 削顶卡为准,别按 50 Hz 老接法想当然) | 串口周期行(`meas:` / `freq(hb)` / `rail:` 位图)达判据即算过 | 判据阈值 ≥ 周期行分辨率(±2 % 对 1 mV、位图对 1 bit),录波无增益 |
| **录波档**——**必须录一段波**才算定量 | 相位、谐波 | 面板触发手动录波 → FTP 把段文件取回 → `wave_read.py fft` PC 浮点重算,与板上读数对表达判据 | 板上周期行是 ×0.1 截断定点(上限表「判不动」列),≤2°、±2 % 只有重算才判得动;谐波轮就算拿 UI 的 1 mV 也不行——**屏上那个数本身就是板子 DFT 算出来的答案**,系数表用错行、索引错位这类算术错会原样透传到屏上,必须靠 PC 独立重算当第二把尺子(段文件还顺带核对频位:100 Hz 确落 2 次 bin);**没录段文件只能退回「心跳档」记,定量判据不算过** |
| **改码退路**(默认不走) | 相位抬打印倍数、测频放宽 `FREQ_AMP_MIN` | 仅当录波档不可用(段取不回、PC 跑不了脚本)才考虑;做则重编 + 烧录 + 按 §8.9 全量还原 | 动了固件就不是「零改动验证」了——**动手前必须问用户** |
### 8.2 设备清单与开机前置门
| 项 | 要求 | 为什么 / 怎么核 |
|---|---|---|
| 信号发生器 | 正弦 / 方波 / 三角,**并有 DC 档**;频率可锁 50.000 Hz、也能设到 2 Hz;幅度 0~3 Vpp | **只要求"波形干净、幅度稳、频率锁得住"**,它的刻度不当基准(`docs/任务规划/数据可信.md` §7 #9)。DC 档是给削顶轮改法 A 用的 |
| ⚠ 发生器输出端接设置 | 接板子时设成**高阻负载**,不要按 50 Ω 端接 | 按 50 Ω 端接而实际接的是高阻板输入 → 面板值与真实电压差 2 倍;这是台架"差一倍"最常见来源 |
| 万用表 AC 档 | 能读到 mV;**记明型号与响应类型**(真 RMS / 均值响应) | 基准就是它;波形轮那一步两种表的读数都与基波期望差很多,不记响应类型就说不清是谁错 |
| 板子 | 产品构建(`test/board/test_config.h` 四个 `TEST_SUITE_*` 全注释)+ `/keil-build` 0 错误 0 警告 + 烧录 `-Rst -Run` 与回读校验 | → `stlink-flash` skill 与 AGENTS.md「构建与验证」 |
| `[adc_cal]` 状态 | **保持未标定**(`eng=0`),别为"读数好看"先写标定值 | 现在 `meas:` / `phasor` 的量纲是 **ADC 引脚电压 V**(`App/algo/meas.h` 文件头的 A-lite 口径);标定一生效就换成二次值,本节全部期望值作废 |
| 串口 | 全程抓 RX 落盘:用 `serial-assistant` skill(`open` → `clear` → 跑 → 读日志文件或 `log --tail`) | 日志文件就是证据本体,§8.10 归档归档的就是它;**长跑别用 `/serial-boot-test`**——它绑定一轮启动语义(静默 8 s、总超时 30 s、`max_boot_count` = 1,且 forbidden 含 `[ERR]`,而削顶轮故意造 `[ERR]`),约 135 min 的 session 必然超时或误判;daemon 全量写 `state/serial.log`(20 MB 上限自动截头保尾 10 MB)→ `docs/测试说明/流程与规范/自动化测试流程.md` 长时间采集一节 |
| 网口(可选) | 要读 104 那一路就插网线、PC 与板同网段(出厂 192.168.31.100),跑现成主站 `test/host/iec104_master.py`(`--ip` / `--port` / `--addr`) | 104 是浮点无量化 + 带品质,是 `meas:` 之外的第二条腿 |
| FTP 客户端 | 走现成 21 端口取段文件(出厂 `[ftp]` 账号,连续 5 次失败锁 60 s) | 段文件是相位 / 谐波轮定量档的样本出口;段文件名 `/wave/WAVE<NN>.BIN`(00~99 轮转),**取完立刻改名归档**,否则下一次触发把它盖掉 |
| 录波触发路径 | 产品构建里唯一**免改代码**的路径 = UI 菜单第 26 叶「手动录波」确认页(`Drivers/BSP/UI/ui_page_wave_manual.c` → `App/task/ui_task.c:605`) | 保护启动上升沿也算一次触发,但保护判据现处**未标定闭锁**态(AGENTS.md「现状」),别指望它自动来段;bench 定时自抓在双层编译门 `DTU_BENCH` 且 `WAVE_BENCH_AUTOCAP` 非 0 之内(默认 0,`App/task/adc_task.c:153`),开它就走 §8.9 的还原判据 |
| 信号发生器 | 正弦 / 方波 / 三角,**并有 DC 档**;频率可锁 50.000 Hz、也能设 2 Hz;幅度 0~3 Vpp | 只要求"波形干净、幅度稳、频率锁得住",刻度不当基准(`docs/任务规划/数据可信.md` §7 #9)。DC 档给削顶轮的直流削顶档 |
| ⚠ 发生器端接 | 接板子时设**高阻负载**,不按 50 Ω 端接 | 50 Ω 端接而实际高阻 → 面板值与真实电压差 2 倍;台架"差一倍"最常见来源 |
| 万用表 AC 档 | 能读 mV;**记明型号与响应类型**(真有效值 / 均值)——判别法:表身或说明书没印 "True RMS" 就当均值档;拿发生器注一个 Vpp 2.828 V 方波到 AC 档,读数 ≈1.41 V = 真有效值档、≈1.57 V = 均值档(差 11 %,一眼分辨) | 基准就是它;波形轮两种表读数都与基波期望差很多,不记响应类型说不清谁错 |
| 板子 | 产品构建(`test/board/test_config.h` 四 `TEST_SUITE_*` 全注释)+ `/keil-build` 0 错 0 警 + 烧录 `-Rst -Run` + 回读校验 | → `stlink-flash` skill 与 AGENTS.md「构建与验证」 |
| `[adc_cal]` 状态 | **保持未标定**(`eng=0`),别为"读数好看"先写标定值 | 现在 `meas:` / `phasor` 量纲是 **ADC 引脚电压 V**——未标定态的设计本来就不折算(`App/algo/meas.h`);标定一生效换二次值,本节全部期望值作废 |
| 串口 | 全程抓 RX 落盘:`serial-assistant` skill(`open` → `clear` → 跑 → 读日志 / `log --tail`) | 日志文件就是证据本体,§8.10 归档它;**长跑别用 `/serial-boot-test`**——它绑一轮启动语义(静默 8 s、总超时 30 s、`max_boot_count`=1,forbidden 含 `[ERR]`,削顶轮故意造 `[ERR]`),约 135 min 必超时或误判;daemon 写 `state/serial.log`(20 MB 截头保尾 10 MB)→ `docs/测试说明/流程与规范/自动化测试流程.md` 长时间采集 |
| FTP 客户端 | 走 21 端口取段文件(出厂 `[ftp]` 账号,连续 5 次失败锁 60 s) | 相位 / 谐波的定量判据只能拿段文件来算;`/wave/WAVE<NN>.BIN`(00~99 轮转),**取回本机后立刻改名归档**,否则下次触发盖掉 |
| 录波触发路径 | 产品构建唯一**免改代码**路径 = UI 菜单第 26 叶「手动录波」确认页(`Drivers/BSP/UI/ui_page_wave_manual.c` → `App/task/ui_task.c:605`) | 保护启动上升沿也算触发,但保护判据现处**未标定闭锁**(AGENTS.md「现状」),别指望自动来段;bench 自抓在 `DTU_BENCH` 且 `WAVE_BENCH_AUTOCAP` 非 0(默认 0,`App/task/adc_task.c:153`),开它走 §8.9 |
| 共地 | 发生器 LO/GND 与板 AGND **单点**相连 | 不共地量到的是两地之差;现象见 §8.8 |
**开机前置门**——接发生器**之前**日志就该长这样,不满足先回 §5 步骤 5.5 查节奏,别往下做:
**开机前置门**——插上网线、开了串口采集、**还没接发生器**之前,串口日志就该通过下面 8 条;任何一条不过,先回 §5.5 处理,别带着脏链往下跑:
- `adc:` 行 10 s 一行,同一心跳里 `frames` 在涨("9 路全 0"要读成"没数据",§4 尾注);`idle=0`、`adc1_err=0`;
- `meas:` 的 `v=1`、`seq` 每 10 s 约 +500(200 ms 一帧;不涨 = 发布闸门停);
- `cal:` 的 `cl=0xE6` —— **这是来源派生**(V0.1 那五路本就触底,见 `docs/任务规划/数据可信.md` §2.6),既不是本轮战果也不是本轮故障;
- 四个位图 `vl` / `cl` / `rail` / `edge` 同一个位序(语义通道枚举 `App/algo/adc_input.h:38`):bit0 `UA`、bit1 `UB`、
bit2 `UC`、bit3 `UN`、bit4 `IA`、bit5 `IB`、bit6 `IC`、bit7 `IN`、bit8 `TEMP` → `0xE6` = bit1/2/5/6/7 = `UB/UC/IB/IC/IN`;
- **先上电、在基线里看到 `adc: UB` 有正常摆动,再开发生器输出**:贴轨锁存要求该通道"此前出现过中带样本"(释放沿前提,
`App/algo/adc_health.c` 的 `adc_health_rail_watch()`),开机就注大信号会让削顶轮的锁存**装不上**,测出假不通过。
- 开机各有一条 `first:` 与 `phasor(first)` / `freq(first)` 单发行(`App/task/adc_task.c:478` 与 `App/task/adc_task.c:201`
的 `tag` 参数),与 10 s 一轮的 `hb` 行是两拨——数心跳时别把 `first` 计进去;
- `phasor` 行**只要有数就打**:打印条件只有 `phasor_get() == 0`,不带任何 valid 位(`App/task/adc_task.c:209`)→
「phasor 有数」既不说明标定可用、也不说明这一路没在削顶,判读必须配 `vl` / `cl` / `rail` 三个位图一起看;
- 注入正弦**不会**点亮 `health:` 或 `sampling fault:` 那几行:`adc_health` 的位只吃序号差、错误计数增量与 tick 差
(`App/algo/adc_health.c:91-189`),与波形幅值无关;它们若亮是节拍 / 丢帧问题,别归因给发生器(§8.8 同一条)。
- `wave:` 行(`App/task/adc_task.c:782`)基线:`armed=0`、`err=0`、`ovf=0`、`drop=0`,`seg=` 是本开机以来的成段数(**可以是 0**)。
本轮每触发一段就核 `seg` +1 且那三个计数不涨;涨了先按 §8.8 的落盘行分诊,别接着往上下注入。
| # | 看什么 | 正常该是这样 | 为什么容易看错 / 不满足怎么办 |
|---|---|---|---|
| 1 | `adc:` 行 | 10 s 一行;`frames` 在涨;`idle=0`、`adc1_err=0` | **九路数值全 0 不等于"没数据"**(没输入当然读 0,判据是 `frames` 涨不涨,§4 尾注);`frames` 不涨或 `adc1_err≠0` → §5.5 |
| 2 | `meas:` 行 | `v=1`;`seq` 每 10 s 约 +500(200 ms 一条) | `seq` 不涨 = 发布闸门停 → §5.5 |
| 3 | `cal:` 行的 `cl=0xE6` | **开机就该是这个数,不是故障** | 这是来源派生静态掩码:V0.1 硬件上 `UB/UC/IB/IC/IN` 五路本就触底(`docs/任务规划/数据可信.md` §2.6)。非战果非故障,别去"修"它。位序(`App/algo/adc_input.h:38`):bit0~8 = `UA UB UC UN IA IB IC IN TEMP`,`0xE6` = bit1/2/5/6/7 恰好这五路 |
| 4 | **开机与注入的先后** | 先上电 → 在串口看到 `adc: UB` 数值有正常摆动 → **再**开发生器输出 | 顺序反了会埋雷:贴轨锁存要求该通道"此前出现过中带样本"(`App/algo/adc_health.c` `adc_health_rail_watch()`),开机就注大信号,削顶轮的锁存**装不上**,测出假"不锁存" |
| 5 | 开机单发行 | `first:`、`phasor(first)`、`freq(first)` 各只一条(`App/task/adc_task.c:478`/`:201`) | 数心跳周期时把它们剔掉,别算进"每 10 s 一行"里 |
| 6 | `phasor(hb)` 行 | 有数就打出来 | **有数 ≠ 数有效**:这行只查 `phasor_get()==0` 不看 valid 位(`App/task/adc_task.c:209`),判读必须配着 `vl`/`cl`/`rail` 一起看 |
| 7 | `health:` / `sampling fault:` | 不该出现 | 这些位只吃序号差/错误计数/tick 差(`App/algo/adc_health.c:91-189`),注入多大正弦都不该点亮;亮了 = 节拍/丢帧问题 → §8.8 |
| 8 | `wave:` 行(`App/task/adc_task.c:782`) | 基线 `armed=0`、`err=0`、`ovf=0`、`drop=0`;`seg=` 成段数(**0 也正常**,从没触发过就该是 0) | 后面每触发一段核一次:`seg` +1 且那三个计数**不涨**;计数涨了先按 §8.8 分诊再谈读数 |
### 8.3 接线的四条(与直流轮次比,差别只在第 2、3 条)
1. **注入点与直流轮次完全相同**:§3 清单的**端子侧**焊盘(`U5` 排针,串阻的 1 脚侧)。③ 段 1:1 已由直流轮次实测
(斜率偏差 −0.14 %,§6),所以端子侧电压就是引脚电压,不用再算变比。引脚侧仍须外串 10 k(§7 第 4 条)。
2. **幅度按峰值核,别看面板上的 Vrms**:1.000 Vrms 正弦峰值已 1.414 V。
1. **夹子接哪儿**:跟直流轮同一个位置——§3 清单的**端子侧**焊盘(`U5` 排针,串阻 1 脚侧)。接这里的好处是**读数与设定值不用换算**:从焊盘到 ADC 引脚这一段是 1:1(直流轮已实测盖章,斜率偏差 −0.14 %,见 §6),端子侧电压就是引脚电压。⚠ 换个位置注(直接进引脚)才需要外串 10 k(§7 第 4 条),照本条接就不用。
2. **幅度一律按峰峰值 Vpp 设定**,别拿面板有效值显示当设定基准——同一个 Vpp 换波形后有效值显示跟着变,切波形瞬间那格还残留上一波形时代的值(2026-11-02 实测就被坑过一轮,见波形轮注)。对表时注意换算:发生器设定 = Vpp;万用表 AC 档与板上读数天然是有效值刻度,正弦下 有效值 = Vpp ÷ 2.828。
| 侧 | 判据上限(§7 红线 2) | 允许的最大正弦 Vrms | 本节用量 |
| 侧 | 判据上限(§7 红线 2) | 允许的最大正弦 Vpp | 本节用量 |
|---|---|---|---|
| TPAFE(`UA` / `UN` / `IA`) | ±2 V 峰值 | 1.414 Vrms | **1.000 Vrms**(峰值 1.414 V) |
| STM32(`UB` / `UC` / `IB` / `IC` / `IN`) | 0~3.3 V 单极性 | 无正向意义 | 只在削顶轮用:注交流 = **故意触底**,负半周本就钉 0 |
| TPAFE(`UA`/`UN`/`IA`) | 峰值 ±2 V | 4 V | **2.828 V**(= 峰值 ±1.414 V) |
| STM32(`UB`/`UC`/`IB`/`IC`/`IN`) | 0~3.3 V 单极性 | 无正向意义 | 只在削顶轮用:注交流 = **故意触底**,负半周本就钉 0 |
3. **一次只注一路**(相位轮除外,它要 `UA` 与 `UN` 两路同源),换表笔前先关输出。端子侧串阻是 **1 k**(R31 / R28 / R19 / R52 …),
STM32 那五路负半周经**片内**钳位 / ESD 路径灌向 VDDA——网表 `docs/硬件平台/V0.1.tel` :228-241 逐条实证这些节点只有
「电容 .2 + 串阻 .2 + MCU 脚」三件,**无外置钳位二极管、无隔直电容**,所以这条电流走的是芯片内部路径;
1.000 Vrms 时峰值电流约 (1.414 − 0.3) / 1 k ≈ **1.1 mA**(按片内钳位压降 0.3 V 估、仓内无实测,只用来论证量级),
但**别往上加幅度**——这种注入只允许出现在削顶轮这类"故意削顶"的用例里。
4. **电流通道也是注电压**:`IA` 的注入点同样是电压进 R19 端子侧。这一轮证的是"给定引脚电压算得对不对",
不是"一次侧 1 A 怎么办"——后者要变比,属 `docs/任务规划/数据可信.md` §5 的端子 / 子板变比确认。
四条接线画在一张图上(发生器 → 端子侧焊盘是一条主干,万用表并接、共地是两条必须存在的旁路):
```mermaid
flowchart LR
G["信号发生器<br/>输出端接 = 高阻<br/>(按 50 Ω 端接读数差 2 倍)"] -->|"注 UA / UN / IA:端子侧焊盘<br/>(1:1 已由直流轮次实测)"| R31["串阻 1 k 的 1 脚侧<br/>R31 / R28 / R19 …"]
R31 --> FE["前端分压 / 滤波"] --> U5["U5 排针 → 转换器引脚<br/>(TPAFE AIN_x 或 STM32 脚)"]
M["万用表 AC 档<br/>记响应类型"] -.->|"并接同一注入点<br/>量真实加到板上的电压"| R31
G -.->|"LO/GND 与板 AGND<br/>单点共地"| AGND["板 AGND"]
AGND -->|"不共地量到的是两地之差"| U5
G -.->|"注 UB 等 STM32 那五路(仅削顶轮)<br/>负半周经片内钳位 ≈1.1 mA"| R52["R52 端子侧"] --> STM["STM32 ADC 脚<br/>(无外置钳位 / 隔直电容)"]
```
3. **一次只注一路**(相位轮除外,它要 `UA` 与 `UN` 两路同源),换表笔前先关输出。端子侧串阻 **1 k**(R31/R28/R19/R52…)。STM32 五路负半周经**片内**钳位灌向 VDDA(网表 `docs/硬件平台/V0.1.tel` :228-241 实证:无外置钳位二极管、无隔直电容);Vpp 2.828 V 时峰值电流 ≈ **1.1 mA**(量级估算),**别往上加幅度**——这种注入只允许出现在削顶轮。
4. **电流通道也是注电压**:`IA` 注入点同样是电压进 R19 端子侧。这一轮证"给定引脚电压算得对不对",不是"一次侧 1 A 怎么办"——后者要变比,属 `docs/任务规划/数据可信.md` §5 的端子 / 子板变比确认。
### 8.4 记录表抬头(每条用例一份,与日志一起归档)
```text
日期 ____ / 操作人 ____ / 板子序列号 ____
固件 commit ________(/keil-build 0 错误 0 警告:是 / 否)
发生器:型号 ______ 输出端接 = 高阻 / 50 Ω 波形 ____ 频率设定 ____
万用表:型号 ______ AC 响应类型 = 真 RMS / 均值 共地方式 = 单点 / 发生器浮地
注入点:路名 ____(端子侧 U5 / 引脚侧外串 ____ Ω)
[adc_cal] = 未标定(eng=0)—— 必须是这个状态
基线(未注时):meas: ua_mv=____ un_mv=____ ia_mv=____ rail=0x____ cl=0x____
段文件(走定量档的用例):文件名 ________ 触发方式 = 手动 / 保护 / bench 取回时刻 ________
脚本:test/host/wave_read.py(先跑 --selftest:通过 / 否) fft / shape / dump 输出与 plot 图归档在 ________
```
这份抬头回答一个问题:**这组数字是在什么条件下量出来的**。缺任何一项,三个月后这页记录就没法复核,§8.10 归档台账的「固件版本」栏也就没有出处。做法只有一件事——照着下表,从右边写的地方**抄**过来,不用你判断任何数:
| 要抄的信息 | 从哪儿抄、为什么它要紧 |
|---|---|
| 日期、操作人 | 王建锋 |
| 板子序列号 + 固件版本 | 串口开机日志里 `fw build:` 开头那一行,**整行照抄**(例:`fw build: Nov 2 2026 14:21:24 suite=NONE dstr=off`)。不抄版本,下次构建一变,这批数就对不上号。 |
| 发生器型号 + 端接 | VICTOR 2026H(端接必须设"高阻",设成 50 Ω 输出会被砍一半,所有期望值作废) |
| 万用表型号 + 响应类型 | FNIRST-DMT-99 + 真有效值档(判别法见 §8.3 设备表;波形轮不写响应类型,说不清 1414/1570 谁对谁错) |
| 标定状态 | 串口 `cal:` 行行尾 `eng=` 后面的数,**必须是 0**(未标定)。是 1 就停下——全部期望表都是按引脚电压写的,标定态下整表不适用。 |
| 基线读数 | **开信号发生器之前**,从串口各抄一行:`meas:` 行的 ua_mv / un_mv / ia_mv,`cal:` 行的 rail / cl。没有这行,分不清"本来就是零"还是"注了没进来"。 |
### 8.5 逐条执行卡
**每条卡的通用动作**:接好 → 开输出 → 等 ≥30 s(相量窗 + `meas` 200 ms 轨稳定)→ 取**连续 ≥10 行**心跳 →
先确认 `frames` 还在涨、`adc1_err=0`,再核数 → 关输出 → 填表。"连续 ≥10 行"不是保守:`meas:` 是
**瞬时基波有效值透传**、200 ms 是上送节拍不是平均窗(`docs/任务规划/数据可信.md` §4.5),
单行读数带拍频式跳动,必须看一片取**中间水平(中位数)**才能定数。
**通用动作(六张卡都按这个走)**:
通用动作主干与两处分岔(采集链没清 → 回头修;偏差没进 → 先复核查再判):
1. 接好线、开发生器输出,等 ≥30 s 读数稳定;
2. 从串口取**连续 ≥10 行**心跳,先确认 `frames` 在涨、`adc1_err=0`(采不到算不得数),再核对卡片要求的读数——数字要取这 ≥10 行的**中位数**,别拿单行(`meas:` 是瞬时基波有效值透传、200 ms 是上送节拍非平均窗,`docs/任务规划/数据可信.md` §4.5,单行带拍频式跳动);
3. 这张卡的判据要录波取证的:抄完数后,从面板第 26 叶「手动录波」触发一段,把录波页屏上显示的文件名(`WAVE<nn>`)抄进该轮记录表;分析前在本机跑一次 `test/host/wave_read.py --selftest`,**不通过,分析结果不算证据**(不赶时间,第 7 步统一取回再做,§8.6);
4. 关掉发生器输出,把数填进该卡记录表。
```mermaid
flowchart TD
W["接好本路,开机前置门已过(§8.2)"] --> ON["开发生器输出"]
ON --> ST["等 ≥30 s:相量窗与 meas 轨稳定"]
ST --> HB["取连续 ≥10 行心跳"]
HB --> Q1{"frames 在涨、adc1_err = 0 ?"}
Q1 -->|"否:是节拍 / 丢帧问题"| TRI["先查 §8.8 分诊<br/>别归因给波形"]
TRI -.->|"修复后重来"| ST
Q1 -->|是| MED["10 行读数排序<br/>取第 5、6 个的平均 = 中位数"]
MED --> Q2{"与期望的偏差在判据内?"}
Q2 -->|是| OK["记通过"]
Q2 -->|"否"| CHK["先复核查:发生器端接、<br/>万用表响应类型、共地"]
CHK -->|"复查仍超"| BAD["记不通过,进 §8.8 分诊"]
CHK -->|"查出问题改完重测"| ST
OK --> OFF["关输出,填记录表"]
BAD --> OFF
OFF --> NEXT["下一条 / 下一轮"]
```
**两种情况先修再测,别往下走**:采集链没清(`frames` 不涨 / `adc1_err≠0`)→ 查 §8.8;偏差没进判据 → 先复查三件事(端接 / 万用表响应类型 / 共地),改完重测,复查仍超才进 §8.8。
为什么这一步是"中位数"而不是单行或平均——机理与操作:
#### 幅值轮(先做:三档幅值的偏差都在 ±2 % 内)
![为什么连取 10 行取中位数:窗滑动让读数拍频式上下跳(左);中位数贴着密集簇,平均被毛刺拖走(右)](../../images/交流定数取中位数.svg)
#### 幅值轮:基波幅值(主用例,先做)
一句话:发生器注 50.000 Hz 正弦,**Vpp 2.828 / 1.414 / 0.566 V 三档挨个来**,每档从串口 `meas:` 行读 `ua_mv`,和并接在同一注入点上的万用表读数比——**每档偏差 ≤2 % 就算通过**。
| 项 | 内容 |
|---|---|
| 接法 | 发生器 → `UA`(R31 / `AIN1` / U5.A3)端子侧;万用表 AC 档**并同一注入点**——量真实加到板上的电压,不是面板值 |
| 设定 | 正弦、50.000 Hz、**1.000 Vrms**(峰值 1.414 V) |
| 主读数 | `meas: ua_mv=`(1 mV) |
| 期望与判据 | `ua_mv` ≈ 万用表读数 × 1000,偏差 **≤2 %**(与静态同档) |
| 交叉读数 | 104 `0x4011`(短浮点)应 ≈ 万用表读数,单位是**引脚电压域**(`eng=0`,不是二次值) |
| 坑 ① | **别用 `phasor(hb)` 比幅值**——×0.1 定点,1 V 只剩 10 格(§4 尾注同一条) |
| 坑 ② | 104 每点 0.5 V(电流 0.005 A)变化死区,生效值在 `App/algo/run_par.c` 的 `[run_par]` 副本:1.000 → 1.100 V **不会**上报变化,那是死区不是坏了;连续扫幅度只看 `meas:` |
| 坑 ③ | **`cal: ua_mv` 与 `meas: ua_mv` 同名不同物**:前者是当拍瞬时码折算(`App/task/adc_task.c:587`),后者是 200 ms 快照里那一周波的基波有效值(`App/task/adc_task.c:605`),50 Hz 下二者可以差很多——`App/task/adc_task.c:595-599` 的原注就是**勿互为判据**,幅值轮只认 `meas:` |
| 设定 | 正弦、50.000 Hz,三档挨个来:**Vpp 2.828 V → 1.414 V → 0.566 V**(档位不用拧精确,记万用表实际读数就行) |
| 读哪个数 | `meas: ua_mv=`(1 mV) |
| 通过判据 | 每档 `ua_mv` ≈ 万用表读数 × 1000,偏差 **≤2 %**(与静态轮同档) |
记录表(记录表每一行 = 连续 10 行心跳 `ua_mv` 的**中位数**:排序后取第 5、6 个的平均;
不取单行、不取峰值——单行带拍频跳动,毛刺行会拖偏算术平均。表里"序号"是一次重测):
记录表(每行 = 连续 10 行心跳 `ua_mv` 的**中位数**:排序取第 5、6 个平均;不取单行、不取峰值。"序号"是一次重测):
| 序号 | 万用表 AC (V) | `meas: ua_mv` | 期望 = 万用表 × 1000 | 偏差 % | 结论 |
|---|---|---|---|---|---|
| 1 | | | | | |
| 2 | | | | | |
| 3 | | | | | |
**加做(3 min,非判据)**:0.500 / 0.200 Vrms 两点看是否**等比**——不是验精度,是看有没有隐藏的触底或死区。
0.2 Vrms 那点 104 必然被死区吞掉,只读 `meas:`。
| 1 | 0.998 | 996 | 998 | -0.20 | PASS |
| 2 | 0.499 | 498 | 499 | -0.20 | PASS |
| 3 | 0.248 | 249 | 248 | +0.40 | PASS |
#### 波形轮:读数是否只跟基波走(同峰值改波形)
按**峰值对齐**(不是按 Vrms 对齐):三者峰值都取 1.414 V,发生器面板 Vrms 分别约 正弦 1.000 V、方波 1.414 V、
三角 0.816 V。期望的**基波有效值**(全周傅氏基波口径:`App/algo/phasor.c:3` 的系数已预乘 √2/N、`fAmSQ` 直接就是
有效值;下表的 20 点整周期 DFT 值就是按固件同一个窗算的):
三个波形都按**峰峰值对齐**:发生器统一设 **Vpp 2.828 V**(峰值 ±1.414 V)。期望的**基波有效值**(全周傅氏基波口径:`App/algo/phasor.c:3` 系数已预乘 √2/N、`fAmSQ` 直接就是有效值;下表 20 点整周期 DFT 值按固件同一个窗算):
| 波形 | 基波有效值 / 峰值 | 峰值 1.414 V 时的期望 `ua_mv` | 真有效值 / 峰值(对照) |
| 波形 | 基波有效值 / 峰值 | Vpp 2.828 V 时的期望 `ua_mv` | 真有效值 / 峰值(对照) |
|---|---|---|---|
| 正弦 | 0.707 | 1000 | 0.707 |
| 方波 | 0.904(闭式 4/π/√2 = 0.900) | ≈1278 | 1.000 |
| 三角 | 0.578(闭式 8/π²/√2 = 0.573) | ≈817 | 0.583 |
- 判据:读数 = **基波**期望 ±2 %,**不是**真有效值。方波那栏最直观——真 RMS 表会读 ≈1414 mV、
均值响应表读 ≈1570 mV,而板上读 ≈1278 mV,**这正是"这台仪表读的是基波"的证据,不是 bug**;
所以抬头里必须写清万用表响应类型(判据文档同一条:拿真有效值表去对会以为差了 10 %)。
- 系数的来路:方波基波幅值 = 4/π × 峰值、三角 = 8/π² × 峰值,再除 √2 得基波有效值 → 闭式 **0.900 / 0.573**,
20 点整周期 DFT 实算 **0.904 / 0.578**;`docs/任务规划/数据可信.md` §4.6.2 的"波形轮"行与本节同值,算术以本节为准。
- 判据:读数 = **基波**期望 ±2 %,**不是**真有效值。方波栏:真有效值表 ≈1414 mV、均值响应表 ≈1570 mV、板上 ≈1278 mV——**正是"读的是基波"的证据,不是 bug**;抬头必须写清万用表响应类型(判据文档同一条)。
- 系数:方波基波 = 4/π × 峰值、三角 = 8/π² × 峰值,除 √2 得基波有效值 → 闭式 **0.900 / 0.573**,20 点 DFT 实算 **0.904 / 0.578**(`docs/任务规划/数据可信.md` §4.6.2 同值,算术以本节为准)。
记录表:
| 波形 | 峰值设定 (V) | 面板 Vrms | 万用表 AC 实测 | `ua_mv` | 期望 | 偏差 % | 结论 |
|---|---|---|---|---|---|---|---|
| 方波 | 1.414 | | | | ≈1278 | | |
| 三角 | 1.414 | | | | ≈817 | | |
| 波形 | 设定 Vpp (V) | 万用表 AC 实测 (V,有效值档) | `ua_mv` | 期望 | 偏差 % | 结论 |
|---|---|---|---|---|---|---|
| 方波 | 2.828 | 1.407 | 1269 | ≈1278 | -0.70 | PASS |
| 三角 | 2.828 | 0.814 | 807 | ≈817 | -1.22 | PASS |
#### 相位轮:相位(只许比同片内)
| 项 | 内容 |
|---|---|
| 接法 | `UA`(R31)与 `UN`(R28)**都走 TPAFE**,同幅 1.000 Vrms、同相——发生器单路输出分两路即天然同相;双通道机型则两通道都设 0° |
| 读数 | `phasor(hb) C02-UA-F1: Re=.. Im=..` 与 `C03-UN-F1: Re=.. Im=..`,各取 `atan2(Im, Re)` 再比差值 |
| 判据(§4.6.2) | **定量档**:同相时同段内两路相位差 ≤2°,把发生器(或 B 通道)改 90° 后差值跟到 ≈90°;**定性档只判跟随**(差值落进 80°~100°,容差写进记录表) |
| ⚠ 分辨率 | 出口只有 ×0.1 且向下截断:1.000 Vrms 时 Re/Im 各只有 ±10 格,**一格就是 0.1 V** → 角度量化误差最坏 ≈ atan(0.1 / 0.707) ≈ 8°,**≤2° 今天用串口判不出来** |
| 三个档 | ① **段文件定量档(首选,零改代码)**:同一次注入触发一段,`test/host/wave_read.py fft` 重算基波相位,比**同段内** `UA`(表序 0)与 `UN`(表序 3)的相位差——浮点重算,不受 ×0.1 量化限制,≤2° 判得动,动作见下面第 2 段;② **定性档**:没取到段时退而用,同相 ≈0°、改 90° 后差值落进 80°~100° 即算跟随,容差写进记录表;③ **抬倍数退路**:临时把 `log_phasors()` 的倍数改成 ×1000 并改掉行尾 `(x0.1)`,跑完按 §8.9 还原——段文件档已落地,这条基本不必走,要走仍**先问用户** |
| 红线 | **只许比同片内**:跨转换器无同刻性(V0.1 硬件缺陷)+ STM32 那五路另有 1 拍乒乓滞后 → `docs/硬件平台/ADC通道映射说明.md` §7 |
| 接法 | `UA`(R31)与 `UN`(R28)**都走 TPAFE**,同幅 Vpp 2.828 V(峰值 ±1.414 V)、同相(发生器单路分两路即天然同相;双通道机型两通道都设 0°) |
| 读数 | `phasor(hb) C02-UA-F1` 与 `C03-UN-F1`,各取 `atan2(Im, Re)` 再比差值 |
| 判据(`docs/任务规划/数据可信.md` §4.6.2) | **录波档**:同段内两路相位差 ≤2°,改 90° 后差值 ≈90°;**心跳档只判跟随**(差值落 80°~100°,容差写记录表) |
| ⚠ 分辨率 | 串口行的 ×0.1 向下截断:Vpp 2.828 V(板上 ≈1000 mV)时 Re/Im 各 ±10 格,**一格 0.1 V** → 角度量化误差最坏 ≈ 8°,**≤2° 串口判不出来** |
| 怎么取证 | ① **录波档(首选,零改代码)**:触发一段,`wave_read.py fft` 重算基波相位,比同段内 `UA`(表序 0)与 `UN`(表序 3)相位差——浮点重算不受 ×0.1 量化限制,≤2° 判得动(动作见下段);② **心跳档**:没录到段文件时退用,同相 ≈0°、改 90° 后差值落 80°~100° 即算跟随;③ **抬倍数退路**:临时 `log_phasors()` 倍数改 ×1000 并改行尾 `(x0.1)`,跑完按 §8.9 还原——录波档可用时基本不必走,要走**先问用户** |
| 红线 | **只许比同片内**:跨转换器无同刻性(V0.1 硬件缺陷)+ STM32 五路另有 1 拍乒乓滞后 → `docs/硬件平台/ADC通道映射说明.md` §7 |
记录表(定性档;定量档记脚本输出,归档口径见 §8.10 第 1 条):
记录表(按心跳档抄屏;录了波的轮次直接记脚本输出,归档口径见 §8.10 第 1 条):
| 发生器相位设定 | C02-UA `Re` / `Im` | C03-UN `Re` / `Im` | 两路 `atan2` 之差 | 结论 |
| 发生器相位设定 | C02-UA `Re`/`Im` | C03-UN `Re`/`Im` | 两路 `atan2` 之差 | 结论 |
|---|---|---|---|---|
| 0° / 0° | | | | |
| 0° / 90° | | | | |
| 0° / 0° | -8 / -5 | -8 / -5 | 心跳档两路象限全同 → Δ=0.0°(×0.1 判不动 ≤2°);**录波档 WAVE06 段实测 Δφ = 0.07°**(fft:UA 995.79 mV ∠+18.23° / UN 995.70 mV ∠+18.16°) | **PASS**(录波档 ≤2°) |
| 0° / 90° | -2 / -9 | 9 / -2 | atan2:UA -102.53°、UN -12.53° → 差 **+90.0°**,跟随成立(该点未录段文件,心跳档判据 80°~100°) | **PASS**(心跳档) |
**段文件定量档的具体动作(相位轮首选,零改代码)**
**录波档的具体动作(相位轮首选,零改代码)**
1. `UA`(R31)与 `UN`(R28)两路接同一发生器输出(同相),注 **1.000 Vrms / 50.000 Hz**;
2. 稳定 ≥30 s 后,在 UI「手动录波」确认页触发一次;成段有**秒级**延迟(落盘在 defaultTask,卷空闲后一次心跳搬完整段)
→ 等串口 `wave:` 行的 `seg=` +1、`armed` 回 0 再去取文件;
3. FTP 取 `/wave/WAVE<NN>.BIN`(本轮那一段的确切号),**取完立刻改名**——100 个号轮转会被覆盖;
4. 主机侧跑:`& '.venv\Scripts\python.exe' test/host/wave_read.py fft WAVE<NN>.BIN --all`
—— 每个整周波给一行:基波 RMS、相位、2 次与 5 次谐波 RMS(单位 mV,系数镜像 `App/algo/phasor.c`);
5. 判据:`UA`(`--ch 0`)与 `UN`(`--ch 3`)在**同一周波**内的相位差——同相注入应 ≈0°,把发生器(或 B 通道)改 90° 后应 ≈90°,
容差 ±2°(`docs/任务规划/数据可信.md` §4.6.2"相位轮"行);
6. ⚠ 段的**绝对**相位与发生器没有锁定关系(触发瞬间固定落在段内点 159),所以**只能比同段内两路的相对差**;
跨段比相位、或拿发生器相位当绝对基准都不成立(段内点序见 `docs/子系统设计/故障录波设计说明.md` §6.2);
7. 交叉旁证:同一段先 `dump`(逐字段 + 双 CRC16,看封存瞬间的标定与品质快照),再 `plot --ch 0`(CRC 不符或零长度它
**必须拒收**而不是画出半张图);板上 `phasor(hb)` 的 `Re` / `Im` 象限应与脚本给的象限一致(×0.1 只够核象限)。
1. `UA`(R31)与 `UN`(R28)两路接同一发生器输出(同相),注 **Vpp 2.828 V / 50.000 Hz**;稳定 ≥30 s 后在 UI「手动录波」确认页触发一次;成段有**秒级**延迟(落盘在 defaultTask,卷空闲后搬段)→ 等 `wave:` 行 `seg=` +1、`armed` 回 0 再取文件;
2. FTP 取 `/wave/WAVE<NN>.BIN`,**取完立刻改名**(100 号轮转会被覆盖);
3. 跑 `& '.venv\Scripts\python.exe' test/host/wave_read.py fft WAVE<NN>.BIN --all`——每个整周波给一行:基波有效值、相位、2 次与 5 次谐波有效值(mV,系数镜像 `App/algo/phasor.c`);
4. 判据:`UA`(`--ch 0`)与 `UN`(`--ch 3`)在**同一周波**内相位差——同相 ≈0°,改 90° 后 ≈90°,容差 ±2°(`docs/任务规划/数据可信.md` §4.6.2);
5. ⚠ 段**绝对**相位与发生器无锁定(触发瞬间落在段内点 159)→ **只能比同段内相对差**,跨段比相位不成立(段内点序 `docs/子系统设计/故障录波设计说明.md` §6.2);
6. 交叉旁证:同一段先 `dump`(逐字段 + 双 CRC16),再 `plot --ch 0`(CRC 不符或零长度**必须拒收**);板上 `phasor(hb)` 象限应与脚本一致(×0.1 只够核象限)。
#### 测频轮(默认 A 档 = 判"如实报不可测")
#### 测频轮(现状:测不出频率才是对的)
一句话:给 `UA` 注与幅值轮同样的 Vpp 2.828 V / 50.000 Hz 正弦,看串口 `freq(hb)` 行——**固件现状就不该出数**,出数反而是算错了。
| 项 | 内容 |
|---|---|
| 接法与设定 | 同幅值轮(`UA`,1.000 Vrms / 50.000 Hz) |
| 读数 | `freq(hb): f=.. valid=..`;UI 交流量页 `Hz`;104 `0x401D` |
| 期望(A 档 = 现状) | **就是不出数**:幅值门 `FREQ_AMP_MIN 50.0f`(`App/algo/freq.h:62`,`App/algo/freq.c:231` 拿它与基波有效值比)在引脚电压域恒不过 → `valid=0`、`f=0`、UI `Hz` 显 `--`、104 `0x401D` 上送 IV |
| 接法与设定 | 同幅值轮(`UA`,Vpp 2.828 V / 50.000 Hz) |
| 读数 | `freq(hb): f=.. valid=..`;UI 交流量页 `Hz` |
| 期望(现状固件) | **就是不出数**:幅值门 `FREQ_AMP_MIN 50.0f`(`App/algo/freq.h:62`,`App/algo/freq.c:231` 拿它与基波有效值比)在引脚电压域恒不过 → `valid=0`、`f=0`、UI `Hz` 显 `--` |
| 判据 | **如实报不可测**,而不是报一个看起来对的 50.00。若门限没改却报出 50.00 → 反而是 bug,停下查 `App/algo/freq.c` |
| B 档(要用户先点头) | 临时把 `FREQ_AMP_MIN` 由 `50.0f` 降到 `0.5f` → 重编(`/keil-build`,要 build 锁)+ 重烧 → 扫 45.000 / 50.000 / 55.000 Hz 三点,PC 侧判据 0.02 Hz → 跑完**必须还原**,收尾判据见 §8.9 |
| 坑 | 非整 50 Hz 时 `meas:` 会拍频式跳动,属预期 → **扫频读 `freq(hb)`,别读 `meas:`**(`docs/任务规划/数据可信.md` §8 风险表同一条);测频的取源顺序是先 `UA`(相量实例 C02)再退 `IA`(C01)(`App/algo/freq.c:47`)——本卡注 `UA` 走的就是 UA 源;若哪天只注 `IA`,测频会跟着 IA 走,别以为它锁在 UA |
记录表(A 档):
| 频率设定 (Hz) | `freq(hb)` f | valid | UI `Hz` | 104 `0x401D` 品质 | 结论 |
|---|---|---|---|---|---|
| 50.000 | | | | | |
#### 削顶轮:触底与品质路由(负向用例)
- **判据**(`docs/任务规划/数据可信.md` §4.6.2"削顶轮"行):给 `UB`(R52 / `AIN2` / U5.B7)注 **DC −1.00 V 保持 ≥5 s**
或 **1.000 Vrms / 2.0 Hz** 的正弦 → 负半周钉下轨 → 连续 20 拍同侧后该路贴轨位锁存、`edge` 起沿、104 该路 IV 且值清零。
- ⚠ **注 50 Hz 同幅正弦造不出这个锁存,这是实现约束不是固件缺功能**:锁存条件是"连续 `ADC_RAIL_N_RUN = 20` 拍
贴同一侧轨带"(`App/algo/adc_health.h:174`),而 `adc_health_rail_watch()` 里**任何一拍回到中带就把两侧计数清零**;
1 kHz 下一个 50 Hz 周波只有 20 个点、正半周必然落在中带 → 连续贴底最长 ≈ 209°/360° × 20 ≈ **11 拍 < 20**。
- **轨带数值**(`App/algo/adc_cal.c:452` 的 `adc_cal_rail_ths()`,TEMP 不监视):STM32 侧贴底 = 码 ≤ **81**(2 % FS ≈ 65 mV)、
贴顶 = 码 ≥ 4013;TPAFE 侧 = ±32112 码(≈ ±4.9 V)→ **TPAFE 侧这一条在 ±2 V 判据上限内根本造不出来**,
只有 STM32 那五路能做。
- **改法 A(首选,零固件改动)**:发生器切 **DC 输出 −1.00 V** 注 `UB` 端子侧,保持 ≥5 s。期望:`cal:` 的 `rail=0x002`、
`edge=0x002`、一条 `[ERR] rail: edge=0x2 sticky=0x2 (code-domain, 20-run+release)`(`App/task/adc_task.c:428`)、
104 `0x4012` 该路 IV 且值清零、`adc: UB` 码值贴 0。撤掉注入后 **sticky 位不随输入恢复而清**(锁存语义,
只有 `adc_health_rail_init()` / 复位清)→ 复位一次并把"是否随复位清"记进表:这条实测行为是本轮的产出之一。
- **改法 B**:发生器 1.000 Vrms 但**频率设 2.0 Hz** → 负半周 250 ms = 250 拍贴底 ≥ 20 → 锁存;
顺带证"贴轨检测与工频无关"这条口径。
- **50 Hz 档照跑,判据就是"不锁存"**:记下 `adc: UB` 负半周钉 0 而 `rail` 仍 `0x000` —— 这一档证的是
"锁存要连续 20 拍同侧"这条实现约束本身,不是失败,也不是战果。
- **反向假阳性**:反过来注一个峰值 <65 mV(<46 mVrms)的 50 Hz 小信号,会让 `UB` 一路贴底而**锁存**——
那是"信号小到进不了中带",不是削顶。读 `rail` 时要把这条一起排除。
- **与 `cl` 区分**:`cl=0xE6` 是**来源派生**的静态触底掩码(`docs/任务规划/数据可信.md` §2.6),削顶轮要的是动态
`rail=` / `edge=`;别拿 `cl` 当本轮战果。
| 另有一档(需先取得同意) | 临时把 `FREQ_AMP_MIN` 由 `50.0f` 降到 `0.5f` → 重编(`/keil-build`,要 build 锁)+ 重烧 → 扫 45.000 / 50.000 / 55.000 Hz 三点,PC 侧判据 0.02 Hz → 跑完**必须还原**,收尾判据见 §8.9。这一档要改固件重烧,动它之前先问过你;不做也不影响上面那条判据成立 |
| 坑 | 非整 50 Hz 时 `meas:` 拍频式跳动属预期 → **扫频读 `freq(hb)` 别读 `meas:`**(`docs/任务规划/数据可信.md` §8 同一条);取源先 `UA`(C02)再退 `IA`(C01)(`App/algo/freq.c:47`)——注 `UA` 走 UA 源;若只注 `IA`,测频跟 IA 走 |
记录表:
| 步 | 设定 | `rail` | `edge` | `[ERR] rail:` 行数 | 104 `0x4012` | 复位后 `rail` | 结论 |
|---|---|---|---|---|---|---|---|
| 1 | 50.000 Hz / 1.000 Vrms 正弦 | | | | | 不适用 | |
| 2 | DC −1.00 V(改法 A) | | | | | | |
| 3 | 2.0 Hz / 1.000 Vrms(改法 B) | | | | | | |
| 频率设定 (Hz) | `freq(hb)` f | valid | UI `Hz` | 结论 |
|---|---|---|---|---|
| 50.000 | 0 | 0 | 未记(期望 `--`,与 fv 同源,无补测价值) | **PASS**:冻结窗口 229 行 `freq(hb)` **全部** `f=0.00 valid=0 src=0`(含 UA 满幅 Vpp 2.828 V 注入时段)——幅值门 `FREQ_AMP_MIN=50.0f`(`App/algo/freq.h:62`、`App/algo/freq.c:231`)拿**电压域有效值**比(`phasor(hb)` rms=9 = ×0.1 V 刻度),引脚域 ≈1 V 恒不过门 → **如实报不可测**,与现状判据逐字一致 |
**段文件档的两把尺子(现在能把"来源派生 vs 实测"一次核清)**
#### 削顶轮:触底与品质路由(负向用例)
`shape` 拿**实测**贴轨判定与段头 `clip_mask` 对表;而段头那一位**来自通道来源、从不实测**(`test/host/wave_read.py`
文件头的实证与本卡上面的 `cl=0xE6` 同源,两处互证)→ 三种注入分别配三把尺子:
- **判据**(`docs/任务规划/数据可信.md` §4.6.2"削顶轮"行):给 `UB`(R52 / `AIN2` / U5.B7)注 **DC −1.00 V 保持 ≥5 s** 或 **Vpp 2.828 V / 2.0 Hz** 正弦 → 负半周钉下轨 → 连续 20 拍同侧后该路贴轨位锁存、`edge` 起沿。
- ⚠ **50 Hz 同幅正弦造不出锁存,是实现约束不是固件缺功能**:锁存条件"连续 `ADC_RAIL_N_RUN = 20` 拍贴同一侧轨带"(`App/algo/adc_health.h:174`),`adc_health_rail_watch()` 里**任何一拍回中带就清零**;1 kHz 下一个 50 Hz 周波只有 20 点、正半周必落中带 → 连续贴底最长 ≈ 209°/360° × 20 ≈ **11 拍 < 20**。
- **轨带数值**(`App/algo/adc_cal.c:452` `adc_cal_rail_ths()`,TEMP 不监视):STM32 贴底 = 码 ≤ **81**(2 % FS ≈ 65 mV)、贴顶 = 码 ≥ 4013;TPAFE = ±32112 码(≈ ±4.9 V)→ **TPAFE 侧在 ±2 V 判据上限内造不出来**,只有 STM32 五路能做。
- **直流削顶档(首选,零固件改动)**:发生器切 **DC −1.00 V** 注 `UB` 端子侧,保持 ≥5 s。期望:`rail=0x002`、`edge=0x002`、一条 `[ERR] rail: edge=0x2 sticky=0x2 (code-domain, 20-run+release)`(`App/task/adc_task.c:428`)、`adc: UB` 贴 0。撤掉注入后 **sticky 位不随输入恢复而清**(只有 `adc_health_rail_init()` / 复位才清)→ 复位一次记录"是否随复位清",本轮战果之一。
- **工频对照档**:原接法注 50 Hz → 连续贴底最长 ≈ **11 拍 < 20**,**不锁存是预期**,非失败非战果。
- **2 Hz 低频削顶档**:发生器 Vpp 2.828 V 但**频率设 2.0 Hz** → 负半周 250 ms = 250 拍贴底 ≥ 20 → 锁存;顺带证"贴轨检测与工频无关"。
- **反向假阳性**:注 Vpp <130 mV(峰值 <65 mV)的 50 Hz 小信号会让 `UB` 贴底**锁存**——"信号太小进不了中带",不是削顶。读 `rail` 时一并排除。
- **与 `cl` 区分**:`cl=0xE6` 是**来源派生**静态贴底掩码(`docs/任务规划/数据可信.md` §2.6),削顶轮要动态 `rail=`/`edge=`;别把 `cl` 当本轮战果。
记录表:
| 步 | 设定 | `rail` | `edge` | `[ERR] rail:` 行数 | 复位后 `rail` | 结论 |
|---|---|---|---|---|---|---|
| 1 | 50.000 Hz / Vpp 2.828 V 正弦 | 0x000 | 0x000 | 0 | 未测 | ✓ 不锁存(正弦连续贴底 ≈11 拍 < 20,本步证"连续 20 拍"约束本身,非战果非失败) |
| 2 | DC −1.00 V ≥5 s(直流削顶档) | — | — | — | — | **本轮未做**:冻结窗 16:25–17:03 段日志 `rail` 恒 0x000、零 `[ERR]`,与"未做"一致;16:25 前日志已被 daemon 截头,无法反证。补做与否待排 |
| 3 | 2.0 Hz / Vpp 2.828 V(低频削顶档) | 0x000 | 0x000 | 0 | 未记 | ⚠ **待确认注入哪一路**:注 `UB` → 期望锁存 `rail=0x002`,填 0x000 即 FAIL 需重测;注 `UA`(对照点,`docs/任务规划/数据可信.md` §4.6.2)→ 0x000 = 期望(TPAFE 侧轨带在 ±2 V 判据上限内造不出,不会锁存) |
**段文件档的两个量具("来源派生 vs 实测"一次分清)**
`shape` 拿**实测**贴底与段头 `clip_mask` 对表;段头 bit **来源派生、从不实测**(`test/host/wave_read.py` 文件头与 `cl=0xE6` 同源互证)→ 三种注入各配一个量具:
| 注入 | 命令 | 期望 |
|---|---|---|
| 改法 A(`UB` 注 DC −1.00 V 保持 ≥5 s) | `shape WAVE<NN>.BIN --strict` | 实测贴底落进 bit1;段头静态已含 bit1 → 等式成立。**实测冒出段头没有的位**才算失败 = 有别的路被推到轨上,先查接线 |
| 极小注入 / 未驱动通道 | 同上再加 `--clip-superset` | 换成"段头覆盖实测"这把尺子:容忍"封存了但本轮没贴轨";实测有、段头没有仍然失败 |
| 原接法(50 Hz 正弦注 `UB`) | `shape WAVE<NN>.BIN`(不带 `--strict`) | 只读逐通道贴轨游程:正弦过零必回中带,`--min-run` 默认 4 也可能判不出贴轨——**别把"没判"读成 bug** |
| 直流削顶档(`UB` DC −1.00 V ≥5 s) | `shape WAVE<NN>.BIN --strict` | 实测贴底落 bit1;段头已含 bit1 → 等式成立。**实测冒出段头没有的 bit** = 失败,先查接线 |
| 极小注入 / 非驱动通道 | 同上 + `--clip-superset` | "段头覆盖实测":容"封存了但没贴底";实测有、段头没有仍判失败 |
| 原接法(50 Hz 注 `UB`) | `shape WAVE<NN>.BIN` | 只读贴底 run:正弦过零必回中带,`--min-run` 默认 4 判不出——**别把"判不出"读成 bug** |
`--min-run`(连续几点算贴轨)与固件的"连续 20 拍"是**两把不同的尺子**,别互相换算;固件侧结论仍以 `rail:` / `edge=`
位图为准(本卡上半段)。
`--min-run` 与固件"连续 20 拍"是**两个量具**,别互换;固件侧结论以 `rail:`/`edge=` 为准(本卡上半)。
#### 谐波轮:谐波轨(**段文件 `fft` 定量档 + UI 目检旁证**)
#### 谐波轮:谐波卡(录波档 fft + UI 目检旁证)
| 项 | 内容 |
|---|---|
| 接法 | 发生器 → `IA`(R19 / `AIN8` / U5.B5)端子侧 |
| 设定 | 基波 + 20 % 二次 + 20 % 五次(发生器有谐波叠加 / ARB 模式就用它) |
| ⚠ 峰值预算 | 1.000 Vrms 基波 + 两个 20 % 分量的最坏对齐峰值 ≈ 1.414 + 0.283 + 0.283 = **1.98 V,已顶到 ±2 V 判据上限**。所以基波改 **0.800 Vrms**、二次与五次各 0.160 Vrms,最坏峰值 ≈ 1.58 V 留余量;期望值随之换算 |
| 主读数 | UI 交流量页 `Ia2` / `Ia5` 两行——**3 位小数 = 1 mV**(`Drivers/BSP/UI/ui_page_ac.c:47`),目检 + 拍照;远端可走 7003 看图截屏 |
| 期望与判据 | 期望 ≈ 各分量注入值(0.160 Vrms)±2 % |
| 旁证 | `phasor(hb) C04-IA-F2` / `C05-IA-F5` 的 `rms=`:×0.1 只有 1~2 格,**只能证明这根轨不是恒 0**,判不了 ±2 %(§8.1) |
| 没有谐波叠加功能时 | 分三次单注:只注 0.160 Vrms / 100 Hz → `Ia2` 有数、`Ia5` 应 ≈0;只注 0.160 Vrms / 250 Hz → `Ia5` 有数、`Ia2` 应 ≈0;再注纯基波 → 两行都 ≈0。这一档证的是"两根轨各认各的次",**不证叠加工况**,结论里要写明 |
| 口径 | 这两根轨**目前没有任何下游消费者**(`App/algo/prot_elm.c` 无引用、`meas` 只算基波)→ 谐波轮只证"算得对",不证"有人用";出口归属 `docs/任务规划/数据可信.md` §9 的谐波轨立项 |
| ⚠ 峰值预算 | 基波 Vpp 2.828 V + 2 个 20 % 分量,最坏对齐峰值 ≈ 1.414 + 0.283 + 0.283 = **1.98 V,已顶到 ±2 V 判据上限**。所以基波改 **Vpp 2.263 V**、二次与五次各 Vpp 0.453 V,最坏峰值 ≈ 1.58 V 留余量;期望值随之换算 |
| 读哪个数 | UI 交流量页 `Ia2`/`Ia5`(3 位小数)——**1 mV**(人工目检 + 拍照留证,`Drivers/BSP/UI/ui_page_ac.c:47`);谐波幅值、交叉旁证 |
| 期望与判据 | 板上读数(有效值刻度)≈ 各分量 0.160 V(对应设定 Vpp 0.453 V)±2 % |
| 旁证 | `phasor(hb) C04-IA-F2`/`C05-IA-F5` 的 `rms=`:×0.1 只 1~2 格,**只能证"该轨非恒 0"**,判不了 ±2 %(§8.1) |
| 无谐波叠加功能时 | 三次单注:只注 Vpp 0.453 V / 100 Hz → `Ia2` 有数(读数 ≈0.160 V)、`Ia5` 应 ≈0;只注 Vpp 0.453 V / 250 Hz → `Ia5` 有数、`Ia2` 应 ≈0;再注纯基波 Vpp 2.263 V → 两轨都 ≈0。这一档证"两轨各认各的次",**不证叠加工况**,结论里写清 |
| 口径 | 这两轨**当前无下游消费者**(`App/algo/prot_elm.c` 无引用、`meas` 只算基波)→ 谐波轮只证"算得对",不证"有人用";这两轨归谁用,见 `docs/任务规划/数据可信.md` §9 谐波轨立项 |
记录表:
| 注入分量 | 发生器设定 | UI 读数 (V) | 期望 (V) | 偏差 % | `phasor` 旁证 | 结论 |
|---|---|---|---|---|---|---|
| 基波 0.800 Vrms + 二次 0.160 + 五次 0.160 | | `Ia2=` / `Ia5=` | 0.160 / 0.160 | | | |
| A 只注二次 | 100.00 Hz / Vpp 0.453 V | `Ia=0` / `Ia2=0.158` / `Ia5=0` | 0.160 / ≈0 | **−1.25 %** | —(A/B 步落在 18:22–18:28 日志盲区,心跳旁证未留) | **过**(±2 % 内;选择性成立——100 Hz 没漏进基波 / 五次桶) |
| B 只注五次 | 250.00 Hz / Vpp 0.453 V | `Ia=0` / `Ia2=0` / `Ia5=0.152` | ≈0 / 0.160 | **−5.0 %**(超 ±2 %) | —(同上盲区) | **待定分诊**:选择性成立(基波 / 二次桶 = 0),但 250 Hz 幅值超差——按注"五次超差分诊"复核查再改本行 |
| C 纯基波 | 50.00 Hz / Vpp 0.453 V(实际按 0.453 注,Vpp 2.263 那档未做) | `Ia=0.159` / `Ia2` `Ia5` 未抄屏 | ≈0 / ≈0 | 基波 **−0.6 %**(对 0.160 读数) | **有**:18:33:43 起串口可见窗 `C01 rms=1 / C04 rms=0 / C05 rms=0`,与 C 步工况吻合 | **过**(两谐波轨零值经串口旁证补认;基波 −0.6 % 与幅值轮同档一致) |
| 叠加(原行,**本轮不做**) | 基波 + 二次 + 五次同段 | — | — | — | — | 发生器无谐波叠加 / ARB 功能 → 本轮不做·设备缺口·TC-PHASOR-006 单测覆盖(`test/host/phasor/phasor_test.c`,3 条谱线各 ±1 %,实跑 57/57 PASSED) |
**段文件定量档(谐波现在判得到位)**
> **2026-11-02 本轮执行档注**:发生器无叠加功能,按本卡"无谐波叠加功能时"行走**三注替代档**(用户裁定)。每注稳定后读 UI `Ia2`/`Ia5`(3 位小数 = 1 mV,判据 ±2 % 只作用于 0.160 那一行),并各触发一段录波取回跑 `fft WAVE<NN>.BIN --ch 4 --all`:A 的二次行应 ≈160 mV、五次行 ≈0;B 相反;C 两谐波行 ≈0。单注峰值 ≈0.226 V(0.800 基波 ≈1.13 V),远离 ±2 V 判据上限,无贴轨风险。
同一次注入(基波 0.800 Vrms + 二次 0.160 + 五次 0.160,峰值预算见上表)触发一段、FTP 取回后跑:
> **五次超差分诊注**(B 行 −5.0 %,2026-11-02):最可能位置在**发生器本身**——多数函数发生器在 250 Hz 段带载(高阻)输出幅值会 sag,5 % 量级完全在其规格影内;板端 50 Hz 幅值轮三点 −0.2 % ~ +0.4 % 只锚定 50 Hz 频响,**证不到 250 Hz**。一刀分两边:**B 步工况用万用表(真有效值档)直接量发生器输出端**——表读 ≈0.152 → 发生器 sag、板端忠实,B 行改判"过(按实际注入基准)"并在设定列补记实测;表读 ≈0.160 → 板端频响嫌疑,登记 IA 前端 250 Hz 频响专项(R19 通道滤波网表核算),不再归因给仪表。同段顺带触发一段录波,`fft --ch 4 --all` 的五次行与 UI `Ia5` 互核(同链复核查,非独立证据,只排除显示档笔误)。
**录波档动作(谐波现在判得到位)**
同一次注入(叠加档设想值:基波 Vpp 2.263 V + 二次与五次各 Vpp 0.453 V,峰值预算见上表;本轮发生器无叠加功能、未跑此档)触发一段,FTP 取回跑:
```text
& '.venv\Scripts\python.exe' test/host/wave_read.py fft WAVE<NN>.BIN --ch 4 --all
```
`fft` 逐整周波给**基波 RMS + 2 次与 5 次谐波 RMS**(mV,浮点重算),±2 % 在这条档是定量判据;`--ch` 是段内通道表序,
`IA` = 4(表序 `UA UB UC UN IA IB IC IN`,TEMP 不录,`App/algo/wave_ring.h:216`)。UI 目检与 7003 截图降为**旁证**——
它证的是"板上 `Ia2` / `Ia5` 与脚本算的是同一件事"(差值应在显示位数之内),不是替代判据。THD 与方和根仍不在本轮,
口径见 `docs/任务规划/数据可信.md` §4.6.5。
`fft` 每整周波给一行:**基波有效值 + 2 次与 5 次谐波有效值**(mV,浮点重算),±2 % 是定量判据;`--ch` = 段内通道表序,`IA` = 4(`UA UB UC UN IA IB IC IN`,TEMP 不录,`App/algo/wave_ring.h:216`)。UI 目检退**旁证**(证"板上与脚本算的是同一个东西"),不是替代判据。THD 与根均方不在本轮(`docs/任务规划/数据可信.md` §4.6.5)。
### 8.6 顺序与耗时(一次台架 session 跑完)
### 8.6 顺序与耗时(一个台架轮次跑完)
| 序 | 做什么 | 预计 | 备注 |
| 序 | 做什么 | 估算 | 注 |
|---|---|---|---|
| 0 | 前置门 + 基线 30 s | 10 min | §8.2,不满足就停 |
| 1 | 幅值轮(含 0.5 / 0.2 Vrms 加做) | 15 min | 主用例 |
| 2 | 波形轮(方波 / 三角,峰值对齐) | 15 min | 抬头里记万用表响应类型 |
| 3 | 谐波轮:段文件 `fft` 定量档 + UI 目检旁证(同一次注入触发一段) | 25 min | 命令见 §8.5 的谐波卡 |
| 4 | 相位轮:段文件相对相位档(`UA` / `UN` 同源,再移 90°) | 20 min | 定性档只在没取到段时退用 |
| 5 | 测频轮 A 档 | 5 min | 判"如实报不可测" |
| 6 | 削顶轮:50 Hz 档 + 改法 A + 改法 B + 复位复观(每档各触发一段) | 30 min | **单独一份日志**,判读规则见 §8.7 |
| 7 | 同一份接线下把 104 交叉读数复跑一遍 | 15 min | `test/host/iec104_master.py` |
| 8 | 取段与脚本产物归档(FTP `get` + `dump` / `fft` / `shape` / `plot`) | 15 min | 每段取完立刻改名,100 号轮转会覆盖 |
| — | (需用户点头)测频轮 B 档 / 相位轮抬倍数档 | +40 min | 各含一次重编、烧录与还原;段文件落地后相位轮这条基本不必走 |
| 0 | 前置门 + 基线 30 s | 10 min | §8.2,不满足先停 |
| 1 | 幅值轮(三档幅值) | 15 min | 先做 |
| 2 | 波形轮(方波 / 三角,峰值对齐) | 15 min | 记万用表响应类型 |
| 3 | 相位轮:段文件相对相位(`UA`/`UN` 同源,再改 90°) | 20 min | 没录到段文件时退心跳档 |
| 4 | 测频轮(判"如实报不可测") | 5 min | 现状就该不出数 |
| 5 | 削顶轮:50 Hz 对照 + 直流档 + 2 Hz 档 + 复位复核 | 30 min | **单独日志**,§8.7 |
| 6 | 谐波轮:段文件 `fft` + UI 旁证 | 25 min | §8.5 谐波卡 |
| 7 | 段文件取回 + 脚本归档(FTP + `dump`/`fft`/`shape`/`plot`) | 15 min | 取完立刻改名,100 号轮转 |
| — | 改固件的档:测频门限降到 `0.5f` / 相位串口行抬十倍读数分辨率 | +40 min | **这两档要改代码、重烧固件,动手前一定先问过用户**;各含重编 + 烧录 + 还原 |
合计约 **135 min**(不含"需用户点头"那两档)。取段与跑脚本集中在末尾第 8 行统一做,中间各条只负责"触发 + 让
`seg=` +1",免得一次 session 里反复插拔网线。
合计约 **135 min**(= 上表各行相加;不含"需用户点头"两档)。各步含换线/改设定/抄表的间隙,前后一步可留点重叠,实际往往用不满。段文件取回与脚本跑集中在第 7 步统一做,中间各步只"触发 + `seg=` +1",避免反复插拔网线。
### 8.7 `[ERR]` 的判读规则(削顶轮单独跑、单独归档)
### 8.7 `[ERR]` 判读与 `/serial-boot-test` forbidden 冲突说明(削顶轮单独一份日志)
- 削顶轮会**故意造出** `[ERR] rail: edge=… sticky=… (code-domain, 20-run+release)`,而 `/serial-boot-test` 的 forbidden 标记含
`[ERR]`(AGENTS.md「构建与验证」)→ **这一轮不要把 `/serial-boot-test` 的标记校验当结论**:改人工判读,并在归档文件名与
抬头里写明「预期 [ERR]:贴轨锁存负向用例」;§8.6 已把它排在最后单独一轮(`docs/任务规划/数据可信.md` §8 风险表「削顶负向用例被当成固件 bug」行同一条)。
- 除这一条 `[ERR] rail:` 之外,**任何 `[ERR]` 都是不通过**;四个 Fault 的崩溃日志也以 `[ERR]` 开头 →
出现 Fault 立即停线取现场(`docs/子系统设计/看门狗设计说明.md` §10),别再继续注。
- 每次开机 `rail:` 边沿只打一条、`SYSLOG` 也只留痕一次("adc code rail fault" 进 `selftest.log`)——这是设计不是漏报;
要看第二次边沿就复位一次。
- 削顶轮**故意造** `[ERR] rail: edge=… sticky=… (code-domain, 20-run+release)`,而 `/serial-boot-test` forbidden 含 `[ERR]`(AGENTS.md「构建与验证」)→ **别拿 `/serial-boot-test` 标记校验当结论**:改人工判读,归档写清"预期 [ERR]:贴轨锁存负向用例"(`docs/任务规划/数据可信.md` §8 风险表同一条)。
- 除这一条 `[ERR] rail:`,**任何 `[ERR]` 都是失败**;四个 Fault 崩溃日志也以 `[ERR]` 开头 → 出现 Fault 即本次不通过(`docs/子系统设计/看门狗设计说明.md` §10),别接着注入。
- 每次开机 `rail:` 沿只打一条、`SYSLOG` 只记一次(设计不是漏报);想看第二条沿就复位一次。
### 8.8 失败分诊(先查这一列,别急着改固件)
| 现象 | 先查 | 依据 |
|---|---|---|
| 与万用表差约 2 倍 | 发生器输出端接设成了 50 Ω | §8.2 表第 2 行 |
| 差约 5.3 倍,或数字带 6553.6 / 1241.2 的痕迹 | 拿错刻度,或把 `adc:` 的码值当 mV 读 | §2 两把尺子、§4「码是什么」 |
| `phasor` 行 `rms` 只有 10 格量级 | 正常(×0.1),不是 bug | §4 尾注、§8.1 |
| 非整 50 Hz 时 `meas:` 来回跳 | 预期:瞬时透传、200 ms 不是平均窗 → 改读 `freq(hb)` | `docs/任务规划/数据可信.md` §8 风险表 |
| 104 读数不动 | 每点 0.5 V / 0.005 A 变化死区(生效值 `App/algo/run_par.c`) | §8.5 的幅值卡坑 ② |
| 50 Hz 正弦注 `UB` 但 `rail` 不锁存 | **预期**(连续贴底不足 20 拍)→ 改法 A / B | §8.5 的削顶卡 |
| 改 DC 也不锁存 | 释放沿前提没满足:开机后该通道没出现过中带样本 → 先建基线再注入 | `App/algo/adc_health.c`、§8.2 前置门末条 |
| 撤掉注入后 `rail` 仍非 0 | 锁存语义(sticky),只 `adc_health_rail_init()` / 复位清 → 复位后仍不清**才是** bug | §8.5 的削顶卡改法 A |
| 读数带与幅度无关的偏置或漂移 | 共地 / 地环 | §8.2 末行 |
| `meas: seq` 不涨 | 发布闸门停 → 先查采集链,别判交流 | §8.2 前置门 |
| `health:` 或 `sampling fault:` 亮 | 与注入的波形无关:`adc_health` 的位只吃序号差、错误计数增量与 tick 差(`App/algo/adc_health.c:91-189`)→ 查节拍 / 丢帧,别查发生器 | §8.2 前置门 |
| 9 路全 0 | 读作"没数据",不是"输入为零" | §4 尾注 |
| `wave_read.py` 报错退出 / 拒绝出图 | **这是正确行为**:CRC 不符或零长度它必须拒收而不是画出东西 → 重取一份、核对是不是搬到一半的半成品;仍拒收就 `dump` 看两处 CRC16 哪个不符 | `test/host/wave_read.py` 文件头 |
| `shape --strict` 说实测与段头不等 | 先分清尺子:段头 `CLIPPED` 位来自**通道来源、从不实测**;DC 偏置 / 极小注入 / 未驱动通道应改用 `--clip-superset` | §8.5 的削顶卡段文件档 |
| 触发后 `seg=` 不涨或 `drop` / `ovf` 涨 | 落盘道在 defaultTask 卷空闲后才搬段,先等几秒;仍不涨查 `wave:` 行三计数与 `/wave` 目录可写(`[ftp]` 写权限) | `App/task/adc_task.c:782` |
| 与万用表差约 2 倍 | 发生器输出端接设成 50 Ω | §8.2 表第 2 行 |
| 差约 5.3 倍,或数带 6553.6 / 1241.2 痕迹 | 拿错刻度尺,或把 `adc:` 码值当 mV 读 | §2 两把尺子、§4「码是什么」 |
| `phasor` 行 `rms` 只 10 格量级 | 正常(×0.1),不是 bug | §4 尾注、§8.1 |
| 非整 50 Hz 时 `meas:` 拍频式跳动 | 预期:瞬时透传、200 ms 不是平均窗 → 改读 `freq(hb)` | `docs/任务规划/数据可信.md` §8 风险表 |
| 50 Hz 正弦注 `UB` 但 `rail` 不锁存 | **预期**(连续贴底不足 20 拍)→ 改用直流档或 2 Hz 档重注 | §8.5 削顶卡 |
| 改 DC 也不锁存 | 释放沿前提没满足:开机后该路从未出现中带样本 → 先建基线再注 | `App/algo/adc_health.c`、§8.2 前置门末条 |
| 撤掉注入后 `rail` 仍非 0 | 锁存语义(sticky),只 `adc_health_rail_init()` / 复位才清 → 复位后仍不清**才是** bug | §8.5 削顶卡直流削顶档 |
| 读数带与幅值无关的偏移或漂移 | 共地 / 地环 | §8.2 共地行 |
| `meas: seq` 不涨 | 发布闸门停 → 先查采集链,别判波形 | §8.2 前置门 |
| `health:` 或 `sampling fault:` 亮 | 与注入波形无关:`adc_health` 的位只吃序号差、错误计数增量与 tick 差(`App/algo/adc_health.c:91-189`)→ 查节拍 / 丢帧,别查发生器 | §8.2 前置门 |
| 9 路全 0 | 读作"没数据",不是"输入零" | §4 尾注 |
| `wave_read.py` 报错退出 / 拒画 | **这是正确行为**:CRC 不符或零长度必须拒收而不是画出半张图 → 取回一段、查是不是传输半品;仍拒 `dump` 看双 CRC16 哪个不符 | `test/host/wave_read.py` 文件头 |
| `shape --strict` 说实测与段头不等 | 先分量具:段头 `CLIPPED` bit 是**来源派生、从不实测**;DC 偏移 / 极小注入 / 非驱动通道该换 `--clip-superset` | §8.5 削顶卡段文件档 |
| 触发后 `seg=` 不涨或 `drop`/`ovf` 涨 | 落盘路径在 defaultTask、卷空闲后才搬段,先等几秒;仍不涨查 `wave:` 行三个计数与 `/wave` 目录可写(`[ftp]` 写权限) | `App/task/adc_task.c:782` |
### 8.9 收尾判据(走过临时改动的一条都不许留)
### 8.9 还原与收尾清单(临时改动一律还原)
| 临时改动 | 收尾判据 |
| 临时改动 | 还原判据 |
|---|---|
| 测频轮 B 档:`FREQ_AMP_MIN` 50.0f → 0.5f(`App/algo/freq.h:62`) | 还原 + `/keil-build` 0 错误 0 警告 + **`git diff` 里 `App/algo/freq.h` 必须为空** + 在 `docs/任务规划/数据可信.md` §7 #8 那行留一句"本轮台架已还原" |
| 相位轮改倍数:`log_phasors()` 的 `* 10.0f` → `* 1000.0f`(`App/task/adc_task.c:209`) | 同上,`git diff` 里 `App/task/adc_task.c` 必须为空 |
| 为 bench 定时自抓开过编译门(`DTU_BENCH` + `WAVE_BENCH_AUTOCAP` 非 0,`App/task/adc_task.c:153`) | 还原成默认 0 + `/keil-build` 0 错误 0 警告 + `git diff` 里 `App/task/adc_task.c` 必须为空(产品镜像里这段必须零存在) |
| 只动接线与发生器、没动代码 | `git status` 除归档目录外干净 |
| 全程 | `test/board/test_config.h` 四个套件宏保持全注释(产品构建);烧录仍须 `-Rst -Run` + 回读校验 |
| 测频轮改码档:`FREQ_AMP_MIN` 50.0f → 0.5f(`App/algo/freq.h:62`) | 还原 + `/keil-build` 0 错 0 警 + `git diff` 的 `App/algo/freq.h` 为空 + `docs/任务规划/数据可信.md` §7 #8 留"本轮台架已还原" |
| 相位轮抬倍数:`log_phasors()` `* 10.0f` → `* 1000.0f`(`App/task/adc_task.c:209`) | 同上,`git diff` 的 `App/task/adc_task.c` 为空 |
| bench 定时自抓门(`DTU_BENCH` + `WAVE_BENCH_AUTOCAP` 非 0,`App/task/adc_task.c:153`) | 还原默认 0 + `/keil-build` 0 错 0 警 + `git diff` 的 `App/task/adc_task.c` 为空 |
| 只动接线与发生器 | `git status` 除归档目录外干净 |
| 全程 | `test/board/test_config.h` 四套件宏全注释(产品构建);烧录 `-Rst -Run` + 回读校验 |
### 8.10 归档与回写(跑完必做,缺一算没收尾)
### 8.10 归档与回写(跑完必做,缺一条不算收尾)
1. **证据归档** → `docs/测试说明/测试数据/boot_log_data/`,沿用现有命名惯例(日期_主题_类型.txt):
`20261104_ac_amp_meas_log.txt`、`20261104_ac_clip_rail_log.txt`、`20261104_ac_iec104_log.txt`;UI 目检照片同目录
(该目录若不收图,就在抬头里写清照片存放位置)。**走段文件定量档的用例另加两样**:取回的段原件(原始字节,
`20261104_ac_phase_wave<nn>.BIN`)与脚本输出(`fft` / `shape` / `dump` 三份文本 + `plot` 的图)——定量档的证据本体是
**那一段原始码值**,日志只是旁证;段原件一旦覆盖就再也拿不回来,先改名再触发下一段。
2. **实测结论回写** → `docs/硬件平台/ADC通道映射说明.md`,在 §8.1(直流轮次)之后**新开一节**——
任务卡 `docs/任务规划/数据可信.md` §5 的 DoD 就是这么分的。本文只留"怎么跑",**不抄实测数**。
3. **本文回写** → 只在 §8.1 那张表下加一行指针级别的句子("YYYY-MM-DD 已按本节跑通,实测见 …");
不在本文建第二份结论表,否则两份必然漂移(`docs/文档规范.md` 同一事实只在一处详述)。
4. **判据文档的一致性维护** → 本文 §8 的期望值算术、接法与出口分档已写进
`docs/任务规划/数据可信.md` §4.6.2(2026-10-29:波形轮的逐波形系数、削顶轮的 DC / 2 Hz 接法与 50 Hz 档的
"不锁存属预期"、相位轮与谐波轮的"定量档走段文件、定性档走 `phasor(hb)`")。今后两边若再分叉,按开头引导块的
两类裁定处理(语义从那节、算术与步骤从本文),**别在本文另立第二份判据表**。
5. **销项** → `docs/任务规划/数据可信.md` §2.7 与 §6 卡片表里这一条按登记簿「完成即销项」处理,属 Ask first,
须用户明确指示后再做。
1. **证据归档** → `docs/测试说明/测试数据/boot_log_data/`(日期_主题_类型.txt):`20261104_ac_amp_meas_log.txt`、`20261104_ac_clip_rail_log.txt`;UI 照片同目录。**录波档多用例多带两份**:段原件(`20261104_ac_phase_wave<nn>.BIN`)+ 脚本输出(`fft`/`shape`/`dump` 文本 + `plot` 图)——录波档证据本体是**那段原始码值**,日志只是旁证;段原件被覆盖就取不回来,先改名再触发下一段。
2. **实测结论回写** → `docs/硬件平台/ADC通道映射说明.md` §8.1 之后**新开一节**(`docs/任务规划/数据可信.md` §5 DoD 这么分)。本文只留"怎么跑",**不抄实测数**。
3. **本文回写** → 只在 §8.1 表下加一句指针("YYYY-MM-DD 已跑通,实测见 …");**不建第二份结论表**(`docs/文档规范.md` 同一事实只详述一处)。
4. **判据一致性** → 本文 §8 期望值算术、接法与证据分档已写进 `docs/任务规划/数据可信.md` §4.6.2(2026-10-29)。再分叉按开头指引块裁定(语义从那节、算术与步骤从本文),**不在本文建第二份判据表**。
5. **销项** → `docs/任务规划/数据可信.md` §2.7 与 §6 卡片表按"完成即删",属 Ask first,须用户指示。
### 8.11 这一轮证不到(别让读数长得像证据)
### 8.11 这一轮证不到什么(别把读数当证据)
`docs/任务规划/数据可信.md` §4.6.5 那张五行表整条适用(端子二次值 / 精度等级 / 跨转换器相位与功率与对称分量 /
THD 与谐波方和根 / 温升 EMC 长时间漂移)只适用,本节按出口已落地改三条现状(2026-10-29 录波数据面并入主干之后):
**样本出口已成立**(`/wave/WAVE<NN>.BIN` + `test/host/wave_read.py`)→ 相位轮 / 谐波轮走定量档时结论是**形状级**,不再只是标量级;
但**板级那一轮对表本身还没跑过**(判据见 `docs/子系统设计/故障录波设计说明.md` §10),本轮跑出来的就是第一批实测;
段与发生器**没有绝对相位锁定**(触发瞬间只钉在段内点 159)→ 能核的是同段内两路的**相对**相位与极性,
全局相角基准仍证不到;一次触发只有 320 点 = 320 ms,**不等于长时间稳定性**。示波器仍旧只作旁证、不进判据。
判据属主 `docs/任务规划/数据可信.md` §4.6.5(端子二次值 / 精度等级 / 跨转换器相位与功率与对称分量 / THD 与谐波根均方 / 温升 EMC 长时间漂移)。本节按录波能力落地改过三条(2026-10-29 并入录波数据面后):**录波段文件已可用** → 相位 / 谐波走录波档,结论**形状级**非标量级;**板端对表还没跑过**(`docs/子系统设计/故障录波设计说明.md` §10),本轮是第一份实测;**段与发生器无绝对相位锁定**(触发点在段内点 159)→ 只能比同段相对相位;**320 点 = 320 ms**,不等于长时间稳定性。示波器只作旁证。
再补一条「别把台架做成功能性重复」的边界:**算法本体的精度已经在纯数字域钉住了**——`test/host/phasor/phasor_test.c`
的 TC-PHASOR-003 与 TC-PHASOR-004(基波 = 峰值 / √2 容差 1 %、注入相角容差 0.5°)和 TC-PHASOR-006(2 / 3 / 5 次
谐波 1 %),以及 `test/host/freq/freq_test.c` 的扫频判据 J1(45~55 Hz 内 ≤0.02 Hz),都是把已知正弦**直接喂进
`sample_ring`**,绕过了 `adc_cal` 的折算(那里的幅值是工程量口径,不是引脚 µV)。所以 §8 这一轮真正要证的只有
「信号走到 `sample_ring` 之前」那一段:发生器刻度与输出端接、前端串阻与滤波电容的幅频、两片转换器的同刻性、
码到 mV 的折算、出口的量化。这一轮过了**不等于**「算法精度已实测验证」,结论里别那么写。
边界:**算法精度已在纯数字域钉住**——`test/host/phasor/phasor_test.c` TC-PHASOR-003/004/006、`test/host/freq/freq_test.c` J1,全把已知正弦直接灌 `sample_ring`、绕开 `adc_cal` 折算(幅值是工程量口径非引脚 µV)。§8 只证"信号到 `sample_ring` 之前":发生器刻度与端接、前端串阻与滤波电容幅频、两转换器同刻性、码到 mV 折算、各处打印的量化损失。过**不等于**"算法精度已实测验证"。
+23 -23
View File
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""生成 docs/images/交流六轮速查.svg —— 交流(正弦)动态验证六轮:每一轮注什么信号、
验什么、主读数走哪个出口,一张图先给全局轮廓,再进 §8.5 逐轮执行卡。
验什么、数字从哪儿读,一张图先给全局轮廓,再进 §8.5 逐轮执行卡。
为什么不用 Mermaid:本图的语义重心是「每轮注入信号的波形形状」与「三块小面板里
信号缩略图 + 判据 + 出口的固定排版对位」——Mermaid 画不出正弦/方波/三角/削顶/谐波
信号缩略图 + 判据 + 读数的固定排版对位」——Mermaid 画不出正弦/方波/三角/削顶/谐波
叠加这些波形,也无法把六格对齐成 3x2 卡片。它只适合关系拓扑(那部分另在
docs/测试说明/专项验证/ADC前端注入验证流程.md §8.3 / §8.5 用 Mermaid 表达)。
@@ -12,7 +12,7 @@ docs/测试说明/专项验证/ADC前端注入验证流程.md §8.3 / §8.5 用
python tools/arch_diagram/gen_ac_rounds_svg.py
输出:
docs/images/交流六轮速查.svg
改内容:轮次事实(接法 / 判据 / 出口)变了才重画;调坐标 / 文案编辑下方常量后重跑。
改内容:轮次事实(接法 / 判据 / 读数)变了才重画;调坐标 / 文案编辑下方常量后重跑。
"""
import html
import math
@@ -74,40 +74,40 @@ GAPY = 14
X0 = PAD
Y0 = 106
THUMB_H = 86
LABEL_W = 36 # 「注入 / 判据 / 出口」标签列宽
LABEL_W = 36 # 「注入 / 判据 / 读数」标签列宽
# ----------------------------- 数据(改这里) -----------------------------
TITLE = "交流动态验证六轮 —— 每一轮注什么信号、读哪个口"
SUB1 = ("一卡一轮:注入信号缩略图 → 接法与设定 → 判据一句话 → 主读数出口。"
SUB1 = ("一卡一轮:注入信号缩略图 → 接法与设定 → 判据一句话 → 数字从哪儿读。"
"先看图建立全局轮廓,再按 §8.5 的对应执行卡逐轮跑")
SUB2 = ("六轮共用同一套接线与通用动作;过判据的属主是 docs/任务规划/数据可信.md §4.6.2,"
"本图只是导航,不含新判据")
# 每卡:(轮名, 角标, 主色, 底色, 波形类型, 注入, 判据, 出口)
# 每卡:(轮名, 角标, 主色, 底色, 波形类型, 注入, 判据, 读数的地方)
CARDS = [
("幅值轮", "先做 · 主用例", C_BLUE, BG_BLUE, "amp",
"UA(R31)端子侧,正弦 50.000 Hz、1.000 Vrms",
"ua_mv 中位数 ≈ 万用表 × 1000,偏差 ≤2 %",
"meas: ua_mv 为主;104 0x4011 只作交叉读数"),
("波形轮", "真 RMS ≠ 基波", C_TEAL, BG_TEAL, "three",
"同峰值 1.414 V 改方波 / 三角(面板有效值各异)",
("幅值轮", "先做 · 三档幅度", C_BLUE, BG_BLUE, "amp",
"UA(R31)端子侧,正弦 50.000 Hz,三档 Vpp 2.828 / 1.414 / 0.566",
"每档 ua_mv ≈ 万用表 × 1000,偏差 ≤2 %",
"meas: ua_mv 为主(1 mV 分辨率)"),
("波形轮", "真有效值 ≠ 基波", C_TEAL, BG_TEAL, "three",
"同设 Vpp 2.828 V 改方波 / 三角(面板有效值各异)",
"读数只跟基波:方波 ≈1278、三角 ≈817,±2 %",
"meas: ua_mv;抬头记万用表响应类型"),
("相位轮", "定量 · 取段", C_GREEN, BG_GREEN, "phase",
"UA(R31)与 UN(R28)同源同幅 1.000 Vrms",
("相位轮", "定量 · 录波", C_GREEN, BG_GREEN, "phase",
"UA(R31)与 UN(R28)同源同幅 Vpp 2.828 V",
"同段内相位差 ≈0°,B 通道改 90° 应跟到 ≈90°,±2°",
"wave_read.py fft 定量;phasor(hb) 只核象限"),
("测频轮", "A 档无数 = 过", C_AMBER, BG_AMBER, "sweep",
"UA 同幅值轮接法,扫 45 / 50 / 55 Hz",
"A 档如实报不可测:valid=0、UI 显 --;报 50.00 反而是 bug",
"freq(hb) 0.01 Hz;UI Hz、104 0x401D"),
"freq(hb) 0.01 Hz;UI Hz"),
("削顶轮", "负向 · 单独日志", C_ROSE, BG_ROSE, "clip",
"UB(R52):DC −1.00 V 保持 ≥5 s,或 2.0 Hz 正弦",
"连续 20 拍贴底 → rail / edge 锁存 + 104 该路 IV 清零;50 Hz 正弦不锁存 = 预期",
"cal: rail / edge;取段再跑 shape 对表"),
("谐波轮", "定量 · 取段", C_PURPLE, BG_PURPLE, "harm",
"IA(R19):基波 0.800 + 二次 0.160 + 五次 0.160 Vrms",
"Ia2 / Ia5 各 ≈0.160 Vrms,±2 %(最坏峰值 1.58 V 留余量)",
"连续 20 拍贴底 → rail / edge 锁存;50 Hz 正弦不锁存 = 预期",
"cal: rail / edge;录波再跑 shape 对表"),
("谐波轮", "定量 · 录波", C_PURPLE, BG_PURPLE, "harm",
"IA(R19):分三注,基波 Vpp 2.263、二五次各 Vpp 0.453",
"Ia2 / Ia5 各读数 ≈0.160 V,±2 %(最坏峰值 1.58 V 留余量)",
"wave_read.py fft --ch 4;UI Ia2 / Ia5 目检旁证"),
]
@@ -203,7 +203,7 @@ def thumb(x, y, w, h, kind, c):
out.append(line(x + pad, yc - amp, x + w - pad, yc - amp, c, 1.0, dash="5 4"))
out.append(line(x + pad, yc + amp, x + w - pad, yc + amp, c, 1.0, dash="5 4"))
out.append(poly(_sample(lambda t: math.sin(2 * math.pi * 2 * t), ix, y + pad, iw, ih), c))
out.append(txt(x + pad, y + pad - 1, "峰 ±1.414 V · 基波 RMS 1.000 V", TINY_FONT, MUTED))
out.append(txt(x + pad, y + pad - 1, "峰 ±1.414 V · 基波有效值 1.000 V", TINY_FONT, MUTED))
elif kind == "three":
yc = y + h / 2.0
amp = ih * 0.36
@@ -217,7 +217,7 @@ def thumb(x, y, w, h, kind, c):
sx = ix + i * slot
out.append(poly(_sample(fv, sx + 6, y + pad, slot - 12, ih, n=120), c, 1.8))
out.append(txt(sx + slot / 2, y + h - 2, names[i], TINY_FONT, MUTED, anchor="middle"))
out.append(txt(x + pad, y + pad - 1, "同峰值对齐(不是同 Vrms)", TINY_FONT, MUTED))
out.append(txt(x + pad, y + pad - 1, "同设 Vpp 2.828 V(不是同有效值)", TINY_FONT, MUTED))
elif kind == "phase":
out.append(line(x + 4, y + h / 2, x + w - 4, y + h / 2, FAINT, 0.8, dash="3 3"))
out.append(poly(_sample(lambda t: math.sin(2 * math.pi * 1.5 * t), ix, y + pad, iw, ih),
@@ -290,7 +290,7 @@ def build():
add(el)
ty = cy + 36 + THUMB_H + 16
for label, s, mx in (("注入", inj, 2), ("判据", rule, 2), ("出口", ex, 2)):
for label, s, mx in (("注入", inj, 2), ("判据", rule, 2), ("读数", ex, 2)):
add(txt(cx + 12, ty, label, LABEL_FONT, c, weight=700))
for ln in wrap(s, BODY_FONT, body_avail, mx, "card %s %s" % (name, label)):
add(txt(body_x, ty, ln, BODY_FONT, INK if label == "判据" else MUTED))