ArduinoとGPSモジュールを使ったLCD時計の製作

ArduinoとGPSモジュールとして秋月電子通商の「GNSS [GPS(アメリカ)、GLONASS(ロシア)、みちびき (日本)]受信機キット」を使ってLCD時計を組み立てました。GPS衛星からUTC(協定世界時)を受信してJST(日本標準時、9時間進めた時刻UTC+9)に変換して表示する、我が家で最も正確な時計となりました。

ELEGOOのNano互換ボードで小型化
ELEGOOのNano互換ボードで小型化
目次

準備したパーツ

ネット通販(今回は秋月電子通商)でパーツを集めてブレッドボード上で結線しました。GPSモジュールは数種類ありましたが、室内時計として使いたかったので設置の自由度があるアンテナ外付けタイプを選びました。
Arduinoはケース組込時は安価なNano互換ボードを使っています。

パーツ仕様個数備考
1Arduino Uno Rev3ATmega328M-07385
※テスト時利用
ELEGOO
Nano互換ボード
CH340/ATmega328P
※3個入りパッケージ
※ケース組込時
2GPSモジュールGNSS受信機キット
1PPS出力 みちびき3機対応
アンテナセット付キット
1K-13850
3スイッチング・
ダイオード
1N41481手持ち
4抵抗10kΩ 1/4W1手持ち
5USBシリアル
変換モジュール
FT2341M-08461
6LCDモジュールI2C接続 16×2行
白色バックライト
ACM1602NI-FLW-FBW-M01
1P-05693
7半固定ボリューム10KΩ1P-03277
8ブレッドボードEIC-8011P-00315
9ジャンパーワイヤオス-オス 10cmセット適量C-05371
10ACアダプタ9V 1.3A 100~240V1M-00030

Arduinoの開発環境「Arduino IDE」のセットアップ手順

Arduinoの公式サイトからArduino IDEをダウンロードしてPCにインストールします。

Software | Arduino

https://www.arduino.cc/en/software

Arduinoボードの開発環境となる「Arduino IDE」のインストール、各種センサや液晶ディスプレイといったモジュールとArduinoとの接続を容易にする「ライブラリ」を活用したスケッチ作成までの手順メモです。

あわせて読みたい
Arduinoの開発環境「Arduino IDE」のセットアップ手順 Arduinoボードの開発環境となる「Arduino IDE」のインストール、各種センサや液晶ディスプレイといったモジュールとArduinoとの接続を容易にする「ライブラリ」を活用し...

組み立てと動作確認

ブレッドボードに実装、初期動作テスト

秋月電子通商の「GNSS[GPS(アメリカ)、GLONASS(ロシア)、みちびき(日本)]受信機キット」は、太陽誘電製・小型高感度GNSSモジュール[GYSFFMANC]を使用したGNSS受信機で、同軸ケーブルで延長された外部アンテナ式となっているので設置の自由度があります。

取扱説明書の「外部機器との接続方法(PCとUSB接続する場合)」記載のようにUSBシリアル変換モジュール(FT234)を介してWindows PCとUSB接続して、GNSS GUIツール[Mini GPS]や衛星モニタ[Power GPS]を実行すると補足した衛星を確認できます。

室内の窓側テーブルに置いたキット付属の外付けアンテナで12個の衛星を補足できています。

GNSS GUIツール [Mini GPS]
GNSS GUIツール [Mini GPS] 。位置情報は写真加工アプリで削除しています。

取扱説明書の「外部機器との接続方法(マイコンと接続する場合)」に記載があるように電源電圧は 5V(DC 3.8V~5V)ですが、信号レベルが3.3Vなので、スイッチング・ダイオード1N4148と10kΩでArduino Unoからの送信(TX) 5Vを3.3Vの電圧に代えています。
GPSモジュール背面の電池ボックスには、再追尾時や電源再起動時(ホットスタートやウォームスタート)用に衛星情報をバックアップする電池(キットにCR2032付属)をセットします。

組立後、取扱説明書の初期動作テストの手順で、天空の見晴らしの良い窓際のテーブルにアンテナを配置して電源を入れて数十秒ほど待つとGPSモジュール上の赤いLEDが1秒毎に点滅します(4衛星以上を追尾)。この状態を15分以上維持して動作テスト完了です。

給電すると赤いLEDが薄く点灯
給電すると赤いLEDが薄く点灯。ブレッドボード上の右側のパーツはPC接続用のUSBシリアル変換モジュール 。
GNSS衛星追尾中は赤いLEDが1秒毎に明るく点滅
GNSS衛星追尾中は赤いLEDが1秒毎に明るく点滅

Arduino Uno Rev3のSoftwareSerialで動作確認

Arduino IDEのメニューから、ファイル –> スケッチ例 –> Arduino Uno用のスケッチ –> SoftwareSerial –> SoftwareSerialExample を使ってGPS信号を受信できるかを確認します。
このサンプルスケッチのRX、TXのポート番号をArduinoへの結線に合わせて修正、シリアル速度を9600bpsに変更して実行します。シリアルモニタにGPSから受信したデータが刻々と表示されます。下記の画像キャプチャではGPZDA情報のみを残して、前後の位置情報部分は写真加工アプリで消去しています。

Arduino Uno用のサンプルスケッチ SoftwareSerialExample.ino を実行
Arduino Uno用のサンプルスケッチ SoftwareSerialExample.ino を実行

スケッチ1:TinyGPSPlusライブラリを使ってGPSから取得したUTCとJSTをシリアルモニタに表示

ライブラリには、GitHub:mikalhart/TinyGPSPlusサイトの TinyGPSPlus-master.zip を利用させていただきました。このライブラリ付属のサンプルスケッチ FullExample.ino を参考に、GPSから取得したUTCを adjustTime でJSTに変換してシリアルモニタに追加表示するスケッチ1「GPS_clock_com_time.ino」を作りました。
曜日はツェラー(Zeller)の公式で算出しています。JSTが9時間差で0時に曜日が替わるのを確認できました。

JSTとUTCをシリアルポートに表示
JSTとUTCをシリアルポートに表示

GPSモジュールで取得したUTCと変換したJSTをシリアルポートに表示するスケッチ1です。

GPS_clock_com_time.ino  ※ここをクリックするとコード表示を開閉できます。
#include <TinyGPS++.h> // https://github.com/mikalhart/TinyGPSPlus
#include <SoftwareSerial.h>
#include <TimeLib.h>

static const int RXPin = 10, TXPin = 11;
static const uint32_t GPSBaud = 9600;

// 曜日
int day_week ;
char DayWeekData[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup()
{
  Serial.begin(9600);
  ss.begin(GPSBaud);
}

void loop()
{
// UTCからJST変換
    setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year());
    adjustTime(9 * SECS_PER_HOUR);
// JSTの日付、曜日、時刻の表示
day_week = getDayWeek(year(), month(), day()) ;
    Serial.print(year()); Serial.print("/");
    SerialzeroSup(month()); Serial.print("/");
    SerialzeroSup(day()); Serial.print("(");
    Serial.print(DayWeekData[day_week]);Serial.print(") ");
    SerialzeroSup(hour()); Serial.print(":");
    SerialzeroSup(minute()); Serial.print(":");
    SerialzeroSup(second());
Serial.print("   ");
// UTCの日付、曜日、時刻の表示
day_week = getDayWeek(gps.date.year(), gps.date.month(), gps.date.day()) ;
    Serial.print(gps.date.year());Serial.print("/");
    SerialzeroSup(gps.date.month());Serial.print("/");
    SerialzeroSup(gps.date.day());Serial.print("(");
    Serial.print(DayWeekData[day_week]);Serial.print(") ");
    SerialzeroSup(gps.time.hour());Serial.print(":");
    SerialzeroSup(gps.time.minute());Serial.print(":");
    SerialzeroSup(gps.time.second());
Serial.println();
  smartDelay(1000);
}

// 曜日の計算(ツェラー(Zeller)の公式)
int getDayWeek(int year,int month,int day){
int w ;
if(month < 3) {
year = year - 1;
month = month + 12 ;
 }
w = (year + (year/4) - (year/100) + (year/400) + (13*month+8)/5 + day ) % 7;
return w;
}

// 月、日、時、分、秒が0~9の場合、1桁目を 空白 もしくは 0 に置換
void SerialzeroSup(int digit)
{
if(digit < 10)
  Serial.print(' ');  // 現在「空白」
  Serial.print(digit);
}

// 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);
}

スケッチ2:GPSから取得した日時(JST)をLCDに表示

スケッチ1のGPSから取得した日時(JST)をシリアルポートに出力する部分をLCDモジュールへの出力に変更したスケッチ2「GPS_clock_LCD.ino」です。
液晶モジュールのI2Cアドレスは0xa0。液晶モジュール用のI2Cライブラリは「構想100年」サイトの LcdCore_20120528.zipLCD_ACM1602NI_20120528.zip を利用させていただきました。

GPSから取得した日時をLCDに表示するスケッチ2
GPSから取得した日時をLCDに表示するスケッチ2
GPS_clock_LCD.ino  ※ここをクリックするとコード表示を開閉できます。
#include <Arduino.h>
#include <Wire.h>            // Arduino IDE のI2Cライブラリ
#include <TinyGPS++.h> // https://github.com/mikalhart/TinyGPSPlus
#include <SoftwareSerial.h>
#include <TimeLib.h>
#include <LcdCore.h>         // LCDコアライブラリ
#include <LCD_ACM1602NI.h>   // 秋月I2C液晶用のI/Oライブラリ
 
static const int RXPin = 10, TXPin = 11;
static const uint32_t GPSBaud = 9600;
LCD_ACM1602NI lcd(0xa0);  // 0xa0は液晶モジュールのI2Cアドレス
// 曜日
int day_week ;
char DayWeekData[7][4] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"} ;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
 
void setup()
{
Serial.begin(9600);
ss.begin(GPSBaud);
Wire.begin();       // I2C初期化
lcd.begin(16, 2);   // ディスプレイの行数(16)と桁数(2)
}
 
void loop()
{
// UTCからJST変換
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year());
adjustTime(9 * SECS_PER_HOUR);
// JSTの日付、曜日、時刻の表示
day_week = getDayWeek(year(), month(), day()) ;
lcd.setCursor(0, 0);
lcd.print(year());
lcd.setCursor(4, 0);
lcd.print("/");
lcd.setCursor(5, 0);
lcdzeroSup(month());
lcd.setCursor(7, 0);
lcd.print("/");
lcd.setCursor(8, 0);
lcdzeroSup(day());
lcd.setCursor(11, 0);
lcd.print("(");
lcd.print(DayWeekData[day_week]) ;
lcd.print(")");
lcd.setCursor(0, 1);
lcdzeroSup(hour());
lcd.setCursor(2, 1);
lcd.print(":");
lcd.setCursor(3, 1);
lcdzeroSup(minute());
lcd.setCursor(5, 1);
lcd.print(":");
lcd.setCursor(6, 1);
lcdzeroSup(second());
smartDelay(1000);
}
 
// 曜日の計算(ツェラー(Zeller)の公式)
int getDayWeek(int year,int month,int day){
int w ;
if(month < 3) {
year = year - 1;
month = month + 12 ;
}
w = (year + (year/4) - (year/100) + (year/400) + (13*month+8)/5 + day ) % 7;
return w;
}
 
// 月、日、時、分、秒が0~9の場合、1桁目を 空白 もしくは 0 に置換
void lcdzeroSup(int digit)
{
if(digit < 10)
lcd.print(' ');   // 現在「空白」
lcd.print(digit);
}

// 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);
}

Arduino Nano互換ボードで小型化、二合枡ケースに実装(2022/7/9更新)

ケースに組み込むため、Arduino Uno Rev3をELEGOOのNano互換ボード(Amazonで購入した3個入り1,480円、2021/5/24時点)と入れ替えました。

NanoのI2C通信用ピンは、SDA:A4ピン、SCL:A5ピンです。

ELEGOOのNano互換ボードで小型化
ELEGOOのNano互換ボードで小型化

構成変更を行うこともあるのでブレッドボードのまま、二合枡に組み込んでいます(2022/7/9写真入れ替え)。

二号枡に格納したGPS時計
二号枡に格納したGPS時計
二号枡の裏面にGPSアンテナコネクタと電源コネクタを配置
二号枡の裏面にGPSアンテナコネクタと電源コネクタを配置
よかったらシェアしてね!
  • URLをコピーしました!
目次