赞
踩
先前采用了串口进行上下位机通讯,由于需要USB转串口,会出现通讯不上的问题。
之后了解了CAN通讯,发现相比串口通信更稳定,在编程上也相对自由些
sudo apt install can-utils
sudo modprobe vcan
sudo ip link add dev can0 type vcan
ifconfig -a
命令可以看到比平时多了一个 can0,但此时状态为:<NOARP>sudo ip link set dev can0 up
candump can0
cansend can0 123#456789
注意
使用 cansend 发布数据需要有一定格式,否则会报错,官方声明如下
cansend - send CAN-frames via CAN_RAW sockets. Usage: cansend <device> <can_frame>. <can_frame>: <can_id>#{data} for 'classic' CAN 2.0 data frames <can_id>#R{len} for 'classic' CAN 2.0 data frames <can_id>##<flags>{data} for CAN FD frames <can_id>: 3 (SFF) or 8 (EFF) hex chars {data}: 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.') {len}: an optional 0..8 value as RTR frames can contain a valid dlc field <flags>: a single ASCII Hex value (0 .. F) which defines canfd_frame.flags Examples: 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 / 1F334455#1122334455667788 / 123#R / 00000123#R3
sudo ip link set dev can0 down
ifconfig -a
命令可以看到 can0 状态变回:<NOARP>sudo ip link del dev can0
ifconfig -a
命令已经看不到 can0 了sudo apt-get install ros-melodic-can-msgs
sudo apt-get install ros-melodic-socketcan-bridge
sudo apt-get install libmuparser-dev
roscore
rosrun socketcan_bridge socketcan_to_topic_node
rostopic echo /received_messages
camdump can0
cansend can0 123#456789
std_msgs/Header header
uint32 seq
time stamp
string frame_id
uint32 id
bool is_rtr
bool is_extended
bool is_error
uint8 dlc
uint8[8] data
主要成员变量解析
id:CAN 通讯的 ID
dlc:数据字节长度
data:用于 CAN 数据存储的数组
<launch>
<!-- topic 转 CAN -->
<node pkg="socketcan_bridge" name="topic_to_socket_node" type="topic_to_socket_node" output="screen">
<param name="can_device" value="can0" />
</node>
<!-- CAN 转 topic -->
<node pkg="socketcan_bridge" name="socket_to_topic_node" type="socket_to_topic_node" output="screen">
<param name="can_device" value="can0" />
</node>
<!-- 示例节点 -->
<node pkg="can_test" name="can_test" type="can_test_node" output="screen" />
</launch>
#include <ros/ros.h> #include <can_msgs/Frame.h> void canCallBack(const can_msgs::Frame::ConstPtr &msg) { static int times = 0; std::cout << times++ << "ID: " << msg->id << " data: " ; for (int i = 0; i < msg->dlc; i++) { printf("%X ", msg->data[i]); } std::cout << std::endl; } int main(int argc, char **argv) { setlocale(LC_ALL, ""); ros::init(argc, argv, "can_test_node"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<can_msgs::Frame>("sent_messages", 100); can_msgs::Frame can_frame_msg; can_frame_msg.id = 0x521; can_frame_msg.dlc = 8; // 分开赋值 can_frame_msg.data[0] = 0x00; can_frame_msg.data[1] = 0x11; can_frame_msg.data[2] = 0x22; can_frame_msg.data[3] = 0x33; can_frame_msg.data[4] = 0x44; can_frame_msg.data[5] = 0x55; can_frame_msg.data[6] = 0x66; can_frame_msg.data[7] = 0x77; // can_frame_msg.data = {00, 11, 22, 33, 44, 55, 66, 77}; // 一次性全部赋值 ros::Subscriber sub = nh.subscribe("/received_messages", 100, &canCallBack); ros::Rate r(1); while (ros::ok()) { pub.publish(can_frame_msg); r.sleep(); ros::spinOnce(); } return 0; }
cansend
命令发布数据,进行 CAN 数据转 ROS 话题数据的方法验证candump can0
:查看CAN 数据rostopic echo /received_messages
:查看话题数据sudo ip link set down can0
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 type can loopback on
sudo ip link set up can0
candump can0
cansend can0 521#010301000001
ip -details -statistics link show can0
sudo ip link set can0 type can bitrate 500000 sjw 4 restart-ms 100 berr-reporting on
命令解析:
ip link: 这是用于操作Linux内核中网络设备链接的工具。它可以用来查看、修改或操作网络接口的各种设置。
set can0 type can: 这部分命令设置can0接口的类型为CAN接口。can0是CAN接口的名字。
bitrate 500000: 这设置了CAN接口的数据传输速率为500,000比特每秒(500 kbps)。
sjw 4: 这设置了同步跳转宽度(sjw)为4。同步跳转宽度决定了时钟同步的精度,它影响时钟同步的延迟和抖动。
restart-ms 100: 这设置了在检测到错误后重新启动通信的时间间隔为100毫秒。
berr-reporting on: 这启用了位错误报告。当这个选项被启用时,如果检测到位错误,系统会发送一个错误报告。
关闭 CAN 回环检测模式
sudo ip link set can0 type can loopback off
检测并发布 CAN 数据
candump can0
cansend can0 521#010301000001
此时可以使用其他 CAN 设备向 CAN 总线发布数据,使用candump查看是否存在数据
[1] ros_canopen使用心得
[2] ROS采用SocketCAN进行通信
[3] TX2/Linux下can总线的接收与发送详解!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。