92
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Raspberry PiでOBD-II (CAN)の情報を取得するための基板を自作する

Last updated at Posted at 2016-05-03

車の自己診断情報から、エンジン回転数や燃費情報などを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のものを選びます。注文の数量単位に注意してください。

その他の材料は、一般的な電子部品の店で用意できるかと思います

回路図

image

汚い手書きですみません(笑

見苦しいようでしたら、ネットに探せば沢山転がってますので、そちらを参考にしてください

実装例

回路図の通りに配線して、作ったのが以下になります

image

image

ケーブルも作り、Raspberry Piと接続します

image

ケーブルは何か補強手段を考えなければなりません。

OBD-II端子の6番ピンにCAN-H、14番ピンにCAN-Lを繋ぎます

Raspberry Pi の設定

/boot/config.txt に以下の設定を追加します

/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 が付いてたのが不要になりました。以前の記事では以下の設定を紹介していましたが、現在では上記の通りに設定しないとドライバは読み込まれませんのでご注意ください

/boot/config.txt(昔のバージョン)
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する

パッケージが用意されていないLinuxの場合は開発環境を整えてmakeします (クリックして開く...)

can-utils
https://github.com/linux-can/can-utils

[Code] → [Download ZIP]をクリックして、ソースコード一式をダウンロードします

ダウンロードしたZIPファイルを解凍します

$ unzip can-utils-master.zip

ソースコードをコンパイルした後、root権限でインストールします

$ ./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になるので面倒な方はこの手順を省略しても構いません

確認後loopbackを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 のどちらかです。車種によって変わりますので適宜変更してください

canインタフェースを有効にする
$ sudo ip link set can0 type can bitrate 500000
$ sudo ip link set can0 up

しかし、これを起動する度に入力するのは手間がかかるので、自動的に実行するようにしましょう

/etc/network/interfaces.d/can0 を以下の内容で追加します

/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

上手くいけば、以下のように車から受信したデータが流れます

image

  1. 初版公開時から状況が大分変ってきており、自作せずとも既にMCP2515のチップが搭載された基板が販売されています。本記事は自作にこだわりたい方のために残しています

92
91
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
92
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?