【CONEXIOBlackBearでこんなことをやってみた】CANでつないでみた！

# CAN（Controller Area Network）とは

CANは**耐ノイズ性、高信頼性が特徴のシリアル通信プロトコル**で、主に車載ネットワーク
において「電子制御ユニット(ECU：Electronic Control Unit)」間の通信で利用されてい
ます。ネットワークトポロジー(接続の構成)は「バス型(1つの共通の通信路を持ちます)」
で、バスが空いている時に、どのノード(バスに接続された機器)でもマスターになって通
信を開始することができる<strong>「マルチマスター方式」</strong>が特徴です。
高速通信が可能なバスとして車載以外でも利用されており、例えば当社が展開する
「ソリューションセット」の1つである[**「ポンプ設備の安心パック**」](https://conexio-iot.jp/serviceproduct/pump-solution.html?utm_source=qiita&utm_medium=blog&utm_campaign=qiita&utm_id=qiita)でもCAN接続の振動
センサーをラインナップの1つとしてご用意しております。</dd>
# 標準装備で、しかも2系統！！
[**CONEXIOBlackBear**](https://conexio-iot.jp/serviceproduct/blackbear.html?utm_source=qiita&utm_medium=blog&utm_campaign=qiita&utm_id=qiita)には「CAN Version 2.0B active」規格に準拠した2系統のCANイ
ンターフェースを搭載しています。2系統分の信号を1つのコネクタに集約した専用のCAN
コネクタ(本体の下図部分)に接続してご利用頂けます。
![ブログ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2637100/dfbffadd-7c6d-7e83-e3ba-ec1dc1be84ec.png)

※そもそも**CONEXIOBlackBear**ってなに？という方はこちらの記事をご確認ください！

https://qiita.com/conexioIoT/items/6de49b078bf3a59436ba

# 肝心のソフトウェアは？
CANプロトコルを制御するソフトウェアとしては「SocketCAN」フレームワークを利用できます。そのためLinuxのネットワークプログラミングでよく利用するソケットAPIの感覚でCANフレームの送受信制御を実現できます。(慣れているエンジニアさんは、たくさんいらっしゃいますよね！)

# CとPythonのサンプルプログラムを紹介します
使用するプログラミング言語には好み？があると思いますが、今回はC言語とPython言語のサンプルコードの勘所をご紹介します！(ポイントだけになりますがご容赦ください…)せっかくなので「ポンプ設備の安心パック」で使用しているCAN接続の振動センサー「LPMS-IG1 CAN」のCANフレーム受信をやってみましょう！実はこのセンサーは、CANフレームのデータフォーマットをカスタマイズすることが可能であり、今回は下記のように設定しました。

### 【振動センサーの設定内容】
![ブログ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2637100/417faf72-d865-542a-2e30-7503d4767d28.png)
### LPMS-IG1 CAN（LP-RESEARCH社）
https://lp-research.com/9-axis-imu-with-gps-receiver-series/
![ブログ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2637100/1305e399-7cee-af1c-71d0-086833052873.png)

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**](https://conexio-iot.jp/serviceproduct/blackbear.html?utm_source=qiita&utm_medium=blog&utm_campaign=qiita&utm_id=qiita)で実現してみませんか？**