ESP32 DivKitCと1.8インチTFT(ST7735S)の表示のためのTFT_eSPIのドライバーにて、上手くTFTへ表示出来るようになってきました。ESP32 DivKitCと1.8インチTFTとの接続が分かると、道が開け、どんどんと先へ進める様な感じになり、凄く楽しさが増してきます。TFT_eSPIのサンプルプログラムを動作チェックし、十分動作を楽しんだ後、皆さんが特に面白いし、なんか、すごくネ!と思うようなサンプルを私もやって見る事にしました。それは、ネットサーバーからの時間取得表示です、実はネットにはゴロゴロたくさんのサンプルがありますが、TFTに表示するサンプルは極僅かです。ここは、TFT_eSPIのTFT表示する為に他のサンプルプログラムを参考にし、改良してみることにします。
結果をまずどうぞ!
今日の昼過ぎに動作中の写真を1枚撮りました。
電源を繋いだ後のネットサーバー時計です。つながるまでのドット表示と接続後にSSID,PASSWORDを表示する様にしました。動画上は本物のSSIDとパスワードは表示出来ないので単なるテキスト文字表示にしてあります。(ブログ用)
サンプルプログラムは”ソースに絡まるエスカルゴ”の表題のWebページです。
これにTFTの表示を付け足します。
通常はシリアルモニター表示の為、データは連続な時間情報で構造体のtmとなっています。この時間情報をそれぞれ好きな長さで取り込みStringに変換できるサンプルと思い元としています。TFT表示用にはとても重宝すると思います。(何処にでも別々に表示可能、勿論任意カラー文字として!)
まず、やる事は、TFTを使うためのライブラリを追加インストールする必要があります。前のブログにも記載していますが、TFTの定義ファイルであるUser_Setup.h でESP32をピンの接続定義ほか、使用するフォント類を必ずセットしておきます。
#define ST7735_DRIVER,#define TFT_WIDTH 128,#define TFT_HEIGHT 160,#define ST7735_BLACKTAB,#define TFT_MISO 19,#define TFT_MISI 23,#define TFT_SCLK 18,#define TFT_CS 15,#define TFT_DC 2,#define TFT_RST 4,(フォントは必要任意設定で省略します。)#define SPI_FREQUENCY 27000000
フォントは使うフォントのみを定義するので良いと思います。わたしは、確認のため、全部使用するようにしてますが! ここいらは最初のTFTを使う為、接続定義の準備です。
以下最初のスケッチへの追加ライブラリです。スケッチー>ライブラリのインストールから追加します。
#include <WiFi.h>はオリジナルで使用してますが、次の2つをTFT用で追加します。
#include <SPI.h>
#include <TFT_eSPI.h>
上記に合わせて、tft で簡略使用するための下記も追加します。
TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
自分の家の ssid と接続パスワードを設定します。
const char* ssid = "********”;
const char* password = "********”;
TFTに表示する情報の年、月、日、曜日、時間&分、秒は文字列にて、つながるまでのドット位置の表示用で使う変数も定義します。最初はバラバラで入手していたのですが、年月日はまとめて抜き出しが使いやすいのでnennを急遽年月日にしました。”2020/09/27"です。元は、”2020”でしたが!なので、月、と日も使わないですが、後でなにかで利用出来るようにコメント化です。Hi
String nenn; // original "2020" change to "2020/09/27"
//String gatu; // "09" Month
//String hi; // "27" Date
String youbi; // "Sun" "day of the week
String jifun; // "11:39" Time(hour:minute)
String myou; // "39" Seconds
int dotkai=10; //ドットの位置表示用
//String gatu; // "09" Month
//String hi; // "27" Date
String youbi; // "Sun" "day of the week
String jifun; // "11:39" Time(hour:minute)
String myou; // "39" Seconds
int dotkai=10; //ドットの位置表示用
ネットサンプルから良いと思ったのは利用しています。ネットサーバーが幾つかあるので、これも定義しておきます。通常はnetServer1の”pool.ntp.org"の1つ使いが多いです!
const char* ntpServer1 = "pool.ntp.org";
const char* ntpServer2 = "time.google.com";
const char* ntpServer3 = "ntp.jst.mfeed.ad.jp";
const char* ntpServer2 = "time.google.com";
const char* ntpServer3 = "ntp.jst.mfeed.ad.jp";
あと標準時はUTCなので、JST用に書き換えました。Web情報より
//const long gmtOffset_sec = 3600;
const long gmtOffset_sec = 3600*9; //JST
//const int daylightOffset_sec = 3600;
const int daylightOffset_sec = 0; //JST
const long gmtOffset_sec = 3600*9; //JST
//const int daylightOffset_sec = 3600;
const int daylightOffset_sec = 0; //JST
お決まりのvoid setup() には、TFTの初期化、画面位置の縦横の決め、TFT画面を黒で塗りつぶし、を追加します。setup end!の表示はTFTには表示してません。とくにいらないかと!
----------------------------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
setupWifi(); // Wifi接続
syncTime(); // 時刻を合わせる
Serial.println("setup end!");
}
----------------------------------------------------------------------------------------------------------------------------Serial.begin(115200);
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
setupWifi(); // Wifi接続
syncTime(); // 時刻を合わせる
Serial.println("setup end!");
}
お決まりのvoid loop()には、文字列のsに変換してある日付時間から新たに関数 substring() で必要な情報を抜き出し文字変数に入れてゆきます。ここでの必要な情報抜き出しが一番楽しいところかと思います。VBとかでは、Midなどがありますが、Arduionoではsubstring()で抜き出しが出来ます。
このサンプルでの文字列化は sprintf で時間情報を文字列sとして取得しています。
今回のTFT表示用の年月日を抜き出しの部分だけのスケッチです。ほかの曜日、時間、秒等のTFTへの表示は同じやり方で出来るので省略しました。TFTへのテキスト文字の表示の基本は最初使うために初期化する。それからカーソル位置と使用するフォントを設定、テキストカラーを設定、テキストサイズ設定、テキストをTFTへ表示の順で設定です。ちなみにデバッグ機能としてはSerial.printlnが使えます。Arduino特有の設定値確認用です。Hi 今回のnenn取得文字列の確認様で追加しました。
----------------------------------------------------------------------------------------------------------------------------
void loop() {
struct tm timeInfo;
char s[20];
getLocalTime(&timeInfo); // 時刻を取得
// 日付と時刻を文字列として取得V
sprintf(s, "%04d/%02d/%02d %02d:%02d:%02d",
timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
// 曜日も含めた書式に変更
String dayInfo = s;
dayInfo = dayInfo.substring(0, 10) + " (" + getDayOfWeek(timeInfo.tm_wday) + ")\n" + dayInfo.substring(11);
Serial.println(dayInfo);
String nenn = dayInfo.substring(0,11);
Serial.println(nenn); //シリアルモニターでの確認用で追加しました。
struct tm timeInfo;
char s[20];
getLocalTime(&timeInfo); // 時刻を取得
// 日付と時刻を文字列として取得V
sprintf(s, "%04d/%02d/%02d %02d:%02d:%02d",
timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
// 曜日も含めた書式に変更
String dayInfo = s;
dayInfo = dayInfo.substring(0, 10) + " (" + getDayOfWeek(timeInfo.tm_wday) + ")\n" + dayInfo.substring(11);
Serial.println(dayInfo);
String nenn = dayInfo.substring(0,11);
Serial.println(nenn); //シリアルモニターでの確認用で追加しました。
tft.setCursor(40,10,2);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(1);
tft.println(nenn);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(1);
tft.println(nenn);
以下省略
〜
delay(10);
}
----------------------------------------------------------------------------------------------------------------------------
残りのyoubi(曜日), jifun(時間:分), myou(秒)も カーソル位置とフォントを設定、テキストの色設定、テキストサイズ設定、そしてTFTへ表示の順番で同じです。
void setup()でのコールする接続時のサブルーチン、および、時間設定サブルーチンのTFT表示追加分です。下記に載せます。
setupWifi()では、TFTにドットを表示させ、つながるまで、X座標を+10ずつ足して表示位置を動かします。1秒ごとにつながるまで、ドットを表示してゆきます。繋がったら、”Connected to"とその下に文字だけですが、”Your SSID"と、”Your Password"の文字をTFTに表示させ、1秒後TFTを黒塗りつぶしして次のループの syncTime()へ移ります。
----------------------------------------------------------------------------------------------------------------------------
/**
* Wifiの設定を行う関数
*/
void setupWifi() {
// WiFiに接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
dotkai=dotkai+5;
tft.fillScreen(TFT_BLACK);
tft.setCursor(dotkai,20,2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.println(".");
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
tft.fillScreen(TFT_BLACK);
tft.setCursor(23,40,2);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(1);
tft.println("Connected to ");
tft.setCursor(25,60,2);
//tft.println(ssid); //通常はこちらです。下はブログの動画用に表示しない設定
tft.println("Your SSID");
tft.setCursor(25,80,2);
tft.println("Your Password"); //パスワード表示はありませんが、ブログ用動画で文字表示追加
delay(1000);
tft.fillScreen(TFT_BLACK);
}
* Wifiの設定を行う関数
*/
void setupWifi() {
// WiFiに接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
dotkai=dotkai+5;
tft.fillScreen(TFT_BLACK);
tft.setCursor(dotkai,20,2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.println(".");
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
tft.fillScreen(TFT_BLACK);
tft.setCursor(23,40,2);
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(1);
tft.println("Connected to ");
tft.setCursor(25,60,2);
//tft.println(ssid); //通常はこちらです。下はブログの動画用に表示しない設定
tft.println("Your SSID");
tft.setCursor(25,80,2);
tft.println("Your Password"); //パスワード表示はありませんが、ブログ用動画で文字表示追加
delay(1000);
tft.fillScreen(TFT_BLACK);
}
----------------------------------------------------------------------------------------------------------------------------
時刻合わせを行うサブルーチンもJST用の設定値を変数で設定、サーバー1,2,3も追加してあります。
gmtOffset_secもdaylightOffset_secもntpServer1,2,3も最初の定義を使い時刻合わせします。
----------------------------------------------------------------------------------------------------------------------------
/**
* 時刻合わせを行う関数
*/
void syncTime() {
//configTime(-9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
//configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1,ntpServer2,ntpServer3);
}
* 時刻合わせを行う関数
*/
void syncTime() {
//configTime(-9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
//configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer1,ntpServer2,ntpServer3);
}
----------------------------------------------------------------------------------------------------------------------------
なお、サンプルプログラムでは、曜日のオリジナル情報では曜日の文字長が長く、まちまちなので、曜日を省略型(3文字)の曜日に曜日変換しています。TFT表示では長い曜日表示は大変使いづらいので、この曜日変換をそのまま使いました。
----------------------------------------------------------------------------------------------------------------------------
/**
* 引数の数値を曜日に変換する関数
*/
String getDayOfWeek(int dayNum) {
String result = "";
switch (dayNum) {
case 0:
result = "Sun";
break;
case 1:
result = "Mon";
break;
case 2:
result = "Tue";
break;
case 3:
result = "Wed";
break;
case 4:
result = "Thu";
break;
case 5:
result = "Fri";
break;
case 6:
result = "Sat";
break;
}
return result;
}
* 引数の数値を曜日に変換する関数
*/
String getDayOfWeek(int dayNum) {
String result = "";
switch (dayNum) {
case 0:
result = "Sun";
break;
case 1:
result = "Mon";
break;
case 2:
result = "Tue";
break;
case 3:
result = "Wed";
break;
case 4:
result = "Thu";
break;
case 5:
result = "Fri";
break;
case 6:
result = "Sat";
break;
}
return result;
}
----------------------------------------------------------------------------------------------------------------------------
以上でESP32 DivKitCと1.8インチTFTを使ったネットサーバー時計が出来ます。電源の5VをUSB で供給するだけで、家のWiFiのつながる場所で、ネットサーバー時計として使用出来ます。
今回は、テキスト文字のTFT表示を覚えました。また、文字列の抜き出しや、文字列への変換、デバッグ用として使えるSerial.println();改行付き表示、改行無しはSerial.print(); また、TFT用ライブラリで 通常はtft_setCursor(x,y);がほとんど使われているのに対し今回使用した tft_setCursor(x,y,?)があり、どの様な設定をすればよいのかで最初迷いましたが、昔を思い出し、そこは、ライブラリを直接確認して難なく解決しました。時々ライブラリは覗いてみるもんです。Hi! プログラムの引数設定が明白になります。
TFT_eSPIライブラリのcppのプログラムです。tft.setCursor(x,y),tft.setCursor(x,y,font)の部分だけの抜粋です。
----------------------------------------------------------------------------------------------------------------------------/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position
***************************************************************************************/
void TFT_eSPI::setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position and font
***************************************************************************************/
void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
{
textfont = font;
cursor_x = x;
cursor_y = y;
}
----------------------------------------------------------------------------------------------------------------------------** Function name: setCursor
** Description: Set the text cursor x,y position
***************************************************************************************/
void TFT_eSPI::setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position and font
***************************************************************************************/
void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font)
{
textfont = font;
cursor_x = x;
cursor_y = y;
}
ちなみにヘッダーファイル TFT_eSPI.h では以下のように定義されています。
----------------------------------------------------------------------------------------------------------------------------
// Text rendering and font handling support funtions
void setCursor(int16_t x, int16_t y), // Set cursor for tft.print()
setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print()
----------------------------------------------------------------------------------------------------------------------------void setCursor(int16_t x, int16_t y), // Set cursor for tft.print()
setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print()
ヘッダーファイルとcppファイルについては下記を参照しました。とてもわかり易いです。おさらいです。NOBUのArduino日記!です。よくページ記載内容を見ると、ライブラリの作成のしかたもありますから、大変参考になります。Hi!
----------------------------------------------------------------------------------------------------------------------------
以下抜粋
〇ヘッダファイル(拡張子.h)
ライブラリの定義を記入します。これは内部にあるすべてのもののリストです。
〇ソースファイル(拡張子.cpp)
実際に仕事をする関数を記入します。
----------------------------------------------------------------------------------------------------------------------------
かなり以前にHamlogデータの取得、や無線機のコントロールでシリアル通信を主体に、VB,C,C++をしてた時期がありましたが、Arduino,ESPを使い始めてから、C,C++をやっていた事が少し、役にたっています。デバッグの仕方が全然他の言語と異なり、Arduinoは少し特殊かと思います。Step by Stepで調べてゆかないとわかりませんね!
今は、兎に角、いろいろなESP32のスケッチで楽しむことが最優先です。コピペ、丸写しでも構いません。ひょんに面白い!と思ったことから、どんどんアイデアが増して、新しい物へと発展してゆくと思います。ハードもソフトも今時用にどんどん進化しているので、本当にハマってしまいました。Hi!
si5351_oled128x64 ,VFOsys,ESP32ブログでの実験基板作成、等々からのつまみ食いからが、のめり込むきっかけになりました。特にTS−820用のDDS-VFOに関しての内容です。無線家のJA2GQP,JF3HZB,JH7UBC他 各OM 諸氏に感謝致しております。
つづく?
続きを書くのタグを使ってみました。何処に続くのでしょうか?はまあ、良いとして、ホットな内にTFTディスプレーへのテキスト文字の表示tft.printlinをやったついでに、tft.drawString の描画と、カラー描画をして見ました。
単純に入れ替えするだけです。色を白色から黄色へ変更し年月日を描画する例です。
void loop() {
struct tm timeInfo;
char s[20];
getLocalTime(&timeInfo); // 時刻を取得
// 日付と時刻を文字列として取得V
sprintf(s, "%04d/%02d/%02d %02d:%02d:%02d",
timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
// 曜日も含めた書式に変更
String dayInfo = s;
dayInfo = dayInfo.substring(0, 10) + " (" + getDayOfWeek(timeInfo.tm_wday) + ")\n" + dayInfo.substring(11);
Serial.println(dayInfo);
String nenn = dayInfo.substring(0,11);
Serial.println(nenn);
tft.setCursor(40,10,2);
//tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextColor(TFT_YELLOW,TFT_BLACK);
//tft.setTextSize(1);
//tft.println(nenn);
tft.drawString(nenn,40,10,2);
//tft.println(&timeInfo);
以下省略
〜
他の年月日、曜日も色つけて描画してみました。描画も全く問題なく、白でも感激はありましたが、色がつくと又違った感じになります。元のしろ色だけの時との違いを見てみました。
サンプルスケッチ変更は一番上の 2020/09/27の年月日の部分です。
白色一色のサンプル
年月日は黄色、曜日は青、時間:分は橙色、秒は白色 テキストデータでなく、すべて描画です。
また、時間:分はフォントをデジタル式の物に変更しました。どちらかというとデジタルフォントが好きなものですから!特にライブラリインストールもなしで色もフォントも変更出来ます。
以上 タグにある続きを書くで書いてみましたけれど、何処にどうつながるのか、前に一度使ったような気がしますが、今では忘れています。
つづく?