以前、Arduino MEGAとCAN-BUS Shieldを用いて車両のCAN情報を取得する事に成功した。→こちら
Arduino MEGA+CAN-BUS Shieldはサイズが大きく、かつ値段が高い。今回は、小型化および低価格化を目的としてArduino NanoとMCP2515モジュールを用いてCAN情報を取得したので、その手順を紹介する。
Arduino Nano
Arduino Nano、および格安の互換ボードELEGOO Nanoについてはこちらの記事で紹介している。
今回はArduino NanoとMCP2515 CAN バス モジュールを組み合わせて、車両CANを受信し、モニターするプログラムを作成てみた。今回はArduino Nanoを使用したものの、互換ELEGOO Nanoを使えばかなり安価にCAN情報が取得可能となる。
MCP2515搭載のCANバスモジュール
通常、Arduinoの場合にはシールドを用いると開発が簡単ではある。しかし、その分コストが高くなってしまうので、今回はCAN-BUS Shieldなどでも使われているCANコントローラMCP2515が搭載された別のCANバスモジュールを使用する。SDカードなどの付属が無いことと、汎用品のためとても安い。CANトランシーバは、CAN-BUS ShieldがMCP2551を使っているのに対し、こちらはTJA1050を使っている。
今回使用したCANバスモジュールはこちら↓CAN-BUS Shieldと比べてかなり安価である。
参考までに、CAN BUS Shieldの情報はこちら↓
CAN取得ハードウェアの構成
今回のCANデータ取得のための構成。
車両のOBDコネクタからCAN信号を取得するカプラを作成し、CANバスモジュールに入力する。Arduinoの電源はノートPCのUSBで取得するとともに、シリアル通信データをArduinoからノートPCに送る。ノートPCにArduinoの開発環境とシリアルモニタ(プログラムをするわけではないので、お好みでTeraTermなどでもOK)を起動する。なお、CANバスモジュールの電源はArduino Nanoから供給される。
ハードウェアの実際の接続はこんな感じ
USBケーブルは、TypeA-miniBが必要
OBDコネクタはこちらを使用
Arduino NanoとCANバスモジュールのピンの接続、およびOBDとの接続はジャンパー線で。
ArduinoとCANバスモジュールの接続は以下の通り。
車両との接続
S660のOBD2コネクタの場所
最近の車両にはOBD2コネクタが搭載されている。S660の場合は運転席左側の足元にある。
アルトワークスのOBD2コネクタの場所
車体側のOBD2コネクタは運転席のアクセルペダルの上の方にある。
今回はここに自作のCANケーブルを接続。あとは、ノートPCにArduinoの開発環境を入れ、USBで接続するだけ。
OBDコネクタ
車両のCANデータを受信するためには、車両のCANネットワークに物理的に接続する必要がある。診断機用にOBD2コネクタが車両側についているため、そこに接続することにした。
ピンが付属しているのでカシメるだけ。やり方は、こちらを参考に。
Arduino用プログラムの開発
ハードウェアの準備が整ったので、今度はプログラム開発を行う。ArduinoMega+CAN-BUS Shieldで開発済みのこちらを修正する。
プログラムの準備(ライブラリインストール)
CANの入出力ライブラリがCAN-BUS Shieldとは異なるので変更する必要がある。CNA-BUS Shieldに搭載されるチップセットの場合は、mcp2515_can.hをインクルードしていたが、今回はmcp_can.hをインクルードして用いる。MCP_CAN Libraryはこちらからダウンロード可能。下図のようにCode▼をクリックして、Download ZIPを選択してダウンロードする。
ZIPファイルを展開したら、フォルダごとArduinoがインストールされたlibrariesフォルダに移動(私の環境では、「C:\Program Files (x86)\Arduino\libraries」の下に「MCP_CAN_lib-master」を配置)。Arduinoの開発環境を起動するとライブラリを呼び出せるようになる。
ちなみに、ArduinoMega+CAN-BUS Shieldで作成したプログラムから関数の仕様が多少違う。こちらにMCP_CAN_lib-masterのヘッダファイルがあるので、そちらを読んで変更を行った。
プログラムの作成
Arduinoのスケッチ例。CANのインスタンス生成関数などを変更。
/*
* File: CAN-RECEIVE_ArduinoNano_MCP2515.ino
* Arduino NANO と MCP2515,TJA1050を用いたCAN受信
* 必要なライブラリ: MCP_CAN Library ⇒ https://github.com/coryjfowler/MCP_CAN_lib
* Author: 岡本一車
* https://kurumashikou.com/
*/
#include <SPI.h>
#include <mcp_can.h>
#include "string.h"
// ピンの設定
// ここではCAN通信用のCSピンとして、digital 9を使用する
const int SPI_CAN_CS_PIN = 9;
// グローバル変数 ///////////////////////////////////////////
// タイムスタンプ用変数
unsigned long timestamp = 0;
unsigned long timestamp_old = 0;
// 受信メッセージ格納用
unsigned long can_ID = 0;
unsigned char len = 0;
unsigned char buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
// CANデータ書き込み値を保持する
String logDataStr;
// CANトランシーバにCSピン設定をセットし、CAN通信インスタンスを生成
MCP_CAN CAN(SPI_CAN_CS_PIN);
// 初期設定 ////////////////////////////////////////////////
void setup() {
// シリアルモニタの設定
SERIAL_PORT_MONITOR.begin(115200);
// シリアルポートの準備が整うまで待つ
while(!Serial);
// CANの初期設定 ///////////////////////////////////////////////
if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) != CAN_OK) {
SERIAL_PORT_MONITOR.println("CAN-BUS initiliased error ..............");
while(1);
}else{
CAN.setMode(MCP_NORMAL);
SERIAL_PORT_MONITOR.println("CAN-BUS initiliased OK !!");
}
}
// メイン処理 ////////////////////////////////////////////////
void loop() {
// CANメッセージ受信したときの動作
if (CAN_MSGAVAIL == CAN.checkReceive()) {
// バッファの初期化
for(int i=0; i<8; i++){
buf[i] = 0;
}
// 受信したデータをシリアルモニタに送信 ////////////////////////////////////
if(timestamp_old == 0){
timestamp_old = millis();
}
// CANデータを取得
//CAN.readMsgBufID(&can_ID, &len, buf);
CAN.readMsgBuf(&can_ID, &len, buf);
// タイムスタンプの取得
timestamp = millis() - timestamp_old;
// デバッグ用出力
logDataStr = "timestamp ";
logDataStr += String(timestamp);
logDataStr += String(" / ID ");
logDataStr += String(can_ID);
logDataStr += String(" : ");
logDataStr += String(len);
logDataStr += String(" : ");
logDataStr += String(buf[0]);
logDataStr += String(" ");
logDataStr += String(buf[1]);
logDataStr += String(" ");
logDataStr += String(buf[2]);
logDataStr += String(" ");
logDataStr += String(buf[3]);
logDataStr += String(" ");
logDataStr += String(buf[4]);
logDataStr += String(" ");
logDataStr += String(buf[5]);
logDataStr += String(" ");
logDataStr += String(buf[6]);
logDataStr += String(" ");
logDataStr += String(buf[7]);
logDataStr += "\r\n";
SERIAL_PORT_MONITOR.print(logDataStr);
}
}
void setup() でCNAモジュールとArduinoのシリアルポートを初期化。void loop()でCANから受信があったら、そのイベントを拾って、受信バッファの内容をシリアルポートに送るだけの単純なもの。
動作確認
車両側に配線し、Arduinoに焼き込んだらクルマのエンジンをONして動作確認。
ノートPCからArduinoの開発環境を起動し、ツールからシリアルモニタを選択。
こんな感じで出力を取得できた。車両から送られてきているCAN情報の時系列データ。これでIDやデータの取得ができていることが確認できた。
必要なデータをフィルタで絞り込むのはこちらを参照
まとめ
Arduino MEGA+CAN-BUS Shieldはサイズが大きく、かつ値段が高い。今回は、小型化および低価格化を目的としてArduino NanoとMCP2515モジュールを用いてCAN情報を取得した。Arduino Nanoを互換品で安く置き換えれば、1セットあたりの部品代は3000円以下となるはずだ。お気軽に車両CANの情報を取得することができる。
コメント