• 車種別
  • パーツ
  • 整備手帳
  • ブログ
  • みんカラ+

k4n4のブログ一覧

2025年06月15日 イイね!

FL4のOBDの件続き(4回目)(一旦完成)

初回:https://minkara.carview.co.jp/userid/3661994/blog/48450663/
2回目:https://minkara.carview.co.jp/userid/3661994/blog/48457713/
3回目:https://minkara.carview.co.jp/userid/3661994/blog/48468738/

このところFLシビックHEVでOBD2のPIDから情報取得してエンジン回転やバッテリー使用状況を表示する補助メーターを作ってきたわけですが、今回一旦完成と言えるところまで来ました。

まず、元々Arduino UNOを使用していましたが、SRAMが2kBしかなくSSD1306 OLEDへの描画バッファが足りない始末だったためお役御免に。手元に転がっていたRaspberry pi picoがSRAMモリモリでArduinoの環境そのまま使えそうだったので移植しました。結果的にかなり小型化できました。



移植したものも無事動き、OLEDの描画バッファ問題もあっさり解決しました。
移植にあたってChatGPTに元のコード丸投げして「Pico用に書き換えて」と言ったらそのまま動くコード出てきて神でした。

ちなみに前回言及していた、SF (req) -> FF (rsp) -> FC (req) -> CF (rsp) の会話がうまくいかずにCFでもらうPID 0x9Aのバッテリ電流がうまく取れない問題ですが、forで回すリクエストを決め打ちでSFのあとにFC送る順番で固定することでとりあえず動くようにしました。本当はちゃんと会話したいんだけど、場当たり対応でお茶を濁した。。。

というわけで本体は動くようになったのでケースを作ります。
いつも通りFusion 360でモデルを作り、Bambu Lab A1 miniで出力。
裏蓋の張り出しは、FLのメーター下部に両面テープで固定するための保持部です。



実際に車に設置した姿がこちら。
前回少し画面を作り込んでいましたが、結局欲しいパラメータはエンジン回転数、バッテリ電力、バッテリ電流、SOCの4つで、バッテリ電圧と稼働時間はそこまで大きくなくても良いなということで、メイン4つを大きく表示するシンプルなレイアウトに変更しました。



これでSSD1306に表示するタイプとしては完成ということにした。
次はILI9341の液晶画面にもうちょっとグラフィカルに表示することを目指そうと思っているので、また進捗があれば何か書くかもしれない。

一応書いたコードを置いておきます。
インデントうまく反映できないのでテキストベタ貼りではなく画像にします。

Posted at 2025/06/15 10:45:57 | コメント(0) | トラックバック(0) | 日記
2025年06月04日 イイね!

FL4のOBDの件続き(3回目)

(また同じ話題の続きになるんですが)
PID 0x9AでFirst frame(以下FF)は受信できるのになぜかその後にくるはずのConsecutive frame(同CF)が受信できず、ハイブリッドバッテリーの電圧は分かるけど電流が分からないという状況になっていた。

最初はFF受信したあとにECUが間髪入れずにレスポンス返してきてマイコン側が受信できてないんじゃないかと考えていたので、ブログの前回の最後に書いたようにCAN受信してバッファに格納するタイマー割り込みとそれ以外を分けなきゃ・・・みたいなことを考えていた。でも更によくよく考えると、FFのあとにFlow control frameを打ってあげないとCFを返さないんじゃないかってところに思い至った。
つまり、受信できていないんじゃなくて、そもそもECUが出してきていない。

だとするともうちょっと光明が見えてきて、現状のloop()の中でFF受信した時だけ分岐でFC打ってあげてCF受信するという形にすれば、必要なデータも取れるんじゃないか??という方針で今後やってみようかなと。

あと、今のところそもそもちゃんと受信できるのかってところを確認する試作段階なのでテキトーなOLEDに表示しているんですが、ゆくゆくは日常ユースで車に設置したいと考えているので、それ用の3.2インチ液晶もアリエクで買いました。
ぼちぼち上記課題を解決しつつ、表示したいデータを満足に作れるようになったら液晶への出し方も考えていきたいな~と。
Posted at 2025/06/04 23:52:18 | コメント(0) | トラックバック(0) | 日記
2025年05月29日 イイね!

FL4のOBDの件続き(2回目)

◯ はじめに
前回(https://minkara.carview.co.jp/userid/3661994/blog/48450663/)こんな話をしていた。

早速ちょっと手詰まり感でてきたのでアプローチを変えてみようと思い、ELM327のリバースエンジニアリングやSAE J1979 DAやISO 15765-2といった規格文書を読んでみて色々分かってきたので、メモを残しておく。


◯ ELM327

正攻法で地道にやるのも飽きてきたので、市販のELM327+Carscannerアプリを使って各値を表示させつつ、ELM327のピンから物理的にCAN信号を傍受して、ELM327と車載ECUとの間の通信がどうなっているかを把握することにしました。
実際に傍受できたリクエストとレスポンスをまとめて、代表的なデータを含めて記載したものがコチラ。


自分が欲しいデータについて、Descriptionの列に色を塗った。基本的にレスポンスを返してくれるのは18DAF101くんのようだ。

ここで、PID 0C, 0D, 5Bに関してはレスポンスが1フレームに収まっているが、9Aに関しては挙動が異なっている模様。でも知識的にこれ以上分からん。。。



◯ ISO 15765-2
こういうのは教科書を読みましょうということで、ISOを参照してみましょう。
分かったこと:
・レスポンスデータの1バイト目の上位ニブルがPCItypeというパラメータで、そのフレームの役割を示す
・PCItype=0:SF (Single Frame):1フレームで完結するレスポンス
・PCItype=1:FF (First Frame):複数フレームに跨るレスポンスの最初のフレーム
・PCItype=2:CF (Consecutive Frame):複数フレームに跨るレスポンスの続き

・レスポンスデータの1バイト目の下位ニブル(FFの場合は2バイト目も)がそのレスポンスのデータ長を示している。
・FFの場合はFF自身だけでなくCFに載るデータも含めたデータの全長が示される。

ということで、PID 0x9Aのレスポンスについては
・FF+CFの2フレームで構成される
・データの全長は8バイト
・表のデータ例だと、FFに07 00 41 BF、CFに00 06のペイロードが載っている

データの見方がわかったので、データの読み方を調べてみましょう。


◯ SAE J1979 DA
OBD法規に引用されているSAE J1979に、具体的なデータの詳細が書いてあります。それを元に読み解いた結果がこちら。

というわけで、CDEFのData Byteを読み取れば良いということが分かった。
なお、CDはFF、EFはCFのペイロードになっている。


◯ おわりに
とりあえず仕様は理解したので、これに合わせてArudinoくんに動いてもらうように躾けが必要ですね。
具体的には、受信したフレームがSF, FF, CFのどれなのかを判別し、FF, CFの場合は連続するそれらのペイロードを連結してデータを再構成する。
ただしこういった処理をする場合は今のようにメインのLoop関数の中で逐次処理するやり方ではおそらく不可能。CAN受信をタイマー割り込みに変えて、そっちで格納した変数をLoop側で処理するという構成になると思う。一発でそこまで行くのは厳しいので、とりあえず次回はCAN受信をタイマー割り込みにするところあたりから。。。
Posted at 2025/05/29 23:06:30 | コメント(0) | トラックバック(0) | 日記
2025年05月25日 イイね!

シビックFL4のOBDを調べて情報を出力してみた

e:HEVの車ってタコメーター無い割にたまに変なタイミングでエンジン回って気持ち悪い時あるじゃないですか。なのでせめて回転数を数字で理解したいな〜と思って、車両からデータを取ることを考えてみました。

とはいえ偉大なる先駆者の方がいらっしゃるので、基本的にこの流れに沿って進めました。
https://www.takach.net/main.html#CIVIC_FL1


ハードウェアは手元にあったものを使ったので、参照先とは異なります。
・Arduino UNO
・MCP2515ボード(Amazonで売ってる)
・SSD1306 OLED

まずはサクッと配線します。
デフォで付いてる水晶だとダメなので交換しましょう。



さてここからは元の流れに戻って進めます。
まずはこの車がOBD2の何のPIDに対応しているかの一覧を取得します。

Arduinoのスケッチはこんな感じです。
読みづらくてすいません。
みんカラでインデント表示ちゃんとできる方法ご存知の方教えてください。

#include <SPI.h>
#include "mcp2515_can.h"

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET -1
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);

const int CAN_CS_PIN = 10;
const int CAN_INT_PIN = 2;

mcp2515_can CAN(CAN_CS_PIN);

void setup() {
Serial.begin(115200);

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);

while(!Serial);
if (CAN.begin(CAN_500KBPS) != 0) {
Serial.println("CAN-BUS init error!");
while(1);
}
Serial.println("CAN-BAS init ok!");

// フィルターの設定
CAN.init_Mask(0 , 1 , 0x00000000);
CAN.init_Filt(0 , 1 , 0x00000000);
CAN.init_Filt(1 , 1 , 0x00000000);
CAN.init_Mask(1 , 1 , 0x00000000);
CAN.init_Filt(2 , 1 , 0x00000000);
CAN.init_Filt(3 , 1 , 0x00000000);
CAN.init_Filt(4 , 1 , 0x00000000);
CAN.init_Filt(5 , 1 , 0x00000000);
delay(1000);
}


String unit;
float data;
unsigned char yax;
unsigned char fct;
unsigned char len = 0;
uint32_t id;
unsigned char buf[8];
unsigned char stmp[] = {0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char cmnd[] = {0x0C, 0x0D, 0x9A};
unsigned long trgt[] = {0x18DAEFF1, 0x18DAEFF1, 0x18DA01F1};
unsigned long ti;

void loop() {

display.clearDisplay();

//for (int i=0; i<3; i++) {
int i=0;
unsigned long t = millis();
unit = "";
stmp[2] = cmnd[i];
CAN.sendMsgBuf(trgt[i] , 1 , 8 , stmp);
if(CAN.checkReceive()){
CAN.readMsgBuf(&len, buf);
id = CAN.getCanId();
Serial.print(t); Serial.print(":");
Serial.print(id , HEX); Serial.print(":");
for (int i = 0; i < len; i++) {
Serial.print(buf[i] , HEX); Serial.print(" "); //注4
}
Serial.println();
}
//}
delay(100);
}

stmp[2]の値を0x00, 0x20,..., 0xC0まで変えながら実行すると、シリアルモニタに各場合の出力が得られます。

0x00 18DAF1EF:6 41 00 90 18 80 11 55 | 1001 0000 0001 1000 1000 0000 0001 0001
0x20 18DAF1EF:6 41 20 00 00 00 01 55 | 0000 0000 0000 0000 0000 0000 0000 0001
0x40 18DAF1EF:6 41 40 40 00 00 01 55 | 0100 0000 0000 0000 0000 0000 0000 0001
0x60 18DAF1EF:6 41 60 02 00 00 00 55 | 0000 0010 0000 0000 0000 0000 0000 0000

0x80 18DAF101:6 41 80 00 00 00 40 55 | 0000 0000 0000 0000 0000 0000 0100 0000
0x80 18DAF110:6 41 80 00 00 00 02 55 | 0000 0000 0000 0000 0000 0000 0000 0010
0x80 18DAF130:3 7F 01 11 55 55 55 55

0xA0 18DAF130:3 7F 01 11 55 55 55 55
0xC0 18DAF130:3 7F 01 11 55 55 55 55

HEX値をバイナリに直して、ここ https://en.wikipedia.org/wiki/OBD-II_PIDs
に書いてある読み方で対応PIDをピックアップすると、以下になる。

PID
01 : 18DAF1EF : Monitor status
04 : 18DAF1EF : Calculated engine load [%] : 100A/255
0C : 18DAF1EF : Engine speed [rpm] : (256A+B) / 4
0D : 18DAF1EF : Vehicle speed [km/h] : A
11 : 18DAF1EF : Throttle position [%] : 100A/255
15 : 18DAF1EF : Oxygen Sensor 2 [V or %]
1C : 18DAF1EF : OBD standards this vehicle conforms to
20 : 18DAF1EF : PID supported
40 : 18DAF1EF : PID supported
42 : 18DAF1EF : Control module voltage [V] : (256A+B) / 1000
60 : 18DAF1EF : PID supported

9A : 18DAF101 : Hybrid/EV Vehicle System Data, Battery, Voltage
9F : 18DAF110 : Fuel System Percentage Use

ということで、FL1から増えてるのは0x9Aくらいですかね。
正直あんまり取れる数字ないな・・・という気持ちになっているが、とりあえず表示したら満足できそうな数字として3つピックアップすることにした。
・エンジン回転数
・車速
・HVバッテリー電圧

これまた偉大な参照先のコードを参考にしながら書いてみると、こんな感じになる。

#include <SPI.h>
#include "mcp2515_can.h"

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET -1
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);

const int CAN_CS_PIN = 10;
const int CAN_INT_PIN = 2;

mcp2515_can CAN(CAN_CS_PIN);

void setup() {
Serial.begin(115200);
while(!Serial);
if (CAN.begin(CAN_500KBPS) != 0) {
Serial.println("CAN-BUS init error!");
while(1);
}
Serial.println("CAN-BAS init ok!");

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);

// フィルターの設定
CAN.init_Mask(0 , 1 , 0x00000000);
CAN.init_Filt(0 , 1 , 0x00000000);
CAN.init_Filt(1 , 1 , 0x00000000);
CAN.init_Mask(1 , 1 , 0x00000000);
CAN.init_Filt(2 , 1 , 0x00000000);
CAN.init_Filt(3 , 1 , 0x00000000);
CAN.init_Filt(4 , 1 , 0x00000000);
CAN.init_Filt(5 , 1 , 0x00000000);
delay(1000);
}


String unit;
float data;
unsigned char yax;
unsigned char fct;
unsigned char len = 0;
uint32_t id;
unsigned char buf[8];
unsigned char stmp[] = {0x02, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char cmnd[] = {0x0C, 0x0D, 0x9A};
unsigned long trgt[] = {0x18DAEFF1, 0x18DAEFF1, 0x18DA01F1};
unsigned long ti;

void loop() {

display.clearDisplay();

for (int i=0; i<3; i++) {
unsigned long t = millis();
unit = "";
int rpm;
float vbat;
int vsp;
stmp[2] = cmnd[i];
CAN.sendMsgBuf(trgt[i] , 1 , 8 , stmp);
if(CAN.checkReceive()){
CAN.readMsgBuf(&len, buf);
switch(buf[2]){
case 0x0C:
data=((float)256*buf[3]+buf[4])/4;
fct = 0;
unit = "rpm";
yax = 0;
Serial.print(data,fct); Serial.println(unit);
break;
case 0x0D:
data=buf[3];
fct = 0;
unit = "km/h";
yax = 20;
Serial.print(data,fct); Serial.println(unit);
break;
case 0x41:
switch(buf[3]){
case 0x9A:
data=((float)256*buf[6]+buf[7])/64.0;
fct = 2;
unit = "V";
yax = 40;
Serial.print(data,fct); Serial.println(unit);
break;
}
break;
}
display.setCursor(0, yax);
display.print(data,fct); display.print(" "); display.println(unit);
}
}

display.display();
delay(100);
}


caseの分岐が増えているが、これはデータ元のECU次第でbufの何バイト目で判別するかが変わっちゃうから。気づくまでけっこう悩んだ。

あとHVバッテリー電圧ですが、PID 0x9Aの末尾2バイトを丸々使っている模様。
(このPIDの使い方は会社によって異なるらしく、ネットにある情報と違った。)
換算式は厳密には不明ですが、ELM327で取れた値とHEX値とをいくつか並べてChatGPTに相談した結果この式になりました。
5/27 新たにELM327の配線からバイパスして同期して数字見られるようにして比較したところ、係数は70でなく64が正しそうと判明しました。(少なくともELM327+Car scannerの数字とはドンピシャで合う)

それで、最終的にこんな感じの表示になりました。


動画だとこんな感じ。


あとはアクセル開度なり何なり、取りたいやつにPIDとか書き換えればまあ上のリストにある項目は取れそう。
別に持ってるELM327だとHVバッテリーの電流とかエンジン出力とかも出せてるから、どういうリクエスト送ってるのかもうちょっと調べて同じことできないか考えたいな〜というのが今後の展望。

以上です〜。



p.s.
上の動画の背景で流れている曲はこれなので、聴いてください。私の最推しのVtuberです。歌が最高なので他も聴いてください(強欲)
Posted at 2025/05/25 19:49:55 | コメント(0) | トラックバック(0) | クルマ
2025年01月05日 イイね!

CAN周りを調べたい

CIVIC e:HEVだとエンジン回転数はメーターに出ず、車両としての使用電力が%表示される形となっている。これを何らかメーター的な表示として出そうと思うと、普通はOBD2を使うと思う。ただOBD2だとそれ以外の情報あまり入ってなくて拡張性ないし、駆動力指示とか発電指示とかも見たいなとなると、普通に制御系のCANを掴めるようにしたいなあと考えていた。

そんな折、comma.ai というオープンソースの自動運転プロジェクトを見ていたら、色々な車のCAN通信に関する情報が解析されてDBCファイルの形で置いてあった。
opendbc/opendbc/dbc/generator
/honda/


色々HWも必要っぽいけど、何かできないか考えてみようかな。
一応手元にArduinoでCAN受信してシリアルで出せる環境は昔作ったのがあるから、これをどうにか流用できると嬉しいんだけど。。。

Posted at 2025/01/05 18:41:23 | コメント(0) | トラックバック(0) | 日記

プロフィール

車はxEVに乗るつもり。 MTでガチャガチャしたい時はバイク乗ります。 CR-Z ZF2 → CIVIC FL4, CB250R MC52
みんカラ新規会員登録

ユーザー内検索

<< 2025/9 >>

 123456
78910111213
14151617181920
21222324252627
282930    

リンク・クリップ

[マツダ ロードスター] 神ツール Savvycan でかんたんCAN分析! 
カテゴリ:その他(カテゴリ未設定)
2025/01/05 17:51:06
[ホンダ シビック (ハッチバック)]YOKOHAMA iceGUARD 6 (IG60) 205/60R16 
カテゴリ:その他(カテゴリ未設定)
2024/12/01 00:54:26
[ホンダ シビック (ハッチバック)] リア用USBポート取り付け(その2) 
カテゴリ:その他(カテゴリ未設定)
2024/11/30 22:53:09

愛車一覧

ホンダ シビック (ハッチバック) ホンダ シビック (ハッチバック)
2024/10/13納車
ホンダ CB250R ホンダ CB250R
最初赤かったのですが、後に青くしました。
ホンダ CR-Z ホンダ CR-Z
CR-Z後期のCVT FL4納車とともにさよならしました。

過去のブログ

2025年
01月02月03月04月05月06月
07月08月09月10月11月12月
2024年
01月02月03月04月05月06月
07月08月09月10月11月12月
ヘルプ利用規約サイトマップ
© LY Corporation