CAN(Controller Area Network)とは
CANは耐ノイズ性、高信頼性が特徴のシリアル通信プロトコルで、主に車載ネットワーク
において「電子制御ユニット(ECU:Electronic Control Unit)」間の通信で利用されてい
ます。ネットワークトポロジー(接続の構成)は「バス型(1つの共通の通信路を持ちます)」
で、バスが空いている時に、どのノード(バスに接続された機器)でもマスターになって通
信を開始することができる「マルチマスター方式」が特徴です。
高速通信が可能なバスとして車載以外でも利用されており、例えば当社が展開する
「ソリューションセット」の1つである「ポンプ設備の安心パック」でもCAN接続の振動
センサーをラインナップの1つとしてご用意しております。
標準装備で、しかも2系統!!
CONEXIOBlackBearには「CAN Version 2.0B active」規格に準拠した2系統のCANイ
ンターフェースを搭載しています。2系統分の信号を1つのコネクタに集約した専用のCAN
コネクタ(本体の下図部分)に接続してご利用頂けます。
※そもそもCONEXIOBlackBearってなに?という方はこちらの記事をご確認ください!
肝心のソフトウェアは?
CANプロトコルを制御するソフトウェアとしては「SocketCAN」フレームワークを利用できます。そのためLinuxのネットワークプログラミングでよく利用するソケットAPIの感覚でCANフレームの送受信制御を実現できます。(慣れているエンジニアさんは、たくさんいらっしゃいますよね!)
CとPythonのサンプルプログラムを紹介します
使用するプログラミング言語には好み?があると思いますが、今回はC言語とPython言語のサンプルコードの勘所をご紹介します!(ポイントだけになりますがご容赦ください…)せっかくなので「ポンプ設備の安心パック」で使用しているCAN接続の振動センサー「LPMS-IG1 CAN」のCANフレーム受信をやってみましょう!実はこのセンサーは、CANフレームのデータフォーマットをカスタマイズすることが可能であり、今回は下記のように設定しました。
【振動センサーの設定内容】
LPMS-IG1 CAN(LP-RESEARCH社)
https://lp-research.com/9-axis-imu-with-gps-receiver-series/
CONEXIOBlackBearのCANインターフェースを使用する場合、プログラミング言語を問わず、まず下記のコマンドでCANインターフェースを有効化する必要があります(can0ポートをボーレート250kbpsで有効にする場合)。
# ip link set can0 up type can bitrate 250000
# ifconfig can0 up
C言語のサンプル
まずSocketCANを初期化します(「linux/can.h」をIncludeしてください)。
ソケットAPIを使用して、対象のCANポート用のソケットを作成します。
soc = socket(PF_CAN, SOCK_RAW, CAN_RAW);
addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, "can0");
ioctl(soc, SIOCGIFINDEX, &ifr);
addr.can_ifindex = ifr.ifr_ifindex;
bind(soc, (struct sockaddr *)&addr, sizeof(addr));
感の良い方はもうお気付きですね。あとはread()するだけでCANフレームを受信できます!
recvbytes = read(soc, &frame_rd, sizeof(struct can_frame));
受信したCANフレーム内の各フィールドの内容は、「linux/can.h」で定義された「struct
can_frame」構造体のメンバーー(can_id、can_dlc、data[]など)で参照が可能です。
では、コンパイルして実行してみましょう。CANフレームを受信しました!!
# gcc can_rcv_sample.c -o can_rcv_sample
# ./can_rcv_sample
ID=0x181 rcv 8 : d0 ff 02 00 1e 00 50 0b
ID=0x181 rcv 8 : d0 ff 04 00 1f 00 50 0b
Python言語のサンプル
SocketCANが利用可能な「python-can」ライブラリをインストールしてみましょう!
pip3 install python-can
CANフレームのダンプ(受信CANフレームの内容表示)なら数行で実現できますよ。
#!/usr/bin/python3
import can
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
notifier = can.Notifier(bus, [can.Printer()])
while True:
pass
実行してみましょう。受信したCANフレームの内容が表示されました!!
# python3 ./can_rcv_sample.py
Timestamp: 1625657765.480975 ID: 0181 S DLC: 8 d1 ff 07 00 1f 00 e0 0b Channel: can0
Timestamp: 1625657765.483183 ID: 0181 S DLC: 8 cf ff 07 00 21 00 e0 0b Channel: can0
車載システムをご検討のお客様、CONEXIOBlackBearで実現してみませんか?