GPS搭載高精度クロック - 安価で信頼性の高い時計製作
必要な部品と材料
| Arduino UNO | ×1 |
| LCDディスプレイ(I2Cアダプター付き、16×2または20×4) | ×1 |
| ブレッドボード | ×1 |
| ジャンパーワイヤー | ×1セット |
| GPS受信機(GY-GPS6MV2、u-blox NEO-6M搭載) | ×1 |
使用するアプリとオンラインサービス
- Arduino IDE
プロジェクト概要
これまで時計プロジェクトではRTCモジュールやNTPサーバーを使ってきましたが、今回はGPS衛星からのNMEA文字列を解析して時刻を取得する方法を紹介します。
GPS受信機が驚くほど安価になっています(ここではGY-GPS6MV2を使用)。

事前テスト
- PCで動作確認(任意): u-bloxの「u-center」ソフトをインストール。FTDIアダプターでGPSモジュールをPCのCOMポートに接続。約1分で衛星捕捉(赤LED点滅)。F8「Text Console」でNMEA文を確認可能。
- オンラインデコーダーでテスト: https://rl.se/gprmc でNMEA文をペーストして解析確認。
衛星捕捉(空が見える場所で)が確認できたら、必要な情報をNMEA文から抽出します。

回路



I2C LCD接続:
- Arduino A4 (SDA) → LCD SDA
- Arduino A5 (SCL) → LCD SCL
#include
#include
LiquidCrystal_I2C lcd(0x3F, 20, 4); // アドレスは0x27や0x3Fが多い
GPS接続(SoftwareSerial使用):
- GPS VCC → 5V
- GPS GND → GND
- GPS TX → Arduino D8
- GPS RX → Arduino D7
#include
#include
SoftwareSerial mySerial(8, 7); // RX, TX
Adafruit_GPS GPS(&mySerial);
※ GPS受信機は3.3V/5V両対応。
表示項目
この時計では以下を表示:
- 時刻(ローカルタイム)
- 日付
- 風速相当(GPS速度から換算)
- 高度
位置情報は不要(窓辺に固定するため)。
タイムゾーン変換
NMEA文の時刻はUTC標準。ローカルタイムへの変換が必要。
int timezone = +1; // Europe/Berlin (UTC+0100)
お住まいのタイムゾーンに合わせて調整。表示時はGPS.hourの代わりにこのhour変数を使用。
// LCD出力例
lcd.setCursor(5, 0);
int hour = (GPS.hour) + timezone;
if (hour < 10) lcd.print('0');
lcd.print(hour, DEC); lcd.print(':');
// 分、秒も同様に0埋めして表示
風速表示(ノット→km/h変換&ビューフォート風力階級)
ヨーロッパでは風速にkm/hを使用。1ノット = 1.852 km/hで変換。
float speed = (GPS.speed) * 1.852; // ノット → km/h
Wikipediaのビューフォート風力階級に基づき分類表示:
if (speed <= 1) lcd.print(" Windstille"); // 静穏
else if (speed <= 9) lcd.print(" leiser Zug"); // 微風
else if (speed <= 46) lcd.print(" Brise"); // 弱風〜やや強風
else if (speed <= 56) lcd.print(" starker Wind"); // 強風
else if (speed <= 74) lcd.print(" stuerm. Wind"); // 疾風
else if (speed <= 83) lcd.print(" Sturm"); // 暴風
else if (speed <= 102) lcd.print(" schwerer Sturm"); // 大暴風
else lcd.print(" Orkan"); // 颶風
表示例

更新頻度はループ内で2秒ごと。秒表示と高度を省けば16×2ディスプレイでも収まります。


GPSの多彩な機能を探求してみてください!
ヨーロッパではDCF77電波時計も選択肢ですが、こちらは高価で受信がデリケートと言われています。
スケッチ
// Adafruit GPSライブラリの例をベースに調整
// GPRMC & GPGGA デコーダー: https://rl.se/gprmc
#include
#include
LiquidCrystal_I2C lcd(0x3F, 20, 4); // 0x27や0x3Fで試行
#include
#include
SoftwareSerial mySerial(8, 7); // RX, TX
Adafruit_GPS GPS(&mySerial);
#define GPSECHO true
int timezone = +1; // UTC+0100 (Europe/Berlin)
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(115200);
delay(5000);
Serial.println("Adafruit GPS library basic test!");
GPS.begin(9600); // UBLOX 6Mの場合
// RMC(推奨最小)+ GGA(測位データ、高度含む)を出力
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // 最小のみの場合
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1Hz更新
GPS.sendCommand(PGCMD_ANTENNA); // アンテナステータス要求
delay(1000);
mySerial.println(PMTK_Q_RELEASE); // ファームウェアバージョン問合せ
}
uint32_t timer = millis();
void loop() {
char c = GPS.read();
if (c && GPSECHO) Serial.write(c);
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) return; // パース失敗なら次待ち
}
if (timer > millis()) timer = millis(); // millis()オーバーフロー対策
if (millis() - timer > 2000) { // 約2秒ごとに表示更新
timer = millis();
// シリアル出力(デバッグ用)
Serial.print("\nTime: ");
if (GPS.hour < 10) Serial.print('0');
Serial.print(GPS.hour, DEC); Serial.print(':');
if (GPS.minute < 10) Serial.print('0');
Serial.print(GPS.minute, DEC); Serial.print(':');
if (GPS.seconds < 10) Serial.print('0');
Serial.print(GPS.seconds, DEC); Serial.print('.');
// ミリ秒表示...
Serial.print("Date: ");
Serial.print(GPS.day, DEC); Serial.print('/');
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
// LCD表示
lcd.setCursor(5, 0);
int hour = (GPS.hour) + timezone;
if (hour < 10) lcd.print('0');
lcd.print(hour, DEC); lcd.print(':');
if (GPS.minute < 10) lcd.print('0');
lcd.print(GPS.minute, DEC); lcd.print(':');
if (GPS.seconds < 10) lcd.print('0');
lcd.print(GPS.seconds, DEC);
lcd.setCursor(5, 1);
if (GPS.day < 10) lcd.print('0');
lcd.print(GPS.day, DEC); lcd.print('.');
if (GPS.month < 10) lcd.print('0');
lcd.print(GPS.month, DEC); lcd.print('.');
lcd.print(GPS.year, DEC);
if (GPS.fix) { // 衛星捕捉できていれば追加情報表示
// 位置、速度、角度、高度、衛星数をシリアル出力...
// 風速換算表示(3行目)
lcd.setCursor(0, 2);
float speed = (GPS.speed) * 1.852; // km/h
// lcd.print("Speed km/h: "); lcd.print(speed);
if (speed <= 1) lcd.print(" Windstille");
else if (speed <= 9) lcd.print(" leiser Zug");
else if (speed <= 46) lcd.print(" Brise");
else if (speed <= 56) lcd.print(" starker Wind");
else if (speed <= 74) lcd.print(" stuerm. Wind");
else if (speed <= 83) lcd.print(" Sturm");
else if (speed <= 102) lcd.print(" schwerer Sturm");
else lcd.print(" Orkan");
// 高度表示(4行目)
lcd.setCursor(0, 3);
lcd.print("Hoehe: ");
lcd.print(GPS.altitude);
}
}
}
製造プロセス
- DIY 低コストグローブコントローラー & プロペラカー – 自分だけの Arduino ハンドコントローラーを作ろう
- DHT11温湿度センサーで作る温度アラート – LEDとピエゾブザーで視覚/聴覚通知
- GPSデータロガー構築と Azure IoT Hub での空間分析
- Arduinoで温湿度ロガーを作る – DHT11とEthernetシールドでSDカード記録
- Arduino Dueと3.2インチTFTで作る温度監視付きリアルタイムクロック
- アナログ風LED POVクロック – Arduino Nanoで作る残像時計
- 光と音で祝おう:Arduinoで作るDIYバースデープロジェクト
- u-blox LEA-6H 02 GPSモジュール: Arduino & Python 統合ガイド
- Arduino Nanoと128x64 OLEDで実行するセルラーオートマトン「ライフゲーム」
- Arduinoで高速・高精度RPM測定 – レーザーとIRセンサーによる新アルゴリズム
- DIYギター高速ピック&ストンプペダル - 3Dプリントモーター駆動ピックの自作