概要
車載組み込み用途に利用されるCAN通信をPC内にてシミュレーションしてみます。
CANについては以下記事に詳細が書かれています。
https://qiita.com/fattolys/items/e8f8081d3cb42d7da0f6
以下は今回作成するシステムのネットワークの構成です。
Nord2からNord1にCANパケットを投げます。
環境
- Python 3.7
- Ubuntu 18.04
仮想インターフェイス作成
以下コマンドにより、仮想CANインターフェイスを作ります。
$ modprobe vcan
$ sudo ip link add dev vcan0 type vcan
$ sudo ip link set up vcan0
ifconfigを打つと以下のようにvcan0が追加されていることがわかります。
$ ifconfig
vcan0: flags=193<UP,RUNNING,NOARP> mtu 72
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Nord 1コード作成
Nord 1はvcan0に流れるて来たパケットを逐次表示するようにします。
# ref: https://elinux.org/Python_Can
import socket
import struct
# CAN frame packing/unpacking (see `struct can_frame` in <linux/can.h>)
can_frame_fmt = "=IB3x8s"
def build_can_frame(can_id, data):
can_dlc = len(data)
data = data.ljust(8, b'\x00')
return struct.pack(can_frame_fmt, can_id, can_dlc, data)
def dissect_can_frame(frame):
can_id, can_dlc, data = struct.unpack(can_frame_fmt, frame)
return (can_id, can_dlc, data[:can_dlc])
# create a raw socket and bind it to the given CAN interface
s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
s.bind(("vcan0",))
while True:
cf, addr = s.recvfrom(16)
print('Received: can_id=%x, can_dlc=%x, data=%s' % dissect_can_frame(cf))
Nord 2コード作成
Nord2はvcan0に対し、"hellowld"のパケットを投げます。
# ref: https://elinux.org/Python_Can
import socket
import struct
# CAN frame packing/unpacking (see `struct can_frame` in <linux/can.h>)
can_frame_fmt = "=IB3x8s"
def build_can_frame(can_id, data):
can_dlc = len(data)
data = data.ljust(8, b'\x00')
return struct.pack(can_frame_fmt, can_id, can_dlc, data)
# create a raw socket and bind it to the given CAN interface
s = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
s.bind(("vcan0",))
try:
s.send(build_can_frame(0x01, b'hellowld'))
except socket.error:
print('Error sending CAN frame')
動作確認
vcan_nord_1.pyをターミナルで起動しておき、別ターミナルでvcan_nord_2.pyを実行してください。
以下のように、vcan_nord_1.py側のターミナルに、パケットが届いたことが表示されます。
今後
Unityなどの3DCGプラットフォーム内で動く車をvcan通信で作ってみると面白いかもですね。
参考サイト
https://elinux.org/Bringing_CAN_interface_up
https://elinux.org/Python_Can