以前、ESP32とGPSモジュールを使い表示にLED-MatrixPanelを使用した時計を作成しました。
(当ホームページのESP32の項目を参照)
今回は、Arduino NANOとGPSモジュールを使い、表示に18"128x160 RGB TFT-LCD(ST7735)を使いました。
このTFT-LCDは、廉価なので購入しましたが、テキストの消去に手間取りました。テキストを表示して、次のテキストを表示すると
重ねて表示されます。
ヘッダーファイルのTFT.hは、テキストのみを消去する関数がありません。
調べたところ、次の2つの方法しかないようです。
①前のテキストを消すために、同じテキスト・同じ位置で背景と同じ色のテキストを書いて前のテキストを消し、それから新たなテキストを表示する
②前のテキストが入るような背景色の四角形で塗りつぶしてから、新たなテキストを表示する。
ほかに良い方法があればよいのですが、今のところこの方法しか見つかりませんでした。今回は②の方法を使いました。
以下にその概要を記します。
GPSモジュールからデータを受信して、時間・日付・曜日を表示しています。
時・分・秒をLCDの上部に表示し、下に年・月・日・曜日を表示しています。
時・分・秒、年、日付の表示が変わるごとに、fillRect()を使って前の表示を削除しています。
1.Arduino NANO

2.GPSモジュール(GY-GPS 8M V3)
3.TFT-LCD(18"128x160 RGB TFT-LCD(ST7735)
4.降圧電源モジュール(ASM1117-3.3
このモジュールは、5Vを3.3Vにステップダウンします。
これを使用した理由は、Arduino NANOの3.3VをGPSモジュールとTFT-LCDの両方で使用すると、電流容量が大きく
LCDのチラツキが生じるため、LCDの電源は、5VからASM1117で3.3Vにステップダウンして使うようにしました。
5.ケースは、3Dプリンターで作成しました。
配線図です。(画像をコピーしてペイント等で拡大表示してください。)

「ツール」、「ライブラリを管理…」から次のライブラリをインストールします。
*TinyGPS++.hは、TinyGPSPlus by Mikal Hert
*Adafruit_GFX.hは、Adafruit GFX Library
*Adafruit_ST7735.hは、Adafruit ST7735 and ST7789 LLibrary
*TimeLib.hは、次のgithubからインストールします。
https://github.com/PaulStoffregen/Time
参考として以下に、スケッチプログラムを掲載しておきます。
秒、分、時刻の消去は、GPSから受信したgps.time.second()、gps.time.minute()、gps.time.hour()の値が変更されたときに、
fillRectで前のテキストを消去するようにしました.
電源を入れた初期段階では、LCDに表示される日付のテキストが重なって表示される
場合があるので、日付の消去は、day()とyear()が変更されたときにfillRectで前のテキストを消去するようにしました。
//Arduino GPS Clock LCD_Adafruit
#include <TinyGPS++.h>
#include <TimeLib.h>
#include <SoftwareSerial.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
TinyGPSPlus gps;
#define GPS_BAUDRATE 9600
#define time_offset 32400
SoftwareSerial mySerial(3, 2); //RX,TX
#define CS 10
#define DC 9
#define RST 8
Adafruit_ST7735 tft = Adafruit_ST7735(CS, DC, RST);
char Timeh[] = "00";
char Timem[] = "00";
char Times[] = "00";
char DateY[] = "2000";
char Date[] = "00/00";
byte Second, Minute, Hour, Day, Month;
byte last_second, last_minute, last_hour, last_day, last_month;
int Year, last_year;
int xoff=6;
int yoff=20;
void setup() {
//Serial.begin(115200);
mySerial.begin(GPS_BAUDRATE);
tft.initR(INITR_BLACKTAB);
tft.fillScreen(ST77XX_BLACK);
tft.setRotation(1);
tft.setTextWrap(false);
}
void loop()
{
while (mySerial.available() > 0)
{
if (gps.encode(mySerial.read()))
{
if (gps.time.isValid())
{
Second = gps.time.second();
Minute = gps.time.minute();
Hour = gps.time.hour();
}
if (gps.date.isValid())
{
Day = gps.date.day();
Month = gps.date.month();
Year = gps.date.year();
}
if(last_second != Second)
{
tft.fillRect(118+xoff, 12+yoff, 146+xoff, 40+yoff, ST7735_BLACK); //Clear Times
last_second = Second;
if(last_minute != Minute)
{
tft.fillRect(67+xoff, -2+yoff, 117+xoff, 32+yoff, ST7735_BLACK); //Clear Timem
last_minute = Minute;
}
if(last_hour != Hour)
{
tft.fillRect(-2+xoff, -2+yoff, 56+xoff, 32+yoff, ST7735_BLACK); //Clear Timeh
last_hour = Hour;
}
setTime(Hour, Minute, Second, Day, Month, Year);
adjustTime(time_offset);
// update time
Times[0] = second() / 10 + '0';
Times[1] = second() % 10 + '0';
Timem[0] = minute() / 10 + '0';
Timem[1] = minute() % 10 + '0';
Timeh[0] = hour() / 10 + '0';
Timeh[1] = hour() % 10 + '0';
// update date array
DateY[2] = (year() / 10) % 10 + '0';
DateY[3] = year() % 10 + '0';
Date[0] = month() / 10 + '0';
Date[1] = month() % 10 + '0';
Date[3] = day() / 10 + '0';
Date[4] = day() % 10 + '0';
if(last_day == 0 || last_day != day())
{
tft.fillRect(22+xoff, 78+yoff, 150+xoff, 100+yoff, ST7735_BLACK);//Clear Date(week)
last_day = day();
}
if(last_year == 0 || last_year != year())
{
tft.fillRect(-2+xoff, 40+yoff, 50+xoff, 62+yoff, ST7735_BLACK);//Clear Year
last_year = year();
}
tft.setTextColor(ST7735_YELLOW);
tft.setTextSize(4);
tft.setCursor(xoff, yoff);
tft.println(Timeh);
tft.setCursor(47+xoff, yoff);
tft.println(":");
tft.setCursor(69+xoff, yoff);
tft.println(Timem);
tft.setTextSize(2);
tft.setCursor(120+xoff, 14+yoff);
tft.println(Times);
tft.setCursor(24+xoff, 80+yoff);
tft.println(Date);
tft.setTextColor(ST7735_GREEN);
tft.setCursor(xoff, 50+yoff);
tft.println(DateY);
print_wday(weekday());
}
}
}
if (millis() > 5000 && gps.charsProcessed() < 10)
{
tft.setTextSize(2);
tft.setTextColor(ST7735_RED);
tft.setCursor(6, 72);
tft.println("No GPSdata");
}
}
void print_wday(byte wday)
{
tft.setCursor(87+xoff, 80+yoff);
switch(wday)
{
case 1: tft.println("(SUN)"); break;
case 2: tft.println("(MON)"); break;
case 3: tft.println("(TUE)"); break;
case 4: tft.println("(WED)"); break;
case 5: tft.println("(THU)"); break;
case 6: tft.println("(FRI)"); break;
default: tft.println("(SAT)");
}
}