6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

仮想CAN通信でHello, world!

Posted at

概要

車載組み込み用途に利用されるCAN通信をPC内にてシミュレーションしてみます。
CANについては以下記事に詳細が書かれています。
https://qiita.com/fattolys/items/e8f8081d3cb42d7da0f6

以下は今回作成するシステムのネットワークの構成です。
Nord2からNord1にCANパケットを投げます。
vcan.jpg

環境

  • 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に流れるて来たパケットを逐次表示するようにします。

vcan_nord_1.py
# 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"のパケットを投げます。

vcan_nord_2.py
# 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側のターミナルに、パケットが届いたことが表示されます。
Peek 2020-02-16 16-35.gif

今後

Unityなどの3DCGプラットフォーム内で動く車をvcan通信で作ってみると面白いかもですね。

参考サイト

https://elinux.org/Bringing_CAN_interface_up
https://elinux.org/Python_Can

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?