Sony Spresense 用 CAN AddOnボードの動作確認方法の情報共有

# この記事は何?
Spresenseの[CAN AddOnボード](https://nextstep.official.ec/items/38434337)を購入しました。
CAN通信が送信・受信が確認できました。確認手順を共有します。

# 確認環境
## ホストPC
* macOS Ventura 13.2.1

## ハードウェア
* [Spresenseメインボード](https://developer.sony.com/develop/spresense/docs/introduction_ja.html#_spresense_%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%89)
* [CAN AddOnボード](https://nextstep.official.ec/items/38434337)

## ソフトウェア
* Arduino IDE 2.0.4
* Spresense Arduino 2.6.0
* [MCP_CAN Library for Arduino ※2023/3/20時点の最新コミット](https://github.com/coryjfowler/MCP_CAN_lib/tree/4c5032361584b6ac15536fbb30b2493431af8ae9)


# 動作確認手順
動作確認は基本、[こちらの参考記事](https://qiita.com/kaz19610303/items/c43bdd8134b3a47b0e3e)とおりにおこなっていきました。該当記事から時間が経っているため、MCP_CAN Library for Arduinoが更新されていました。この記事では参考記事と若干違う手順になっています。

## MCP_CAN Library for Arduinoのインストール
CAN AddOnボードのCANコントローラはMCP2515です。このコントローラを制御するライブラリがMCP_CAN Library for Arduinoです。このライブラリをGitHubからダウンロードします。
私は[動作確認時の最新コミット](https://github.com/coryjfowler/MCP_CAN_lib/tree/4c5032361584b6ac15536fbb30b2493431af8ae9)をzip形式でダウンロードし、Arduino IDEのメニューからインストールしました。

## コードの変更
スケッチ例の中の MCP_CAN_lib-master -> CAN_loopbackを選択します。こちらのCAN_loopback.inoをベースにして確認を進めていきます。

### ピン配置
つぎのピン配置に変更しました。

```diff_c
// CAN0 INT and CS
-#define CAN0_INT 2                              // Set INT to pin 2
-MCP_CAN CAN0(10);                               // Set CS to pin 10
#define CAN0_INT 20                             // Set INT to pin D20
MCP_CAN CAN0(19);                               // Set CS to pin D19
```

### MCP2515周波数設定
CAN AddOnボードの周波数は8MHzのため周波数設定を変更しました。

```diff_c
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
-  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
```

### MCP_CAN Library for Arduino
SpresenseとCAN　AddOnボードはSPI5で接続しています。SpresenseはSPI５でMCP２５１５を制御する必要があるためmcp_can.cppを修正します。

```diff_cpp
MCP_CAN::MCP_CAN(INT8U _CS)
{
    MCPCS = _CS;
    MCP2515_UNSELECT();
    pinMode(MCPCS, OUTPUT);
-    mcpSPI = &SPI;
    mcpSPI = &SPI5;
}
```

私の環境の場合、mcp_can.cppはつぎのディレクトリに格納されていました。

* /Users/ユーザー名/Documents/Arduino/libraries/mcp_can/mcp_can.cpp

[参考記事](https://qiita.com/kaz19610303/items/c43bdd8134b3a47b0e3e)にも書いてある通りSpresense以外のArduinoでMCP_CAN Library for Arduinoを使いたい場合は、元のコードに戻す必要があるのでご注意ください。

## ジャンパー設定
### INTピン
CAN AddOnボードではMCP2515のINTピンの接続をジャンパーで設定可能です。
今回は参考記事のとおりJP１の1-2間をはんだショートします。
これでSpresenseのD20ピンとMCP2515のINTピンが接続されます。

### CSピン
CAN AddOnボードではMCP2515のCSピンの接続をジャンパーで設定可能です。
今回は参考記事のとおりJP2の1-2間をはんだショートします。
これでSpresenseのD19ピンとMCP2515のCSピンが接続されます。

### 終端抵抗
CAN AddOnボードのJP3をショートすることで120オームの終端抵抗を接続できます。今回はJP3はオープンのまま、終端抵抗なしの設定とします。

## コンパイル・書き込み
Arduino IDEでコンパイル・書き込みをおこないます。

## 動作確認
# ループバックモード
ループバックの動作を確認してみます。
SpresenseメインボードのUSB miniBコネクタにUSBケーブルを接続し電源供給すると動作が開始されます。
Arduino IDEのシリアルモニタを立ち上げると下図が表示されていました。

![loopbackmode動作確認結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/61703bee-68f6-ba27-b1e9-f67c7e943eb0.png)

送信成功のつぎのメッセージが表示されています。

```
Message Sent Successfully!
```

ループバックモードなので送信データを受信します。受信するとCAN ID, データ長、受信データを表示します。つぎのメッセージが表示されているので受信できていると判断しました。

```
Standard ID: 0x100 DLC: 8 Data: 0xAA 0x55 0x01 0x10 0xFF 0x12 0x34 0x56
```

# ノーマルモード
つぎはノーマルモードにしてCANバスに接続されている他のデバイスと通信できるか確認します。

## コード変更
ノーマルモードにするにはつぎのコードを変更します。

```diff_cpp
void setup()
{
  Serial.begin(115200);  // CAN is running at 500,000BPS; 115,200BPS is SLOW, not FAST, thus 9600 is crippling.
  
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  // Since we do not set NORMAL mode, we are in loopback mode by default.
-  //CAN0.setMode(MCP_NORMAL);
  CAN0.setMode(MCP_NORMAL);

  pinMode(CAN0_INT, INPUT);                           // Configuring pin for /INT input
  
  Serial.println("MCP2515 Library Loopback Example...");
}
```

コード変更が終わったらコンパイル、書き込みをします。

## 配線
CANバスにCAN AddOnボード、通信相手のデバイスを接続します。
今回は自宅にあったNI-CAN(NI USB-8473)を接続しました。
CAN AddOnボード、NI-CANは終端していないので下図のようにブレッドボード上に120Ωの終端抵抗を挿し接続しました。

![接続写真7256_サイズ調整.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/61a00b74-0a17-6473-3337-3c5ce1bcfd69.png)


## 通信相手の設定
通信相手のボーレート、ビットタイミングを確認、調整します。
対象にしたソースコードののボーレート設定(CAN_500KBPS, MCP_8MHZ)を追うとサンプルポイントは75%になっていることがわかりました。
よって、通信相手のボーレート、ビットタイミングも同様に設定します。
下図が通信相手(NI-CAN)のボーレート、ビットタイミングの設定画面です。

![ボーレート、タイミング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/52f2a419-4f80-6d2d-ba48-c11a6f9cfe5a.png)

## 動作確認結果
接続ができたらCAN AddOnボード、NI-CANに電源を供給します。

# CAN AddOnボードの送信確認
CAN AddOnボードの送信を確認します。
NI-CANは受信データを確認できるバスモニタ機能があるのでこちらで確認します。
バスモニタを起動すると下図のようにCAN AddOnボードの送信データが確認できました。
バスモニタのタイムスタンプも1秒毎に更新されていたのでCAN AddOnボードの送信間隔も問題なさそうです。

![バスモニタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/f5de7571-026b-0de5-94f3-7125ad7e658c.png)

# CAN AddOnボードの受信
NI-CANではCAN送信する方法がわかりませんでした。
別なデバイスとCAN AddOnボードを接続し、別なデバイスからCAN送信をおこなったところ、CAN ID, データ長、受信データを示すシリアルメッセージが表示されていたので受信も問題なさそうです。

# まとめ
SpresenseとCAN AddONボードでループバックモード、ノーマルモードでCAN通信が確認できました。
SpresenseメインボードとCAN AddONボードを接続しても未使用IOポートがあるのでセンサなどを接続し、意味のあるメッセージをセットしてCANデータ送信を確かめてみたいと考えています。

読んでいただきありがとうございました。