RaspberryPiでドライブレコーダ 【SPI+MCP2515でCAN通信を実装】
1.はじめに
今回はRaspberryPiからSPI通信経由でCANコントローラMCP2515に接続し、車両情報を取得する方法を紹介します。CAN(Controller Area Network)は車や産業用機器などで利用される通信規格で、一つの通信線に複数のノードを接続できることができます。CAN IDの小さいものほど優先度が高いデータとして扱われ、各ノードは他のノードのデータ送信状況を見ながらデータを送信します。今回のドライブレコーダーのキモとなる技術ですのでじっくり解説したいと思います。
2.準備したもの
基板製作のために下記の部品を準備します。
CANコントローラ/トランシーバはチップワンストップから、マイコン/素子関係は秋月電子から入手すると良いでしょう。車両情報を取得するためのOBDⅡコネクタはAmazonで売っています。運転席足元付近に診断コネクタ(メス)がありますので、そこからCAN-H、CAN-L端子に接続し車両情報を取得します。とりあえず今回は試験的にブレッドボードで回路を構築します。
【準備したもの(箇条書き)】
3.ハードウェア設計(回路図)
まずハードウェアの設計です。ブレッドボードで下記の回路を構築してください。下記の回路図をクリックすると拡大画像を見ることができます。MCP2551のCAN-H、CAN-Lは車両のCAN-H、CAN-Lに接続します。今回は車両まで行くのが面倒くさかったので、転がっていたCAN接続の中古部品(トヨタ製ヨーレートセンサ)を接続しました。R4の終端抵抗は必要に応じて接続してください。(車両に接続する場合は必要ありません)
実装の様子
4.Linuxカーネル再構築
Raspberry PiのカーネルはデフォルトでCAN通信には対応していません。CAN通信を行うにはカーネルソースからコンパイルを行う必要があります。MCP2515のSPI通信に対応するための専用パッチを当てたあと、カーネルを再構築します。Raspberry Pi上でカーネルをコンパイルすることもできますが、非力なマシンゆえめちゃくちゃ時間がかかります。(4~5時間) 母艦マシンでのクロスコンパイルをお勧めします。VMWareにUbuntuをインストールし、Ubuntu上でカーネルをクロスコンパイルしました。
最初にRaspberry Pi arm用コンパイラとmenuconfigを使うためのncurses開発パッケージをインストールします。
$ sudo apt-get install gcc-arm-linux-gnueabi ncurses-dev
カーネルソースをgitで取得します。
$ cd /opt
$ sudo mkdir raspberrypi
$ cd raspberrypi
$ sudo chmod og+w .
$ sudo git clone --depth 1 https://github.com/raspberrypi/linux/
$ cd linux
.configファイルをコピーして適用します。
$ sudo cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- oldconfig -j 3
色々聞かれますが下記の項目以外基本デフォルトでOK。Enter押すだけ。
Cross-compiler tool prefix (CROSS_COMPILE) [] (NEW) arm-linux-gnueabi-
Default hostname (DEFAULT_HOSTNAME) [(none)] (NEW) raspberrypi
MCP2515に対応するためのパッチを当てます。
$ sudo wget http://clientes.netvisao.pt/anbadeol/linux-mcp2515-20101018.patch.gz
$ sudo gunzip linux-mcp2515-20101018.patch.gz
$ sudo patch -p1 < linux-mcp2515-20101018.patch
menuconfigを起動します。
$ cd /opt/raspberrypi/linux
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
下記のモジュールを有効にしてください。
[*] Networking support --->
....<M> CAN bus subsystem support --->
........<M> Raw CAN Protocol (raw access with CAN-ID filtering)
........<M> Broadcast Manager CAN Protocol (with content filtering)
............CAN Device Drivers --->
................<M> Platform CAN drivers with Netlink support
................[*] CAN bit-timing calculation
................<M> Microchip MCP251x SPI CAN controllers
................[*] CAN devices debugging messages....Device Drivers --->
........[*] SPI support --->
............<M> BCM2798 SPI controller driver (SPI0)
............<M> User mode SPI driver support
.......-*- GPIO Support --->
............[*] /sys/class/gpio/... (sysfs interface)
SPIバス情報、割り込み端子(GPIO25)の設定をデバイスドライバに追加します。下記パッチを当ててください。
$ sudo patch -p1 < can1.patch
いよいよカーネルをクロスコンパイルします。
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j3
終わったらカーネルツールをgitから入手。
$ cd /opt/raspberrypi/
$ sudo git clone --depth 1 git://github.com/raspberrypi/tools.git
buildディレクトリを作成し、カーネルイメージを作成。
$ cd tools/mkimage
$ sudo ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
$ sudo mkdir -p /opt/raspberrypi/build/boot
$ sudo mv kernel.img /opt/raspberrypi/build/boot
カーネルモジュールをインストールし、buildディレクトリにコピー。
$ cd ../../linux/
$ sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install INSTALL_MOD_PATH=/opt/raspberrypi/build/ -j3
$ sudo cp .config ../build/boot/
最新のRaspberryPiファームウェアを入手しbulidディレクトリにコピー。
$ cd ..
$ sudo git clone --depth 1 git://github.com/raspberrypi/firmware.git
$ cd firmware
$ sudo git fetch --depth 1 git://github.com/raspberrypi/firmware.git next:refs/remotes/origin/next
$ sudo git checkout next
$ sudo cp boot/bootcode.bin /opt/raspberrypi/build/boot
$ sudo cp boot/fixup.dat /opt/raspberrypi/build/boot
$ sudo cp boot/start.elf /opt/raspberrypi/build/boot
$ sudo mkdir -p /opt/raspberrypi/build/opt
$ sudo cp -r hardfp/opt/vc /opt/raspberrypi/build/opt
あとはbuildディレクトリをRaspberryPiにコピーします。(SCP経由)
$ scp -rp /opt/raspberrypi/build pi@YourIPアドレス:~/
コピーしたカーネル、モジュール、ファームウェアを適切な場所へ配置します。
$ sudo mv /boot/kernel.img /boot/kernel_old.img
$ sudo mv build/boot/* /boot
$ sudo mv build/modules/lib/modules/* /lib/modules
あとは最新のカーネルが動作していることを確認します。
$ sudo reboot
$ uname -r
3.6.11-cutdown+
長々とお疲れ様でした。これでCAN通信対応カーネルになりました。筆者の場合はカーネルバージョン3.6.11(2013年5月2日現在最新)を使用しました。バージョンによって多少挙動が変わるところがあるかもしれませんのでご注意ください。
5.ユーザー空間プログラム
Linuxユーザー空間からCANデバイスにアクセスするためのツールが用意されていますのでそれを利用します。netlinkからsocket関数でCANに透過的にアクセスできるようです。Linuxのネットワークプログラミングができる方なら、色々な実装がC言語でできそうです。
$ git clone git://gitorious.org/linux-can/can-utils.git
$ cd can-utils/
$ make
$ sudo make install
これでユーザー空間からコマンドでCANデバイスにアクセスできるようになりました。
6.実機確認
ユーザー空間からCANデバイスにアクセスします。CANコントローラMCP2515とSPI通信が正しく行えているかを確かめるためにループバックモードで動作確認します。
まずはmodprobeコマンドでカーネルモジュールをロード。
$ sudo modprobe spi-bcm2708
次にcanデバイスをループバックモードでリンクアップ。
$ ip link set can0 type can bitrate 500000 loopback on
ターミナルを2つ起動し、片方から送信、もう一方で受信してみます。
(Term1) $ candump any,0:0,#FFFFFFFF
(Term2) $ cansend can0 123#1234ABCD
一方のターミナルから他方のターミナルへループバックさせることができました。
次に実機でCAN通信が行えることを確認します。
$ sudo modprobe spi-bcm2708
$ ip link set can0 type can bitrate 500000
$ candump any,0:0,#FFFFFFFF
ヨーレートセンサからID:024のCANデータが受信出来ました。
7.まとめ
ドライブレコーダーのキモとなる車両情報の取得部分を実装しました。これによりエンジン回転数などの車両状態を取得できるようになりました。CAN情報は検索すれば解析をされている方がいますし、OBDⅡという規格で定義されている情報は規格で定義されたコマンドを送信すれば欲しい情報が取得出来ます。詳細はOBDⅡのページを参考にしてください。
↓合わせて読みたい記事
RaspberryPiでドライブレコーダ 【RaspberryPiセットアップ】
RaspberryPiでドライブレコーダ 【AVR+MCP2515でCAN通信を実装】
参考HP・文献
- これでダメなら諦めた方が良い程度にRasberry Piのカーネルクロスコンパイル手順をまとめてみた。
- RPi Kernel Compilation
- CAN + Raspberry Pi
- RPi CANBus
- OBDシステム通信のフォーマット
- OBD-II PIDs


- スポンサードリンク -