feat(motor): 反馈刷新率 Hz 适配(0x0400/0x0401 扩展格式)+ ECAT 密排槽与判活自适应
反馈刷新率(配套电机固件 v0.4.1:0x0400 DLC4/0x0401 DLC2 扩展格式, 选择器 0x0100=STATUS · 0x0101=CONFIG 帧,协议值为周期 ms): - 「节点 ID」页签新增 STATUS/CONFIG 刷新率读取/写入;界面单位一律 Hz (写入按 周期ms=round(1000/Hz) 换算下发,读取反算 Hz 并附原始周期, 取整有损如实展示),0=停发,写入掉电保存;配置值以「读取」回读电机为准 - WiFi 应答回执走 0xC1 per-ID 快照(/can/feedback 全量 entries): GD32 0xC0 ACK 仅 1 字节状态、不携带电机回帧;同 ID 回帧快照只存最新 一条,故一次快照只配一次请求(STATUS/CONFIG 分开读写) - ECAT 回执走批量接收区 takeNodeIdReport,按长度分派 2B 旧格式/4B GET/5B SET ACK - GET_NODE_ID 迁移到扩展选择器 0x0000,兼容旧固件 2B 节点 ID 应答 (SET DLC2 旧格式行为不变) - transport-wifi 新增 fetchFeedbackFull(全量 CAN 反馈快照) EtherCAT/基础设施(密排槽固件 1.6.21 配套): - 快照槽位 5→9 一拍整轮(扫描周期数 6→1);判活阈值随实测 seq 间隔 自适应 clamp(3×EWMA, 2s, 30s),秒级回报档不再被固定 2s 误判离线; STATUS 面板 Hz 明确为网页到达口径(按槽 seq 实测电机回报率的方案已否掉) - esp32_server.py:ecat_native 单实例收紧(后起独占 + taskkill 残留实例, 双实例并存会抢 Npcap 致后起者抓不到从站)+ native stdout 落盘 - flash_gd32.py:刷写后校验「GD32 真的在跑新代码」(版本变化或 uptime 归零), 防"写入≠在跑"假台账 - lab:新增 LAN9252 电源诊断台、PDO 布局页;SPI 测速并入 EtherCAT 接收看板 并更名「SPI/ECAT 通信测速」;移除 continuity_test.html;新增 ECAT 单拍耗时 优化报告;/_local/ 排除入库;测试同步更新(62+58 项全过)
This commit is contained in:
@@ -15,11 +15,13 @@
|
||||
* 4 取值:缺失/脏值回落该链路默认,不回落成另一条链路的值
|
||||
* 5 隔离:改一条链路不影响另一条(这就是本次改动的全部意义)
|
||||
* 6 不限速谓词:6ms 档要关掉卡顿黄标与理论 Hz 显示(6ms ≠ 166Hz)
|
||||
* 7 判活阈值 staleLimitMs:随实测 seq 间隔自适应,钳在 [2s, 30s]
|
||||
*/
|
||||
import {
|
||||
REFRESH_DEFAULTS, REFRESH_MIN_MS, REFRESH_MAX_MS, REFRESH_MIN_BY_TP,
|
||||
UNTHROTTLED_MAX_MS, minRefreshFor, isUnthrottled,
|
||||
defaultRefreshMap, normalizeRefreshMap, pickRefresh
|
||||
defaultRefreshMap, normalizeRefreshMap, pickRefresh,
|
||||
staleLimitMs, STALE_OFFLINE_MS, STALE_IV_FACTOR, STALE_MAX_MS
|
||||
} from "../js/motor/refresh-rate.js";
|
||||
|
||||
let pass = 0, fail = 0;
|
||||
@@ -143,6 +145,27 @@ check("WiFi 下限 50ms 永远不进不限速区(该链路无此档)",
|
||||
check("ECAT 下限 6ms 一定在不限速区", isUnthrottled(REFRESH_MIN_BY_TP.ecat) === true);
|
||||
check("非数字不炸且判 false", isUnthrottled(undefined) === false && isUnthrottled(NaN) === false);
|
||||
|
||||
/* ── 7. ECAT 判活阈值自适应 ──
|
||||
* 固定 2s 阈值的问题:电机 CAN 回报周期调到秒级后,两次**正常**回报之间
|
||||
* 就超过 2s,节点反复判离线(LED 闪/波形虚线/面板切离线层)。
|
||||
* 生效阈值 = clamp(3×EWMA(实测间隔), 2s, 30s)。
|
||||
* 注:STATUS 面板的 Hz 刻意不按 seq 实测电机回报率 —— 面板显示的是网页
|
||||
* 实际刷新率(数据到达口径),WiFi 慢于电机时按电机档位显示就是谎报。 */
|
||||
section("[7] 判活阈值 staleLimitMs(随实测 seq 间隔自适应)");
|
||||
check("下限 2s / 系数 3 / 上限 30s(契约常量)",
|
||||
STALE_OFFLINE_MS === 2000 && STALE_IV_FACTOR === 3 && STALE_MAX_MS === 30000);
|
||||
check("还没观察到第二次变化(iv=0)→ 下限 2s,与旧固定阈值行为一致",
|
||||
staleLimitMs(0) === 2000, `实际 ${staleLimitMs(0)}`);
|
||||
check("undefined 同样落到下限(防御)", staleLimitMs(undefined) === 2000);
|
||||
check("快周期 20ms → 仍取下限 2s(兜底快周期,阈值不小于扫表+抖动)",
|
||||
staleLimitMs(20) === 2000, `实际 ${staleLimitMs(20)}`);
|
||||
check("回报周期 1s → 阈值 3s(连丢 3 拍才判离线,2s 不再误判)",
|
||||
staleLimitMs(1000) === 3000, `实际 ${staleLimitMs(1000)}`);
|
||||
check("回报周期 5s → 阈值 15s", staleLimitMs(5000) === 15000,
|
||||
`实际 ${staleLimitMs(5000)}`);
|
||||
check("回报周期 20s → 被 30s 上限压住(长停顿后不能迟迟不判离线)",
|
||||
staleLimitMs(20000) === 30000, `实际 ${staleLimitMs(20000)}`);
|
||||
|
||||
console.log(out.join("\n"));
|
||||
console.log("\n" + "=".repeat(56));
|
||||
console.log(`通过 ${pass} 项,失败 ${fail} 项`);
|
||||
|
||||
Reference in New Issue
Block a user