おうちでできるCAN通信（Arduino+MCP2515+sigrok）

# はじめに
ArduinoマイコンとMCP2515 CANモジュール、オープンソースのロジックアナライザ [sigrok](https://sigrok.org/)を使い、安価で手軽にCAN通信を実験できる環境を構築します。

# 準備するもの
### ハードウエア
- Arduino Unoマイコンボード x1 (または、互換ボード）
- MCP2515 CAN通信モジュール x2　([Amazon](https://www.amazon.co.jp/s?k=MCP2515&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss)で１個あたり500円程度で入手できます）
- USBロジックアナライザ ([Amazon](https://www.amazon.co.jp/s?k=8%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%ABUSB+%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%E3%82%A2%E3%83%8A%E3%83%A9%E3%82%A4%E3%82%B6&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss)で1000円～入手できます。:smiling_imp:） 

### ソフトウエア
- [Arduino IDE](https://www.arduino.cc/en/main/software)
- [Sigrok/PulseView](https://sigrok.org/wiki/Windows) オープンソースのロジックアナライザ
- [MCP_CAN_lib](https://github.com/coryjfowler/MCP_CAN_lib) Arduino MCP2515ライブラリ

Seeed-Studioの[CAN-BUS Shield用ライブラリ](https://github.com/Seeed-Studio/CAN_BUS_Shield)など類似のCAN用ライブラリが多数存在し、コマンドに微妙な差あるので注意が必要です。今回はMCP_CAN_libを用います。

# ハードウエアの結線
- 2台のMCP2515間でCAN通信を行います。
- ArduinoからSPI通信でMCP2515を制御するため、以下のように接続します。
- Pin9,Pin10をCS端子に接続し、２台を切り替えできるようにしています。
- 終端抵抗を有効にするため、J1-J2間のジャンパを接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/a67f3414-a275-0275-4bf3-c499b0683aed.png)

# 動作確認
## テスト用ソースコード
- 本プログラムでは、一定周期(100ms)毎に、CAN0モジュールからCAN ID(0x100,0x101)にデータを送信し、CAN1モジュールで受信します。
- CAN.begin関数でCANのビットレート(250KBps)とMCP2515のクロック(8MHz／水晶発振器の刻印)を設定します。 


```ruby:CAN_Send_Recieve_Test.ino
// MCP2515 CAN Send and Recieve Test

#include <mcp_can.h> //https://github.com/coryjfowler/MCP_CAN_lib
#include <SPI.h>

unsigned long rxId;
byte len;
byte rxBuf[8];
byte txBuf0[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
byte txBuf1[] = {0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8};
long Pre_millis;

MCP_CAN CAN0(10);// CAN0 CS: pin 10
MCP_CAN CAN1(9); // CAN1 CS: pin 9

void setup()
{
  Serial.begin(115200);
  
  // init CAN0 bus, baudrate: 250kbps@8MHz
  if(CAN0.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK){
    Serial.println("CAN0: Init OK!");
    CAN0.setMode(MCP_NORMAL);
  } else{ 
    Serial.println("CAN0: Init Fail!");
  }

  // init CAN1 bus, baudrate: 250kbps@8MHz
  if(CAN1.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ) == CAN_OK){
    Serial.println("CAN1: Init OK!");
    CAN1.setMode(MCP_NORMAL);
  }else{ 
    Serial.println("CAN1: Init Fail!");
  }

  Pre_millis = millis();
}

void loop(){
  static int count=0; 
  if(millis()-Pre_millis > 100){ // Period: 100ms
    CAN0.sendMsgBuf(0x100, 0, 8, txBuf0);
    CAN0.sendMsgBuf(0x101, 0, 8, txBuf1);
    Serial.println("Send ID: 0x100,0X101");
    Pre_millis=millis();
  }
  
  if(CAN1.checkReceive()==CAN_MSGAVAIL){
    CAN1.readMsgBuf(&rxId, &len, rxBuf);
    Serial.print("Recive ID: ");
    Serial.print(rxId, HEX);
    Serial.print(" Data: ");
    for(byte i = 0; i<len; i++){
      Serial.print(rxBuf[i], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}
```
## ビルド
1. あらかじめ、ArduinoのライブラリフォルダにMCP_CAN_libを入れておきます。
2. 上記、テスト用のソースコードをArduino IDEでビルドします。

## シリアル通信によるモニター
シリアル通信でデータの送受信を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/902aa451-2393-13a5-a2ee-0c8ff7c3edba.png)
##ロジックアナライザ(sigrok/PulseView)によるCANデータの確認
1. ロジックアナライザのGNDをArduinoのGNDピン、CH0をLAN Lピンに接続します。
2. PulseViewを起動します。
3. サンプリング数とサンプリング周波数を設定します。(2M samples ,2MHz)
4. Decoderアイコンをクリックし、CANを追加します。
5. CANの設定でCh=D0,Nominal bitrate(bits/s)=250000に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/4a116d62-52c9-a52d-f6d8-bfcb6152edbb.png)
6. Runで計測します。
7. パルス波形を拡大すると、CANデータのプロトコルを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329764/b4c7a6cd-bc1c-ab4b-0b04-01a355f7bc92.png)


# さいごに
外出自粛の中、おうちでCAN通信を試してみました。:sunglasses: