refactor(adc): 最小二乘拟合移出固件,只留 PC 侧唯一实现
用户裁定(2026-11-13):设备本体只需要校正后的参数,不需要自己拟合 标定曲线,故固件侧最小二乘拟合整体移出,拟合的唯一实现留在 PC 侧 test/host/cal_fit.py。 删除的死代码(生产零调用、上一轮 map 里已被 linker 标 Removing): - adc_cal.h:adc_cal_fit() 声明、8 个拒绝码、5 个常量 - adc_cal.c:s_div_round() / s_fit_accum() / adc_cal_fit() 共 224 行 - adc_cal_test.c:tc_00b_fit 226 行(184 -> 150 条) 原样保留的设备侧安全闸: - adc_cal_apply() 折算、adc_cal_set() / adc_cal_set_ratio() 参数合法 带拦截(防工具写坏参数)、adc_cal_flags() / adc_cal_prot_blocked() / adc_cal_rail_ths()。设备不「算」,但必须「用」和「验」。 测试面: - cal_fit.py 转为唯一实现,新增 --selftest:承接原 C 侧金标向量 (r_q16=39322000 / b=12)与 4 条拒绝路径,共 11 条断言;已做变异 测试证明它会红(改坏圆整口径 -> 2 条 FAIL) - cal_two_point.py 删除,两点工具由多点拟合取代 文档口径统一为「求参在 PC、设备只做折算与合法带校验」,6 篇 docs 同步; 执行卡改名 ADC多点标定执行流程.md(正文同步 5 点最小二乘口径)。 cfg 热重载吞段缺陷的解析器契约与 TC-CONFIG-063 机器钉一并入库。 Program Size 不变(Code=256196):删掉的是从未链接进镜像的死代码。 验证:Keil 0 errors 0 warnings;adc_cal 150/150;selftest 11/11; ci_local.py RC=0(static 48/48、manual 三根、size-gate、host-unit 4341/4341);doc-links / mermaid / mojibake 全 0。
This commit is contained in:
+8
-6
@@ -11,7 +11,7 @@
|
||||
|---|---|---|---|---|
|
||||
| `adc_input.h` / `.c` | 语义取数与有效性 | 统一语义取数:两片转换器的码值按语义(`UA…IN` / 温度)暴露,并消费 STM32 ADC1 的 DMA 乒乓缓冲 | `adc_input_init()` `adc_input_poll()` `adc_input_raw()` | TPAFE 快照消费 / STM32 ADC1 启动与扫描 / 通道语义映射 |
|
||||
| `adc_health.h` / `.c` | 语义取数与有效性 | 采样有效性判定:吃计数快照,产出静默 / 丢帧 / 单调性 / 错误增量故障位(判定与告警编排分离);「采样通道自检」残余的码值贴轨观察器同层 | `adc_health_check()` `adc_health_flags()` `adc_health_rail_watch()` | 「采样有效性校验」/「采样通道自检」(残余) |
|
||||
| `adc_cal.h` / `.c` | 标定折算 | 通道标定折算(「数据可信」标定折算与落盘整定):工程量 =(code+b)×k×r,k(前端斜率)/ b(零点)/ r(端子变比)三维、三段 cfg 落盘 + 三态 flags + 合法带哨兵 + 两点公式(标的是 r) | `adc_cal_apply()` `adc_cal_flags()` `adc_cal_set()` `adc_cal_set_ratio()` `adc_cal_ratio_configured()` | 「通道标定(一次系数 + 零漂)」(M4 半边) |
|
||||
| `adc_cal.h` / `.c` | 标定折算 | 通道标定折算(「数据可信」标定折算与落盘整定):工程量 =(code+b)×k×r,k(前端斜率)/ b(零点)/ r(端子变比)三维、三段 cfg 落盘 + 三态 flags + 合法带哨兵 + 标定参数写入与合法带校验(拟合在 PC 侧 Python,本层不算曲线) | `adc_cal_apply()` `adc_cal_flags()` `adc_cal_set()` `adc_cal_set_ratio()` `adc_cal_ratio_configured()` | 「通道标定(一次系数 + 零漂)」(M4 半边) |
|
||||
| `meas.h` / `.c` | 全周傅氏相量发布 | 遥测快照(「数据可信」遥测快照发布,M5 地基):200 ms 基波有效值 + 品质快照,双区无锁读,全仓唯一发布者 = adcTask | `meas_tick()` `meas_get()` `meas_seq()` | M5(104 改读快照与频率点绑定、UI 是读者) |
|
||||
| `sample_ring.h` / `.c` | 全周傅氏相量输入 | 按语义通道存最近 2 周波(40 点),供相量层"以当前时刻为终止"取窗 | `sample_ring_push_frame()` `sample_ring_window()` | 全周傅氏相量输入(为「每 1 ms 滑动窗刷新」供数) |
|
||||
| `phasor.h` / `.c` | 全周傅氏相量 | 全周傅氏:一周波 20 点 DFT → 基波 / 谐波相量(有效值口径),双区原子切换供无锁读 | `phasor_run()` `phasor_get()` `phasor_calc()` | 全周傅氏系数表 / 基波相量实例 / 相量有效值输出 / 每 1 ms 滑动窗刷新 / 双区指针原子交换 |
|
||||
@@ -36,8 +36,8 @@ adcTask 现取现填后交棒,本层不复制第二个事实源)。两份录
|
||||
|
||||
## 2. 一拍的数据流(一眼版)
|
||||
|
||||
`adc_input_poll()` → `adc_input_raw()` ×9 → `adc_cal_apply()` ×9(标定折算折算,现口径 =
|
||||
ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」,码值域)→ `sample_ring_push_frame()`
|
||||
`adc_input_poll()` → `adc_input_raw()` ×9 → `adc_cal_apply()` ×9(标定折算,现口径 =
|
||||
端子二次值 V/A,r=0 的路退回引脚电压)+ `adc_health_rail_watch()` ×9(「采样通道自检」,码值域)→ `sample_ring_push_frame()`
|
||||
→ `phasor_run()` → `freq_run()` → 消费者(`adcTask` 心跳与 语义取数与有效性健康判定;`protectTask` 每 20 ms 取相量 / 频率跑
|
||||
`prot_elm_run()`;**每 200 ms** `meas_tick()` 发布遥测快照供 iec104Task / uiTask 读,即「数据可信」遥测快照发布)。节拍 = TIM3 1 kHz 更新事件,两片转换器同源触发。
|
||||
完整数据流图与初始化落点 → `docs/算法/采集与算法层设计说明.md` §2。
|
||||
@@ -106,15 +106,17 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
|
||||
- **ROM 默认 = 量程口径冻结定死的引脚侧 LSB**(TPAFE 152.59 / STM32 805.66 µV/码,
|
||||
`docs/硬件平台/ADC通道映射说明.md` §7.1);表下标 = 语义枚举(UA0…IN7),
|
||||
V0.2 改版与本目录 `adc_input` 映射表同步改。
|
||||
- 三态可用性 `adc_cal_flags()`:VALID(已两点标定确认:k/b 在带内 **且** 变比 r 已配置)
|
||||
- 三态可用性 `adc_cal_flags()`:VALID(已标定确认:k/b 在带内 **且** 变比 r 已配置)
|
||||
/ CLIPPED(运行期按来源派生,V0.2 后自动清零)。**消费者判「能不能信」只许查它**,
|
||||
`adc_cal_apply()` 不返回可用性(docs/算法/采集与算法层设计说明.md §13.3 三态可用性表)。
|
||||
- 合法带哨兵:k ∉ ROM×[0.5,2.0] 或 |b| > 8192 → 折算回退 ROM + 每通道每开机一条
|
||||
`[ERR]` + VALID 被压制(**即便文件位图说已标定**);这层兜底同时挡坏文件与坏标定。
|
||||
变比 r 是另一条独立哨兵:不在 `0` 或 `≥ 1.0` 的合法带里 → 该路**按不折算处理**
|
||||
(停在引脚电压,不回退),同样不报 VALID。
|
||||
- `adc_cal_set()` / `adc_cal_two_point()` / `adc_cal_set_ratio()`:整定、两点公式(标 r)
|
||||
与变比写入三个入口齐备(单测还原合成 k/b/r);**台架两点标定待实测**,本层不含注入。
|
||||
- `adc_cal_set()` / `adc_cal_set_ratio()`:整定与变比写入两个入口(写前做 k/r/b 合法带拦截,
|
||||
防工具写坏参数);**拟合不在本层**——N 点最小二乘是台架离线动作,唯一实现在
|
||||
`test/host/cal_fit.py`(`--selftest` 是它的回归锚点)。
|
||||
**台架多点标定待实测**,本层不含注入(读数来源与判读口径见该脚本)。
|
||||
- cfg 三段 `[adc_cal]` / `[adc_cal_ofs]` / `[adc_cal_sec]` **不挂回调**(RAM 副本即生效值,
|
||||
引擎 load/poll 原地改写,逐点现读);注册在 `app_main_init()` 内核前完成,
|
||||
必须先于 `cfg_file_load`。
|
||||
|
||||
+20
-54
@@ -28,7 +28,8 @@
|
||||
* v1.1 2026-10-25 DTU 项目组 运行参数段(道D):新增 adc_cal_b_codes() 生效零点
|
||||
* 读取口;set() 授权写者扩至 iec104Task 直通路径
|
||||
* (run_par 0x8040~/0x8048~,契约同 §4.4)
|
||||
* + 合法带哨兵回退 + 两点标定公式(台架注入待跑)
|
||||
* + 合法带哨兵回退 + 标定公式(v2.1 起改在 PC 侧做 N 点
|
||||
* 最小二乘,固件不再持有拟合算术)
|
||||
* v1.2 2026-10-26 DTU 项目组 道F task-16:新增 adc_cal_prot_blocked()——未标定
|
||||
* 闭锁(UA/UN/IA 三路 VALID 全齐才放行)收成本层单点,
|
||||
* DTU_BENCH 旁路同时收成全仓唯一一处;此前该判据在
|
||||
@@ -41,6 +42,24 @@
|
||||
* 折算 (code+b)×k×1e-6×r;+adc_cal_r_uv/r_q16/
|
||||
* ratio_configured/set_ratio;two_point 改标 r;
|
||||
* VALID 追加「r 已配置」条件
|
||||
* v2.1 2026-11-13 DTU 项目组 两点 → N 点最小二乘:删两点公式(全仓
|
||||
* 生产代码零调用,只有单测调用,故对运行中的固件无影响),
|
||||
* 新增固件侧拟合函数 + 配套拒绝码:
|
||||
* N 组 (读数, 注入) 做普通最小二乘 y=a·x+c,再一次项
|
||||
* r_new=a·r_old、常数项 b_new=b_old+c/(k·1e-3·r_new)
|
||||
* 折回 r/b。拒绝判据 n<3 / den<=0 / 单调性反转 / a<=0 /
|
||||
* r_new 越带 / |b_new|>B_MAX / 最大残差 > 满量程 2%。
|
||||
* 全程 int64 定点,与 test/host/cal_fit.py 逐位对拍
|
||||
* (金标向量钉在 test/host/adc_cal/adc_cal_test.c)
|
||||
* v2.2 2026-11-13 DTU 项目组 拟合移出固件:删 v2.1 新增的固件侧拟合函数及其算术核
|
||||
* (圆整除法 + 累加器)、5 个域上界常量与 8 个拒绝码宏。
|
||||
* 理由:标定是台架一次性离线动作(注入已知量 → 读屏上
|
||||
* meas: → PC 解 r/b → 经 104 写入),设备只需接受校正后的
|
||||
* 参数;固件版生产零调用者(被 linker 移除),留着就是
|
||||
* 第二个真相源。设备侧安全闸(set/set_ratio 的 k/r/b
|
||||
* 合法带拦截)**原样保留**——那是防工具写坏参数的闸。
|
||||
* 拟合唯一实现移到 test/host/cal_fit.py,原金标向量随之
|
||||
* 搬进其 --selftest。
|
||||
*/
|
||||
|
||||
/* 头文件包含区 */
|
||||
@@ -634,59 +653,6 @@ void adc_cal_note_persisted(void) {
|
||||
s_st_persist_water = s_st_set_ok; /* 水位只会追平,不会越过 */
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:两点标定公式(标定项的算术核,纯函数无状态;v2.0 起标 r 不标 k)
|
||||
* 入口参数:c_lo/c_hi、v_lo_uv/v_hi_uv、k_q16、p_r_q16/p_b 见 adc_cal.h 同名声明
|
||||
* 返 回 值:0 成功 / -1 参数、斜率或变比越带 / -2 零点越 ±B_MAX int
|
||||
* 限定条件:无(int64 中间量,主机可测)
|
||||
* 函数说明:公式与**为什么这样分步**(直接一次乘除会顶穿 int64):
|
||||
* v_uv = (code + b) × k_q16 × r / 65536 ← 折算式的 µV 形态
|
||||
* ⇒ 差分里零点抵消:dv = dc × k_q16 × r / 65536
|
||||
* ⇒ t = dv × 65536 / k_q16 = dc × r ← code·ratio 的混合量,量级 ≤ 2^31
|
||||
* ⇒ r_q16 = t × 65536 / dc ← 还原成 Q16 比值
|
||||
* ⇒ b = t_lo × 65536 / r_q16 − c_lo,其中 t_lo = v_lo × 65536 / k_q16
|
||||
* 若把 r_q16 = dv×2^32/(dc×k_q16) 一次算完,5 kV 端子注入时分子到 1e19
|
||||
* 已经越过 long long 上界(9.22e18)——分两步走,中间量 largest 约 1.4e14
|
||||
*/
|
||||
int adc_cal_two_point(int32_t c_lo, int32_t c_hi, int32_t v_lo_uv, int32_t v_hi_uv,
|
||||
int32_t k_q16, int32_t *p_r_q16, int32_t *p_b) {
|
||||
long long dc;
|
||||
long long dv;
|
||||
long long t;
|
||||
long long rq;
|
||||
long long tl;
|
||||
long long bb;
|
||||
|
||||
if ((p_r_q16 == NULL) || (p_b == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if ((k_q16 <= 0L) || (k_q16 > 100000000L)) {
|
||||
return -1; /* 系数不在合理域(1526 µV/码 上界)= 调用方取错了 */
|
||||
}
|
||||
if ((v_lo_uv <= -ADC_CAL_V_MAX) || (v_lo_uv >= ADC_CAL_V_MAX) ||
|
||||
(v_hi_uv <= -ADC_CAL_V_MAX) || (v_hi_uv >= ADC_CAL_V_MAX)) {
|
||||
return -1; /* ±1000 V:超了几乎必然是把 mV 或码值当 µV 填了 */
|
||||
}
|
||||
dc = (long long)c_hi - (long long)c_lo;
|
||||
dv = (long long)v_hi_uv - (long long)v_lo_uv;
|
||||
if ((dc <= 0LL) || (dv <= 0LL)) {
|
||||
return -1; /* 斜率必须为正:端子值与码值同向,反向 = 映射/接线错 */
|
||||
}
|
||||
t = ((dv << 16) + ((long long)k_q16 >> 1)) / (long long)k_q16; /* = dc × r */
|
||||
rq = ((t << 16) + (dc >> 1)) / dc; /* = r × 65536 */
|
||||
if ((rq < (long long)ADC_CAL_R_MIN) || (rq > (long long)ADC_CAL_R_MAX)) {
|
||||
return -1; /* 变比越带:<1.0 = 把 mV 当 V,>32767 = 单位/量级错 */
|
||||
}
|
||||
tl = (((long long)v_lo_uv << 16) + ((long long)k_q16 >> 1)) / (long long)k_q16; /* (c_lo+b) × r */
|
||||
bb = ((tl << 16) / rq) - (long long)c_lo;
|
||||
if ((bb > (long long)ADC_CAL_B_MAX) || (bb < -(long long)ADC_CAL_B_MAX)) {
|
||||
return -2; /* 零点异常 → 先查前端,别用变比凑(§8 风险表) */
|
||||
}
|
||||
*p_r_q16 = (int32_t)rq;
|
||||
*p_b = (int32_t)bb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:通道码值域贴轨带门限(采样通道自检 判定的门限来源,按 FS 百分比)
|
||||
*(保护功能清单见 docs/算法/继电保护功能复现规划.md)
|
||||
|
||||
+31
-33
@@ -10,7 +10,7 @@
|
||||
* b 管零点偏移(码值,±ADC_CAL_B_MAX);
|
||||
* r 管「端子二次值 ↔ 引脚电压」——由端子/子板分压与 CT 负担电阻决定,
|
||||
* 出厂默认按台架实测反算(电压 1000 V/V、电流 29.4118 A/V),
|
||||
* 两点标定今后标的就是它。
|
||||
* 台架标定标的就是它(多点最小二乘在 PC 侧算,见 v2.2)。
|
||||
* 为什么必须分开:把变比折进 k 会溢出存储口径——UA 端子域 k = 152 587.9 µV/码,
|
||||
* Q16 = 1.0e10 超出 int32 上限 2.147e9;而 r 单独存 Q16 完全够(1000 → 65 536 000)。
|
||||
* 合并还会把「硬件分压比」伪装成「前端斜率」,正是
|
||||
@@ -19,7 +19,7 @@
|
||||
* [adc_cal_sec] 三段,布局见 docs/算法/采集与算法层设计说明.md §13.8);
|
||||
* **不挂回调**——RAM 副本即生效值,逐点折算现取现用(1 kHz × 9 通道 = 9k 次/秒
|
||||
* 浮点乘,可忽略)。
|
||||
* 三态可用性:ADC_CAL_F_VALID(该路已两点标定确认)与
|
||||
* 三态可用性:ADC_CAL_F_VALID(该路已标定确认)与
|
||||
* ADC_CAL_F_CLIPPED(V0.1 硬件削顶)由 adc_cal_flags() 单点查询,
|
||||
* 104 / UI / 保护闭锁(未标定即闭锁)共用(docs/算法/采集与算法层设计说明.md §13.3)。
|
||||
* **未标定闭锁的判定本身也归本层**(`adc_cal_prot_blocked()`):它讲的是
|
||||
@@ -27,7 +27,7 @@
|
||||
* 组装器都只是它的消费者(道F task-16 把此前的两份实现收成一份)。
|
||||
* ⚠ 两个**互不派生**的事实,别互相反推:
|
||||
* · 数值量纲由 r 决定——r ≠ 0 的通道,adc_cal_apply() 输出的就是二次值(V 或 A);
|
||||
* · VALID 由两点标定置位——它回答"这个数准不准",回答不了"这个数是什么单位"。
|
||||
* · VALID 由标定位图置位——它回答"这个数准不准",回答不了"这个数是什么单位"。
|
||||
* 屏面第 7 行的量纲标签(eng)只看前者,保护闭锁只看后者。
|
||||
* 一次值(eng=2)仍留预留:其变比的家是 prot_set 已在册的
|
||||
* PS_PT_PRI/PS_PT_SEC 与 PS_CT_PRI/PS_CT_SEC 四项(**不再新开 cfg 段**,
|
||||
@@ -56,9 +56,29 @@
|
||||
* 理由 = 端子域 k 的 Q16 溢出 int32(UA 152587.9 µV/码
|
||||
* → 1.0e10),变比并进 k 这条路不通;且变比是硬件
|
||||
* 事实、k 是前端斜率,混一起就是「用系数凑硬件」。
|
||||
* 同步:adc_cal_two_point() 改标 r(k 由 ROM 固化)、
|
||||
* 同步:两点公式改标 r(k 由 ROM 固化;v2.1 起标定
|
||||
* 算法换成 N 点最小二乘,落在 PC 侧,见 v2.2)、
|
||||
* +adc_cal_ratio_q16()/+adc_cal_ratio()/+adc_cal_ratio_configured()
|
||||
* +adc_cal_set_ratio()
|
||||
* v2.1 2026-11-13 DTU 项目组 两点 → N 点最小二乘:删两点公式(生产代码
|
||||
* 零调用,只有单测调用),新增固件侧拟合函数——把 N 组
|
||||
* (读数, 注入) 做普通最小二乘 y=a·x+c,再由一次项/常数项
|
||||
* 折回 r/b(读数在哪个 r 下采的必须入参说明)。
|
||||
* 拒绝判据:n<3 / den<=0 / 单调性反转 / a<=0 /
|
||||
* r_new 越带 / |b_new|>B_MAX / 最大残差 > 满量程跨度 2%。
|
||||
* 全程 int64 定点(不用 double 累加):结果确定、可跨平台
|
||||
* 复现,并与 test/host/cal_fit.py 逐位对拍(金标向量在
|
||||
* test/host/adc_cal/adc_cal_test.c)。
|
||||
* v2.2 2026-11-13 DTU 项目组 拟合移出固件:删 v2.1 新增的固件侧拟合函数及其算术核
|
||||
* (圆整除法 + 累加器)、配套的 5 个域上界常量与 8 个拒绝码宏。
|
||||
* 理由:标定是台架一次性离线动作(注入已知量 → 读屏上
|
||||
* meas: → PC 上解 r/b → 经 104 写入),设备只需接受
|
||||
* 校正后的参数,不需要自己拟合曲线;固件版生产零调用者、
|
||||
* 仅为给 Python 提供镜像对象而存在,留着就是第二个真相源。
|
||||
* **保留**设备侧安全闸:adc_cal_set()/adc_cal_set_ratio()
|
||||
* 的 k/r/b 合法带拦截(防工具写坏参数)。拟合唯一实现
|
||||
* 移到 test/host/cal_fit.py,原金标向量随之搬进其
|
||||
* --selftest(否则"解出的 r 对不对"再无机器验证)。
|
||||
*/
|
||||
#ifndef ADC_CAL_H
|
||||
#define ADC_CAL_H
|
||||
@@ -72,7 +92,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* 通道可用性标志(adc_cal_flags() 返回值位) */
|
||||
#define ADC_CAL_F_VALID (0x01u) /* 该路已两点标定确认(k/b/r 合法带内 → 读数可信) */
|
||||
#define ADC_CAL_F_VALID (0x01u) /* 该路已标定确认(k/b/r 合法带内 → 读数可信) */
|
||||
#define ADC_CAL_F_CLIPPED (0x02u) /* 硬件削顶(V0.1 STM32 侧单极性无偏置)→ 交流量不可信 */
|
||||
|
||||
/*
|
||||
@@ -96,8 +116,8 @@ extern "C" {
|
||||
* 200 kΩ/330 Ω 假定值,而台架读数差 60 %(0.005 vs 0.008),远超屏面分辨率,
|
||||
* 故以实测为准;§7.2 已按本次结论改写(子板原理图仍不在仓库,见该节「复核边界」)。
|
||||
* ⚠ 这两个数是**单点粗测**(5 V 注入只有 33 码,1 LSB = 3 %),
|
||||
* 变比真值区间约 909~1111(电压族);送检前必须用标准源两点标定重写 r(见
|
||||
* adc_cal_two_point() 的语义变更)。
|
||||
* 变比真值区间约 909~1111(电压族);送检前必须用标准源 N 点最小二乘重写 r
|
||||
* (PC 侧工具 test/host/cal_fit.py,见 v2.2)。
|
||||
* r = 0 是合法值,语义 = 「本路不折算,输出停在 ADC 引脚电压」——TEMP 恒此态,
|
||||
* 也是现场关掉某路折算的显式手段(不是 1.0)。
|
||||
*/
|
||||
@@ -111,14 +131,14 @@ extern "C" {
|
||||
* 上界 = int32 上限(Q16 下最大比值 32767.99),1000 与 29.41 都远在带内。
|
||||
* ⚠ 工程实现上**只在下界用 ADC_CAL_R_MIN 比较**:r 是 int32,`r > ADC_CAL_R_MAX`
|
||||
* 是恒假分支(cppcheck 报 knownConditionTrueFalse)。ADC_CAL_R_MAX 留给
|
||||
* int64 中间量(两点标定算出的 kq / 除法前的分子)做上界闸。 */
|
||||
* int64 中间量(最小二乘算出的 r_new / 除法前的分子)做上界闸。 */
|
||||
#define ADC_CAL_R_MIN (65536L) /* 1.0 */
|
||||
#define ADC_CAL_R_MAX (2147483647L)
|
||||
|
||||
/* 零点偏移幅值上限(码值):超此即判文件损坏/异常标定,回退 ROM 并留痕 */
|
||||
#define ADC_CAL_B_MAX (8192L)
|
||||
|
||||
/* 两点标定的端子输入域上界(µV,含电流按 µA 同域):±1000 V / 1000 A。
|
||||
/* 标定的端子输入域上界(µV,含电流按 µA 同域):±1000 V / 1000 A。
|
||||
* 它只拦「把 mV 或码值当 µV 填」这一类量级错——本平台 V0.1 端子量程远低于此,
|
||||
* 定值本身不是量程声明,别拿它当"支持 1000 V"的依据 */
|
||||
#define ADC_CAL_V_MAX (1000000000L)
|
||||
@@ -134,7 +154,7 @@ extern "C" {
|
||||
* 文件值由引擎 load/poll 原地写入 RAM 副本,本层逐点折算现读。
|
||||
* ⚠ 变比段 [adc_cal_sec] 的 ROM 默认**不是 0**(电压 1000 / 电流 29.4118),
|
||||
* 因此烧进新固件后屏上立刻显二次值——这是刻意的:变比是硬件事实,
|
||||
* 出厂就该带着;而 VALID(准不准)仍然要求两点标定,两者互不代替。
|
||||
* 出厂就该带着;而 VALID(准不准)仍然要求标定,两者互不代替。
|
||||
*/
|
||||
void adc_cal_init(void);
|
||||
|
||||
@@ -239,7 +259,7 @@ int32_t adc_cal_k_q16(adc_semantic_t sem);
|
||||
* 别拿它反推 VALID——VALID 是"标定过没有",r 是"折算比是多少",
|
||||
* 两者由两个字段各记各的(见 adc_cal_flags 的注释)。
|
||||
* ⚠ 本值是**整体折算比**(端子二次值 ÷ 引脚电压),不是纯硬件分压比:
|
||||
* k 由 ROM 固化成板级名义斜率,其残差被 r 吸收(见 adc_cal_two_point 说明)。
|
||||
* k 由 ROM 固化成板级名义斜率,其残差被 r 吸收(台架标定时一并吸收进 r)。
|
||||
*/
|
||||
float adc_cal_ratio(adc_semantic_t sem);
|
||||
|
||||
@@ -300,28 +320,6 @@ int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes);
|
||||
*/
|
||||
int adc_cal_set_ratio(adc_semantic_t sem, int32_t r_q16);
|
||||
|
||||
/*
|
||||
* 函数功能:两点标定公式(「数据可信」标定项的算术核,纯函数无状态)
|
||||
* 入口参数:c_lo/c_hi - 两点码值(c_hi > c_lo) int32_t
|
||||
* v_lo_uv/v_hi_uv - 两点**端子侧**实测值(µV:电压填 1e6 域,电流填
|
||||
* 1e6 域但单位是 µA,即「0.5 A → 500000」) int32_t
|
||||
* k_q16 - 该路生效系数(走 adc_cal_k_q16() 取,不要自己填) int32_t
|
||||
* p_r_q16 / p_b - 输出:变比(Q16)与零点(码值) int32_t *
|
||||
* 返 回 值:0 - 成功;-1 - 参数/斜率非法或算出的变比越出 [ADC_CAL_R_MIN, ADC_CAL_R_MAX];
|
||||
* -2 - 零点越 ±ADC_CAL_B_MAX(先查前端,不得用系数凑错斜率,
|
||||
* docs/算法/采集与算法层设计说明.md §13.2 尾注) int
|
||||
* 限定条件:无(纯整数运算,主机侧可直接单测)
|
||||
* 函数说明:**v2.0 起标的是 r,不再标 k**——k 是板级前端斜率(ROM 固化,现场
|
||||
* 不该改也改不动),真正未知的是「端子↔引脚」这一层。公式:
|
||||
* r = (v_hi−v_lo) / [ (c_hi−c_lo) × k ] ← 零点在差分里抵消
|
||||
* b = v_lo / (k × r) − c_lo
|
||||
* 两条都用 int64 中间量;`k × r` 的量级先按 Q16 归一到同一个 2^32 再除,
|
||||
* 避免先乘后除把 int64 顶到溢出边。v 上限 1e9 µV(1000 V / 1000 A)——
|
||||
* 超了几乎必然是把 mV 或码值当 µV 填了,直接判参数错而不是算个假变比出来。
|
||||
*/
|
||||
int adc_cal_two_point(int32_t c_lo, int32_t c_hi, int32_t v_lo_uv, int32_t v_hi_uv,
|
||||
int32_t k_q16, int32_t *p_r_q16, int32_t *p_b);
|
||||
|
||||
/*
|
||||
* 函数功能:通道码值域「贴轨带」门限(采样通道自检 越界检出的门限来源,按 FS 百分比)
|
||||
* 入口参数:sem - 语义通道 adc_semantic_t
|
||||
|
||||
Reference in New Issue
Block a user