All MicroEvals
方案文档审核
Create MicroEval

方案文档审核

嵌入式领域C编程功能方案审核

Prompt

评审下面这份方案文档 # 游标电位器线性度校准 + 死区识别设计 日期:2026-10-05 项目:f426_32(AT32F426 multi-turn vernier 重构第一阶段) 前身:`773bd5d` 查表法问题多,改用游标相位差计算法;本阶段只做可靠游标角度数据源。 ## 0. 目标与范围 - 为后续相位差多圈计算提供可靠游标角度:`pot_raw -> pot_ang (0..16383 count/圈)`。 - 包含:线性度标定(CSP 转 `2*17/18` 电机圈 = 游标 2 圈,停顿采样建表)+ 死区识别(沿用 `ADC>3900` 粗判)。 - 不包含:相位差多圈解算、软限位联动、JOG 脱困(下一阶段)。 ## 1. 表结构与角度单位 ```c #define POT_CAL_TURNS 2 #define POT_MAIN_TEETH 18 #define POT_VERN_TEETH 17 #define POT_PTS_PER_TOOTH 3 #define POT_LIN_PTS (POT_VERN_TEETH * POT_PTS_PER_TOOTH) // 51,运行时表 #define POT_RAW_MAX (POT_CAL_TURNS * POT_LIN_PTS) // 102,原始采样 #define POT_DEAD_THR 3900u #define POT_SAMPLE_PERIOD_MS 10u // 普通组触发周期;标定停顿采样复用同一节拍,改这里两边同步变 #define POT_CAL_AVG_N 32u // 停顿采样平均次数,即 32*POT_SAMPLE_PERIOD_MS ≈ 320ms #define POT_CAL_KP 450u // 标定专用(2104 默认 300 的 1.5x,上板再调),结束恢复原值 #define POT_CAL_KD 15u // 标定专用(2105 默认 10 的 1.5x,上板再调),结束恢复原值 typedef struct { uint16_t adc; uint16_t ang; } pot_lin_pt_t; pot_lin_pt_t pot_lin[POT_LIN_PTS]; // ADC 升序方向与实测一致,ang 0..16383 int8_t pot_dir; // +1/-1,标定识别并保存;0=未标定 ``` - 真值链:`pot_unwrap = motor_pos_cnt * POT_MAIN_TEETH / POT_VERN_TEETH`(int64 中间量,先乘后除), `fold = pot_unwrap mod 16384`(负数先加模)。直接用 `motor_pos_cnt`(dir 已修正的增量多圈, 与 `6064` 同源),不对 `motor_pos_cnt` 预取模。 - 零点在最开头做:标定启动取当前 MT raw → `2303=raw` + `motor_pos_init` 重建 → 校验 `motor_pos_cnt==0` 才继续。`2303` 仍是单圈 raw 语义;成功时与线性表一起 commit。 - 查表语义: - 表内:二分 + 整数线性插值(int32)。 - 表外但非死区:首/末段斜率线性外推。 - 死区(`ADC > POT_DEAD_THR`):不进表;运行时 `pot_ang` 钳位到最近端点。 - `lin_valid==0 → pot_ang=0xFFFF`。 ## 2. 扫表运动与采样时序 - 前置:`aligned=1`,可进 CSP RUN;标定期间旁路 `607D` 软限位(结束恢复); MOEN 全程开,FAULT/超时即中止回 DISABLED。 - 置零见 §1;起点死区不特殊处理(`dead=1` 跳过,与其他死区点同一逻辑)。 - 行程:`TOT = 2*16384*POT_VERN_TEETH/POT_MAIN_TEETH`(代码 int64 算,约 30947 count), 102 点含起点:`pos_ref[i] = i*TOT/101`,`i=0..101`,单向递增。 - 单点节拍(1ms 状态机,复用 `mctrl_imp` CSP 阻抗环 + `POT_CAL_KP/KD`): 到点 → 稳定(`|pos-ref|<30cnt 且 |vel|<5cnt/s 持续 300ms`)→ 采 `motor_pos_cnt`×1 + pot ADC `POT_CAL_AVG_N` 次平均 → 存 `(adc, motor_pos_cnt, dead)` → 下一点。 平均的每次取值间隔即普通组触发周期 `POT_SAMPLE_PERIOD_MS`(异步采样节拍共用, 改周期只改这一处宏);`motor_pos_cnt` 取最后一次平均完成时刻的值。每点超时 5s。 - 结束停在终点不自动返回(免回差),`pos_cnt=TOT`;零点+表一起 commit 才持久化。 ## 3. 建表算法(方向只识别+保存) 1. 剔除 `dead` 点;`fold = (motor_pos_cnt*18/17) mod 16384`。 2. 方向识别:首尾有效点 `(adc, fold)` 趋势,`adc↑随fold↑ → dir=+1` 否则 `-1`;只记录, 表内保持实测顺序。运行时 `dir==-1` 则 `ang_eff = 16383 - ang` 后再插值/外推。 3. 折叠平均:51 bin,`bin = fold*51/16384`;bin 内两圈点分别平均 `adc/ang`; 空 bin 记缺失;缺失用相邻有效 bin 线性补齐后直接写入表(补齐来源仅 RTT 上报, 不持久化缺失掩码,保持 Flash 定长);连续缺失 >3 bin → 失败。 4. 校验:同 bin 两圈 `adc` 差 `max<40码`;`adc` 按实测方向严格单调; 有效 bin ≥47/51。死区占比不做失败判据。 运行时表即 51 点;102 原始点只放 RAM。 ## 4. 采样 + 存储 + OD - 普通组长度 1→2:`rank1=IN0/Vbus` 不变,`rank2=pot`(恢复旧 `POT_SEL` 引脚复用 + `wk_adc` helper)。 1ms 任务每 `POT_SAMPLE_PERIOD_MS` 软件触发一次(与 §2 共用宏),一次读双 EOC; Vbus 原滑动均值不变,pot 存 `s_pot_raw` (4 拍滑动均值防抖)。标定停顿采样复用同一通路(静置后 `POT_CAL_AVG_N` 次平均)。 - Flash:`pot_lin[51] + dir + crc` 一个 blob,随 `2303` 在标定成功时按 `1010 save` 落盘 (A/B 双备份语义,点数写死 51)。启动 CRC 错 → 表无效。 - OD(RO,`0x2330` 组;EDS 需新增,`cofd.eds` 落实 sub 定义): - `2330-01 dir` I8:+1/-1,0=未标定 - `2330-02 pot_raw` U16 LIVE:当前普通组 pot 原始码 - `2330-03 lin_valid` U8:0/1 - `2330-04 pot_ang` U16 LIVE:查表/外推后 count;`lin_valid==0→0xFFFF`; 死区时钳位最近端点(高侧死区钳到末点;DEAD 由 `pot_raw>3900` 判断) ## 5. 验收与测试 - 标定成功判据见 §3(47/51、<40码、单调、连续缺失≤3)。 - 主机单测 `tests/test_pot_lin.c`:插值/外推、`dir=±1` 镜像、DEAD 粗判、fold 负数取模、 两圈平均、单调性校验;沿用 `run_tests.sh`,`-Wall -Wextra -Wpedantic` 零警告; `motor_pot_lin` 层禁 MCU 头。 - 板级:新增 `2500=5` 触发一键标定(若与现有命令号冲突则顺延,drive.c 落实;标定中 非中止类 CAN 命令拒绝);RTT **通道 1(SEGGER RTT terminal 1)** 10Hz 打印 `(i, pos_ref, pos_cnt, adc_avg, dead)`; 无论成功失败,结束时都把完整标定过程数据全量打印到 RTT 通道 1: 102 原始点 `(adc, motor_pos_cnt, dead)` + 51 点 `(adc/ang)` + dir + 逐 bin 重复差 + 失败原因/bin;成功判据见 §3(47/51、<40码、单调、连续缺失≤3)。

Drag to resize

Response not available

Drag to resize
Drag to resize
Drag to resize
Drag to resize