Owniceもそうでしたが、NaviFly UIS7862もCAN-BOXを接続することができるようになっています。またこのナビにはそれ用のコネクタも同梱されており、そこからTx, Rxのリード線が出ています。
・OwniceにはCAN-BOXも付属していたので、Fit3でステア連動が動作することは確認しましたが結局使わずじまいでした。(エアコンやドアなど不要な表示がされるのと、そもそもバックガイド線の表示アプリの出来がいまいちだった)・ちなみにCAN-BOXのメーカーはSimpleSoftです。
・今はOwniceを車から降ろし机上でいじれる状態になったので、それを使ってCAN-BOXとナビ間ののプロトコルを解析し、自作のCAN-BOXでステア舵角だけをナビに送ることで、NaviFlyでバックガイド線のステアリング連動ができるはずだと考えました。
●まずは実車でB-CAN解析
・CAN通信ボードMCP2515とArduino NANOを接続し、簡単なプログラムを焼いて実車のB-CAN信号をログしてEXCELでIDでソートして解析を行いました。
ビットレート:125kbps
ステア舵角信号ID:0x12F97150(拡張フォーマット)
DLC:3
data:D0=?, D1=ステア舵角(MSB), D2=ステア舵角(LSB) モトローラフォーマット
1LSB:0.1deg
方向:右回転が正(すなわちステアを右に90deg回すとデータは900)
インターバル:100ms
●CAN-BOX / NAVI間通信解析
・部屋に戻って先ほどのArudinoを使い、今度はダミーのステア舵角データをB-CANに送信するプログラムを作ってCAN-BOXとOwnice間の通信をモニタしました。
電圧レベル:0-3V
・以前amazonで\800で購入したこのロジアナ(今は\1000以上するみたいですが)でプロトコル解析までできてしまいます。
ビットレート:38400bps 非同期シリアル(async)8bit,1stop,パリティ無し
・それぞれがフレームを送信した後でACK(0xff)を受信するハンドシェークを互いに行っています。
・通電後はネゴシエーションを行いCAN-BOXのソフトバージョンやその他の情報をやり取りしています。
・その後0.2秒ごとにナビはCAN-BOXにステア舵角データのリクエストを送信し、CAN-BOXはそれに対する応答としてステア舵角を返しています。
★CAN-BOX→NAVIへのステア舵角の送信フレーム
D0=0x2e, D1=0x29, D2=2, D3=ステア舵角(LSB), D4=ステア舵角(MSB), D5=チェックサム
・D0はSTXで全てのフレームの始まりは常に0x2eです。
・D1はファンクションIDで、0x29がステア舵角を示します。
・D2はデータのバイト数でステア舵角の場合は2です。
・D3,D4がステア舵角で、並びはCANと逆のインテルフォーマットです。
・D5はD1~D4の合計をビット反転した下8bitです。
・ネゴシエーション部分をコピーするのはめんどうだなぁと思い、ものは試しでArduinoでダミーのステア舵角の送信フレームだけを100msでOwniceに送ったら、それだけでバックガイド線が曲がることがわかりました。ハンドシェイクもネゴシエーションもやらなくてもエラーにはならないようです。(当然システム情報のCANバージョンは表示されませんが。)
・同じことを実車のNaviFlyで試してバックガイド線が曲がることを確認しました。
・NaviFlayのコネクタから出ている線のTx/RxというラベルはCAN-BOXから見たもので、NAVIに送信する信号をTxに接続する必要があるので要注意です。
・「工場設定」「モデル選択」でCAN-BOXのメーカーで「XP」を選択します。XPというのがSimpleSoftの別名のようです。
・「工場設定」「車のカメラ方式を使用する」で「バック連動ガイドライン」をオンにしないとガイド線はそもそも表示されません。・その下の「バックガイド線を表示」はオフにしておかないとステア連動になりません。なんか逆みたいに感じますが。
・その下の「バックトラック反転」をオンにすると操舵方向とガイド線の曲がる方向が逆になります。
●結果・自作のCAN-BOXを使ってフル転舵した時の表示です。
●回路・ハードはArduino NANOとCANボードMCP2515と3端子レギュレータを接続しただけです。ただしCAN-BOXの送信レベルは3Vなので抵抗分圧で5→3Vに変換しています。
・電源は外付けの3端子レギュレータで5Vを作っています。Arduinoにはもともと3端子レギュレータが搭載されているのですが、私の使った中国製のArduinoにはFS1117という中華なチップが使われていて、これの絶対最大定格が+12.0Vなので車の電圧(14V台になることがある)には耐えられないはずです。電流は40mAも流れないので78L05で十分かと思います。少し暖かくはなりますが。本物の(?)Arduinoでは耐圧の高い3端子レギュレータが載っているのかもしれませんが、その場合はVin端子に直結できますね。
・バックの時だけ機能すればいいので、電源はリアカメラへの給電の+12Vと同じところからもらうようにします。
・ということは普段はこのユニットは電源オフのままCANバスにぶら下がっていることになりますが、CANトランシーバー用のICはそのような使われ方でも他の通信に影響しないように作られているので問題ありません。
●製作・ダイソーのプラケースにArduinoNANOとMCP2515をクッションテープと両面テープでガタつかないように収めました。空中配線の部分はグルーで固定しています。
●ソフトウェア・B-CANからステア舵角を受信したら補正してNAVIに送信するだけの機能です。
・ステア舵角は1/4に補正しています。そのまま送信するとラインが曲がりすぎるので。ネゴシエーションしていないのでそこで舵角の分解能とかを送っているのかもしれません。あるいは車種とモデルイヤーを選べばいいのかもしれませんが詰めていません。
・今回は実車でざっくり合わせただけで全然厳密な予測進路ではないです。バックガイド線の表示設定との兼ね合いで微調整をした方が良いと思います。
・CANのステア舵角の受信間隔が100msなので受信2回に対して送信1回としています。
・ビルドするためには次に置いたソースを例えばMyCanBox.inoという名前で作成したら同じ名前のMyCanBoxフォルダを作って入れてください。
・CAN制御のソフトはhttps://github.com/coryjfowler/MCP_CAN_libから取得しています。私はライブラリとして組み込むのが好きではないのでzipからmcp_can.cpp, mcp_can.h, mcp_can_dfs.hを取り出してソースと同じローカルフォルダに置いています。IDEにライブラリとして組み込んでそちらを使う場合は#include文の"mcp_can.h"を<mcp_can.h>に変更してください。その場合はローカルへのコピーは不要です。
[↓ソースはここから]
/*****************************************************************************
*
* MyCanBox.ino -- B-CANのステア舵角をNAVIに送信(SimpleSoft[XP]プロトコル)
*
* rev1.0 2021/09/06 initial revision by Toshi
*
*****************************************************************************/
#include <string.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include "mcp_can.h" // https://github.com/coryjfowler/MCP_CAN_lib
#define CAN_CS 10 // MCP2515ボードのCSが接続されているピン番号
#define CANID_STEER_ANGLE 0x12F97150 // Fit3ステア舵角のCAN ID
MCP_CAN CAN0(CAN_CS); // CANオブジェクト
SoftwareSerial Serial2(8, 9); // ソフトシリアル(Rx, Tx)
unsigned char TxBuf[6]; // 送信データバッファ
void setup()
{
Serial.begin(115200); // デバッグ用
Serial2.begin(38400); // NAVIへの送信はソフトシリアルを利用
TxBuf[0] = 0x2e; // STX
TxBuf[1] = 0x29; // ステア舵角を示すコード
TxBuf[2] = 0x02; // データ長
CAN0.begin(MCP_STDEXT, CAN_125KBPS, MCP_8MHZ);// CAN初期設定
CAN0.init_Mask(0, 1, 0x1fffffff); // マスクビット設定 0だとDon'tCare
CAN0.init_Mask(1, 1, 0x1fffffff); // マスクレジスタは2つある
CAN0.init_Filt(0, 1, CANID_STEER_ANGLE);// このIDだけ受け取る
CAN0.setMode(MCP_NORMAL); // CAN開始
}
void loop()
{
unsigned long id;
unsigned char dlc, rxbuf[8];
short angle;
static short i;
if (CAN0.checkReceive() == CAN_MSGAVAIL)// CAN受信したら
{
CAN0.readMsgBuf(&id, &dlc, rxbuf); // データを読み出す
id &= CAN_EXTENDED_ID; // 拡張IDなので上位ビットを落とす
if (id == CANID_STEER_ANGLE) // 念のためIDをチェック
{
if (i) // 2回に1回(200ms)
{
// そのままだとラインが曲がりすぎるので補正する
angle = (rxbuf[1] << 8 | rxbuf[2]) / 4; // 補正したステア舵角
Serial.println(angle); // デバッグ用
TxBuf[3] = angle & 0xff; // 補正ステア舵角LSB
TxBuf[4] = (angle >> 8) & 0xff; // 補正ステア舵角MSB
// チェックサム(TxBuf1~4の合計のビット反転した物)をセット
TxBuf[5] = ~(TxBuf[1] + TxBuf[2] + TxBuf[3] + TxBuf[4]);
Serial2.write(TxBuf, 6);// バイナリ―データを送信
}
i ^= 1; // 0→1, 1→0
}
}
}
/*** end of MyCanBox.ino ***/
[↑ここまで]