模块 2 练习项目
目录
练习 1:EDS 文件验证器
目标
编写一个程序,验证 EDS 文件的语法正确性和语义一致性。
要求
解析 EDS 文件(INI 格式)
验证以下规则:
- 每个对象必须有
[DeviceInfo]节 - 对象索引必须在有效范围内(0x1000-0xFFFF)
- 数据类型必须是 CiA 301 定义的有效值
- 访问类型必须是 ro/rw/wo/rwr/rwpre/const 之一
- ARRAY/RECORD 类型的 sub0 必须表示元素个数
- 子索引编号必须与节中声明的数量一致
- 每个对象必须有
输出验证报告:
EDS Validator Report
====================
File: sample.eds
Status: PASS (2 warnings)
Objects found: 11
Mandatory: 5
Optional: 3
Manufacturer: 3
Warnings:
- Object 0x2000: PDOMapping=1 but access type is wo
- Object 0x1003: SubNumber=9 but only 8 sub-entries found
Errors:
(none)测试用例
使用示例 4 中的 sample.eds 进行验证,然后故意修改文件制造错误:
- 删除
[DeviceInfo]节 - 将数据类型改为无效值(如
0xFFFF) - 减少子索引数量
提示
- 可以使用示例 4 的 EDS 解析器作为基础
- 验证逻辑与解析逻辑分离
练习 2:SDO 批量配置工具
目标
编写一个命令行工具,通过 SDO 批量配置多个节点参数。
要求
- 从 JSON 配置文件读取配置:
- 对每个节点依次执行配置
- 记录每个配置的结果(成功/失败/超时)
- 生成配置报告:
SDO Batch Configuration Report
================================
Interface: vcan0
Nodes: 3, 4, 5
Node 3:
[OK] 0x1017:00 = 1000 (Heartbeat period)
[OK] 0x1005:00 = 0x80000080 (COB-ID SYNC)
Node 4:
[OK] 0x1017:00 = 1000 (Heartbeat period)
[FAIL] 0x1005:00 - Timeout (COB-ID SYNC)
Node 5:
[OK] 0x1017:00 = 1000 (Heartbeat period)
[OK] 0x1005:00 = 0x80000080 (COB-ID SYNC)
Summary: 5/6 succeeded, 1 failed运行方式
./sdo_batch_config config.json提示
- 复用示例 5 的 SDO Client 代码
- 每个配置之间添加 100ms 延时(避免总线拥塞)
- 使用
select()实现超时机制
练习 3:SDO 传输性能测试
目标
测量不同数据类型和传输模式下的 SDO 传输延迟。
要求
测试以下场景:
- Expedited Upload 1 字节(错误寄存器)
- Expedited Upload 2 字节(心跳周期)
- Expedited Upload 4 字节(设备类型)
- Segmented Upload 16 字节(设备名称)
- Segmented Upload 256 字节(大数据块)
每种场景测试 100 次,计算:
- 平均延迟(毫秒)
- 最小延迟
- 最大延迟
- 成功率
输出测试报告:
SDO Performance Test Report
============================
Interface: vcan0
Iterations per test: 100
Test Avg(ms) Min(ms) Max(ms) Success
─────────────────────────────────────────────────────────
Expedited 1B 0.52 0.48 0.61 100/100
Expedited 2B 0.53 0.49 0.65 100/100
Expedited 4B 0.54 0.50 0.72 100/100
Segmented 16B 1.21 1.10 1.45 100/100
Segmented 256B 18.35 17.80 20.12 100/100
Analysis:
- Expedited transfers are ~2x faster than Segmented (small data)
- Segmented 256B requires 37 segments (256/7 bytes per segment)
- Each segment adds ~0.5ms round-trip latency实现方式
- 使用示例 7 的 SDO Demo 作为 Server
- 编写测试脚本自动发送请求并计时
提示
- 使用
clock_gettime(CLOCK_MONOTONIC)获取高精度时间戳 - 考虑 CAN 总线发送延迟(通常 0.1-0.5ms)
- 在虚拟 CAN 上测试的延迟比真实 CAN 硬件低
思考题
1. Expedited vs Segmented 的选择
问题:如果数据正好是 4 字节,必须使用 Expedited 传输吗?可以使用 Segmented 吗?
提示:CANOpen 规范允许服务端根据数据类型自主选择传输模式。考虑服务端实现的复杂度。
2. Toggle 位的作用
问题:为什么 Segmented 传输需要 Toggle 位?如果只用序号(0, 1, 2…)而不是翻转位,会有什么优缺点?
提示:考虑丢包场景。如果服务端发送了段 0、1、2,但客户端只收到 0、2,序号方案和 Toggle 方案分别如何检测这个问题?
3. 多节点 SDO 并发
问题:如果主站同时向节点 3 和节点 5 发送 SDO 请求,会发生什么?CAN 总线的仲裁机制如何保证帧不混淆?
提示:考虑 COB-ID 的仲裁优先级。节点 3 的请求(0x603)和节点 5 的请求(0x605)在总线上如何区分?
4. 对象字典的动态性
问题:在机械臂应用中,关节数量可能变化(4-DOF、6-DOF、7-DOF)。如何设计对象字典使其能适应不同配置?
提示:
- 方案 1:预定义最大数量的条目,未使用的标记为"不可用"
- 方案 2:运行时动态创建对象字典条目
- 方案 3:使用 EDS 文件生成工具,为每个配置生成不同的 EDS
分析每种方案的优缺点和实现复杂度。
扩展阅读
- CiA 301:CANOpen 应用层规范(SDO 协议详细定义)
- CiA 306:EDS 文件格式规范
- CANopenNode 源码:https://github.com/CANopenNode/CANopenNode
301/CO_SDOserver.c:服务端实现301/CO_SDOclient.c:客户端实现
- CANFestival 源码:https://forge.canfestival.org/
src/sdo.c:SDO 核心逻辑
验收标准
| 项目 | 完成标准 |
|---|---|
| 练习 1 | 能正确解析和验证 sample.eds,并检测故意引入的错误 |
| 练习 2 | 能对 3 个节点进行批量配置,并生成报告 |
| 练习 3 | 能测量不同传输模式的延迟,数据合理 |
| 思考题 | 有清晰的分析和答案 |
如果这篇文章对你有帮助,欢迎请我喝杯咖啡 ☕
支付宝
微信