Excel で自作したカスタムフォントを M5stack に表示してみる

M5Stack

2種類のカスタムフォントで Wi-Fi NTP 時計を M5Stack に表示させてみる

では、今度はバイナリ形式カスタムフォントを使って、ESP32 の Wi-Fi 機能を使って、インターネットの NTPサーバーから時刻を定期的に補正する NTP 時計を M5Stack に表示させてみます。

バイナリ形式カスタムフォントの場合、先ほど述べたように、micro SD カードのフォントアドレス計算が簡単なので、スケッチプログラムも書きやすいです。

では、2種類作成したカスタム(自作)フォントを表示させてみたいと思います。

追加ライブラリのインストール

このブログを何度も見ている方は既に済んでいるかと思いますが、事前準備として、私の以下のライブラリを予め Arduino IDE にインストールを済ませておいてください。
ZIPファイルの Arduino IDE へのインストール方法はこちらを参照してください。
(※古いバージョンのライブラリは必ずフォルダごと削除してから再インストールしてください)

ESP32_WebGet ライブラリ

私の自作ライブラリで、NTP サーバー取得プログラムをライブラリ化しています。

https://github.com/mgo-tec/ESP32_WebGet

Time ライブラリ

Arduino 標準の時刻関連ライブラリです。

https://github.com/PaulStoffregen/Time

使用するカスタム(自作)フォント

自分で作ったバイナリ形式カスタムフォントを2種類作って置きます。
ここでは、先ほどダウンロードしたファイルの中に同梱されている以下の私の自作フォントを例に使ってみます。

MyFont_ver3.0.fnt
MyFont.fnt

これを micro SD カードの /font/ フォルダにコピーしておいてください。

スケッチの入力

M5Stack とパソコンを接続し、Arduino IDE を起動し、以下のスケッチを入力してみてください。

【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#include "ESP32_LCD_ILI9341_SPI.h" //beta ver 1.25-
#include "ESP32_WebGet.h" //beta ver 1.12-
#include "TimeLib.h" //Use Arduino time library ver1.5-
#include <SD.h>

const int8_t sck = 18; // SPI clock pin
const int8_t miso = -1; // MISO(master input slave output) don't using
const int8_t mosi = 23; // MOSI(master output slave input) pin
const int8_t cs = 14; // Chip Select pin
const int8_t dc = 27; // Data/Command pin
const int8_t rst = 33; // Reset pin
const int8_t LCD_LEDpin = 32;

const uint8_t CS_SD = 4; //SD card CS ( Chip Select )

const char* ssid = "xxxxxxxx"; //ご自分のルーターのSSIDに書き換えてください
const char* password = "xxxxxxxx"; //ご自分のルーターのパスワードに書き換えてください

ESP32_LCD_ILI9341_SPI LCD(sck, miso, mosi, cs, dc, rst, LCD_LEDpin);
ESP32_WebGet _EWG;

const char* my_fontfile1 = "/font/MyFont_ver3.0.fnt";
const char* my_fontfile2 = "/font/MyFont.fnt";
File _MyF1, _MyF2;

const uint8_t MAX_TXT_NUM = 3; //文字列表示最大列数

uint8_t test_buf[ MAX_TXT_NUM ][ 20 ][ 16 ] = {};
uint16_t test_sj_len[ MAX_TXT_NUM ] = {};
uint8_t num = 0; //文字列番号
uint8_t X0 = 0, Y0 = 0;
uint8_t H_size = 2, V_size = 4; //H_size(水平方向サイズ)、V_size(垂直方向文字サイズ)
uint8_t Fnt_Cnt = 0; //半角相当フォントカウント
uint8_t red = 31, green = 63, blue = 31;
uint8_t bg_red = 0, bg_green = 0, bg_blue = 0;

uint32_t LastTime = 0;
uint32_t NTPget_LastTime = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
  LCD.ILI9341_Init(false, 40000000); //※M5StackでSDカードと併用する場合は必ずfalseにすること
  LCD.Display_Clear();
  LCD.Brightness(255); //LCD LED Full brightness

  SD.begin(CS_SD, SPI, 40000000, "/sd");
  _MyF1 = SD.open(my_fontfile1, FILE_READ);
  if (!_MyF1) {
    Serial.print(my_fontfile1);
    Serial.println(" File not found");
    return;
  }else{
    Serial.print(my_fontfile1);
    Serial.println(" File read OK!");
  }

  _MyF2 = SD.open(my_fontfile2, FILE_READ);
  if (!_MyF2) {
    Serial.print(my_fontfile2);
    Serial.println(" File not found");
    return;
  }else{
    Serial.print(my_fontfile2);
    Serial.println(" File read OK!");
  }

  //--------Wi-Fiアクセスポイント接続---------
  Serial.println();
  Serial.print(F("Connecting to "));
  Serial.println(ssid);
 
  _EWG.EWG_AP_Connect(ssid, password); //Wi-Fi ルーターと接続
  delay(1000);
  _EWG.EWG_NTP_TimeLib_init(9, "time.windows.com"); //NTPサーバー取得初期化
  _EWG.NTP_OtherServerSelect(9); //NTPサーバーと接続できなかった場合、他のNTPサーバーと接続できるか試す関数
  delay(1000);

  LastTime = millis();
  NTPget_LastTime = millis();
}

void loop() {
  if( LastTime != now() ){
    num = 0;
    red = 0, green = 63, blue = 0;
    bg_red = 0, bg_green = 0, bg_blue = 0;
    X0 = 0, Y0 = 0;
    MyFont_Watch_DisplayOut(_MyF1, num, X0, Y0, red, green, blue, bg_red, bg_green, bg_blue);

    num = 1;
    red = 31, green = 63, blue = 31;
    bg_red = 0, bg_green = 0, bg_blue = 31;
    X0 = 0, Y0 = 80;
    MyFont_Watch_DisplayOut(_MyF1, num, X0, Y0, red, green, blue, bg_red, bg_green, bg_blue);

    num = 2;
    red = 31, green = 0, blue = 31;
    bg_red = 31, bg_green = 63, bg_blue = 31;
    X0 = 0, Y0 = 160;

    MyFont_Watch_DisplayOut(_MyF2, num, X0, Y0, red, green, blue, bg_red, bg_green, bg_blue);

    LastTime = now();
  }

  if( millis() - NTPget_LastTime > 300000){ //5分毎にNTPサーバー時刻補正
    time_t get_time = EWG_Get_Ntp_Time();
    if( get_time > 0 ) setTime( get_time );
    NTPget_LastTime = millis();
  }
}
//****************************************************
void MyFont_Watch_DisplayOut(File F, uint8_t Line_Num, uint8_t x0, uint8_t y0, uint8_t Red, uint8_t Green, uint8_t Blue, uint8_t Bg_Red, uint8_t Bg_Green, uint8_t Bg_Blue ){
  uint8_t hour1 = 0, hour2 = 0, min1 = 0, min2 = 0, sec1 = 0, sec2 = 0;
  if( hour() < 10 ){
    hour1 = 0;
    hour2 = hour();
  }else{
    hour1 = hour() / 10;
    hour2 = hour() % 10;
  }
  if( minute() < 10 ){
    min1 = 0;
    min2 = minute();
  }else{
    min1 = minute() / 10;
    min2 = minute() % 10;
  }
  if( second() < 10 ){
    sec1 = 0;
    sec2 = second();
  }else{
    sec1 = second() / 10;
    sec2 = second() % 10;
  }
  Serial.printf("%2d:%02d:%02d\r\n",hour(), minute(), second());
  if( hour1 == 0 ){
    MyFont_SD_Read(F, 2, 32, &test_buf[ Line_Num ][ 0 ]); //スペース
  }else{
    MyFont_SD_Read(F, 2, hour1, &test_buf[ Line_Num ][ 0 ]);
  }
  MyFont_SD_Read(F, 2, hour2, &test_buf[ Line_Num ][ 2 ]);
  MyFont_SD_Read(F, 2, 29, &test_buf[ Line_Num ][ 4 ]); //コロン
  MyFont_SD_Read(F, 2, min1, &test_buf[ Line_Num ][ 6 ]);
  MyFont_SD_Read(F, 2, min2, &test_buf[ Line_Num ][ 8 ]);
  MyFont_SD_Read(F, 2, 29, &test_buf[ Line_Num ][ 10 ]); //コロン
  MyFont_SD_Read(F, 2, sec1, &test_buf[ Line_Num ][ 12 ]);
  MyFont_SD_Read(F, 2, sec2, &test_buf[ Line_Num ][ 14 ]);

  LCD.HVsizeUp_8x16_Font_DisplayOut(H_size, V_size, 16, x0, y0, Red, Green, Blue, test_buf[ Line_Num ], Bg_Red, Bg_Green, Bg_Blue);
}
//*****************************************************
void MyFont_SD_Read(File F, uint8_t ZorH, uint8_t font_num, uint8_t buf[][16]){
  //ZorH : 全角=2, 半角=1
  F.seek(font_num * (16 * ZorH));
  F.read(buf[0], 16);
  F.read(buf[1], 16);
}

16-17行目を、ご自分のWi-Fi ルーターの環境に合わせて、SSID とパスワードを書き替えてください。

22-23行目は2つのフォントファイル名を指定しています。

107-110行目で5分毎に NTP サーバーから時刻を取得して補正しています。

このスケッチからも分かる通り、バイナリ形式のフォント番号の引数が、時刻数値に直接割り当てられるというところがミソです。
カスタムフォント番号がゼロから数値のゼロ文字を作っていけば、プログラムが簡単で済みますね。

コンパイル書き込み実行

では、コンパイル書き込み実行させてみてください。
最初に紹介した動画と同じものですが、以下の様に表示されていればOKです。

本当は以下の記事にあるように、縦スクロールする NTP 時計にしたかったのですが、これは次回に持ち越しとします。

https://www.mgo-tec.com/blog-entry-esp32-oled-ssd1331-my-font-ntp-watch.html

編集後記

いかがでしょうか?

今回は、ある方からカスタムフォントを M5Stack で作成する方法を質問されたのと相まって、自分自身も表示させたかったこともあり、この記事作成に取り掛かりましたが、作っている段階でいろいろと付け足したいことが出てきてしまって、収拾がつかなくなってしまいました。
それでもって、疲労困ぱい・・・。

いつものことですが、最近特に感じているのが、うまくまとめるということにストレスを感じて来ています。

「文章が汚くても、日本語になっていなくてもイイから、思った事を自由に書けばいい!」

と思うようになりました。
年齢を重ねると、ストレスに弱くなってきますね・・・。

スイマセン、ただ単にコンパクトにまとめることが下手なだけの愚痴でした。

ということで、今回はここまでです。

ではまた・・・。

コメント

タイトルとURLをコピーしました