#!/bin/bash # 04_pdo_demo.sh - PDO 通信演示 # 目标:节点 1 通过 TPDO 发送数据,节点 2 通过 RPDO 接收 # PDO = 生产者→消费者(无需确认,适合实时控制数据) SOCKET1="/tmp/CO_command_socket_1" SOCKET2="/tmp/CO_command_socket_2" cocc() { local socket=$1 local node=$2 local cmd=$3 echo " → [$node] $cmd" cocomm -s "$socket" "$node $cmd" } echo "================================================" echo " CANopen PDO 实验" echo "================================================" echo "" echo "--- Step 1: 启动 NMT(使节点进入 Operational 状态)---" echo " (NMT pre-operational → operational 才能传输 PDO)" cocc "$SOCKET1" 1 "start" sleep 1 cocc "$SOCKET2" 2 "start" sleep 1 echo "" echo "--- Step 2: 配置 TPDO1 映射(节点 1)---" echo " 将 0x2000 子索引 1(自定义生产数据)映射到 TPDO1" echo "" echo " 先确认当前映射状态:" cocc "$SOCKET1" 1 "read 0x1A00 0 u8" echo "" echo " 映射 0x2000 sub1 (u32) 到 TPDO1:" echo " 写映射条目:0x20000120 (index 0x2000, sub 1, 32 bits)" cocc "$SOCKET1" 1 "write 0x1A00 1 u32 0x20000120" echo "" echo " 更新映射数量:" cocc "$SOCKET1" 1 "write 0x1A00 0 u8 1" sleep 1 echo "" echo " TPDO 传输类型设为 254(事件触发):" cocc "$SOCKET1" 1 "write 0x1800 2 u8 254" sleep 1 echo "" echo "--- Step 3: 配置 RPDO1 映射(节点 2)---" echo " 将 TPDO1 的 0x2000 sub1 映射到节点 2 的 RPDO1" echo "" echo " 写入映射条目(与 TPDO 相同的对象):" cocc "$SOCKET2" 2 "write 0x1600 1 u32 0x20000120" cocc "$SOCKET2" 2 "write 0x1600 0 u8 1" sleep 1 echo "" echo " RPDO COB-ID 设为 0x00000200(匹配 TPDO1 默认 ID):" cocc "$SOCKET1" 1 "read 0x1800 1 u32" cocc "$SOCKET2" 2 "write 0x1400 1 u32 0x00000200" echo "" echo "--- Step 4: 启动 candump 监控 PDO 报文 ---" echo " 在后台监控 vcan0 上的 PDO CAN ID 0x200..." candump vcan0,200:FFF & CANDUMP_PID=$! sleep 1 echo "" echo "--- Step 5: 通过 SDO 写入节点 1 的 0x2000 触发 TPDO ---" echo " 节点 1 产生 TPDO → CAN ID 0x200 → 节点 2 接收" echo "" echo " 写入值 0x12345678 到节点 1 的 0x2000 sub1:" cocc "$SOCKET1" 1 "write 0x2000 1 u32 0x12345678" sleep 1 echo "" echo " 写入值 0xDEADBEEF 到节点 1 的 0x2000 sub1:" cocc "$SOCKET1" 1 "write 0x2000 1 u32 0xDEADBEEF" sleep 1 echo "" echo " 再次写入 0x0000000A:" cocc "$SOCKET1" 1 "write 0x2000 1 u32 0x0000000A" sleep 2 echo "" # Stop candump kill $CANDUMP_PID 2>/dev/null wait $CANDUMP_PID 2>/dev/null echo "" echo "--- Step 6: 验证节点 2 是否收到了 PDO 数据 ---" echo " 读取节点 2 的 0x2000 sub1(被 PDO 更新后应有值):" cocc "$SOCKET2" 2 "read 0x2000 1 u32" echo "" echo "================================================" echo " PDO 实验完成" echo " 关键认知:" echo " - PDO 是生产者→消费者、无确认的组播通信" echo " - 适合高频实时控制数据(如 SVPWM 占空比、编码器位置)" echo " - TPDO CAN ID = 0x180 + NodeId(默认 TPDO1)" echo " - RPDO CAN ID = 0x200 + NodeId(默认 RPDO1)" echo " - 传输类型 254 = 事件触发(对象变化即发送)" echo " - 传输类型 1-240 = SYNC 同步传输" echo "================================================"