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:
@@ -17,6 +17,10 @@
|
||||
* 见 UNTHROTTLED_MAX_MS。
|
||||
* 共用一个值的实际后果:ECAT 的快值带到 WiFi 上会让 HTTP 请求排队
|
||||
* (tickStuck 常亮黄),WiFi 的 250ms 带到 ECAT 上又白白浪费了本地快照的低延迟。
|
||||
*
|
||||
* 后半部分还住着一块与「实测数据率」相关的纯逻辑(同样为了脱离 DOM 自测):
|
||||
* staleLimitMs —— EtherCAT 槽判活的离线阈值,随实测 seq 间隔自适应,
|
||||
* transport-ecat.js 用它,慢速回报的电机不再被固定 2s 误判离线。
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
@@ -105,3 +109,32 @@ export function pickRefresh(map, tpId) {
|
||||
if (Number.isFinite(n)) return clampFor(tpId, n);
|
||||
return REFRESH_DEFAULTS[tpId] || REFRESH_DEFAULTS.wifi;
|
||||
}
|
||||
|
||||
/* ═══════════ ECAT 槽判活阈值:随实测 seq 间隔自适应 ═══════════
|
||||
*
|
||||
* 背景:电机 CAN 回报率可变(可在电机侧调档),回报周期调到秒级后 seq 几秒
|
||||
* 才动一次,固定 2s 判活阈值会在两次**正常**回报之间把电机判离线。
|
||||
* 注:STATUS 面板的 Hz 刻意**不**按 seq 实测电机回报率 —— 面板要显示的是
|
||||
* 网页实际刷新率(数据到达口径),WiFi 慢于电机时按电机档位显示就是谎报;
|
||||
* seq 只用于这里的判活。 */
|
||||
|
||||
/**
|
||||
* 槽 seq 停涨多久算离线的**下限**(ms),生效阈值 = staleLimitMs(实测间隔)。
|
||||
* 下限 2s 的来由(历史):要大于「扫完全表 + 一点抖动」—— 1.6.15 滑窗时代
|
||||
* period 10ms × 6 周期 = 60ms,2s 有充足余量;1.6.21 密排后一拍整轮,更不是问题。
|
||||
*/
|
||||
export const STALE_OFFLINE_MS = 2000;
|
||||
/** 生效阈值 = 实测 seq 变化间隔(EWMA) × 该系数。3 倍 ≈ 连丢 3 拍才判离线。 */
|
||||
export const STALE_IV_FACTOR = 3;
|
||||
/** 阈值上限:防一次长停顿(后台挂起/总线冻结恢复)把 EWMA 拉飞后迟迟不判离线。 */
|
||||
export const STALE_MAX_MS = 30000;
|
||||
|
||||
/**
|
||||
* 该槽的离线阈值:clamp(3 × EWMA(实测 seq 变化间隔), 2s, 30s)。
|
||||
* 电机 CAN 回报率可变:回报周期调到秒级后,固定 2s 会在两次正常回报之间
|
||||
* 把电机判离线(LED 闪烁/波形虚线/面板切离线层),阈值必须跟着间隔放大。
|
||||
* ivMs = 0(还没观察到第二次变化)时返回下限 2s,与旧固定阈值行为一致。
|
||||
*/
|
||||
export function staleLimitMs(ivMs) {
|
||||
return Math.max(STALE_OFFLINE_MS, Math.min(STALE_MAX_MS, (ivMs || 0) * STALE_IV_FACTOR));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user