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

アンドロ沼のブログ一覧

2020年11月22日 イイね!

水温計の作り方(ソフトの説明編4)

ソフトの説明も、これで終わりです。なぜか、最後に初期化の説明してしまいます。まず、一行目のところですが、LCDライブラリの初期化で、I2Cのアドレスが0x3F(ジャンパで変えられるそうですが・・)、16桁、2行だという定義をしてる形です。

Setup関数の中では、CANの通信ボーレートを500kbps(フリードでは、500kbpsでいいですが、古い車違ったりすることもあります。)、CANのTxをGPIOの5番、CANのRxをGPIOの4番に指定しています。私の回路図とは違うつなぎ方をしてしまったときは、このピン番号を変更すれば、別なピンにアサインすることが可能です。つぎの行では、受信Queueの大きさをセットしていますが、これで足りてるかどうかは、さっぱり私も知りません。この辺りは、CANドライバのサンプルコードから適当に持ってきてるだけだったりします。ただ、足りなければメッセージの取りこぼしが出るし、多すぎれば使えるRAMの量が減るので、規模の大きいプログラムを作るときは、ちゃんと考慮しましょう。(今回程度の軽負荷の場合は、適当で大丈夫かと。)

そのあとは、LCDの初期化をして、バックライトをつけ、CANを受信するまで、「Waiting CAN」の文字を表示する処理をしています。

一応、ソフトの説明もここまでとなります。わからないことがあれば、コメントで聞いてくれれば、回答します。

LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
void setup() {
CAN_cfg.speed=CAN_SPEED_500KBPS;
CAN_cfg.tx_pin_id = GPIO_NUM_5;
CAN_cfg.rx_pin_id = GPIO_NUM_4;
CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t));
//start CAN Module
ESP32Can.CANInit();
prev_time = millis();
lcd.begin(); // initialize the lcd
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Waiting CAN");
}
Posted at 2020/11/22 14:09:47 | コメント(0) | トラックバック(0) | 日記
2020年11月22日 イイね!

水温計の作り方(ソフトの説明編3)

今回は、受信処理を主に説明します。ソフトの説明編1で書いたように、0x18db33f1の機能アドレスを送信すると、誰から返事が来るのかわからない状況です。そうなると、リクエストの返信のIDの最後一バイトは、何が入ってもいいようにしないといけません。(関連情報URLのところで、解説があります。)
このため、下記の受信処理の冒頭で、受信を判断したら次のIF文で、最後の1バイトを除くIDがこちらの送信メッセージに対する返信かどうかを判断してます。(これをしないと、余計なメッセージにもいちいち反応してしまい、処理が回らなくなったりします。)

次のIF文では、受信データの3バイト目がPIDの0x05だったら、水温の情報だと判断して、LCDの0行目に受信した温度データから40を引いて、その値を表示してます。(PIDの0x05のデータは、摂氏の温度に+40したものだとWikipediaに書いてあります。)

受信データの3バイト目が、0x05ではなく、0x0Cだったときは、エンジンの回転数と判断して、LCDの2行目に回転数を表示しています。ただ、このLCDの関数は左詰めで数字表示するので、桁数が減る(例えば、モーター駆動に切り替わって、エンジンが止まる等)と、前回エンジンが回ってた時の桁が残り、なんだかわからなくなります。(実際そうなった。)なので、前のところで、余計にスペースを書き込んで、前回のデータを消してから、回転数を表示してます。

この方法で直ったかと思いきや、今度はエンジンが止まった時に、数字がちらちらするようになりました。エンジンが止まってる間、0rpmの値を受け取り続けると、毎回毎回0を書こうとして、「消して書く。」動作を200msで繰り返すためです。なので、最後のIF文で仕方なく、前回と同じ値を受け取ったときは表示を書き換えないようにして、見た目がまともになりました。

回転数の情報は、受信したデータの4バイト目に256をかけて、5バイト目を足し、4で割ったものが回転数だとWikipediaに書かれているので、その通りに計算しています。

if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){
if ((rx_frame.MsgID & 0xFFFFFF00) == 0x18daf100) {
if ((rx_frame.data.u8[2])== 0x05) {
lcd.setCursor(0,0);
lcd.print("Water Temp = ");
lcd.setCursor(13,0);
lcd.print((signed char)(rx_frame.data.u8[3]) - 40);
}else if ((rx_frame.data.u8[2])== 0x0c) {
current_rpm=(int)(((int)rx_frame.data.u8[3])*256 + (int)rx_frame.data.u8[4])/4;
if (current_rpm != last_rpm) {
lcd.setCursor(0,1);
lcd.print("ENGINE rev: ");
lcd.setCursor(12,1);
lcd.print(current_rpm);
last_rpm = current_rpm;
}
}
}
}
Posted at 2020/11/22 13:52:19 | コメント(0) | トラックバック(0) | 日記
2020年11月22日 イイね!

水温計の作り方(ソフトの説明編2)

前回、リクエストの中身を解説しましたけど、今度はスケジューラーのところを解説します。取得したいデータの性質を考えると、水温なんて頑張っても数秒に一回しか変わりません。また、エンジン回転数は数ms毎に変化する値なので、なるべく速く取得したい数値です。ただ、人間はそんなに早く数値読むことができません。(今回は手抜きで数字表示だし。)

ということで、今回は50msで周期を作り、回転数は200msに一回、水温は1秒に一回取得することにします。なので、回転数は50msでカウントアップされるタイマーの4回に一回で送れば良いということになり、カウンタを4で割って、4かけて元の数と一致するときに送信要求を送ることにしました。(4で割って余りが0の時でもよかったかもしれない。)

で、水温は0から始まって、20回目の19になったときに、送信要求を送っています。(ついでにカウンタをクリア)

if ((prev_time-millis())> 50) {
prev_time=millis();
if (loop_counter == ((loop_counter/4)*4)) { // if counter value is even
/* ここに回転数の取得メッセージの送信処理が入る */
} else if (loop_counter == 19) { // 1sec expired
/* ここに水温の取得メッセージの送信処理が入る */
}
if (loop_counter >= 19) {
loop_counter = 0;
} else {
loop_counter++;
}
}
}

実際、水温は最初100msくらいで更新したときは、数値が戻ることもあったのですが、これで問題なくゆっくり変化するようになりました。

また、エンジン回転数は人間の読み取りもそうなんですが、実際にはLCDもさほど速くないので、200msで更新してもさっぱり読み取れないことが分かったので、0.3秒とか、0.5秒でもよかったかもしれない。

表示するときに、グラフ表示などでグラフィカルに表示するのであれば、100msなどに早めるのも手ですが、CANバスはいつも混み合っていて、そこにこの読み出し要求とその応答が混ざると混み具合が激しくなり、車両の重要な通信が妨げられて、遅延する可能性があります。これは、車両のエラー表示の原因になりかねないので、10msに一回とかの高速で要求することはやめてください。(どうせ人間読めないから。)

まあ、反省点ですが、頑張って外字機能とか使えば、この液晶でも棒グラフは出せると思います。この液晶は1文字が5x7ドットなので、500rpmで一文字、100rpmで1ドットなので、1,2,3,4幅の縦ドットをそれぞれ外字登録してあげれば、横棒グラフ表示できると思います。(とはいえ、どうせATなので自分で変速できないから、回転数を正確に見れてもあまり意味はないですが・・・) 見栄えをよくしたい人はチャレンジしてもいいのかも。
参照情報URLに外字登録のやり方を解説しているところを貼り付けておきました。ヤフオクで売ってるハイブリットモニターのように、自作のアイコン的なものを表示したいときは、これ使えばできます。(このブログ全部読むと、自分で2000円くらいであのモニタは作れると思います。ただ、そこに至るまでの労力を考えると、あの値段は妥当だな(むしろ安い?)というのも理解できると思います。)
Posted at 2020/11/22 09:26:58 | コメント(0) | トラックバック(0) | 日記
2020年11月20日 イイね!

水温計の作り方(ソフトの説明編1)

まずは水温とエンジン回転数の取得方法を説明します。今回車両のOBDコネクタに繋ぎましたが、これは元々カリフォルニア州の法律で設置が義務付けられ、その後世界各国で法制化されたコネクタの規格になります。
で、このカリフォルニアの法律では、コネクタの形状、ピン配だけでなく水温や車速、回転数といった情報も読み出すことができるように、通信のフォーマットも決めています。そのため、基本的には1990年代以降の車では、同じ方法でこれらの情報を読み出すことが可能です。
で、その規格がSAE J1979になるんですが、この規格の内容は、関連情報URLに書いた、英語版のWikipediaが一番わかりやすいので、こちらを参考にしてください。(Google先生に翻訳してもらえば、誰でも読めるかと思います。)

とはいえ、実際に取得する方法には読んでもわかりにくいので、水温の取得方法に絞って、説明していきます。

まず、水温情報を取得するには、水温情報を持っているECUにリクエストしなければいけません。このリクエストするメッセージフレームをCANドライバに渡しているところが下記になります。

rx_frame.FIR.B.FF = CAN_frame_ext;
1)CANのメッセージID長の設定
CANのメッセージIDの長さには、11bitと29bitの二種類があり、Freedの場合は29bitの拡張IDと呼ばれるものを使ってます。この行では、CANドライバに送信する、メッセージID長を拡張IDにしますよというフラグを立ててます。

rx_frame.MsgID = 0x18db33f1 ;
2)CANのメッセージIDのセット
ここで、次に送信するメッセージのIDとして、「0x18db33f1」という機能アドレスを設定しています。このIDにすると、「誰でもいいから水温わかる人返事して」みたいな呼びかけをすることになります。(実際このメッセージを送ると、2つぐらいのノードから返事が返ってきてました。)

rx_frame.FIR.B.DLC = 3;
3)CANのメッセージ長のセット
ここでは、IDに連なるCANのデータ長を3バイトにしています。ここで、CANは8バイトまでのメッセージ長を許すのですが、実際には次の最初のデータバイトで長さを指定していますので、8バイト送ったとしても特に問題は起きません。結論としてここでは、3~8のうちの何の値でも特に問題はないです。(指定しなくても問題ないかも?)

rx_frame.data.u8[0] = 0x02;
4)1バイト目のデータの指定
ここからが本当の送信データの中身になります。ここで、「02」を送ると受け取り側は、そのあとに続く2バイトが要求だということがわかるということになります。

rx_frame.data.u8[1] = 0x01;
5)要求するサービスの指定
SAE J1979では下表の10個のサービスが規定されています。今回は現在値を読み出すため、サービス0x01を利用することになるので、2バイト目に数値として0x01を指定しています。


rx_frame.data.u8[2] = 0x05; // Request coolant temperature
6)要求するPIDの指定
PIDには200個近いものが用意されています。今回はこのうちのエンジン水温を読み出したいので、WikipediaにあるPIDの表(下表)から、0x05の値を送信しているわけです。


この応用で、回転数が見たければ0x0Cをここに入れればよく、車速は0x0D、吸気温0x0F、外気温は、0x46といった具合です。
Posted at 2020/11/20 20:09:42 | コメント(0) | トラックバック(0) | 日記
2020年11月19日 イイね!

水温計の作り方(コンパイル編)

うまいこと、今回私が使ったDoit devkitのボードのコンパイルのやり方を説明してるページを見つけたので、関連情報URLのところへ行って、「DOIT ESP32 DEVKIT V1」と書いてあるあたりからのやり方を参考にして、コンパイル&ダウンロードしてください。回路がうまく接続されていれば、フリードにつなぐことで、水温計とタコメータとして動作するはずです。

なお、他の計器(速度計、燃費計、外気温計)にしたい方のために、後日ソースコードの解説を追加します。

ちょっと反省点を書くと、

1)本体のところと、OBDのところは、面倒でもコネクタで脱着できるようにしておくと、後でソフトを書き替えたいとき、簡単に自宅に持ち帰れるのでその方がよかった。(本当は、表示をもっとかっこよくしたいのだけれど、もう外すのが面倒でやる気なし。)

2)タコメータの表示は、数字で表示するのではなく、バーグラフで表示するようにしとけばよかった。

3)タコメータを200msで更新するようにしたのだけれど、まだ速すぎる。300ms
で十分だった。

4)本体に接着で蓋したので、実はコントラスト調整ができませぬ。なので、かっこ悪くとも斜め上からLCDを覗き込むようにしないとまともに見えない。あの設置角が実は肝だったりします。皆さんは蓋する前にちゃんと表示が見えるのを確認するようにしましょう。
Posted at 2020/11/19 20:03:13 | コメント(0) | トラックバック(0) | 日記

プロフィール

「水温計の作り方(M5StickC plus ソースコード編2) http://cvw.jp/b/1552949/45254112/
何シテル?   07/05 22:01
アンドロ沼です。アクアからフリードハイブリッドに買い換えしました。
みんカラ新規会員登録

ユーザー内検索

<< 2020/11 >>

1234567
891011121314
15 1617 18 19 2021
22232425262728
2930     

愛車一覧

ホンダ フリードハイブリッド ホンダ フリードハイブリッド
家族が増え、強い圧力がかかり買い換えました。
スズキ ワゴンRハイブリッド スズキ ワゴンRハイブリッド
電車通勤から、車通勤に替り買い足しました。
トヨタ アクア トヨタ アクア
Fitからアクアに買い替えついでに、いろいろいじろうと思ってます。

過去のブログ

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