車の自己診断情報から、エンジン回転数や燃費情報などをRaspberry Piを使って取得する方法を紹介します
ここでは、その前段階として車のOBD-II端子とRaspberry PiのSPIインタフェースを繋ぐためのCAN-SPI変換基板と、OBD-IIケーブルを作るための手順を書いています
手軽に済ますにはELM327を使うのが良いと思いますが、以下のような懸念が考えられます
- 偽物が出回っている
- 電波を使うのでセキュリティーホールになり得る
せっかく買ったのに使えなかったという話も聞きますが、中にはエンジンや各種装置の警告灯が付くようになってディーラーに行く羽目になったという痛々しい体験談もあるようです。また、(運よく?)使えたとしても、見ず知らずの誰かが勝手にペアリングして悪さをすることも考えられます
その点、自作すれば
- チップが偽物である可能性は低い
- ケーブル接続なのでセキュリティー面では安心
なにより、博打に掛けるより自分でやった方が楽しいでしょう!1
前提
ここで作成する基板は車のOBD-II端子のCANとRaspberry PiのSPI端子を繋ぐための物です。そのため、車両側にCANのインタフェースがあることが必要となります。ほとんどの最近の車(2001年以降)にはOBD-II端子は付いていますが、中には古い規格のK-LINEしか付いていなかったり、TOYOTA CANのように独自の形式を使ったりする場合もあります。この辺りの事情は 別の記事 にまとめましたので合わせてご覧ください
材料
基板を作るための材料です
- CAN Controller MCP2515 ×1
- CAN Transceiver MCP2551 ×1
- OBD-II コネクタ ×1
- 水晶発振子 16MHz ×1
- セラミックコンデンサ 15pF ×2 (※)
- セラミックコンデンサ 0.1μF ×2
- 抵抗 10kΩ ×3
- ユニバーサル基板 ×1
※ 参考にしたサイトでは16pFと書かれていましたが、売っていなかったので近い容量の15pFにしました
MCP2515とMCP2551は、アールエスコンポーネンツから購入しました。色々種類はありますが、ユニバーサル基板に実装するのでPDIPのものを選びます。注文の数量単位に注意してください。
その他の材料は、一般的な電子部品の店で用意できるかと思います
回路図
汚い手書きですみません(笑
見苦しいようでしたら、ネットに探せば沢山転がってますので、そちらを参考にしてください
実装例
回路図の通りに配線して、作ったのが以下になります
ケーブルも作り、Raspberry Piと接続します
ケーブルは何か補強手段を考えなければなりません。
OBD-II端子の6番ピンにCAN-H、14番ピンにCAN-Lを繋ぎます
Raspberry Pi の設定
/boot/config.txt に以下の設定を追加します
dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
dtoverlay=spi-bcm2835
config.txtを変更したら、Raspberry Piを再起動します
補足
いつの頃か(kernel 4.4あたり)にoverlayパラメータの変更があり、それまで後ろに -overlay
が付いてたのが不要になりました。以前の記事では以下の設定を紹介していましたが、現在では上記の通りに設定しないとドライバは読み込まれませんのでご注意ください
dtoverlay=mcp2515-can0-overlay,oscillator=16000000,interrupt=25
dtoverlay=spi-bcm2835-overlay
参考: パラメータの意味
oscillatorに水晶発振子の周波数、interruptに割込み用のGPIOピンを指定します。なお、MCP2515のCSをRaspberry PiのCE1(26番)に繋いだ場合はcan0をcan1に変更します
以下のREADMEより
https://github.com/raspberrypi/firmware/tree/master/boot/overlays
Name: mcp2515-can0
Info: Configures the MCP2515 CAN controller
Load: dtoverlay=mcp2515-can0,<param>=<val>
Params: oscillator Clock frequency for the CAN controller (Hz)
spimaxfrequency Maximum SPI frequence (Hz)
interrupt GPIO for interrupt signal
ドライバーが読み込まれたことの確認
再起動後にCANコントローラーのドライバーが読み込まれていることを確認します
lsmodを実行するとCAN関連とmcp251xのドライバが読み込まれていることがわかります
$ lsmod | grep mcp251x
mcp251x 20480 0
can_dev 28672 1 mcp251x
mcp251x の表示が無い場合 config.txt の設定が間違っていないかご確認ください
また、dmesgコマンドでMCP2515のドライバが successfully initialized と出力されていればCANコントローラーとの通信はうまくいっています
$ dmesg | egrep -i "can|spi"
[ 6.305202] CAN device driver interface
[ 6.334702] mcp251x spi0.0 can0: MCP2515 successfully initialized.
もしも、CANコントローラーが繋がっていない場合は、以下のようなエラーが出ます
$ dmesg | egrep -i "can|spi"
[ 6.319000] CAN device driver interface
[ 7.350380] mcp251x spi0.0: MCP251x didn't enter in conf mode after reset
[ 7.350441] mcp251x spi0.0: Probe failed, err=16
[ 7.350523] mcp251x: probe of spi0.0 failed with error -16
接続が上手くいかない場合はオシロスコープを使うと切り分けが出来るようです
https://misoji-engineer.com/archives/oscilloscope-4ch.html
補足: カーネルパッチについて
別のサイトでは、カーネルにパッチを当てて再構築する手順を紹介しているものがありますが、新しいLinuxではその手順は不要になっています。パッチも古いもので最近のLinux 4.xでは当てられないと思います
カーネルのバージョンを確認するには、unameコマンドを使います
実行例
$ uname -r
4.19.97-v7+
can-utils
CAN通信を行うために can-utils をインストールします
インストール
Raspberry Pi OS (Raspbian)であればaptコマンドでインストールします
$ sudo apt install can-utils
参考: 自前でmakeする
can-utils [Code] → [Download ZIP]をクリックして、ソースコード一式をダウンロードします ダウンロードしたZIPファイルを解凍します ソースコードをコンパイルした後、root権限でインストールしますパッケージが用意されていないLinuxの場合は開発環境を整えてmakeします (クリックして開く...)
https://github.com/linux-can/can-utils$ unzip can-utils-master.zip
$ ./autogen.sh
$ ./configure
$ make
# make install
CANインタフェースの動作確認
CANインタフェースをループバックモードでリンクアップにします
$ sudo ip link set can0 type can bitrate 500000 loopback on
$ sudo ip link set can0 up
ターミナルを2つ開きます
■ターミナル1 (待ち受け)
1つのターミナルでcandumpを実行し、CANインタフェースの全パケットをdumpするように待ち受けます
$ candump any,0:0,#FFFFFFFF
■ターミナル2 (送信)
もう1つのターミナルでcansendを実行して、適当なメッセージ 1234ABCD
を送信します
$ cansend can0 123#1234ABCD
candumpを実行したターミナルで、以下のようにメッセージが表示されます
$ candump any,0:0,#FFFFFFFF
can0 123 [4] 12 34 AB CD
can0 123 [4] 12 34 AB CD
確認が終わったらloopbackをoffにします。再起動すればoffになるので面倒な方はこの手順を省略しても構いません
$ sudo ip link set can0 down
$ sudo ip link set can0 type can bitrate 500000 loopback off
$ sudo ip link set can0 up
loopbackをoffにしないとCANのデータが車に流れないのでご注意ください
起動時にcanインタフェースを有効にする
canインタフェースを有効にするには以下のコマンドを入れます。
なお、bitrate の後に設定する 500000
は通信速度で 500kbps
を指します。自動車のCAN通信においては 250kbps か 500kbps のどちらかです。車種によって変わりますので適宜変更してください
$ sudo ip link set can0 type can bitrate 500000
$ sudo ip link set can0 up
しかし、これを起動する度に入力するのは手間がかかるので、自動的に実行するようにしましょう
/etc/network/interfaces.d/can0
を以下の内容で追加します
auto can0
iface can0 inet manual
pre-up /sbin/ip link set $IFACE type can bitrate 500000
up /sbin/ip link set $IFACE up
down /sbin/ip link set $IFACE down
設定した後に reboot すれば can インタフェースが有効になっているはずです
この設定が有効になっていれば、ifup / ifdown コマンドでcanインタフェースを有効/無効の切り替えが出来るようになります
# 有効にする時
$ sudo ifup can0
# 無効にする時
$ sudo ifdown can0
OBD-II端子を抜き差しして通信できなくなった時も、一度 ifdown した後に ifup を行うと復帰できます
車に繋いでみる
車のOBD-II端子に自作したケーブルを繋いで、candumpを実行してみます
$ candump any,0:0,#FFFFFFFF
上手くいけば、以下のように車から受信したデータが流れます
-
初版公開時から状況が大分変ってきており、自作せずとも既にMCP2515のチップが搭載された基板が販売されています。本記事は自作にこだわりたい方のために残しています ↩