2021年7月11日日曜日

CANをArduinoで使ってみた


背景

CANとは、Controller Area Networkの略であり、CAN busとも呼ばれる自動車の電装間通信などに利用される通信規格です。
I2Cよりノイズに強そうだったので、対応するチップを買ってArduinoで試してみました。

備忘録を兼ねて分かったことと取り組んだことを共有します。
なお、誤りなどがありましたら、コメントなどで指摘していただけると嬉しいです。

CANについて分かったこと

自分がCANについて知りたかったことをまとめます。

参考にしたサイト
CAN bus -Wikipedia
Standard CAN vs Extended CAN

2.0Aの識別子は11ビット(2048種類)

2.0A規格規格で設定可能な識別子は11ビットでした。

2.0Bの拡張形式の識別子は11 + 18 = 29ビット(536870912種類)

2.0Bは拡張形式に対応しており、2.0Aの11ビットに18ビットを加えた29ビットが識別子として設定可能でした。

データは8バイト

2.0Aも2.0Bも、データの長さは同じ8バイトです。

全ての端末で発信と受信が可能

通信の衝突はCANの通信回路が回避してくれるため、情報の発信をどの端末からでも行なえ、全ての情報を各端末が参照可能なようです。

相手に値を送信する場合に利用するフラグがある: RTR

CANの通信網内で特定のIDで存在可能な端末は基本1台とされています。
(今回試したICではIDが被っていても通信できましたが、仕様としては重複しないのが良いです。)
Remote transmission request(略RTR)というフラグがあり、特定のIDの端末に値の送信要求や設定変更を行う場合はこれを有効にして情報を送信するのが仕様のようです。

使ったもの

ArduinoでCAN busを試すのに使った材料や道具はこれらです。
具体的な接続方法は後ほど共有します。
  • プログラムを書き込むためのPC
  • MicroB USBケーブル
  • ProMicro*3
    Arduino Leonardo互換のマイコンボードです
  • MCP25625を動かすセット * 3
    下記のどれかでMCP25625が使える回路を作ります。

    変換基板などを組み合わせて組み上げる場合
    • MCP25625
      2.0BのCANに対応したSPIで利用可能なICです。
      ProMicroなどのArduinoはCANの回路を持っていないので、このようなICを通してCANを利用します。
      秋月電子で買いました。
      CANトランシーバー MCP25625
    • SSOP28 DIP変換基板 + ピンヘッダ
      MCP25626を実装してブレッドボードに信号線を展開します。
    • はんだごて + はんだ
      SSOP変換基盤へのIC実装や、ProMicroの組み立てに利用しました。
    • 16MHz コンデンサ内蔵型セラロック
      MCP25626に接続します。
      内蔵のコンデンサは15pfのでも30pfのでも動きました。
      セラロックを利用する場合は125kbpsが上限です。
      1Mbpsなど125kbpsを超える通信速度で利用したい場合は、16MHzの水晶振動子と15pfくらいのコンデンサを組み合わせて使ってください。
    • 120Ω抵抗
      CANの終端に接続します。
    • 0.1ufコンデンサ
      MCP25626の電源周辺に接続します。

    便利基板を使う場合
    • MCP25625-breakout
      MCP25625の駆動に必要な発振子、抵抗、コンデンサなどをまとめた基板です。

    この記事ではMCP25625を使いますが、新規製品への利用が推奨されていないMP2515とCANトランシーバーがセットになった装置でも動かせると思います。
  • ブレッドボード * 3
  • 硬いジャンパワイヤ
    ブレッドボード上の信号線の接続に利用します。
  • ワイヤストリッパー
    硬いジャンパワイヤを欲しい長さに切って被覆を剥くのに利用しました。
  • ジャンパワイヤ
    ブレッドボード間の接続に利用します。

今回組む通信網

ProMicro + MCP25625で作るCANの装置3台を用意し、CANで接続します。
MCP25625とProMicro間はSPIで通信します。


回路: ProMicro + MCP25625

1台の回路を説明します。
今回はこれを3台分作成しました。

MCP25625のデータシートを参考にしつつ下記回路図のように接続しました。
CSピンとして10番、INTピンとして7番を利用してます。


変換基板を利用して組み上げる場合

MCP25625は変換基盤だけだとピンの役割を都度データシートで確認するのが手間だったので、ビニールテープに役割を書いて貼り付けました。



ビニールテープを貼りやすいように、ピンヘッダの頭を短くしてはんだ付けしています。



組み立てるとこうなりました。



便利基板を利用する場合

MCP25625-breakoutを利用する場合は、ジャンパワイヤでProMicroと必要な線を接続すれば済みます。
CSピンとして10番、INTピンとして7番を利用してます。



3つのCAN装置を接続

接続するとこうなりました。


CANHとCANLを繋ぐ終端抵抗120Ωは、その名の通り終端に付けるものなので、中間のMCP25625には取り付けていません。
(台数が少なく信号線も短いからか、今回の回路なら取り付けていても通信できはしました。)

端の回路には抵抗を設置しています。


便利基板は端の回路なので、終端抵抗切り替えスイッチをUSEにして抵抗を有効にしています。


3つを繋げた通信網でCAN通信の動作確認を行います。

プログラム開発環境の準備

既存のライブラリが使いにくく感じたのでライブラリを作りました。
名前がMCP2515となっていますが、今回利用したMCP25625にも使えます。

https://github.com/asukiaaa/CanBusMCP2515-arduino

開発環境への設定方法を解説します。

Arduino IDEの場合

ライブラリマネージャからCanBusMCP2515_asukiaaaをインストールしてください。


PlatformIOの場合

下記のようにplatformio.iniのlib_depに記述すると利用できます。

platformio.ini
lib_deps = CanBusMCP2515_asukiaaa

loopback機能を利用した単体でのテスト

MCP25625はloopbackという、CAN通信しないもののSPIで送信データを受信したデータとして返却する機能があるので、それを利用するとSPI通信できているか確認できます。

loopbackで動作確認用のプログラムはArduino IDEだとスケッチ例から開けます。


PlatformIOの場合はgithubのコードからコピーするのが分かりやすいと思います。

書き込んでシリアルモニタを確認して、下記のように自分が送信したものを受信できていればマイコンとMCP24625が期待通りに接続されている状態です。
Sent
id: 3000, rtr: false, ext: true, bytes: 152 27 0 0 0 0 0 0
Succeeded at 7064
Received
id: 3000, rtr: false, ext: true, bytes: 152 27 0 0 0 0 0 0
at 7069

MCP25625の配線や設定が不十分な場合は下記のように初期化設定時のエラーが表示されます。
Configuration error: 0x1

エラーコードはDriver.hのErrorクラスにまとめているので、内容を把握したい場合はそちらを参照してください。

通信動作確認

作った3つの装置をCANで通信します。
送信と受信のサンプルプログラムを利用します。


github上のコード: examples/sendAndReceive/sendAndReceive.ino

16MHzのセラロックを利用するため、周波数16MHz、ビットレートは125kbpsを利用します。
(プログラムはどちらも標準でそうなっています。)
static const auto QUARTZ_FREQUENCY =
CanBusMCP2515_asukiaaa::QuartzFrequency::MHz16;
static const auto BITRATE = CanBusMCP2515_asukiaaa::BitRate::Kbps125;

IDとして左から3001、3002、3003を割り当てます。


プログラムのCAN_IDを変えつつ書き込みます。
#define CAN_ID 3001

書き込んだらシリアルモニタでログを確認します。
今回はID3001の装置のログを確認しました。
Sent
id: 3001, rtr: false, ext: true, bytes: 149 86 0 0 0 0 0 0
Succeeded at 22165
Received
id: 3002, rtr: false, ext: true, bytes: 182 86 0 0 0 0 0 0
at 22209
Received
id: 3003, rtr: false, ext: true, bytes: 115 90 0 0 0 0 0 0
at 23165

ID3001として発信している自分の情報は受信しませんが、他の3002と3003から発信される情報を受信しているのを確認できました。

まとめ

MCP25625を利用してCANの通信網を作り、125kbpsのCAN通信でArduino間のやりとりができました。

0 件のコメント :