GPS CLOCK with M5STACK
M5STACK と GPS Module で GPS時計 を作りました 2017.12.26
日時、時刻を アナログ と デジタル で表示し 切り替えは3つの ボタンで選択します。
動作:
GPS 情報 : 左のボタンを押し 受信すると 右上の丸が 赤から緑。数値は白から緑。
アナログ時計:中央ボタンを押し 受信すると 右上の丸が 赤から緑になります。
デジタル時計: 右ボタンを押し 受信すると 右上の丸が 赤から緑。数値は白から緑。
![]() |
![]() |
No | Nomen | Link、説明 | Price |
1 | M5STACK BASIC | M5Stack Store ( $33.25 ) | 3767円 |
2 | M5STACK GPS Module (NEO-M8N−0-10) | M5Stack Store ( $37.91 ) | 4295円 |
3 | M5STACK Battery Module | M5Stack Store ( $15.11 ) | 1712円 |
4 | 28dBi Gain GPS Antenna | importjewelrylover($2.52) | 322円 |
—————————————- | ————————- | —— | |
5 | M5STACK ライブラリー | GitHub:M5STACK | |
6 | Free_Fonts:M5STACKライブラリーの中にある。 | .inoフォルダの中へ入れる | |
7 | TineGPS++ ライブラリー | TinyGPS++ | |
8 | jpg 画像:55×55 pixels程度。(apple mark) | SD に入れる。 |
.
GPS Module:価格は高いですが 初めてですので 純正品を使用しました。
GPS Module:付属品:1.5mm ケーブル | Battery Module |
![]() |
![]() |
GPS Antenna |
![]() |
.
_ GPS Module のカバーが無く 綺麗でないです。そこで 部品が入っていた
_ 小さな透明なケースがあり サイズがピッタリでしたので 被せました。
.
.
GPS Module:GPSのチップは NEO-M8N-0-10 が使用されています。
配線:M5STACK と GPS Module ( NEO-M8N-0-10 )
_ ESP32 UART2 GPIO-16 ( U2RXD ) — GPS TXD ( NEO-M8N-0-10 ) 。
_ ハードウエアーシリアルの設定:例:HardwareSerial ss(2);
追記:2018.01.13
小型の GPS アンテナ を取り付けました。ケースの中に入り綺麗に仕上がります。
_ ケース内部に取り付ける事が可能で、受信は正常に受ける事ができました。
_ 小型ですので感覚的に受信感度が少ないかなとも思いましたが最初の
_ 受信時間も数分間で同じでした。
_ 名称:GPS Module with Active Ceramic Antenna IPEX Interface 1575MHz
_ 販売:ebay:chip_partner:価格:$2.30 ( 256円 ):輸送期間 = 26日。
_ サイズ:20mm x 6mm x 6mm:ワイヤーの長さ:20mm
_ ケースの中の高さは 6.4mm ですので入ります。
感想:
M5STACK の利点 (強み) は サンプルやライブラリーの充実にあります。
単独で使用するか 今回の様に 合体して多くの機能を直ぐ作る事ができます。
特に 表示操作では SD内のjpg 画像 を DISPLAY へ表示する命令があります。
例: M5.Lcd.drawJpgFile(SD, “/apple_marks/apple_50.jpg”);
_ SD の中にある apple_50.jpg を LCD へ DRAW します。
_ M5STACK のライブラリーは 強力な開発環境です。
疑問と課題 ( Questions and tasks ):
_ ESP32 M5STACK と 画像のバイト配列:
_ これまで画像をスケッチ内に保存するには xx.c という バイト配列のデーター
_ に変換し 変数名で使用していました。
_ M5STACK は バイト配列を表示すると 色づれ があり使用できません。
_ 色が反転している訳でも無いです。TFT Display と Display library は 何か細工
_ されている様に思えてしまいます。
_ 対策は SD から jpg を読み込む事ですが バイト配列も使用したい。
_ それと 画像データーを変数名で扱うには どうしたら良いのか解らず課題です。
.
スケッチ:GPS CLOCK with M5STACK : 2017.12.26 : macsbug
M5STACK Library にある「GPS/FullExample」と「Display/TFT_Clock」を
合体し作成しました。表示は GPS受信 と 日時、時刻を アナログとデジタル。
切り替えは A,B,C ボタンで選択します。
「time_set」は 場所に応じて設定します。日本の場合は JST に合わせます。
アナログ時計の左上は 55×55ピクセル程度の jpg画像を SD に入れて起きます。
SD に画像が無い場合は 何も表示せず動作します。
// GPS CLOCK WITH M5STACK : 2017.12.26 : macsbug #include <M5Stack.h> #include "Free_Fonts.h" #include <TinyGPS++.h> TinyGPSPlus gps; HardwareSerial gs(2); // ESP32 UART2 GPIO-16 ( RXD2 ) --- GPS TXD //========================================================================= int time_set = 9; // Set to the time of your country. : JST = +9 hour float sx = 0,sy = 1,mx = 1,my = 0,hx = -1,hy = 0; float sdeg=0, mdeg=0, hdeg=0; uint16_t osx=120,osy=120,omx=120,omy=120,ohx=120,ohy=120; uint16_t x0=0, x1=0, yy0=0, yy1=0; uint32_t targetTime = 0; // for next 1 second timeout static uint8_t conv2d(const char* p); uint8_t hh=conv2d(__TIME__); // Get H, M, S from compile time uint8_t mm=conv2d(__TIME__+3), ss=conv2d(__TIME__+6); boolean initial = 1; static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002; unsigned long distanceKmToLondon = (unsigned long) TinyGPSPlus::distanceBetween( gps.location.lat(),gps.location.lng(),LONDON_LAT,LONDON_LON)/1000; double courseToLondon = TinyGPSPlus::courseTo( gps.location.lat(),gps.location.lng(),LONDON_LAT,LONDON_LON); const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon); int ym, dm, dd; // year,month,day String ym_, dm_, dd_, hh_, mm_, ss_; // year,month,day,hour,min,sec char f1, f2, f3, b1, b2, b3; // digital:year,month,day buffer String L1[11]={"0000/00/00","00:00:00","000.00" // old gps,time,date,, ,"000.00","000.00","000.00","000.00" ,"000.00","000.00","000.00"}; String L2[11]={"0000/00/00","00:00:00","000.00" // new gps,time,date,, ,"000.00","000.00","000.00","000.00" ,"000.00","000.00","000.00"}; String mode_ = "gps"; // gps,digital,analog //========================================================================= void setup(){ Serial.begin(115200); M5.begin(); gs.begin(9600); //static const uint32_t GPSBaud = 9600; M5.Lcd.fillScreen(BLACK); // DISPLAY CLEAR pinMode(BUTTON_A_PIN, INPUT_PULLUP); // Set A button pinMode(BUTTON_B_PIN, INPUT_PULLUP); // Set B button pinMode(BUTTON_C_PIN, INPUT_PULLUP); // Set C button } //========================================================================= void loop(){ if ( M5.BtnA.wasPressed()){ mode_ = "gps" ; gps_setup() ;} if ( M5.BtnB.wasPressed()){ mode_ = "analog" ; analog_setup() ;} if ( M5.BtnC.wasPressed()){ mode_ = "digital"; digital_setup();} // gps mode ------------------------------------------------------------- if ( mode_ == "gps" ){ // GPS MODE if ( initial == 1 ){ gps_setup();} // INITIAL SET time_date_read(); // READ DATA L2[0] = String(gps.date.year()) + "/" + dm_ + "/" + dd_; // DATE L2[1] = hh_ + ":" + mm_ + ":" + ss_; // TIME L2[2] = String(gps.location.lat(),6); // LAT L2[3] = String(gps.location.lng(),6); // LNG L2[4] = String(gps.speed.kmph()) + " km/sec"; // SPEED L2[5] = String(gps.speed.mps()) + " m/sec"; // SPEED L2[6] = String(gps.speed.value()) + " Raw deg"; // CRS L2[7] = String(gps.course.deg()) + " deg"; // CRS L2[8] = String(gps.altitude.kilometers()) + " km"; // ALT L2[9] = String(gps.altitude.meters()) + " m"; // ALT M5.Lcd.setFreeFont(FM12); for ( int i = 0; i < 11; i++ ){ // DISPLAY M5.Lcd.setTextColor(BLACK, BLACK); M5.Lcd.drawString( L1[i], 100, 0 + ( 24 * i )); // ERASE M5.Lcd.setTextColor( WHITE, BLACK); if (gps.location.lat() > 0){ M5.Lcd.setTextColor(GREEN,BLACK);} // RX M5.Lcd.drawString( L2[i], 100, 0 + ( 24 * i )); // DRAW L1[i] = L2[i]; // SAVE } smartDelay(1000); } // analog mode ----------------------------------------------------------- if ( mode_ == "analog" ){ // ANALOG MODE time_date_read(); // READ DATA sdeg = ss*6; // 0-59 -> 0-354 Pre-compute mdeg = mm*6+sdeg*0.01666667; // 0-59 -> 0-360 - includes seconds hdeg = hh*30+mdeg*0.0833333; // 0-11 -> 0-360 - inc min and seconds hx = cos((hdeg-90)*0.0174532925); hy = sin((hdeg-90)*0.0174532925); mx = cos((mdeg-90)*0.0174532925); my = sin((mdeg-90)*0.0174532925); sx = cos((sdeg-90)*0.0174532925); sy = sin((sdeg-90)*0.0174532925); M5.Lcd.drawLine(ohx, ohy, 160, 121, TFT_BLACK); // ERASE HOUR M5.Lcd.drawLine(omx, omy, 160, 121, TFT_BLACK); // ERASE MIN M5.Lcd.drawLine(osx, osy, 160, 121, TFT_BLACK); // ERASE SEC ohx = hx*62+161; ohy = hy*62+121; // NEW HOUR omx = mx*84+160; omy = my*84+121; // NEW MIN osx = sx*90+161; osy = sy*90+121; // NEW MIN M5.Lcd.drawLine(ohx, ohy, 160, 121, TFT_WHITE); // DRAW HOUR M5.Lcd.drawLine(omx, omy, 160, 121, TFT_WHITE); // DRAW MIN M5.Lcd.drawLine(osx, osy, 160, 121, TFT_RED ); // DRAW SEC M5.Lcd.fillCircle(160, 121, 3, TFT_RED); // DOT CENTER smartDelay(1000); } // digital mode ---------------------------------------------------------- if ( mode_ == "digital" ){ // DIGITAL MODE time_date_read(); // READ DATA L2[0] = String(gps.date.year()) + "/" + dm_ + "/" + dd_; // OLD DATA L2[1] = hh_ + ":" + mm_ + ":" + ss_; // NEW DATA M5.Lcd.setFreeFont(FMB24); // FONT for ( int i = 0; i < 2; i++ ){ // DISPLAY M5.Lcd.setTextColor(TFT_BLACK, TFT_BLACK); // BLACK M5.Lcd.drawString(L1[i], 20, 60 + ( 80 * i )); // ERASE M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); // WHITE if (gps.location.lat() > 0){M5.Lcd.setTextColor(GREEN,BLACK);} // RX M5.Lcd.drawString(L2[i], 20, 60 + ( 80 * i )); // DRAW L1[i] = L2[i]; // SAVE } smartDelay(1000); } M5.update(); } // END OF MAIN //========================================================================= static void smartDelay(unsigned long ms){ unsigned long start = millis(); do{ while (gs.available()) gps.encode(gs.read()); } while (millis() - start < ms); if (millis() > 5000 && gps.charsProcessed() < 10){none_gps();} } //========================================================================= static uint8_t conv2d(const char* p){ uint8_t v = 0; if ('0' <= *p && *p <= '9'){v = *p - '0';} return 10 * v + *++p - '0'; } //========================================================================= void gps_setup(){ // GPS SETUP M5.Lcd.fillScreen(TFT_BLACK); // CLEAR DISPLAY M5.Lcd.setFreeFont(FM12); // FONT M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); // GPS TITLE String L[11] = {"DATE","TIME","LAT","LNG","SPEED" // GPS TITLE ,"SPEED","CRS","CRS","ALT","ALT"}; // GPS TITLE for ( int i = 0; i < 11; i++ ){ M5.Lcd.setCursor ( 5, 0 + ( 24 * i )); M5.Lcd.drawString(L[i],5, 0 + ( 24 * i )); // DRAW TITLE } initial = 0; } //========================================================================= void analog_setup(){ // ANALOG SETUP M5.Lcd.fillScreen(TFT_BLACK); // CLEAR DISPLAY M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK); M5.Lcd.fillCircle( 160, 120, 118, TFT_GREEN); // CLOCK FACE M5.Lcd.fillCircle( 160, 120, 110, TFT_BLACK); // LOCK FACE for(int i = 0; i<360; i+= 30) { // 12 LINES sx = cos((i-90)*0.0174532925); sy = sin((i-90)*0.0174532925); x0 = sx*114 + 160; yy0 = sy*114 + 120; x1 = sx*100 + 160; yy1 = sy*100 + 120; M5.Lcd.drawLine(x0, yy0, x1, yy1, TFT_GREEN); // DRAW 12 LINES } for(int i = 0; i<360; i+= 6) { // 60 DOTS sx = cos((i-90)*0.0174532925); sy = sin((i-90)*0.0174532925); x0 = sx*102 + 160; yy0 = sy*102 + 120; M5.Lcd.drawPixel(x0, yy0, TFT_WHITE); // MINUTE if(i== 0 || i==180)M5.Lcd.fillCircle(x0,yy0,2,WHITE); // DOTS if(i==90 || i==270)M5.Lcd.fillCircle(x0,yy0,2,WHITE); // DOTS } M5.Lcd.fillCircle(160, 121, 3, TFT_RED); // DOTS CENTER M5.Lcd.drawJpgFile(SD, "/apple_marks/apple_50.jpg"); // apple ICON targetTime = millis() + 1000; } //========================================================================= void digital_setup(){ M5.Lcd.fillScreen(TFT_BLACK); return; } //========================================================================= void time_date_read(){ // READ YY.MM.DD, HH,MM,SS if (gps.location.lat() > 0){ M5.Lcd.fillCircle(315,5,5,GREEN);} // Rx if (gps.location.lat() < 1){ M5.Lcd.fillCircle(315,5,5,RED );} // not Rx ym = gps.date.year(); ym_ = String(ym); dm = gps.date.month(); dm_ = String(dm); if (dm < 10){ dm_="0"+dm_;} dd = gps.date.day(); dd_ = String(dd); if (dd < 10){ dd_="0"+dd_;} ss = gps.time.second();ss_ = String(ss); if (ss < 10){ ss_="0"+ss_;} mm = gps.time.minute();mm_ = String(mm); if (mm < 10){ mm_="0"+mm_;} hh = gps.time.hour(); if ( hh < 15 ){ hh = hh + time_set;} goto t; // JST *** if ( hh > 14 ){ hh = hh - time_set - 6;} goto t; // JST *** t:hh_ = String(hh); if (hh < 10){ hh_ = "0" + hh_;} // ADD ZERO } //========================================================================= void none_gps(){ // NONE GPS M5.Lcd.setFreeFont(FMB24); // FONT M5.Lcd.setTextColor(RED, BLACK); M5.Lcd.drawString("No GPS data received:", 20, 50); // MESSAGE M5.Lcd.drawString("check wiring", 20, 130); // MESSAGE } //=========================================================================
はじめまして!
macsbug様のGPSCLOCKを使わせてもらっている者です
質問なんですがAM0~AM9になるとなぜかUTC時刻になってしまうのですが
これは仕様でしょうか?
よろしくお願いします。
もこたん
6月 17, 2020 at 12:11 am
もこたんさん、サイトの訪問をありがとうございます。
スケッチは UTC24時間に対し 時刻変換が正しく行われていないかも知れません。
日本時間に変換する場合 UTC/協定世界時とJST/日本標準時の変換と時差の計算が必要で時差は9時間です。
時刻は 12進法か24進法です。例として 25時はありません。
そのまま9時間変換すると 時刻が切り替わる 0 ,12,24 等の切り替わりで 正しい値を示さなくなります。
この点を考慮して 正しい時刻変換を行う必要があります。
質問に対し これらを考慮した スケッチの検証が必要ですが 他の工作中で時間がとれません。
ご自身で変換するスケッチを記載するか、GPS時には必ず必要な方法ですので ネットで検索すれば計算方法があるかと思います。
macsbug
6月 17, 2020 at 5:33 pm