注目キーワード

【Arduino】「M5Stack」画面制御を極める!(Lovyan_GFXライブラリ)

すけろく
標準ライブラリでの画面描画はできた。
しかし、M5Stack向けのライブラリなので
汎用性がないな。
げんろく
たしかに。
M5StickCや他のAruduino機器でも使えるものが必要だな。
すけろく
そのようなものがあるのか?
げんろく
よし。今回は、汎用的に使えるライブラリを紹介しよう。
lovyan03さんが公開されている「Lovyan_GFX」だ。

この記事では、Arduino IDEを使ってM5Stackのディスプレイに時刻や日付を表示させるため、画面制御の方法を確認します。

今回は、「lovyan03」さんが公開されているArduino IDE向けのライブラリ「Lovyan GFX」 Libraryを使用します。

Arduino IDE共通で使用でき、かつ様々なディスプレイコントローラに対応されているので、、Arduino対応機器間で同じソースを使いたい場合に有効です。

しかも、ディスプレイへの描画速度に定評があります。

 

M5社の「M5Stack」標準ライブラリを使った画面制御は、こちらの記事で紹介しています!

関連記事

すけろく M5Stackも時刻同期や日本語表示までできた。 うまくいっておるな。 げんろく ああ、「M5Stack」でもノウハウがたまってきている。 すけろく そういえば、大き[…]

 

 

これからはじめる方にお勧めの参考図書はこちら!

 

今回の記事では、「Lovyan GFX」 Library「M5Stack」ディスプレイで使用するための設定と、描画を行う各関数を紹介します。

リファレンスとしてお使いくださいね!

 

M5StackでLovyan GFX Libraryを使うための設定

今回使用する「Lovyan GFX」 Libraryを「M5Stack」で使用するためには、次の3つの設定が必要となります。

  • 対応ディスプレイの確認
  • AdafruitGFXライブラリの読み込み

 

対応ディスプレイの確認

「M5Stack」のディスプレイは、「ILI9342C」というコントローラを使っています。このコントローラは、M5Stackの各モデルで共通になっています。

「Lovyan GFX」から、「ILI9342C」を制御できるか確認する方法は、次のGitHubリポジトリを確認します。

他のM5Stack以外の機器を使用する場合もこのリポジトリは有効ですので、覚えておきましょう!

 

上記のリポジトリのReadmeから、「対応環境 support environments」を確認します。M5Stackに搭載されている「ILI9342C」があることがわかります。ほかにもたくさんのディスプレイに対応されています。

 

AdafruitGFXライブラリの読み込み

Lovyan GFX」 Library を使用するためには、ライブラリとしてArduino IDEにインストールする必要があります。

そのため、Arduino IDEのライブラリ管理で、「Lovyan GFX」 Library というライブラリをインストールする必要があります。

事前にインストールしておきましょう!

 

ライブラリのインストールは、次の記事で紹介しています。

関連記事

Arduino IDE」では、使用する機能やセンサー、ボードを使用するプログラムで使用できる有効なライブラリが公開されています。ライブラリを使用すると、効率的かつ品質を確保したプログラミングが可能です。 ここでは、Ardu[…]

 

ディスプレイごとのチューニングは必要か?

ディスプレイの制御を行うライブラリは、使用する際に主に次のチューニングや設定が必要となります。

  • ディスプレイ接続GPIOの指定
  • ディスプレイコントローラのドライバ組み込み

 

でも安心してください。

Lovyan GFX」では、このあたりの設定について、ライブラリ側の自動認識機能で適切に調整してくれます!

 

ライブラリを使用するためのプログラム記述

①使用する機器を指定

Arduino IDEでプログラミングする機器を以下の中から選んで、コメントアウトを解除(//を削除)します。

今回は「M5Stack」を使用するので、次のようになります。

#define LGFX_M5STACK // M5Stack (Basic / Gray / Go / Fire)
// #define LGFX_M5STACK_CORE2 // M5Stack Core2
// #define LGFX_M5STACK_COREINK // M5Stack CoreInk
// #define LGFX_M5STICK_C // M5Stick C / CPlus
// #define LGFX_M5PAPER // M5Paper
// #define LGFX_M5TOUGH // M5Tough
// #define LGFX_ODROID_GO // ODROID-GO
// #define LGFX_TTGO_TS // TTGO TS
// #define LGFX_TTGO_TWATCH // TTGO T-Watch
// #define LGFX_TTGO_TWRISTBAND // TTGO T-Wristband
// #define LGFX_TTGO_TDISPLAY // TTGO T-Display
// #define LGFX_DDUINO32_XS // DSTIKE D-duino-32 XS
// #define LGFX_LOLIN_D32_PRO // LoLin D32 Pro
// #define LGFX_ESP_WROVER_KIT // ESP-WROVER-KIT
// #define LGFX_WIFIBOY_PRO // WiFiBoy Pro
// #define LGFX_WIFIBOY_MINI // WiFiBoy mini
// #define LGFX_MAKERFABS_TOUCHCAMERA // Makerfabs Touch with Camera
// #define LGFX_MAKERFABS_MAKEPYTHON // Makerfabs MakePython
// #define LGFX_WT32_SC01 // Seeed WT32-SC01
// #define LGFX_WIO_TERMINAL // Seeed Wio Terminal
// #define LGFX_PYBADGE // Adafruit PyBadge
// #define LGFX_ESPBOY // ESPboy

この定義部分を見る限り、M5社の機器や、Wio Terminal、など、様々な機器の対応されているのがわかりますね!

 

②自動認識まわりの設定を行う

次に自動認識を有効にするために以下のように記述します。

コメントにあるように機器によっては、ディスプレイパネルのIDが読めないため自動認識できないものがあるようです。

M5Stackは認識できるので、以下の記述を使えます。

また、旧バージョンからの移行処置としてバージョン指定を行う必要があるようです。

   #define LGFX_AUTODETECT // 自動認識 (D-duino-32 XS, PyBadge はパネルID読取りが出来ないため自動認識の対象から外れています)
   #define LGFX_USE_V1            // v1.0.0 を有効にします(v0からの移行期間の特別措置です。これを書かない場合は旧v0系で動作します。)

 

③ヘッダのインクルードとインスタンスの作成

次にライブラリを読み込むためのヘッダ記述(インクルード)と「Lovyan GFX」のインスタンスを作成します。

「M5Stack.h」を読み込みたい場合は、「Lovyan GFX」のヘッダインクルードより前に「include <M5Stack.h> 」と記述します。

※ただし、M5.Lcdは使うことができません。

// M5Stackのライブラリをインクルードする場合はこの位置に記載
include <M5Stack.h> 

// ヘッダをincludeします。
#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp> // クラス"LGFX"を用意します
// #include <lgfx_user/LGFX_ESP32_sample.hpp> // またはユーザ自身が用意したLGFXクラスを準備します
static LGFX lcd; // LGFXのインスタンスを作成。
static LGFX_Sprite sprite(&lcd); // スプライトを使う場合はLGFX_Spriteのインスタンスを作成。

 

 

画面描画とSprite

ディスプレイなどの画面描画する場合、描画タイミングなどを考慮した描画が必要になるケースがあります。

その際に有効になるのが「Sprite」です。

通常、lcdを使って図形描画する場合、一定単位でディスプレイに順次描画されます。

「Sprite」は、その描画内容を一度メモリ上にイメージを保存しておき、それをディスプレイ(Lcd)に描画させることができます。

 

「Sprite」についての詳しい説明は、別の記事で紹介予定です。ご期待ください。

 

 

画面描画してみる

それでは、画面に描画してみましょう。

まずは、「Lavyan GFX」で準備されているものを順を追って確認していきます。

説明の前提として、「lcd」という「Lovyan GFX(LGFX)」インスタンスを生成した場合で記述します。

最後にSpriteの使用有無によってどう変わるかを確認してみます。

  • 初期化
  •  プロパティ系
    • 画面の向き
    • バックライトの輝度
    • 画面サイズ
    • カラーモードの設定
    • カラーコード変換
    • 画面の塗りつぶし
    • 画面表示色
  • 文字描画系
    • カーソル位置
    • フォント/フォント色/フォントサイズ
    • 文字描画
    • テキスト座標
  • その他の描画系
    • 図形描画

 

初期化

描画関数を使う前に、初期化します。

関数 説明
lcd.init(); インスタンスの初期化を行います。

 

画面プロパティ系

画面の向き

M5Stackのディスプレイには以下の4つの向きがあります。使う方向に応じて向きを設定できます。

関数 説明
lcd.setRotation(value) 画面の向きを指定します。(value=0~3)

 

 

バックライトの輝度

ディスプレイのバックライトの輝度を指定できます。

関数 説明
lcd.setBrightness(value); 画面の向きを指定します。(value=0~255)

 

画面サイズ

画面サイズを確認することができます。画面の向きを変えると高さと幅が変わります。
画面が縦向きの場合:高さ(240px)、幅(320px)
画面が横向きの場合:高さ(320px)、幅(240px)

関数 説明
lcd.height() 画面の高さを返します(int32_t
lcd.width() 画面の幅を返します。(int32_t

 

カラーモードの設定

使用するカラーモードを設定します。(初期値は16です)

モード:16 
ディスプレイに対するSPI通信量が少ないので高速動作。
(ただし、赤と青の諧調は5bit)

モード:24
ディスプレイに対するSPI通信量が多い。諧調表現が綺麗になる。

関数 説明
lcd.setColorDepth(mode) 画面の高さを返します(mode : 16 or 24 )

 

カラーコード変換

関数 説明
lcd.color332(r, g, b) RGBカラーをカラーコードに変換します。
lcd.color565(r, g, b) RGBカラーをカラーコードに変換します。
lcd.color888(r, g, b) RGBカラーをカラーコードに変換します。
※色情報の欠損防止のためこの関数が推奨

カラーコード生成関数を使用しない場合は、次のように指定します。
RGB888 24ビットで指定 →uint32_t型
RGB565 16ビットで指定 →uint16_t型、int32_t型
RGB332 8ビットで指定  →uint8_t型

 

画面の塗りつぶし

関数 説明
lcd.fillScreen(color) 画面全体を指定した色で塗りつぶします。
Color=int
lcd.clear(color) clearは描画系の関数とは別で背景色という扱いで、指定した色で塗りつぶします。
Color=int

 

画面表示色

色見本として次の色(lcd.color888(r, g, b))を表示してみました。

次の画面表示は、Brightness:128、ColorDepth:24 に設定しています。

BLACK DARKGREY ORANGE
NAVY BLUE GREENYELLOW
DARKGREEN GREEN PINK
DARKCYAN CYAN OLIVE
MAROON RED YELLOW
PURPLE MAGENTA
LIGHTGREY WHITE

 

文字描画系

カーソル位置

関数 説明
lcd.setCursor(x, y) 画面の中のカーソルの位置を指定します。
lcd.setCursor(x, y, font) 画面の中のカーソルの位置とフォントを指定します。
※フォントについては、文字描画系で記載します。font (uint8_t  or IFont )

 

フォント/フォントカラー/フォントサイズ

フォントは以下のものが含まれています。フォントカラーは、画面色のものを参照してください。

関数 説明
lcd.setFont(&fonts::Font4) フォントを指定します。(font=1~8)

標準的なフォントを指定する場合
・&fonts::Font”value”  value = (0, 2, 4, 6, 7, 8)
・value (0, 2, 4, 6, 7, 8) ※非推奨
プリセットフォントを指定する場合
・&fonts::”Font Name”

lcd.setTextColor(Fcolor, Bcolor) フォントの色(Fcolor)および背景色(Bcolor)を指定します。
lcd.setTextSize(width, height) フォントサイズ(倍数)を指定します。
width:横方向の倍率
height:縦方向の倍率

フォントの指定値と表示イメージは次の通りです。(高さ240px、幅320px:横向き指定の場合)
フォント自体のピクセル値と後で出てくるフォントサイズは異なります。

表示サイズは(フォント自体の大きさ×フォントサイズ)になります。

 

標準フォント
1 &fonts::Font0 英数字フォント
FontSize : 1~ 5  ※縦横同比を指定
2 &fonts::Font2 英数字フォント
FontSize : 1 ~ 4 ※縦横同比を指定
3 &fonts::Font4 英数字フォント
FontSize : 1 ~ 2※縦横同比を指定
4 &fonts::Font6 英数字フォント
FontSize : 1 、1.5 ※縦横同比を指定
5 &fonts::Font7 数字フォント
FontSize : 1 、1.2 ※縦横同比を指定
6 &fonts::Font8 数字フォント
FontSize : 1   ※縦横同比を指定

 

プリセットフォント

LovyanGFXには、標準フォント以外に180ほどのフォントが含まれています。
サンプリング表示をしてみました。

1 &fonts::TomThumb FontSize :4  ※縦横同比を指定

2 &fonts::FreeMono24pt7b FontSize : 1  ※縦横同比を指定

3 &fonts::FreeSans24pt7b FontSize : 1    ※縦横同比を指定

4 &fonts::lgfxJapanMincho_24 FontSize : 1    ※縦横同比を指定

5 &fonts::lgfxJapanGothic_24 FontSize : 1   ※縦横同比を指定

6 &fonts::efontJA_24 FontSize : 1  ※縦横同比を指定

 

文字描画

関数 説明
lcd.printf(text)
lcd.println(text)
文字を描画します。(text=String)
printfは改行なし、printlnは改行ありになります。

注意が必要なのは、上記のM5.Lcd.print(text)を連続で描画するとカーソル位置は文字描画後の終端座標が次の描画の開始点となります。次に記載するテキスト座標と合わせて表示域を制御する必要があります。

 

テキスト座標

右揃え や 中央揃え で描画したい場合は、setTextDatum 関数で基準位置を指定します。縦方向が top、middle、baseline、bottomの4通り、横方向が left、center、rightの3通りです。

縦と横の指定を組み合わせた12通りの中から指定します。

※Print系の文字描画では、縦方向の影響しか与えられません。drawString系で縦横の影響を与えることができます。

関数 説明
lcd.setTextDatum(datum) テキストの座標は、次の通り12通りから選択して指定します。

テキスト座標指定

ID 設定 Print系描画結果 drawPrint系描画結果
1 top_left
2 top_center
3 top_right
4 middle_left
5 middle_center
6 middle_right
baseline_left
baseline_center
baseline_right
10 bottom_left
11 bottom_center
12 bottom_right

 

その他描画系

図形描画

関数  表示イメージ 説明
lcd.drawPixel(x, y, color) ピクセル単位で描画します。
画像は正弦波(Sine Wave)を表示してみました。
lcd.drawLine(x0, y0, h, color) 線を描画します。
lcd.drawLine(0, 68, 240, 68, c_RED);
lcd.drawLine(0, 0, 240, 135, c_BLUE);
lcd.drawLine(0, 135, 240, 0, c_GREEN);
lcd.drawCircle(x0, y0, r, color) 円を描画します。
lcd.drawCircle(10, 10, 10, RED);
lcd.drawCircle(50, 30, 30, BLUE);
lcd.drawCircle(100, 60, 30, GREEN);
lcd.drawCircle(150, 90, 30, YELLOW);
lcd.drawCircle(200, 120, 30, PURPLE);
lcd.drawRect(x, y, w, h, color) 四角形を描画します。
lcd.drawRect(10, 10, 10, 10, RED);
lcd.drawRect(50, 30, 20, 20, BLUE);
lcd.drawRect(100, 40, 30, 30, GREEN);
lcd.drawRect(150, 60, 40, 40, YELLOW);
lcd.drawRect(200, 90, 50, 50, PURPLE);
lcd.drawTriangle(x0, y0, x1, y1, x2, y2, color) 塗りつぶした三角形を描画します。
lcd.drawTriangle(15, 5, 0, 15, 30, 15, RED);
lcd.drawTriangle(60, 30, 30, 60, 90, 60, BLUE);
lcd.drawTriangle(100, 40, 50, 75, 150, 75, GREEN);
lcd.drawTriangle(150, 60, 100, 100, 240, 100, YELLOW);
lcd.drawTriangle(200, 80, 150, 125, 300, 125, PURPLE);
lcd.fillCircle(x0, y0, r, color) 塗りつぶした円を描画します。
M5.Lcd.fillCircle(10, 10, 10, RED);
M5.Lcd.fillCircle(50, 30, 30, BLUE);
M5.Lcd.fillCircle(100, 60, 30, GREEN);
M5.Lcd.fillCircle(150, 90, 30, YELLOW);
M5.Lcd.fillCircle(200, 120, 30, PURPLE);
lcd.fillRect(x0, y0, x1, y1, color) 塗りつぶした四角形を描画します。
M5.Lcd.fillRect(10, 10, 10, 10, RED);
M5.Lcd.fillRect(50, 30, 20, 20, BLUE);
M5.Lcd.fillRect(100, 40, 30, 30, GREEN);
M5.Lcd.fillRect(150, 60, 30, 30, YELLOW);
M5.Lcd.fillRect(200, 90, 50, 50, PURPLE);
lcd.fillTriangle(x0, y0, x1, y1, x2, y2, color) 塗りつぶした三角形を描画します。
M5.Lcd.fillTriangle(15, 5, 0, 15, 30, 15, RED);
M5.Lcd.fillTriangle(60, 30, 30, 60, 90, 60, BLUE);
M5.Lcd.fillTriangle(100, 40, 50, 75, 150, 75, GREEN);
M5.Lcd.fillTriangle(150, 60, 100, 100, 240, 100, YELLOW);
M5.Lcd.fillTriangle(200, 80, 150, 125, 300, 125, PURPLE);
lcd.drawFastVLine ( x, y , h , color) 垂直線を描画します。
lcd.drawFastVLine(15, 20, 200, c_RED);
lcd.drawFastVLine(35, 40, 160, c_BLUE);
lcd.drawFastVLine(55, 60, 120, c_GREEN);
lcd.drawFastVLine(75, 80, 80, c_YELLOW);
lcd.drawFastVLine(95, 100, 40, c_PURPLE);
lcd.drawFastHLine ( x, y, w , color) 水平線を描画します。
lcd.drawFastHLine(15, 20, 200, c_RED);
lcd.drawFastHLine(35, 40, 160, c_BLUE);
lcd.drawFastHLine(55, 60, 120, c_GREEN);
lcd.drawFastHLine(75, 80, 80, c_YELLOW);
lcd.drawFastHLine(95, 100, 40, c_PURPLE);
lcd.drawRoundRect ( x, y, w, h, r, color) 角丸の矩形の外周を描画します。
lcd.drawRoundRect(10, 10, 10, 10, 2, c_RED);
lcd.drawRoundRect(50, 30, 20, 20, 5, c_BLUE);
lcd.drawRoundRect(100, 40, 30, 30, 10, c_GREEN);
lcd.drawRoundRect(150, 60, 30, 30, 10, c_YELLOW);
lcd.drawRoundRect(200, 90, 50, 50, 15, c_PURPLE);
lcd.fillRoundRect ( x, y, w, h, r, color) 角丸の矩形の塗りを描画します。
lcd.fillRoundRect(10, 10, 10, 10, 2, c_RED);
lcd.fillRoundRect(50, 30, 20, 20, 5, c_BLUE);
lcd.fillRoundRect(100, 40, 30, 30, 10, c_GREEN);
lcd.fillRoundRect(150, 60, 30, 30, 10, c_YELLOW);
lcd.fillRoundRect(200, 90, 50, 50, 15, c_PURPLE);
lcd.drawEllipse ( x, y, rx, ry , color) 楕円の外周を描画します。
lcd.drawEllipse(10, 10, 10, 40, c_RED);
lcd.drawEllipse(50, 30, 20, 80, c_BLUE);
lcd.drawEllipse(100, 40, 60, 30, c_GREEN);
lcd.drawEllipse(150, 60, 80, 30, c_YELLOW);
lcd.drawEllipse(200, 90, 100, 50, c_PURPLE);
lcd.fillEllipse ( x, y, rx, ry , color) 楕円の塗りを秒gします。
lcd.fillEllipse(10, 10, 10, 40, c_RED);
lcd.fillEllipse(50, 30, 20, 80, c_BLUE);
lcd.fillEllipse(100, 40, 60, 30, c_GREEN);
lcd.fillEllipse(150, 60, 80, 30, c_YELLOW);
lcd.fillEllipse(200, 90, 100, 50, c_PURPLE);
lcd.drawBezier ( x0, y0, x1, y1, x2, y2, color)
lcd.drawBezier ( x0, y0, x1, y1, x2, y2, x3, y3, color)
3点間または4点間のベジエ曲線を描画します。
lcd.drawBezier(10, 10, 160, 200, 250, 10, c_RED);
lcd.drawBezier(10, 10, 180, 220, 220, 50, 300, 150, c_BLUE);
lcd.drawArc ( x, y, r0, r1, angle0, angle1, color) 円弧の外周を描画します。
lcd.drawArc(160, 120, 100, 100, 0, 90, c_RED);
lcd.drawArc(160, 120, 100, 100, 180, 270, c_BLUE);
lcd.drawGradientLine( x1, y1, x2, y2, color1, color2) 2点間を結ぶ線をcolor1からcolor2の指定色までグラデーション描画します。
for (int i=0; i < 50; i++) {
lcd.drawGradientLine(10, 10+i, 300, 10+i, c_RED, c_GREEN);
}

 

編集後記

いかがだったでしょうか。

M5StackをArduino IDEで使用できる「LovyanGFX」ライブラリにおけるディスプレイ表示処理をまとめました。

リファレンスとしてご活用いただければと思います。

今後、他のディスプレイ描画ライブラリを使った場合の、プログラムの実行例などをご紹介していきたいと思います。

ご期待ください。

 

今回の記事は以上になります。

最後までご覧いただきありがとうございました。