今回は、受信処理を主に説明します。ソフトの説明編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