USB to CAN モジュールをの使い方
この記事では、USB to CAN モジュール(Amazonで購入)を使用して、Ubuntu 22.04環境でCAN通信を監視する方法を紹介します.
動作環境
- OS: Ubuntu 22.04
-
CANアダプタ: USB to CAN モジュール CANable2
購入した商品はこちら → Amazonリンク - CANツール: can-utils、python-can
- Pythonバージョン: 3.12
必要なツールのインストール
まずは、CAN通信に必要なパッケージをインストールします.
1. can-utilsのインストール
ターミナルで以下のコマンドを実行してください.
sudo apt-get update
sudo apt-get install can-utils
2. python-canのインストール
Pythonライブラリpython-can
をインストールします.
pip3 install python-can
(※ pipを利用できない場合は、apt-get install python3-can
などで)
USB-CANアダプタの接続と初期確認
CANable2をUSBポートに接続すると、以下のようにシリアルデバイスとして認識されます.
ls /dev/ttyACM*
# 出力例:
# /dev/ttyACM0
この結果から、CANable2はSLcanモードで動作していると判断できます.
SLcanモードでのCANインターフェース作成
SLcanモードの場合、slcand
コマンドを用いてシリアルデバイスからCANネットワークインターフェース(通常はcan0)を作成します.以下の手順で進めます.
1 . カーネルモジュールのロード
sudo modprobe slcan
sudo modprobe can
sudo modprobe can_raw
2 . CANインターフェースの作成と起動
ここでは1000 kbps(1 Mbps)を想定し、-s8
オプションで設定します.
sudo slcand -o -c -s8 /dev/ttyACM0 can0
sudo ip link set can0 up
3 . 通信の確認
CAN通信が流れていれば、candump
コマンドで確認できます.
candump can0
※ 何も表示されない場合は、CANバス上にメッセージが流れていない可能性があります.テストでメッセージを送信するなどして動作を確認してください.
Pythonとcursesによるリアルタイムモニタリング
CANバス上のメッセージは非常に多く流れるため、candump
では見づらくなりがちです.そこで、Pythonを使って各CAN IDごとに最新の情報を表形式で表示するモニタリングツールを作成しました.
以下は、Pythonとcursesを用いたサンプルコードです.
#!/usr/bin/env python3
import curses
import can
import time
def main(stdscr):
# カーソルを非表示にし、入力待ちをしない設定
curses.curs_set(0)
stdscr.nodelay(True)
# SocketCANを利用してcan0から受信(必要に応じてbitrate指定)
bus = can.interface.Bus(channel='can0', bustype='socketcan')
# 各CAN IDの最新メッセージと受信回数を記録する辞書
messages = {}
counts = {}
while True:
try:
# タイムアウト付きでメッセージを受信(0.1秒待機)
msg = bus.recv(timeout=0.1)
if msg is not None:
# 受信したCAN IDをキーに最新メッセージを保存し、受信回数を更新
messages[msg.arbitration_id] = msg
counts[msg.arbitration_id] = counts.get(msg.arbitration_id, 0) + 1
# 画面をクリアして再描画
stdscr.clear()
stdscr.addstr(0, 0, "CAN Bus Monitor - Real Time Table")
stdscr.addstr(1, 0, "Press Ctrl+C to exit")
header = "ID Count DLC Data"
stdscr.addstr(3, 0, header)
stdscr.hline(4, 0, '-', len(header)+4)
row = 5
# 受信したCAN IDを昇順に表示
for can_id in sorted(messages.keys()):
m = messages[can_id]
count = counts[can_id]
# IDは16進数表記に変換
id_str = f"0x{can_id:X}"
dlc = m.dlc
# データバイトを2桁の16進数で表示
data_str = " ".join(f"{byte:02X}" for byte in m.data)
line = f"{id_str:8} {count:6} {dlc:5} {data_str}"
stdscr.addstr(row, 0, line)
row += 1
stdscr.refresh()
time.sleep(0.01) #安定化のため.なくても可能
except KeyboardInterrupt:
break
if __name__ == "__main__":
curses.wrapper(main)
-
CAN受信:
bus.recv(timeout=0.1)
により、タイムアウト付きでCANメッセージを受信し、各IDごとに最新のメッセージと受信回数を辞書に保存します. -
画面表示:
curses
ライブラリを用いて、画面全体をクリアした後、ヘッダーと各CAN IDの最新情報(ID、受信回数、DLC、データ)をリアルタイムに再描画します. -
実行方法:
このコードを例えばcan_monitor.py
として保存し、以下のコマンドで実行します.python3 can_monitor.py
実行前にカーネルモジュールのロードとCANインターフェースの作成と起動をしている必要があります
終了はCtrl+Cで行います.
CAN pic.twitter.com/adoC47S545
— -Altair- (@Flying___eagle) March 9, 2025
まとめ
-
CANable2の動作確認:
USB接続後、SLcanモードで認識されるので、/dev/ttyACM0
として確認できます. -
CANインターフェースの作成:
slcand
コマンドを用い、1000 kbpsに設定してcan0
インターフェースを作成しました. -
リアルタイムモニタリング:
Pythonのpython-can
とcurses
を組み合わせ、各CAN IDごとに最新メッセージを表形式で表示するツールを作成。流れる大量のメッセージから必要な情報を効率的に監視できます.
また,送信もできるようなのでロボマスモーターをPCから直接動かせたりするのは面白そうですね.