CANの信号波形をオシロスコープとアナライザで確認してみました。
電圧レベルの測定からプロトコルの解析まで実施しています。
CAN通信の基礎を初心者の方に分かりやすく紹介します。
CAN通信に入門!波形とプロトコルを確認してみた
CAN通信の波形測定・解析をしてみました。
ラズベリーパイとPythonでCAN通信のテストを行っています
オシロスコープでCAN通信の差動電圧レベルを確認できました。
1bitあたりの時間も確認してCANの通信速度も実際に測定しています
またアナライザでプロトコルを確認し、フレームの始めから終わりまで解析しました。
CAN通信のCRC・ACKの解析まで実施できました
CAN通信のテスト方法、測定の仕方まで詳細に紹介していきます。
CAN通信の仕組み
CAN通信の仕組みに関して概略だけ紹介させてもらいます。
CANは半2重通信の差動信号となっており、ノイズに強い通信となっています。
通信速度は最大で1Mbpsです。(実使用では125kbps~500kbpsの使用が多いということ)
自動車の中という過酷な環境でも安定した通信が可能となっています。
CAN通信と同じく、差動信号であるRS485通信に関しても下記記事で紹介しています。
参考になると思います。よろしければご覧ください。(リンク先はこちらから)
CAN通信の勉強を始める
CAN通信が初めて、また仕事で全く使っていない方も多くいるかと思います。
下記記事でも紹介しましたが、実際にデバッグすると理解が深まり力が付きます。
組み込みエンジニアのおすすめ勉強方法 ハードとソフト両方できる人に
今回も実際にハードの接続して、ソフトを用意してCAN通信を行います。
今回は1000円足らずで買えるCAN通信モジュールを使ってデバッグ・測定していきます。
ラズパイやArduinoとSPI接続でCAN通信可能です。(※ラズパイ接続には後述する改造が必要)
SPI通信の詳細については下記記事でも紹介しています。
よろしければご覧ください。(リンク先はこちらから)
CAN通信のボードの回路図・仕組み
今回のCAN通信モジュール(ボード)に搭載されている主要な部品としては下記になります。
- SPI-CANコントローラ(Microchip製_MCP2515)
- CANトランシーバ(NXP製_TJA1050)
- 8MHz発振子
- 終端抵抗120Ω(ジャンパー接続)
また簡易的な回路図としては下記になります。
(細かい抵抗・コンデンサなどは省略しています。)
このボードによりラズベリーパイからはSPI接続でCAN通信することが可能となります。
今回のCAN通信モジュールとのSPI通信もオシロで確認しています。
デコード機能を使って通信の詳細まで確認しています。(リンク先はこちら)
ラズベリーパイでCAN通信を行う
今回はラズベリーパイを使ってCAN通信モジュールを動かします。
但し、今回のCAN通信モジュールはそのまま使うと5V接続のIFとなりNGです。
もともとはラズパイ用ではなくArduino用のボードのためです。
ラズパイのGPIOの電圧レベルは3.3Vのため、5VのIFとは直接通信できません。
GPIOの詳細に関しては下記記事でも紹介しています。(リンク先はこちら)
CANトランシーバのみに5V電源を入れる改造
ラズベリーパイへのIFは3.3V接続に変更する必要があります。
またCANトランシーバーIC用に5V電源も確保しなければいけません。
そのためCAN通信モジュール(ボード)を改造して対応します。
CANトランシーバの電源パターンをカット
最初にSPI-CANコントローラとCANトランシーバの電源を分離します。
基板上のパターンで繋がっているのでルータでパターンカットします。
(ルーターで無くても鋭利な物でパターンを削ればOKです)
ルーターでパターンカットする方法に関しては下記記事で紹介しています。
裏面にCANトランシーバへの電源パターンが有りますのでカットします。
ジャンパー線を電源箇所にはんだ付けする
電源の分離ができましたので、CANトランシーバのみに5V接続できる改造をします。
最初にはんだ付け用のジャンパー線を用意して対応します。
ワイヤーストリッパーで被膜を剥いておきます。
今回使ったHOZAN製のワイヤーストリッパーに関しては下記記事で紹介しています
はんだごてを使ってジャンパー線をはんだ付けします。
CANトランシーバ電源箇所のコンデンサ(C5)にはんだ付けをしました。
上記改造により「CANトランシーバは5V電源」「ラズパイとは3.3V接続」が可能になりました。
ラズベリーパイとCAN通信ボードを接続する
CAN通信モジュール(ボード)の改造も終わりましたのでラズパイと接続させます。
下記の信号・電源の合計8本程度をジャンパー線で接続する必要があります。
- SPI信号…SCK,SI,SO,CS
- 割り込み信号…INT
- 電源・GND…5V,3.3V(VCC),GND
ジャンパー線は下記記事でも紹介しましたように簡単に通販で入手可能です。
今回の接続図としては下記形になります。5V含めて全てラズベリーパイから接続可能です。
ラズベリーパイでSPI-CANコントローラを認識する
ラズベリーパイでSPI-CANコントローラを認識できるようにします。
特に編集するツールは何でも構いませんので「/boot/config.txt」を編集します。
追記・編集するのは下記内容です。(筆者は一番最後に貼り付けたのみです)
1 2 3 |
dtparam=spi=on dtoverlay=spi-bcm2835 dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25 |
boot/config.txtの編集箇所で参考にさせていただいたのは下記記事です。
Raspberry PiでOBD-II (CAN)の情報を取得するための基板を自作する
上記サイトの運営者様・管理者様にはこの場を借りて深くお礼申し上げます。
CANコントローラと正常に接続できたか確認
接続に成功すれば、次回起動時からCAN通信モジュールが「CAN0」として使用できます。
下記のようにdmesgで確認すれば、MCP2515と通信成功できていることが分かります
MCP2515は今回のCAN通信モジュールに搭載されているSPI-CANコントローラです
また下記のようにifconfig上でも「CAN0」が存在するようになります
CAN通信の終端抵抗の120Ωを接続する
CAN通信の終端抵抗は基本的に120Ωです。
CAN通信の各端箇所の2か所に120Ωを接続する必要があります。
今回CAN通信ボード側には120Ωが実装されており、ジャンパーでON/OFFを切り替え可能です。
そのため今回のオシロスコープで測定する際には下記接続にしています
- CAN通信モジュール側…基板内の終端抵抗120ΩをON
- オシロスコープ側…ブレッドボードで120Ωを接続
CAN通信のケーブル
今回のCAN通信のケーブルに関してはデバッグレベルのためジャンパー線で接続しています。
(本来はインピーダンス特性が終端抵抗と同じく120Ωのものを使用した方が良いです。)
差動なので一応気持ちでツイストしているレベルです。
趣味でオシロ・アナライザの測定する分には特に問題ないかと思います。
波形・プロトコルは無事確認できました。
PythonでCAN通信を行う
今回はPythonのプログラムでCAN通信のテストを行います
最初にラズベリーパイとPythonでCAN通信を行えるようにライブラリをインストールします
ライブラリはpython-canという名前で上記コマンドでインストール可能です。
Pythonのプログラム
PythonでCAN通信するプログラミングを行っていきます。
ラズベリーパイ(raspberry pi)はPythonがデフォルトでインストールされています。
一度もプログラミング・Pythonを使ったことが無い方でも大丈夫です。
下記記事でラズパイで簡単なプログラムの作成・実行方法を紹介しています
(リンク先はこちらから)
「~~.py」というファイルを作って、Pythonの環境で開けば簡単に作成可能です。
今回のCAN通信は下記プログラムをコピペすれば完了です。
プログラム内容としては無限に特定のデータを送信し続けるものとなります
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# import the library import can import os os.system('sudo ip link set can0 up type can bitrate 250000') # create a bus instance # many other interfaces are supported as well (see below) bus = can.Bus(interface='socketcan', channel='can0', receive_own_messages=True) # send a message message = can.Message(arbitration_id=123, is_extended_id=True, data=[0x11, 0x22, 0x33]) bus.send(message, timeout=0.2) |
上記プログラムはpython-CANの公式HPのサンプルプログラムを改造修正したものです。
CAN通信の設定を変更可能
今回はPythonでプログラムしているためCAN通信の設定を簡単に変更できます。
設定を変更しつつ、オシロ・アナライザで波形解析すると非常に勉強になります。
CAN通信の速度を変更可能
CAN通信の速度を変更したい場合、bitrateの後の数字を変更すればOKです。
例えば125kbpsから500kbpsに速度変更したい場合は500000にすればOKです。
通信速度を変更すると、CAN通信の波形も変わります。
例えば500kbpsの場合は1bitあたりの時間は2usとなります。(1/500k=2u)
CAN通信のIDを変更可能
またCAN通信の中身を識別するIDに関しても変更可能です。
今回のテストプログラムではIDを「123」と指定しています。
また拡張フォーマットを使用するかどうかも選択できます。
ID(拡張ID)はデータフレームの先頭箇所に記載される形となります。
プロトコルの詳細に関しては後述します。
CAN通信のデータも変更可能
CAN通信で送りたいデータも変更可能です。
今回は「0x11」「0x22」「0x33」の3byte分のデータを送信しています
実際にアナライザで解析したCAN通信のデータも8bitが3つで3byteとなっています。
CAN通信の電圧をオシロスコープで確認してみた
準備も完了しましたので最初にオシロスコープでCAN通信の電圧測定を行います。
今回使ったオシロスコープに関しては下記記事で紹介しています。
4chでコストパフォーマンスも高くおすすめのオシロです。(リンク先はこちら)
CAN通信のバス電圧レベル
CAN通信のバス電圧の中間が2.5Vであることを確認しました。
CANHは2.5V-3.5V、CANLが1.5V-2.5Vの電圧波形となっています
CANH-CANLの差動波形を追加したのが下記です。
CANH,CANLがそれぞれ1Vの電位差のため,0V-2Vの差動電圧となりました。
CAN通信の速度
通信速度が125kbpsの場合は1bitあたりの時間は8usとなります。
1/125k=8uであることが波形からも確認できます。
CAN通信の速度を変更すると波形も変わります。(横軸の単位も変わっています)
500kbpsの場合は1bitあたりの時間は2usとなります(1/500k=2u)
CAN通信のプロトコルをアナライザで確認してみた
CAN通信のロジック論理としてはCANLの論理と同じになります。
そのため、CANLをアナライザで解析すればCAN通信のプロトコルが確認できます。
CANLとGNDをジャンパー線でアナライザに接続すれば準備は完了です。
アナライザの購入は個人でも可能です
趣味のロジックアナライザ(ロジアナ)は簡単に購入できます
最近はI2CやSPIなど数MHz程度の解析するアナライザが1000円足らずで買えます。
筆者はモジュール化されていないアナライザの開発ボードを買いました。
値段は安く多くのピンで遊べますが、EEPROMなどの設定が少し手間でした。
下記のようなモジュールのアナライザを買った方が簡単に測定できて楽です。
値段としても数百円程度の差です。
以前にUSBのプロトコルもアナライザで解析しました。
アナライザで解析することは信号の勉強にもなりますので非常におすすめです。
ロジアナをCAN通信の設定にする
ロジアナ(アナライザ)でのCAN通信の設定方法は簡単です。
プロトコルの選択でCANを選びます。
あとは通信速度(bitrate)と測定チャンネルを入力するだけです
アナライザでの測定時の通信速度は250kbpsに設定しています。
CAN通信のフレームを確認してみる
測定条件として「サンプリング数が1M」で「サンプリング速度が1MHz」で確認しました。
250kbps(1bitあたり4us)の波形に対して測定時間としては1秒は長いです。
波形全体で見ても分からないため拡大していきます
拡大していくとCAN通信のデータフレームが見えていきます。
今回は無限に送信するPythonプログラムですので、同じデータが並んでいます。
更に拡大するとCAN通信のデータフレームが確認できました。
細かい箇所を挙げると足りないのですが、大まかに下記のデータフレームを確認していきます
- SOF(Start Of Frame)
- ID(ベース・拡張)
- データフィールド
- CRCシーケンス
- ACK
- EOF(Start Of Frame)
CAN通信にはスタッフビットがあります
CAN通信ではフレームの同期合わせのためにスタッフビットが存在します。
スタッフビットはCAN通信のプロトコル解析する上で注意しておく必要があります。
(大抵の場合、ロジアナ(アナライザ)が勝手に解析してくれますが…)
同レベルが5bit連続するとスタッフビットが発生します。
下記例のようにデータ値としては「0x0」でも、「0」が5つ並ぶと「1」が立ちます。
CAN通信のSOF
データフレームの最初にはSOF(Start Of Frame)があります。
送信側が受信側にデータフレーム送る合図となります。
CAN通信のベースID・拡張ID
CAN通信の中身や送信先を識別するためにIDがあります。
今回はPythonのプログラムでは「123」「拡張ID有り」で設定をしていました。
拡張フォーマットの場合はベースID(11bit)+拡張ID(18bit)の合計29bitで構成されます。
アナライザでIDが「0x7b」で「123」を確認できました。
CAN通信のデータフィールド
データフィールドはCAN通信のデータ本体箇所となります。
今回のテストでは「0x11」「0x22」「0x33」の3byteのデータを送信しています。
アナライザでも「0x11」「0x22」「0x33」のデータを確認できました
またデータフィールドの前にDLC(データレングスコード)が有ります。
データが何byteのものかを示しており、今回の3byteの「3」も確認できました
CAN通信のCRC
CRC(巡回冗長検査)により、送信したデータが正しいものかを受信側でチェックできます。
CAN通信のCRCは15bitで構成されていて、アナライザで確認できています。
CAN通信のACK
CAN通信にはACKが有り、受信側がCRC箇所まで正常に通信を受け取った場合は反応があります。
但し今回のテストでは受信側がいないため、ACKは「1(レセシブ)」のままとなります。
アナライザでもACKスロット箇所が「1(レセシブ)」のままを確認できました。
(ACK終了を示すACKデリミタは常に「1(レセシブ)」)
受信ICがあり、正常通信できた場合はACKスロットが「0(ドミナント)」になるはずです。
CAN通信のEOF
CAN通信のデータフレームの終わりを示すのがEOF(End Of Frame)となります。
フレームの最後に7bit分「1(レセシブ)」となります。
まとめ
今回はCAN通信に関して紹介させていただきました。
記事をまとめますと下記になります。
オシロは難しいかもしれませんが、アナライザならば1000円程度で購入可能です。
ラズベリーパイ(raspberry pi)と一緒に使えばCAN含めて多くの通信テスト・解析が可能です。
よろしければ皆さまも是非試してみてください
コメント