自作ライブラリ ( M5Stack , ESP32 用 )を HTML カラーコード入力できるようにしてみた

M5Stack

こんばんは。

今回は Web 制作では当たり前に使われている HTML カラーコードによるプログラミングを、 Arduino – ESP32 用および M5Stack 用の私の自作ライブラリで実現してみたというお話です。
プログラマの方々には当たり前すぎて、取るに足らないことだと思いますが、私にとってはとても画期的な事なので、自己満足で紹介したいと思います。

スポンサーリンク


今までは、65K カラーで色の値を入力していました。
例えば、M5Stack の LCD ディスプレイに RGB 三原色で色を作って線を描くときに、以下のような感じです。

uint8_t red = 31, green = 63, blue = 31;
LCD.drawLine( 0, 0, 239, 319, red, green, blue );

65Kカラーとは、いわゆる約 65,000 色(正しくは 65,536 色)ということです。
これは、ILI9341 LCD ドライバーのデータシートに記載されているとおりに実行したものです。

ILI9341 は、262Kカラーで入力する方法もありますが、送信するデータ量が多くなってしまうので、速度重視となると、65Kカラーが圧倒的に速いので、私は 262K カラーは使っていません。

65Kカラーの場合、以下の範囲となります。

赤色: 0 ~ 31 までの値。
緑色: 0 ~ 63 までの値。
青色: 0 ~ 31 までの値。

緑色だけが、2倍の値となっています。
これでプログラミングすると、入力がとても面倒な上に、コードをパッと見ても何色なのか直感的に良く分からなかったんです。

それに、私は最近、スマホや Web とリンクして M5Stack を動かすことが多く、その場合 HTML カラーコードを扱う事が多くなってきたので、なんとかそれをそのまま使えないかと試行錯誤していました。
そして、ついに私のライブラリで図形描画から日本語文字表示まで、全面的に HTML カラーコードに対応できるようになりました。

例えば、こんな感じで入力します。

LCD.drawLine( 0, 0, 239, 319, “#FF00FF” );

HTML カラーコードとは、赤、緑、青色をそれぞれ 16進数表記で合体させたものです。
白色の場合の表記は以下のようになります。

この場合、赤色、緑色、青色がそれぞれ最大の FF となっていて、ディスプレイ上では白色になります。

それぞれの色は、16進数で 00 ~ FF という範囲になります。
10進数に換算すると 0~255 の 256段階ということになります。
すると、256 x 256 x 256 = 16777216 色となりますが、私の自作ライブラリの ILI9341ドライバーは 65K カラーなので、赤色と青色に関しては 256 段階を 32 段階に換算しています。
green は 64 段階換算にしています。
ですから、厳密には HTMLカラーコードほどの微妙な色は表現できません。
でも、この小さいディスプレイでは 65K カラーで十分だと思います。

HTMLカラーコード表記を使うと、直感的に色が判別できて、しかもプログラミングが簡単になります。

16進数は大文字と小文字の混在もOKです。
“#FfA1bc”
という表記でも問題無しです。

そして、HTML カラーコードの他に、”yellow” というような表記も可能にしました。
HTML , CSS でプログラミングされている方にはおなじみだと思います。
例えばこんな感じです。

LCD.drawLine( 0, 0, 239, 319, “yellow” );

これはとても分かりやすいですよね。
現在、この表記で登録しているのは以下の8色です。

“white” = “#FFFFFF”
“black” = “#000000”
“red” = “#FF0000”
“green” = “#00FF00”
“blue” = “#0000FF”
“yellow” = “#FFFF00”
“cyan” = “#00FFFF”
“magenta” = “#FF00FF”

では、この使い方およびサンプルプログラムを紹介します。

因みに、M5Stack 標準ライブラリと同時に使用はできません。
あくまで、私の自作ライブラリは単独使用の場合のみです。
そして、私は独学素人アマチュアですので、動作保証はしません。
私の単なる自己満足プログラミングです。
でも、何か不具合やお気づきの点がありましたら、コメント投稿等でご連絡いただけると、とても助かります。

使うもの

M5Stack

(追記)
M5Stack Basicは、この記事を書いた当時より格段にバージョンアップしております。
以下のスイッチサイエンスさんの公式サイトをご参照ください。
https://www.switch-science.com/collections/%E5%85%A8%E5%95%86%E5%93%81/products/9010

※M5Stack Gray(9軸IMU搭載)現在は販売終了しております

 

micro SDHC カード

私は以下のもので動作確認していますが、もっと高性能高信頼性の Sandisk とか、TOSHIBA 製などを使っても良いと思います。
ただ、容量の少ない micro SD や micro SDXC は動作しない場合がありますので、micro SDHC を使った方が無難です。

Arduino – ESP32 をインストールしておく

Arduino IDE は 1.8.7 で動作確認しています。
Arduino core for the ESP32 ( 以下 Arduino – ESP32 と表記 )は、Stable 1.0.0 で動作確認しています。
Arduino – ESP32 のインストール方法は以下の記事を参照してください。

Arduino core for the ESP32 のインストール方法

micro SDHC カードに東雲フォントと UTF-8→Shift_JIS 変換テーブルを保存しておく

micro SDHC カードに、/font/ フォルダを作成して、その中に以下の3つのファイルを保存しておいてください。
UTF-8→Shift_JIS変換テーブルファイルは、私の自作です)

Utf8Sjis.tbl (UTF8→Shift_JIS変換テーブル)
shnmk16.bdf (16×16 全角フォント)
shnm8x16.bdf  ( shnm8x16r.bdf のファイル名中の ’r’ 文字を削除しておく)

このファイルのダウンロードについては、以下の記事を参照してください。

Arduino – ESP32 ( SPIFFS 又は micro SD ) 自作Fontライブラリインストール方法

自作ライブラリをインストールしておく

私の独学自作ライブラリをインストールしておきます。
因みに、先にも述べましたが、M5Stack 標準ライブラリとは互換性が無く、同時使用もできませんのでご了承ください。

GitHub の以下のリンクにありますので、ZIPファイルをダウンロードしてください。

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

インストールする前に古い ESP32_mgo_tec ライブラリはフォルダごと削除してから再インストールしてください

※BOSCH純正BME280, および BME680 ドライバライブラリをインストールしていない場合はコンパイルエラーになります。
その場合、インストール後に /Sensor/ フォルダを削除して下さい

Windows10 の場合のファイルパスは以下です。
User-Name はご自分のユーザー名です。

C:\Users\User-Name\Documents\Arduino\libraries\ESP32_mgo_tec-master\src\ESP32_mgo_tec_bV1\Sensor

また、ダウンロードしたライブラリを、ZIPファイルのまま Arduino IDE にインストールする方法は以下の記事を参照してください。

GitHubにある ZIP形式ライブラリ のインストール方法 ( Arduino IDE )

図形描画だけのサンプルプログラム(スケッチ)

では、まず、直線や四角形、円を描くサンプルプログラムで、HTML カラーコードを入力する方法です。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#define MGO_TEC_BV1_M5STACK_SD_SKETCH
#include <mgo_tec_bv1_m5stack_sd_simple1.h>

void setup() {
  LCD.ILI9341init();
  LCD.brightness( 255 ); //LCD LED Full brightness
}

void loop() {
  uint16_t x0 = 32, y0 = 64, x1 = 272, y1 = 112;
  String html_color_code = "#FFFFFF";
  x0 = 0, y0 = 0;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 319, y0 = 0;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 0, y0 = 239;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 319, y0 = 239;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  delay(2000);

  x0 = 0, x1 = 319, y0 = 0;
  LCD.drawHorizontalLine( x0, x1, y0, html_color_code );
  delay(500);
  x0 = 319, y0 = 0, y1 = 239;
  LCD.drawVerticallLine( x0, y0, y1, html_color_code );
  delay(500);
  x0 = 319, x1 = 0, y0 = 239;
  LCD.drawHorizontalLine( x0, x1, y0, html_color_code );
  delay(500);
  x0 = 0, y0 = 239, y1 = 0;
  LCD.drawVerticallLine( x0, y0, y1, html_color_code );
  delay(500);
  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#FF0000" );
  x0 = 319, y0 = 0, x1 = 0, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#00FF00");
  x0 = 160, y0 = 0, x1 = 160, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#0000FF" );
  x0 = 0, y0 = 120, x1 = 319, y1 = 120;
  LCD.drawLine(0, 120, 319, 120, "#FFFF00");
  delay(2000);

  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawRectangleFill( x0, y0, x1, y1, "white" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "red" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "green" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "blue" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "yellow" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "cyan" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "magenta" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "black" );
  delay(2000);

  LCD.displayClear();
  int i, j;
  for( i = 0; i < 120 ; i = i + 5 ){
    LCD.drawRectangleLine( 40 + i, i, 279 - i, 239 - i, "white" );
  }
  delay(2000);

  uint8_t Width = 50;
  LCD.drawRectangleFill( 0, 0, 319, 239, "#0000ff" );
  LCD.drawRectangleFill( 10, 10, 10 + Width, 10 + Width, "#ff2211" );
  LCD.drawRectangleFill( 309 - Width, 10, 309, 10 + Width, "#5Affcc" );
  LCD.drawRectangleFill( 10, 229 - Width, 10 + Width, 229, "#77FF66" );
  LCD.drawRectangleFill( 309 - Width, 229 - Width, 309, 229, "#baff33" );
  delay(2000);

  LCD.displayClear();
  x0 = 40, y0 = 0, x1 = 279, y1 = 239;
  LCD.drawRectangleLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 40, y0 = 0, x1 = 279, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 40, y0 = 239, x1 = 279, y1 = 0;
  LCD.drawLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 159, y0 = 119;
  uint16_t r = 119;
  LCD.drawCircleLine( x0, y0, r, "white" );
  x0 = 25, y0 = 25, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ff0000" );
  x0 = 294, y0 = 25, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#00ff00" );
  x0 = 25, y0 = 214, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ffff00" );
  x0 = 294, y0 = 214, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ff00ff" );
  for( i = 0; i < 120; i = i + 5 ){
    LCD.drawCircleLine( 159, 119, 119-i, "white" );
  }
  delay(2000);

  LCD.displayClear();
  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawRectangleFill( x0, y0, x1, y1, "#000020" );
  x0 = 159, y0 = 119, r = 119;
  LCD.drawCircleFill( x0, y0, r, "#ff00ff" );
  x0 = 25, y0 = 25, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#ff0000" );
  x0 = 294, y0 = 25, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#00ff00" );
  x0 = 25, y0 = 214, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#ffff00" );
  x0 = 294, y0 = 214, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#00ffff" );
  x0 = 159, y0 = 119, r = 51;
  LCD.drawCircleFill( x0, y0, r, "#0000ff" );
  delay(2000);

  LCD.displayClear();
  for( i = 0; i < 240; i = i + 10 ){
    LCD.drawLine( 0, i, i, 239, "#10FF20" );
    LCD.drawLine( 80 + i, 0, 319, i, "#00ffff" );
  }
  delay(2000);

  LCD.displayClear();
  uint8_t red = 0, green = 0, blue = 0;
  //red (0-31), green (0-63), blue (0-31)
  j = 31;
  for( i = 0; i < 32; i++ ){
    red = i, green = 0, blue = 0;
    LCD.drawRectangleFill( i * 10, 0, i * 10 + 9, 59, red, green, blue );
    red = 0, green = i * 2, blue = 0;
    LCD.drawRectangleFill( i * 10, 60, i * 10 + 9, 119, red, green, blue );
    red = 0, green = 0, blue = i;
    LCD.drawRectangleFill( i * 10, 120, i * 10 + 9, 179, red, green, blue );
    red = j, green = j * 2, blue = j;
    LCD.drawRectangleFill( i * 10, 180, i * 10 + 9, 239, red, green, blue );
    j--;
  }
  delay(2000);
  LCD.displayClear(0, 0, 319, 239);
}

だいぶ簡単に直感的に色を入力できるようになったと思います。

では、これを Arduino IDE でコンパイル書き込みして下さい。
表示はこちらの記事の動画と同じように表示されればOKです。

文字表示だけのサンプルプログラム(スケッチ)

では、文字の固定表示だけの場合のサンプルプログラムは以下のようになります。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#define MGO_TEC_BV1_M5STACK_SD_SKETCH
#include <mgo_tec_bv1_m5stack_sd_simple1.h>

const char* utf8sjis_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* shino_full_font_file = "/font/shnmk16.bdf"; //オリジナル東雲全角フォントファイル
const char* shino_half_font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義

void setup() {
  Serial.begin(115200);
  mM5.init( utf8sjis_file, shino_half_font_file, shino_full_font_file );
  //font[max=8], scl_set[max=8], disp_fnt[max=8]

  mM5.font[0].x0 = 100; mM5.font[0].y0 = 0;
  mM5.font[0].htmlColorCode( "#FFFFFF" );
  mM5.font[0].Xsize = 1, mM5.font[0].Ysize = 1;
  mM5.disp_fnt[0].dispText( mM5.font[0], "Hello World!" );

  mM5.font[0].x0 = 16; mM5.font[0].y0 = 16;
  mM5.font[0].htmlColorCode( "white" );
  mM5.font[0].htmlBgColorCode( "#FF0000" );
  mM5.font[0].Xsize = 2, mM5.font[0].Ysize = 2;
  mM5.disp_fnt[0].dispText( mM5.font[0], "こんにちは。世界!" );

  mM5.font[0].x0 = 48; mM5.font[0].y0 = 50;
  mM5.font[0].htmlColorCode( "#00FF00" );
  mM5.font[0].htmlBgColorCode( "black" );
  mM5.font[0].Xsize = 3, mM5.font[0].Ysize = 7;
  mM5.disp_fnt[0].dispText( mM5.font[0], "日本語漢字" );

  mM5.font[1].x0 = 32; mM5.font[1].y0 = 160;
  mM5.font[1].htmlColorCode( "blue" );
  mM5.font[1].htmlBgColorCode( "yellow" );
  mM5.font[1].Xsize = 1, mM5.font[1].Ysize = 2;
  String str = "文字表示関数が簡単になりました!";
  mM5.disp_fnt[1].dispText( mM5.font[1], str );

  mM5.font[1].x0 = 0; mM5.font[1].y0 = 192;
  mM5.font[1].htmlColorCode( "black" );
  mM5.font[1].htmlBgColorCode( "cyan" );
  mM5.font[1].Xsize = 2, mM5.font[1].Ysize = 2;
  str = " HTML Color Code入力";
  mM5.disp_fnt[1].dispText( mM5.font[1], str );

  mM5.font[1].x0 = 0; mM5.font[1].y0 = 224;
  mM5.font[1].htmlColorCode( "magenta" );
  mM5.font[1].htmlBgColorCode( "black" );
  mM5.font[1].Xsize = 1, mM5.font[1].Ysize = 1;
  str = "東雲フォント、半角カタカナもOK.アイウエオァィゥェォ";
  mM5.disp_fnt[1].dispText( mM5.font[1], str );
}

void loop() {
}

いかがでしょうか。
以前より格段に簡単になったと思います。

htmlColorCode が文字フォントの色設定で、
htmlBgColorCode が文字の背景色を設定する関数です。

font配列は最大8ですが、このサンプルプログラムのように、一つの配列を使い回せば、かなり多くの文字列を描画することができると思います。

では、これを Arduino IDE でコンパイル書き込みしてみてください。
以下のように表示されればOKです。

文字スクロールだけのサンプルプログラム(スケッチ)

今度は、文字列および日本語漢字文字列を電光掲示板スクロール表示させる場合のサンプルプログラムは以下になります。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#define MGO_TEC_BV1_M5STACK_SD_SKETCH
#include <mgo_tec_bv1_m5stack_sd_simple1.h>

const char* utf8sjis_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* shino_full_font_file = "/font/shnmk16.bdf"; //オリジナル東雲全角フォントファイル
const char* shino_half_font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義

void setup() {
  Serial.begin(115200);
  mM5.init( utf8sjis_file, shino_half_font_file, shino_full_font_file );
  //font[max=8], scl_set[max=8], disp_fnt[max=8]

  String str1 = "Hello! World Scrolle. こんにちは! スクロールしてまっせ~! ";
  mM5.font[0].y0 = 16;
  mM5.font[0].htmlColorCode( "white" );
  mM5.font[0].htmlBgColorCode( "red" );
  mM5.font[0].Xsize = 1, mM5.font[0].Ysize = 2;
  mM5.scl_set[0].interval = 3; //(millisecond)
  mM5.disp_fnt[0].initScrolle( mM5.font[0], mM5.scl_set[0] );
  mM5.disp_fnt[0].newSetText( mM5.scl_set[0], str1 );
  String str2 = "HTMLカラーコード入力関数を追加です。";
  mM5.font[1].y0 = 100;
  mM5.font[1].htmlColorCode( "#00ff00" );
  mM5.font[1].htmlBgColorCode( "#552222" );
  mM5.font[1].Xsize = 3, mM5.font[1].Ysize = 5;
  mM5.scl_set[1].interval = 8; //(millisecond)
  mM5.disp_fnt[1].initScrolle( mM5.font[1], mM5.scl_set[1] );
  mM5.disp_fnt[1].newSetText( mM5.scl_set[1], str2 );
}

void loop() {
  mM5.disp_fnt[0].scrolleText( mM5.font[0], mM5.scl_set[0] );
  mM5.disp_fnt[1].scrolleText( mM5.font[1], mM5.scl_set[1] );
}

これも以前よりだいぶシンプルになりました。

スクロール文字列の場合は、font配列の使い回しはできません。
最大8列までです。

そして、setup内で font設定や、スクロールの速さを決める interval を設定して、スクロールさせる文字列を予め代入しておくところがポイントです。
メインloop内で文字列を入れ換えたければ、新たに newSetText関数でセットします。
文字の大きさが大きくなると、CPUの計算が少なくなるので、その分スクロール速度がアップすることに注意してください。

では、Arduino IDE でコンパイル書き込みしてみてください。
以下の動画のように表示されればOKです。

「図形表示と文字表示を合わせたサンプルプログラム(スケッチ)

今度は、グラフィック表示と文字表示を合わせた場合のサンプルプログラムです。
【ソースコード】 (※無保証 ※PCの場合、ダブルクリックすればコード全体を選択できます)

#define MGO_TEC_BV1_M5STACK_SD_SKETCH
#include <mgo_tec_bv1_m5stack_sd_simple1.h>

const char* utf8sjis_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* shino_full_font_file = "/font/shnmk16.bdf"; //オリジナル東雲全角フォントファイル
const char* shino_half_font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義

void setup() {
  Serial.begin(115200);
  mM5.init( utf8sjis_file, shino_half_font_file, shino_full_font_file );
  //font[max=8], scl_set[max=8], disp_fnt[max=8]

  String str1 = "Hello! World Scrolle. こんにちは! スクロールしてまっせ~! ";
  mM5.font[0].y0 = 16;
  mM5.font[0].htmlColorCode( "white" );
  mM5.font[0].htmlBgColorCode( "red" );
  mM5.font[0].Xsize = 1, mM5.font[0].Ysize = 2;
  mM5.scl_set[0].interval = 3; //(millisecond)
  mM5.disp_fnt[0].initScrolle( mM5.font[0], mM5.scl_set[0] );
  mM5.disp_fnt[0].newSetText( mM5.scl_set[0], str1 );
  String str2 = "HTMLカラーコード入力関数を追加です。";
  mM5.font[1].y0 = 200;
  mM5.font[1].htmlColorCode( "#0000FF" );
  mM5.font[1].htmlBgColorCode( "#555555" );
  mM5.font[1].Xsize = 3, mM5.font[1].Ysize = 2;
  mM5.scl_set[1].interval = 8; //(millisecond)
  mM5.disp_fnt[1].initScrolle( mM5.font[1], mM5.scl_set[1] );
  mM5.disp_fnt[1].newSetText( mM5.scl_set[1], str2 );
}

void loop() {
  uint16_t x0 = 32, y0 = 64, x1 = 272, y1 = 112;
  LCD.drawRectangleFill( x0, y0, x1, y1, "#fFaA1c" );
  LCD.drawRectangleLine( x0, y0, x1, y1, "#00ff00" );
  mM5.font[2].x0 = x0 + 8; mM5.font[2].y0 = y0 + 8;
  mM5.font[2].htmlColorCode( "#ffffff" );
  mM5.font[2].htmlBgColorCode( "#ff0000" );
  mM5.font[2].Xsize = 2, mM5.font[2].Ysize = 2;
  mM5.disp_fnt[2].dispText( mM5.font[2], "図形描画テスト" );
  delay(2000);
  LCD.displayClear();

  String html_color_code = "#FFFFFF";
  x0 = 0, y0 = 0;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 319, y0 = 0;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 0, y0 = 239;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  x0 = 319, y0 = 239;
  LCD.drawPixel65k3Color_sd( x0, y0, html_color_code );
  delay(2000);

  x0 = 0, x1 = 319, y0 = 0;
  LCD.drawHorizontalLine( x0, x1, y0, html_color_code );
  delay(500);
  x0 = 319, y0 = 0, y1 = 239;
  LCD.drawVerticallLine( x0, y0, y1, html_color_code );
  delay(500);
  x0 = 319, x1 = 0, y0 = 239;
  LCD.drawHorizontalLine( x0, x1, y0, html_color_code );
  delay(500);
  x0 = 0, y0 = 239, y1 = 0;
  LCD.drawVerticallLine( x0, y0, y1, html_color_code );
  delay(500);
  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#FF0000" );
  x0 = 319, y0 = 0, x1 = 0, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#00FF00");
  x0 = 160, y0 = 0, x1 = 160, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#0000FF" );
  x0 = 0, y0 = 120, x1 = 319, y1 = 120;
  LCD.drawLine(0, 120, 319, 120, "#FFFF00");
  delay(2000);

  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawRectangleFill( x0, y0, x1, y1, "white" );
  mM5.font[3].x0 = 80; mM5.font[3].y0 = 96;
  mM5.font[3].Xsize = 3, mM5.font[3].Ysize = 3;
  mM5.font[3].htmlColorCode( "black" );
  mM5.font[3].htmlBgColorCode( "white" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "white" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "red" );
  mM5.font[3].htmlColorCode( "white" );
  mM5.font[3].htmlBgColorCode( "red" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "red" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "green" );
  mM5.font[3].htmlColorCode( "black" );
  mM5.font[3].htmlBgColorCode( "green" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "green" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "blue" );
  mM5.font[3].htmlColorCode( "white" );
  mM5.font[3].htmlBgColorCode( "blue" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "blue" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "yellow" );
  mM5.font[3].htmlColorCode( "black" );
  mM5.font[3].htmlBgColorCode( "yellow" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "yellow" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "cyan" );
  mM5.font[3].htmlColorCode( "black" );
  mM5.font[3].htmlBgColorCode( "cyan" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "cyan" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "magenta" );
  mM5.font[3].htmlColorCode( "white" );
  mM5.font[3].htmlBgColorCode( "magenta" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "magenta" );
  delay(1000);
  LCD.drawRectangleFill( x0, y0, x1, y1, "black" );
  mM5.font[3].htmlColorCode( "white" );
  mM5.font[3].htmlBgColorCode( "black" );
  mM5.disp_fnt[3].dispText( mM5.font[3], "black" );
  delay(2000);

  LCD.displayClear();
  int i, j;
  for( i = 0; i < 120 ; i = i + 5 ){
    LCD.drawRectangleLine( 40 + i, i, 279 - i, 239 - i, "white" );
  }
  delay(2000);

  uint8_t Width = 50;
  LCD.drawRectangleFill( 0, 0, 319, 239, "#0000ff" );
  LCD.drawRectangleFill( 10, 10, 10 + Width, 10 + Width, "#ff2211" );
  LCD.drawRectangleFill( 309 - Width, 10, 309, 10 + Width, "#5Affcc" );
  LCD.drawRectangleFill( 10, 229 - Width, 10 + Width, 229, "#77FF66" );
  LCD.drawRectangleFill( 309 - Width, 229 - Width, 309, 229, "#baff33" );

  mM5.font[2].x0 = 64; mM5.font[2].y0 = 80;
  mM5.font[2].htmlColorCode( "#FFFFFF" );
  mM5.font[2].htmlBgColorCode( "#ff00FF" );
  mM5.font[2].Xsize = 1, mM5.font[2].Ysize = 3;
  mM5.disp_fnt[2].dispText( mM5.font[2], "Hello World 日本語漢字" );
  delay(2000);

  LCD.displayClear();
  x0 = 40, y0 = 0, x1 = 279, y1 = 239;
  LCD.drawRectangleLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 40, y0 = 0, x1 = 279, y1 = 239;
  LCD.drawLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 40, y0 = 239, x1 = 279, y1 = 0;
  LCD.drawLine( x0, y0, x1, y1, "#0000ff" );
  x0 = 159, y0 = 119;
  uint16_t r = 119;
  LCD.drawCircleLine( x0, y0, r, "white" );
  x0 = 25, y0 = 25, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ff0000" );
  x0 = 294, y0 = 25, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#00ff00" );
  x0 = 25, y0 = 214, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ffff00" );
  x0 = 294, y0 = 214, r = 25;
  LCD.drawCircleLine( x0, y0, r, "#ff00ff" );
  for( i = 0; i < 120; i = i + 5 ){
    LCD.drawCircleLine( 159, 119, 119-i, "white" );
  }
  delay(2000);

  LCD.displayClear();
  x0 = 0, y0 = 0, x1 = 319, y1 = 239;
  LCD.drawRectangleFill( x0, y0, x1, y1, "#000020" );
  x0 = 159, y0 = 119, r = 119;
  LCD.drawCircleFill( x0, y0, r, "#ff00ff" );
  x0 = 25, y0 = 25, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#ff0000" );
  x0 = 294, y0 = 25, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#00ff00" );
  x0 = 25, y0 = 214, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#ffff00" );
  x0 = 294, y0 = 214, r = 25;
  LCD.drawCircleFill( x0, y0, r, "#00ffff" );
  x0 = 159, y0 = 119, r = 51;
  LCD.drawCircleFill( x0, y0, r, "#0000ff" );
  delay(2000);

  LCD.displayClear();
  for( i = 0; i < 240; i = i + 10 ){
    LCD.drawLine( 0, i, i, 239, "#10FF20" );
    LCD.drawLine( 80 + i, 0, 319, i, "#00ffff" );
  }
  delay(2000);

  LCD.displayClear();
  uint8_t red = 0, green = 0, blue = 0;
  //red (0-31), green (0-63), blue (0-31)
  j = 31;
  for( i = 0; i < 32; i++ ){
    red = i, green = 0, blue = 0;
    LCD.drawRectangleFill( i * 10, 0, i * 10 + 9, 59, red, green, blue );
    red = 0, green = i * 2, blue = 0;
    LCD.drawRectangleFill( i * 10, 60, i * 10 + 9, 119, red, green, blue );
    red = 0, green = 0, blue = i;
    LCD.drawRectangleFill( i * 10, 120, i * 10 + 9, 179, red, green, blue );
    red = j, green = j * 2, blue = j;
    LCD.drawRectangleFill( i * 10, 180, i * 10 + 9, 239, red, green, blue );
    j--;
  }
  delay(2000);

  uint32_t time_out = millis();
  while( millis() - time_out < 10000 ){
    mM5.disp_fnt[0].scrolleText( mM5.font[0], mM5.scl_set[0] );
    mM5.disp_fnt[1].scrolleText( mM5.font[1], mM5.scl_set[1] );
    delay(1);
  }

  LCD.displayClear(0, 0, 319, 239);
}

これのポイントは、図形を描いてから、その上に文字を描画させることです。
文字の背景色を図形と同じにすることで、透過色のような感じにできます。

では、これをコンパイル書き込みしてみて下さい。
以下の動画のように表示されればOKです。

編集後記

今回は Webプログラマの方々にとっては取るに足らないことだと思いますが、私の場合、C++ のクラスを駆使して、グラフィック表示とフォント表示の両方に共通の関数を使って HTML カラーコード入力できるようになったことは、とっても画期的な事でした。
Arduino IDE の ESP32 や M5Stack で、それができることにとっても意味があります。
Web との連携がスムースになるからです。
いつか、HTMLカラーコード入力で統一したいなと思っていましたが、ようやく実現できました。
これで Firebase との連携もやりやすくなります。

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

Amazon.co.jp 当ブログのおすすめ

スイッチサイエンス ESPr Developer 32 Type-C SSCI-063647
スイッチサイエンス
¥2,420(2024/03/19 08:55時点)
ZEROPLUS ロジックアナライザ LAP-C(16032)
ZEROPLUS
¥22,504(2024/03/19 15:23時点)
Excelでわかるディープラーニング超入門
技術評論社
¥2,068(2024/03/19 03:23時点)

コメント

  1. haiga より:

    いつもお世話になっております。haigaです。
    この、MGO_TEC_BV1_M5STACK_SD_SKETCH 環境に於いて、”ESP32_SD_UTF8toSJIS.h”にて行っていた、UTF8_to_SJIS_str_cnv関数を使おうとしているのですが、
    UTF8toSjis file has not been uploaded to the flash in SD file system
    のエラーが回避できません(ファイル名などを新環境に合わせただけです)

    この新ライブラリーに対応したUTF8toSJISの使い方サンプルなどは何処を見れば宜しいでしょうか?

    • mgo-tec mgo-tec より:

      haigaさん

      いつも当ブログをご覧いただき、ありがとうございます。

      この記事も3年以上前で、自分の作ったコードを見返しても、すっかり思い出せなくなってしまいました。
      この記事のライブラリは、内部でUTF8とShift_JISを変換しているので、UTF8_to_SJIS_str_cnv関数は使えません。
      というか、このライブラリ内のutf8tosjis.hファイルのソースコードを見て頂ければ分かるのですが、UTF8_to_SJIS_str_cnv関数は定義しておらず、名前を変更して、convUtf8ToSjis関数となっています。
      その当時は関数の命名規則を勉強中だったので、いろいろ名前を変更していました。
      統一性が無く、申し訳ございません。(何分、素人なもので…)

      どうしてもShift_JISコードをそのまま使いたいのであれば、もしかしたら、SdUtf8toSjisクラスのインスタンスを生成して、
      mgo_tec_esp32_bv1::SdUtf8toSjis UtoS
      などと定義すれば使えるかも知れません。(ダメかも…)
      いろいろ試してみて下さい。
      (私は当分時間が無く試すことが出来ないので、ごめんなさい。)

      • haiga より:

        mgo-tecさま

        返信ありがとうございます。
        アドバイスして頂いた方式とは少し変わっていますが、小生なりに使用する関数を変更する方法でトライしてみました。しかし、下記のようなエラーが出ます。

        no matching function for call to ‘mgo_tec_esp32_bv1::SdUtf8toSjis::convUtf8ToSjis(fs::File&, String&, uint8_t [( + 1)], uint16_t*)’

        スミマセン、C言語系にプアなもので理解できません。このエラーは何処が悪いと示しているのでしょうか?(関数の定義そのものに差異があるのでしょうか?)

        お忙しいのに、全くスミマセン。コメントをお願いいたします。

        • mgo-tec mgo-tec より:

          haigaさん

          先ほどは、想像でお答えしたのですが、私の提案が全然見当違いでした。
          これは、あまりにイレギュラーな使い方なので、無理です。
          と、思って、何となく動かしてみたら、以下のコードでUTF-8文字列をShift_JISコードに変換できました。
          因みに、今後の動作は保証しませんが…。

          #define MGO_TEC_BV1_M5STACK_SD_SKETCH
          #include <mgo_tec_bv1_m5stack_sd_simple1.h>
           
          const char* utf8sjis_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
          const char* shino_full_font_file = "/font/shnmk16.bdf"; //オリジナル東雲全角フォントファイル
          const char* shino_half_font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義
           
          void setup() {
            Serial.begin(115200);
            mM5.init( utf8sjis_file, shino_half_font_file, shino_full_font_file );
           
            uint8_t sj[20] = {};
            //UTF-8文字列からShift_JISコードに変換
            int sj_len = SFR.convStrToSjis("あ", sj);
            Serial.printf("%02x,%02x\r\n", sj[0], sj[1]);
            Serial.printf("sj_len = %d\r\n", sj_len);
          }
           
          void loop() {
          }
          
  2. haiga より:

    mgo-tecさま

    お忙しいのに早速のお返事頂きありがとうございました。
    私のプログラムに組み込んで動作することを確認いたしました。ありがとうございます。

    mgo-tecさまが作られたILI9341 LCDドライバ等を仕事に使う内製計測機器に組み込んで、大変有用させて頂いております。
    計測結果をExcelで見たり処理することが多いので、Shift-JIS変換が欠かせません。
    これまではESP32からBlutoothでPCへ転送していましたが、スマホ受信が安直なので
    それを行っていたところでした。

    変換後のShit-JISコードはBluetoothでスマホやPCに送るのですが、スマホソフトのSerial Bluetooth Terminal では漢字部分の先頭文字で文字化けする問題が生じています。PCでは問題無いですので変換には問題ありません。UTF8での文字送信のように、文字コードを一気に送る必要があるようです。

    • mgo-tec mgo-tec より:

      haigaさん

      動いて良かったですね。
      業務に使ってらっしゃるなんて、お役に立てて嬉しいです。
      ただ、その反面、私の未熟なコードが業務に使われるのには心配でもあります。
      ExcelはいいかげんにUTF8に統一して欲しいですよね。

      漢字部分の先頭で文字化けするのは変ですね。
      先頭部分に他の数値が入ってしまっているか、または、先頭部分の数値が消去されてしまっているかもしれませんね。
      勝手な想像ですが、半角英数字とか半角スペースを挟むと改善するかもしれません。

      何はともあれ、動いて良かった!
      (^^)

  3. haiga より:

    mgo-tecさま

    お察しの通り、文字の先頭に、1. や 2. 等のように入れてみるとかなり改善されました。

    ありがとうございました。

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