M5Stack GrayにGPSモジュールを取り付けてセンサー値をLCDに表示
目的
M5Stack GrayにGPSモジュールを取り付けて、センサー値(GPS座標、加速度センサー、ジャイロセンサー)の値をLCDに出力したので、コード内容を共有します。Arduino IDEを使用する前提です。捕捉した衛星の数、HDOP、日時、GPS座標、加速度・ジャイロセンサー値、を画像の様に出力します。
コード
リポジトリから入手可能。
M5Stack GrayとGPSモジュールを準備すれば、上記リポジトリのコードで上記画像のLCD出表示力が得られます。
ハードウェア下準備
- GPSモジュールをそのまま使うと内部アンテナを使う設定になっているため、衛星を捉える(FIXする)まで時間がかかります。外部アンテナにするとFIXが早くなるので、変更することをおすすめします。
-
付属するアンテナを付けるだけでは切り替わらず、画像のようにGPSモジュール内の灰色の線を外して黒い線を接続する必要があります。
- 灰色の線の電極は動いてショートを発生させる可能性があるので、テープなどで絶縁したほうがよいです。
- 外部アンテナの先端は窓際あたりに設置すると効果的。屋内でも1分くらいでFIXしました。
ライブラリ下準備
TinyGPSPlus:http://arduiniana.org/libraries/tinygpsplus/ からライブラリをダウンロード(.zip)
スケッチ→ライブラリをインクルード→ZIP形式のライブラリをインストール
コード解説
サンプル例のGPS_NEO_M8N→FullExampleのコードをベースとして、MPU9250のセンサー出力の記述を足しています。
#define M5STACK_MPU9250
#include <M5Stack.h>
#include <TinyGPS++.h>
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
HardwareSerial ss(2);
float accX = 0.0F;
float accY = 0.0F;
float accZ = 0.0F;
float gyroX = 0.0F;
float gyroY = 0.0F;
float gyroZ = 0.0F;
float pitch = 0.0F;
float roll = 0.0F;
float yaw = 0.0F;
float temp = 0.0F;
セットアップでスピーカーオフにするとスピーカーからのノイズが減ります(結構ノイズ大きい)。
void setup()
{
M5.begin();
dacWrite(25, 0); /* スピーカーオフにしてノイズを消す */
M5.Power.begin();
ss.begin(GPSBaud);
M5.IMU.Init();
M5.Lcd.setTextSize(1);
}
void loop()
{
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(0, 0);
M5.Lcd.setTextColor(WHITE, BLACK);
M5.Lcd.print("Num of Sat[-]:");
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
M5.Lcd.print("HDOP[-]:");
printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
M5.Lcd.print("DateTime[-]:");
printDateTime(gps.date, gps.time);
M5.Lcd.println();
M5.Lcd.setTextColor(BLUE, BLACK);
M5.Lcd.setTextSize(2);
M5.Lcd.print("LAT[-]:");
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
M5.Lcd.print("LNG[-]:");
printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
// printInt(gps.location.age(), gps.location.isValid(), 5);
M5.Lcd.print("ALT[-]:");
printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
// printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
// printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
// printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
// printInt(gps.charsProcessed(), true, 6);
// printInt(gps.sentencesWithFix(), true, 10);
// printInt(gps.failedChecksum(), true, 9);
M5.Lcd.println();
if (millis() > 5000 && gps.charsProcessed() < 10)
M5.Lcd.println(F("No GPS data received: check wiring"));
ここまではGPS座標の取得と表示。FIXするまでは表示が「」になります。「」が長く続く場合(1min以上かかる)は、アンテナの接続を確認し、位置を変えてみてください。
ここから下は加速度・ジャイロセンサーの値を取得・表示。
- GPSモジュールは1sec間隔でアクセスする必要があり(間隔が短いとおかしくなる)、1secの間は加速度・ジャイロセンサーの値を取得・表示します。コード上では1msec間隔でアクセスして10回平均を計算して表示、を100回繰り返します。平均化回数を増やすと更新頻度が減ります。精度と応答性のトレードオフだと思えば良く、適宜調整してください。
- カーソル設定をしてるのは、値を更新していないGPS側の値がLCDから消えてしまうためです。
- 温度センサーを出力してもよいですが、M5Stack内部の温度なので外気温とは違います(結構高め)。
int div_num = 10; //平均化回数
int total_delay_num = 1000 / div_num; //平均化して1secになるようにループ回数を設定
for(int ii = 0;ii < total_delay_num;ii++){
float ave_accX = 0.0F;
float ave_accY = 0.0F;
float ave_accZ = 0.0F;
float ave_gyroX = 0.0F;
float ave_gyroY = 0.0F;
float ave_gyroZ = 0.0F;
float ave_pitch = 0.0F;
float ave_roll = 0.0F;
float ave_yaw = 0.0F;
float ave_temp = 0.0F;
//ジャイロ、加速度、温度センサーの平均化
for(int jj = 0;jj < div_num;jj++){
M5.IMU.getGyroData(&gyroX,&gyroY,&gyroZ);
M5.IMU.getAccelData(&accX,&accY,&accZ);
M5.IMU.getAhrsData(&pitch,&roll,&yaw);
M5.IMU.getTempData(&temp);
ave_accX += accX;
ave_accY += accY;
ave_accZ += accZ;
ave_gyroX += gyroX;
ave_gyroY += gyroY;
ave_gyroZ += gyroZ;
ave_pitch += pitch;
ave_roll += roll;
ave_yaw += yaw;
ave_temp += temp;
delay(1);
}
ave_accX /= div_num;
ave_accY /= div_num;
ave_accZ /= div_num;
ave_gyroX /= div_num;
ave_gyroY /= div_num;
ave_gyroZ /= div_num;
ave_pitch /= div_num;
ave_roll /= div_num;
ave_yaw /= div_num;
ave_temp /= div_num;
M5.Lcd.setCursor(0, 90);
M5.Lcd.setTextColor(GREEN , BLACK);
M5.Lcd.println("GYRO XYZ[o/s]");
M5.Lcd.printf("%6.2f %6.2f %6.2f ", ave_gyroX, ave_gyroY, ave_gyroZ);
M5.Lcd.println("");
M5.Lcd.println("ACC[G]");
M5.Lcd.printf("%5.2f %5.2f %5.2f ", ave_accX, ave_accY, ave_accZ);
M5.Lcd.println("");
M5.Lcd.println("P-R-Y[deg]");
M5.Lcd.printf("%5.2f %5.2f %5.2f ", ave_pitch, ave_roll, ave_yaw);
M5.Lcd.println("");
// M5.Lcd.printf("Temperature[C] %.2f", ave_temp);
// M5.Lcd.println("");
}
}
ここから下は内部関数
// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do{
while (ss.available())
gps.encode(ss.read());
}while(millis() - start < ms);
}
static void printFloat(float val, bool valid, int len, int prec)
{
if(!valid){
while (len-- > 1)
M5.Lcd.print('*');
M5.Lcd.print(' ');
}else{
M5.Lcd.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i){
M5.Lcd.print(' ');
}
}
M5.Lcd.println();
smartDelay(0);
}
static void printInt(unsigned long val, bool valid, int len)
{
char sz[32] = "*****************";
if(valid)
sprintf(sz, "%ld", val);
sz[len] = 0;
for(int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if(len > 0)
sz[len-1] = ' ';
M5.Lcd.print(sz);
M5.Lcd.println();
smartDelay(0);
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
if(!d.isValid()){
M5.Lcd.print(F("********** "));
}else{
char sz[32];
sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
M5.Lcd.print(sz);
}
if(!t.isValid()){
M5.Lcd.print(F("******** "));
}else{
char sz[32];
sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
M5.Lcd.print(sz);
}
printInt(d.age(), d.isValid(), 5);
smartDelay(0);
}
static void printStr(const char *str, int len)
{
int slen = strlen(str);
for(int i=0; i<len; ++i){
M5.Lcd.print(i<slen ? str[i] : ' ');
}
M5.Lcd.println();
smartDelay(0);
}
終わりに
M5Stackを久しぶりにちゃんと使ってみました。例題がバラバラに存在してたので、結合して必要な情報を出しただけですが、何かの役に立ったならLGTMお願いします。
Author And Source
この問題について(M5Stack GrayにGPSモジュールを取り付けてセンサー値をLCDに表示), 我々は、より多くの情報をここで見つけました https://qiita.com/takurot/items/d94b3612d96dcf7aada9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .