M5StickCで速度と進行方向を表示する ~ ラズパイと連携
今までも、車載用の速度計をRaspberry Piを用いて作りました。しかし、表示器を設置する場所や、GPSセンサーを受信条件の良い場所に設置するなどの制約で、使い勝手が良くありませんでした。
また、スマートフォンを活用するなど、いろいろな方法も考えて試してみましたが、今のところ一番使い勝手が良いかなと思う方法を今回は紹介します。
それは、Raspberry PiでGPSデータを受信し、M5StickCで表示させるというものです。Raspberry PiからUDPソケット通信でM5StickCにデータを送信します。Raspberry PiとM5StickCは、条件の良い場所に設置します。
それでは、詳しく説明します。
Raspberry Pi側プログラム
これまで提供してきた「FormGPS」プログラムに、UDP送信ロジックを追加しました。提供記事からプログラムをダウンロードしてください。
起動すると、入力項目に送信先のIPアドレスがあります。送信先のIPアドレスが分かり次第、入力してください。入力後は「IP SET」ボタンを押すことでIPアドレスが有効になります。
なお、送信データは、"速度(3桁),進行方向(2文字)“のテキストデータですから、オリジナルのプログラムを作成してもらっても構いません。
M5StickC側プログラム
プログラムの仕組み自体は、今まで公開した高度表示などのプログラムと変わりません。UDPソケット通信で、速度と進行方向が渡ってくるので、それを表示します。
// Raspberry PiからGPS速度と方角を取得する
// UDP : speed,direction
#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#define BUFSIZE 1024
const char* ssid = "XXXXXXXX";
const char* password = "XXXXXXXX";
const int port = 60000;
WiFiUDP udp;
void print_wifi_state(){
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(YELLOW);
M5.Lcd.setCursor(3, 3);
M5.Lcd.println("WiFi connect");
M5.Lcd.print("IP address: ");
M5.Lcd.println(WiFi.localIP());
M5.Lcd.print("Port: ");
M5.Lcd.println(port);
}
void setup_wifi(){
M5.Lcd.setTextColor(RED);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(3, 3);
M5.Lcd.print("Connecting to ");
M5.Lcd.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
M5.Lcd.print(".");
}
print_wifi_state();
udp.begin(port);
}
void setup() {
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
setup_wifi();
}
void split(String data, String *lines){
int count = 0;
int datalength = data.length();
for (int i = 0; i < datalength; i++) {
char onec = data.charAt(i);
if ( onec == ',' ) {
count++;
if ( count == 2) {
break ;
}
}
else {
lines[count] += onec;
}
}
}
void loop() {
char packetBuffer[BUFSIZE];
String lines[2] ;
// M5.update();
int packetSize = udp.parsePacket();
if (packetSize){
int len = udp.read(packetBuffer, packetSize);
if (len > 0){
packetBuffer[len] = '\0';
}
split(packetBuffer, lines) ;
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.setCursor(3, 10, 7); //x,y,font 7:48ピクセル7セグ風フォント
M5.Lcd.printf("%03d", lines[0].toInt()); // 速度を表示
Serial.println("Speed=");
Serial.println(lines[0]);
float direction = lines[1].toInt() ;
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setCursor(105, 34, 4); //x,y,font 4:26ピクセルASCIIフォント
if ((direction >=337.5 && direction <= 360) ||
(direction >=0 && direction <= 22.5)) {
// 北
M5.Lcd.println("N");
} else if (direction > 22.5 && direction < 67.5) {
// 北東
M5.Lcd.println("NE");
} else if (direction >=67.5 && direction <= 112.5) {
// 東
M5.Lcd.println("E");
} else if (direction >112.5 && direction < 157.5) {
// 南東
M5.Lcd.println("SE");
} else if (direction >=157.5 && direction <= 202.5) {
// 南
M5.Lcd.println("S");
} else if (direction >202.5 && direction < 247.5) {
// 南西
M5.Lcd.println("SW");
} else if (direction >=247.5 && direction <= 292.5) {
// 西
M5.Lcd.println("W");
} else if (direction >292.5 && direction < 337.5) {
// 北西
M5.Lcd.println("NW");
} else {
// ERROR
M5.Lcd.println("XX");
}
// M5.Lcd.setTextColor(WHITE);
// M5.Lcd.setCursor(25, 65, 1); //x,y,font 1:Adafruit 8ピクセルASCIIフォント
// M5.Lcd.println(lines[1]); // 方角を表示
Serial.println("Direction=");
Serial.println(lines[1]);
}
}
起動すると、Wi-Fiに接続が行われ、成功するとIPアドレスが表示されます。表示されたIPアドレスを、送信側で設定してください。
UDPソケット受信に成功すると、速度と進行方向(N,E,S,W,NE,SE,SW,NW)が表示されます。M5StickCの内部バッテリーだけなら、1時間位でバッテリー切れになるでしょう。外部のバッテリーを用意してください。
実際に動作させてみる
Raspberry Piは助手席に、M5StickCはダッシュボードに設置します。最初はM5StickCをメーター類の空いている場所に置こうと思ったのですが、今一つしっくりしません。結局、ダッシュボードの1Dinスペースに置きました(最初の写真)。
スマートフォンでテザリングをしてWi-Fiを有効にします。Raspberry PiとM5StickCは、どちらを先に起動しても構いません。起動後は、M5StickCのIPアドレスをRaspberry Piのアプリ「FormGPS」に設定してください。
Raspberry Piは、スマートフォンでVNCクライアントを使って操作しました。
実際に使ってみて、M5StickCの液晶は、日が当たっても良く見えるところが良いです。速度と進行方向が良く見えて、キャラクタ表示液晶やスマートフォンでの表示よりも見やすく感じます。
進行方向は、日本語か、矢印をビットマップで表示した方が良いと感じました。これは、いずれ改良したいです。
これからも試行錯誤してみます
今回は速度と進行方向でしたが、高度もそのうちに用意してみます。また、ヘッドアップディスプレイにしてみるなど、試行錯誤をしていきたいと思います。