一幢痘、CAN協(xié)議簡介
1.1 CAN發(fā)展歷程
1.2 標準CAN與拓展CAN區(qū)別
CAN 1.0 定義的 CAN 具有 11 位消息標識唬格,提供可能的 2048 個消息標識符。2.0 版允許有效的 29 位消息 ID颜说。為了使新的 CAN 設(shè)備與舊的實現(xiàn)兼容购岗,CAN 2.0 規(guī)范分為兩部分,2.0A 和 2.0B门粪。在 CAN 2.0A 中喊积,消息格式與僅使用 11 位消息 ID 的舊版本 CAN 一致。 CAN 2.0B 中玄妈,允允許有效的 29 位消息 ID乾吻,然后可以在被動或主動模式下實現(xiàn) CAN 2.0B髓梅。CAN 版本 1.0 和 2.0A 被稱為“標準 CAN”,因為它們都使用 11 位消息 ID溶弟。CAN 2.0 B 被稱為“擴展 CAN”女淑,因為它使用擴展的 29 位消息 ID
1.3 參考
https://www.can-cia.org/can-knowledge/can/can-history/
https://en.wikipedia.org/wiki/CAN_bus#History
https://www.edaboard.com/threads/difference-between-can1-0-and-can-2-0.217912/
二、基于CAN的典型應(yīng)用協(xié)議
SAE J1939/ISO11783
CANOpen
CANaerospace
DeviceNet
NMEA 2000
三辜御、Linux上使用CAN的幾種方式
3.1 Linux中CAN設(shè)備掛載的總線類型
Linux可以通過串口鸭你、USB、網(wǎng)口擒权、PCIE等接口與CAN設(shè)備間接進行通信袱巨。
CAN設(shè)備連接在不同的硬件接口時,意味著CAN設(shè)備被掛載在Linux中不同的總線上碳抄,如USB總線愉老、PCI-E總線(直接通過PCI-E與linux通訊),因此Linux采用不同的通訊協(xié)議與CAN設(shè)備進行通訊剖效。
3.2 CAN轉(zhuǎn)串口
-
設(shè)備形態(tài):
CAN轉(zhuǎn)串口
- 數(shù)據(jù)傳輸流程:
Linux->串口->單片機->CAN
- 通訊協(xié)議:
利用linux自帶的串口庫嫉入,或ros的serial庫對串口進行讀寫。
通過定義串口協(xié)議璧尸,如10個字節(jié)咒林,前兩個字節(jié)為CAN ID,后面8個字節(jié)為CAN Data爷光。通過此對串口發(fā)送數(shù)據(jù)垫竞,讓單片機對其進行轉(zhuǎn)換為CAN數(shù)據(jù)。
協(xié)議參考:https://manual.zlg.cn/web/#/64/2607
3.3 CAN轉(zhuǎn)USB
-
設(shè)備形態(tài):
CAN轉(zhuǎn)USB
注意蛀序,不是所有的周立功CAN轉(zhuǎn)USB設(shè)備都支持Linux欢瞪,見表:https://manual.zlg.cn/web/#/146
- 數(shù)據(jù)傳輸流程:
Linux->USB->單片機->CAN
- 通訊協(xié)議:
與CAN轉(zhuǎn)串口不一樣,利用的庫是libusb和libusbcan徐裸,對CAN轉(zhuǎn)USB數(shù)據(jù)直接進行讀寫
libusb是linux驅(qū)動遣鼓,可以操作USB接口對USB設(shè)備進行讀寫操作。
libusbcan是CAN轉(zhuǎn)USB設(shè)備廠商給的驅(qū)動重贺,其中定義了can數(shù)據(jù)幀的數(shù)據(jù)結(jié)構(gòu)體譬正,填充相應(yīng)的CAN ID和CAN Data,最后通過USB進行讀寫檬姥。
協(xié)議參考:https://manual.zlg.cn/web/#/55/2282
3.4 CAN轉(zhuǎn)網(wǎng)
-
設(shè)備形態(tài):
CAN轉(zhuǎn)網(wǎng) 數(shù)據(jù)傳輸流程:
Linux->TCP(UDP)/IP->單片機->CAN
- 通訊協(xié)議:
利用Linux的socket庫對網(wǎng)絡(luò)設(shè)備進行讀寫操作。
Linux通過IP地址利用Socket與CAN設(shè)備通信粉怕,一個TCP/UDP幀包中包含若干個連續(xù)的CAN幀健民,每個CAN幀包含若干個字節(jié),包含CAN ID和CAN Data贫贝。
協(xié)議參考:https://manual.zlg.cn/web/#/67/2693
3.5 CAN轉(zhuǎn)PCI-E
-
設(shè)備形態(tài):
PCI-E轉(zhuǎn)CAN
注意周立公CAN轉(zhuǎn)PCI-E設(shè)備秉犹,型號PCI-5010-P不支持Linux:https://manual.zlg.cn/web/#/146
- 數(shù)據(jù)傳輸流程:
Linux->SocketCAN->單片機->CAN
- 通訊協(xié)議:
Linux提供了SocketCAN接口蛉谜,使得CAN總線通信近似于和以太網(wǎng)的通信。網(wǎng)絡(luò)設(shè)備通過IP確定地址崇堵,CAN設(shè)備通過CAN ID確定地址型诚,如can0
,can1
...
CAN ID可以通過ifconfig -a
查看
Linux利用SocketCAN庫根據(jù)CAN的設(shè)備ID對其進行讀寫操作鸳劳,CAN的數(shù)據(jù)結(jié)構(gòu)在Socket CAN中被結(jié)構(gòu)體定義狰贯,填充相應(yīng)數(shù)據(jù)后發(fā)送即可。
協(xié)議參考:https://manual.zlg.cn/web/#/77/3180
3.6 USB轉(zhuǎn)CAN(CANable)
-
設(shè)備形態(tài):
USB轉(zhuǎn)CAN(SocketCAN)
開源地址:https://canable.io/
淘寶有售賣
- 數(shù)據(jù)傳輸流程:
注意與上面周立功的CAN轉(zhuǎn)USB設(shè)備數(shù)據(jù)傳輸流程不同赏廓,利用的是SocketCAN
涵紊,不是USB
。
Linux->SocketCAN->單片機->CAN
- 通訊協(xié)議:
Linux利用SocketCAN庫根據(jù)CAN的設(shè)備ID對其進行讀寫操作幔摸,CAN的數(shù)據(jù)結(jié)構(gòu)在Socket CAN中被結(jié)構(gòu)體定義摸柄,填充相應(yīng)數(shù)據(jù)后發(fā)送即可。
SocketCAN簡介:https://en.wikipedia.org/wiki/SocketCAN
協(xié)議參考1:https://canable.io/getting-started.html#socketcan-linux
協(xié)議參考2:https://manual.zlg.cn/web/#/77/3180
四既忆、ROS中的CAN通信
4.1 ROS提供三個層次的驅(qū)動庫
-
ros_canopen
:canopen包驱负,http://wiki.ros.org/ros_canopen -
socketcan_bridge
:將SocketCAN接口封裝為ROS的topic,http://wiki.ros.org/socketcan_bridge -
socketcan_interface
:直接操作SocketCAN接口患雇,http://wiki.ros.org/socketcan_interface
socketcan_interface
是較為底層的包跃脊,與Linux的socketcan打交道。
socketcan_bridge
是ros中最常用的包庆亡,通過將接收到的topic轉(zhuǎn)換為can數(shù)據(jù)發(fā)出去匾乓,或者把接收到的can數(shù)據(jù)轉(zhuǎn)換為ros的topic。
ros_canopen
是基于canopen應(yīng)用協(xié)議的包又谋,是上層協(xié)議拼缝。
4.2 socketcan_bridge包
該功能以三個節(jié)點的形式提供:socketcan_bridge_node
、socketcan_to_topic_node
和topic_to_socketcan_node
彰亥。要從同一個 CAN 設(shè)備接收和發(fā)送幀咧七,需要使用socketcan_bridge_node
來防止每個發(fā)送的消息都回顯到接收主題。
4.2.1 socketcan_bridge_node
從 SocketCAN 設(shè)備接收幀并將這些幀發(fā)布到主題上任斋,同時它偵聽 CAN 消息并將這些消息發(fā)送到 SocketCAN继阻。發(fā)送到 CAN 設(shè)備的幀不會作為接收消息發(fā)布。
訂閱的話題名稱:
sent_messages
(can_msgs/Frame)废酷,此處收到的消息將被發(fā)送到 SocketCAN 設(shè)備瘟檩。發(fā)布的話題名稱:
received_messages
(can_msgs/Frame),在 SocketCAN 設(shè)備上接收到的幀在本主題中發(fā)布澈蟆。ROS節(jié)點參數(shù):~
can_device
(string, default: can0)墨辛,SocketCAN 設(shè)備的名稱,默認情況下這些設(shè)備被命名為can0及以上趴俘。
4.2.2 socketcan_to_topic_node
將在 SocketCAN 設(shè)備上接收到的幀發(fā)布到topic睹簇。
發(fā)布的話題名稱:received_messages (can_msgs/Frame)奏赘,在 SocketCAN 設(shè)備上接收到的幀在本主題中發(fā)布。
ROS節(jié)點參數(shù):~
can_device
(string, default: can0)太惠,SocketCAN 設(shè)備的名稱磨淌,默認情況下這些設(shè)備被命名為can0及以上。
4.2.3 topic_to_socketcan_node
將收到的topic的 CAN 消息發(fā)送到 SocketCAN 設(shè)備凿渊。
訂閱的話題名稱:
sent_messages
(can_msgs/Frame)梁只,此處收到的消息將被發(fā)送到 SocketCAN 設(shè)備。ROS節(jié)點參數(shù):~
can_device
(string, default: can0)嗽元,SocketCAN 設(shè)備的名稱敛纲,默認情況下這些設(shè)備被命名為can0及以上。
4.3 基于ROS中轉(zhuǎn)節(jié)點松耦合的CAN通信
4.3.1 松耦合需求的原因
對于一些成熟的包剂癌,或者比較復(fù)雜的包淤翔,要想把其中的topic轉(zhuǎn)為CAN數(shù)據(jù)發(fā)出去,有兩種修改方式:
- 直接修改源碼中相應(yīng)topic的數(shù)據(jù)類型佩谷,或者在源碼中新發(fā)布一個can_msgs/Frame數(shù)據(jù)類型旁壮,名稱為sent_messages的topic
- 新建一個中轉(zhuǎn)節(jié)點,接收該復(fù)雜節(jié)點的topic(消息類型為該復(fù)雜節(jié)點的消息類型)谐檀,將其轉(zhuǎn)換為一個can_msgs/Frame數(shù)據(jù)類型抡谐,名稱為sent_messages的topic,將反饋的can信息桐猬,通過指定的topic麦撵,反饋給該復(fù)雜節(jié)點。
第二種方式更為簡單和快速溃肪,但會增加通信中轉(zhuǎn)延時免胃,ROS的節(jié)點通信是基于TCP/IP,對于本機節(jié)點通信而言惫撰,此延時大概在1ms以內(nèi)(百兆網(wǎng)卡以上)羔沙。
4.3.2 中轉(zhuǎn)節(jié)點
對于該中轉(zhuǎn)節(jié)點,需要訂閱兩個topic厨钻,發(fā)布兩個topic
- 訂閱:
- 復(fù)雜節(jié)點發(fā)布的topic
- socketcan_bridge_node節(jié)點的topic:
received_messages
- 發(fā)布:
- 復(fù)雜節(jié)點訂閱的topic
- socketcan_bridge_node節(jié)點的topic:
sent_messages
4.3.3 CAN數(shù)據(jù)幀
socketcan_bridge_node的話題的消息類型都為ROS內(nèi)置消息類型can_msgs/Frame
:
Header header
uint32 id
bool is_rtr
bool is_extended
bool is_error
uint8 dlc
uint8[8] data
需要填充的數(shù)據(jù)是
-
id
:CAN ID -
dlc
:數(shù)據(jù)長度扼雏,一般為8 -
is_extended
:是否是拓展幀,一般為0 -
uint8[8] data
:can數(shù)據(jù)
4.3.4 使用
一般把該中轉(zhuǎn)節(jié)點與socketcan_bridge_node放在一個launch文件中夯膀。
如果socketcan_bridge_node節(jié)點的名稱沖突了诗充,可以在launch文件中添加group,或者remap話題名稱诱建。
五其障、總結(jié)
推薦CANable + socketcan_bridge包實現(xiàn)ROS中的CAN通信!
Github:https://github.com/wanghuohuo0716/ros_can_driver
ROS socketcan_bridge包使用參考:
https://blog.csdn.net/zyf_to_utopia/article/details/116209605
https://blog.csdn.net/m0_58322903/article/details/121630592
https://blog.csdn.net/wangrunhuan/article/details/117962857
SocketCAN介紹:
https://en.wikipedia.org/wiki/SocketCAN