はじめに
数年前にWioTerminalを購入していたのですが、積マイコン状態が続いていたので、何かおもしろいことができないかとSeeed社のサイトを見ているとこちらの記事が目に留まりました。車の情報を取得できるとはなかなか面白そうではないですか。
車に使用されている様々なデバイス(電子制御装置:ECU)やマイクロコントローラーはCAN(Controller Area Network)というシリアル通信の一種で相互に通信しているそうです。このCANに流れている情報をWio Terminalで受信しモニターに表示するプロジェクトということですね。
CANについての詳しくは、Seeed社のこちらのサイトやWikiPediaなどの情報をご参照下さい。
上記サイトの内容に従って実際に愛車のホンダN-WGNで試してみたのですが、少々解りづらいところがあったので、うまく再現できない方は当記事を参考にして試していただければと思います。
必要なデバイスの準備
CAN情報を取得するには、マイコン、CAN通信用IC(モジュール)、および車に装備されているOBD-IIコネクタに接続するケーブルがあれば可能です。今回はWioTerminalを使用した場合の例ですが、Arduinoボードでも実際に試してみましたが問題なく車速情報などが取得できました。
メインのマイコンボードであるWioTerminalについては、スイッチサイエンスやマルツオンラインなどもアマゾンで発売していますので、アマゾンポイントを活用して購入することも可能ですのでリンク先をご紹介しておきます。
Wio Terminalはバッテリーが内蔵されていませんので、車内にもちこんで取り回しを良くするのであればバッテリーを用意しておくと良いですね。
今回のCAN通信を行うためのメインデバイスのCAN-BUSモジュールが必要です。
車のOBD-Ⅱコネクタに接続するケーブルが付属しているOBD-II CAN-BUS Development Kitを準備するのが手っ取り早そうです。
OBD-Ⅱケーブルアッセンブリとモジュールとの結線
開発キットではOBD-Ⅱコネクタに2本の配線を半田付けする必要がありますので、seeed社のサイトを参照して組み立てましょう。とは言え、赤色線を6番端子、黒色を14番端子に接続するだけです。6番端子に接続した赤色配線がCANH、14番端子に接続した黒色がCANLの信号ラインとなります。
配線が完了したらキットに含まられるシリアルCAN-BUSモジュールのターミナルにCANHとCANLを接続します。あとは、WioTerminalとGroveコネクタを介してモジュールを接続するだけです。
ここで、seeed社の例では、バッテリーベースのGroveUARTポート(TXD,RXD)コネクタにCAN-BUSモジュールを接続しているようですが、(プログラムスケッチを改造すれば動作するのかもしれませんが)この接続ではうまく動かく事ができなかったため、バッテリーベースのGroveアナログ/デジタルポート(D2,D3)コネクタに接続しました。
プログラムスケッチの改造
CAN-BUSモジュールに実装されているCAN通信用IC(MCP2515)は、必要なCAN信号だけをとりだせるように信号のフィルタリング機能を有していて、マスク0がフィルタ0およびフィルタ1と連動していて、マスク1がフィルタ2、3、4、5と連動しています。
CAN-BUSモジュールはすでにデフォルト値が書き込まれているようですが、デフォルト値が不明なこともあり、すべての信号を取り出せるように設定しました。
なお、N-WGNのOBD2通信規格は ISO157654-4 29bitID とのことなのでGitHubで紹介されている”setting.ino”ファイルのフィルタ設定を以下に改造しました。
// MASK&FILE EXAMPLE OF SERIAL CAN MODULE // SUPPORT: joney.sui@longan-labs.cc #include <Serial_CAN_Module.h> #include <SoftwareSerial.h> Serial_CAN can; #define STANDARD_CAN_11BIT 0 // 29Bitの場合は 0 にする #if STANDARD_CAN_11BIT unsigned long mask[4] = { 0, 0x7FC, // ext, maks 0 0, 0x7FC, // ext, mask 1 }; unsigned long filt[12] = { 0, 0x7E8, // ext, filt 0 0, 0x7E8, // ext, filt 1 0, 0x7E8, // ext, filt 2 0, 0x7E8, // ext, filt 3 0, 0x7E8, // ext, filt 4 0, 0x7E8, // ext, filt 5 }; #else unsigned long mask[4] = { 1, 0x00000000, // ext, maks 0 ※すべてのデータが通るようにした 1, 0x00000000, // ext, maks 1 ※すべてのデータが通るようにした }; unsigned long filt[12] = { 1, 0x00000000, // ext, filt 0 ※すべてのデータが通るようにした 1, 0x00000000, // ext, filt 1 1, 0x00000000, // ext, filt 2 1, 0x00000000, // ext, filt 3 1, 0x00000000, // ext, filt 4 1, 0x00000000, // ext, filt 5 }; #endif void set_mask_filt() { /* * set mask, set both the mask to 0x3ff */ MASK: if(can.setMask(mask)) { Serial.println("set mask ok"); } else { Serial.println("set mask fail, try again."); goto MASK; } FILT: /* * set filter, we can receive id from 0x04 ~ 0x09 */ if(can.setFilt(filt)) { Serial.println("set filt ok"); } else { Serial.println("set filt fail, try again"); goto FILT; } } void setup() { Serial.begin(9600); while(!Serial.available()); can.begin(D2, D3 9600); // Rx-Pin No, Tx-Pin No, Baudrate ※D2とD3端子を使用するようにした set_mask_filt(); } void loop() { } // END FILE
同様にdemo.inoファイル内に記述されている次の2行も変更します。
#define STANDARD_CAN_11BIT 0
can.begin(D2, D3 9600);
おわりに
整理しますと、次の3点を変更しdemo.inoファイルを使用して無事にエンジン回転数と車速の取得をすることができましたが、”Engine coolant temperature”と”Intake air temperature”は取得できませんでした。
PIDについてネット検索して調べてみると取得できるデータは車により異なるようで、利用可能なパラメータID(PID)を調査してプログラムスケッチを書き換える必要があります。
① CAN-BUSモジュールをWio Terminal用バッテリベースのGroveアナログ/デジタルポート(D2,D3)コネクタに接続
② プログラムスケッチのフィルタ設定の変更
③ プログラムスケッチのシリアル通信ポート番号の変更
出来てしまえば簡単なことですが、サイトに記載の手順通りに行っても私と同じように上手く動かせずあきらめていた方がいらっしゃいましたらぜひ試してみて下さい。
コメント