跳到主要内容

20. 电机 Heartbeat 监视与组件限制

学习形式工程分析
硬件要求完整实验平台
配套 Demo沿用 lab_19
本课动作只监听电机

第 19 课能用 SDO 读取电机,但“刚才读成功”不能证明电机之后一直在线。电机 Node 0x01 周期发送 0x701 Heartbeat,程序可以记录它最后一次出现的时间。

CANopenNode 原本提供专门的 Heartbeat Consumer 模块来完成这类监视。本课先说明标准做法,再解释 Espressif 组件 0.1.0 在当前移植中的实际限制。

Producer 和 Consumer

Heartbeat 通信中有两个角色:

角色本项目中的设备动作
Heartbeat Producer电机 Node 0x01周期发送 0x701
Heartbeat ConsumerESP32 Node 0x20接收并判断是否超时

Producer 是“生产 Heartbeat 报文”的节点,Consumer 是“消费并监视 Heartbeat 报文”的节点。

电机发送:

CAN-ID 0x701 DLC 1 DATA 05

这里的 05 是电机当前 NMT Operational 状态。它不是 CiA 402 的 “Operation enabled”;两套状态要到第 22 课结合 0x6041 再区分。

官方 CANopenNode 的标准做法

标准 Heartbeat Consumer 会:

  1. 根据对象 0x1016 配置要监视的远程 Node-ID 和超时时间;
  2. 接收对应的 0x700 + Node-ID
  3. 保存远程 NMT 状态;
  4. 在规定时间没有收到时报告超时事件。

这比应用只打印一帧更完整,因为它维护“是否曾经启动”“当前状态”“是否超时”等状态。

CANopenNode 官方说明:Heartbeat consumer

为什么当前组件里不能直接打开

本课程固定使用 espressif/canopennode 0.1.0。检查该组件的移植配置可以看到:

#define CO_CONFIG_HB_CONS 0

同时,组件 Kconfig 没有提供一个菜单选项把 Heartbeat Consumer 打开。这不是应用工程忘记勾选,而是该版本 ESP32 移植的功能配置把模块关闭了。

如果直接在 managed_components/ 里改宏,会带来几个问题:

  • 组件管理器下次重新解析可能覆盖修改;
  • 工程不再能只靠依赖清单复现;
  • 学员难以判断代码来自官方版本还是本地补丁;
  • 还需要核对对象字典 0x1016 和接收缓冲区配置。

因此当前课程不修改托管组件。

应用层临时监视怎样工作

现有 Demo 仍使用 CANopenNode 的同一套 TWAI 接收机制,没有创建第二套驱动。

当前组件下的应用层 Heartbeat 监视

程序为 0x701 配置一个接收槽,收到后记录:

  • DATA 中的 NMT 状态;
  • 最后接收时间;
  • 是否曾收到 Boot-up;
  • Heartbeat 是否超过预期时间未出现。

为什么 SDO 读取时会临时切换到 0x581

当前组件和对象字典配置只给应用留出了有限的接收资源。访问电机 SDO 时,需要接收 0x581;平时又希望监听 0x701

于是程序按下面的顺序使用同一个接收槽:

  1. 平时接收 0x701
  2. 开始 SDO 前,把槽配置为 0x581
  3. SDO Client 收到响应或超时;
  4. 关闭本次 SDO;
  5. 把槽恢复为 0x701

这就是“SDO 读取期间临时切到 0x581,读完再恢复 0x701”的完整意思。

它不是把 TWAI 驱动关掉重开,也不是两套协议栈争用总线。

这种方案会漏掉什么

在接收槽用于 0x581 的短时间内,如果电机恰好发出 0x701,应用可能不处理那一帧。只要 SDO 操作时间短、Heartbeat 周期较长,下一帧 Heartbeat 仍会恢复监视。

但这仍不是完整 Heartbeat Consumer 的等价实现:

能力应用层临时监视官方 HB Consumer
打印远程 NMT 状态可以可以
判断简单超时可以可以
使用标准 0x1016 配置没有可以
监视多个节点当前未实现按配置支持
完整状态和回调语义没有

项目记录

这个限制必须保留在项目说明中,后续升级组件时重新检查:

  • 新版本 Kconfig 是否开放 CO_CONFIG_HB_CONS
  • 对象字典是否包含正确的 0x1016
  • 接收缓冲区数量是否足够;
  • 能否删除应用层临时监听代码。

当前方案适合本教程的单电机调试,但不应被描述为官方 Heartbeat Consumer 已经启用。

本课回顾

0x701 是电机主动发送的在线状态,不是 SDO 读取对象。当前 Espressif 组件关闭了官方 Heartbeat Consumer,因此应用在同一套 CANopenNode/TWAI 接收机制中做了有限监视;这个限制已经明确记录,不能悄悄修改托管组件来掩盖。