液晶モジュールでグラフィック

 今回は前回に続いて「1.8inch TFT 液晶モジュール」を使います。

・micro:bit用液晶モジュール(www.waveshare.comでの製品紹介) https://www.waveshare.com/1.8inch-lcd-for-micro-bit.htm
(Amazonでの販売) https://www.amazon.co.jp/dp/B07HD2TXQZ/

・GitHub https://github.com/waveshare/WSLCD1in8

 今回はグラフィック表示を使ったサンプルを作成してみます。以後に説明するサンプルでは、あらかじめ液晶モジュールの拡張機能を読み込んでおく必要があります。機能拡張を読み込む方法については前回の連載を参照してください。
 なお、液晶モジュールは160×128ドットなので、指定できる座標範囲は0〜159,0〜127のはずですが、用意されているブロックでは0〜160,0〜128までの範囲を指定できるようになっています。以後の説明ではブロックで指定できる座標値にあわせて0〜160,0〜128としてあります。

基本的なグラフィック描画(1)

 まず、基本的なグラフィック描画を行ってみましょう。液晶モジュールには以下のグラフィック描画機能が用意されています。

(1)塗りつぶし
(2)点の描画
(3)線の描画
(4)四角形の描画
(5)正円の描画

 順番に試していきましょう。 まず、(1)の塗りつぶしです。塗りつぶしは「Filling Color」ブロックを使います。以下のようにすると赤、青、緑の順番で画面が塗りつぶされます。描画速度は遅いので、かなり長いウェイトを入れてあります。なお、この塗りつぶしブロックに限って描画データを送るブロックは不要です。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    LCD1IN8.LCD_Filling(LCD1IN8.Get_Color(LCD_COLOR.RED))
    basic.pause(4000)
    LCD1IN8.LCD_Filling(LCD1IN8.Get_Color(LCD_COLOR.BLUE))
    basic.pause(4000)
    LCD1IN8.LCD_Filling(LCD1IN8.Get_Color(LCD_COLOR.GREEN))
    basic.pause(4000)
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

次に(2)の点の描画です。点の描画は「Draw Point」ブロックを使います。描画する座標と色、そしてピクセルサイズ(1〜4)を指定します。X座標は0〜160、Y座標は0〜128までの範囲の数値になります。色は0〜65536までの数値か、あらかじめ用意されているカラーブロックを使います。なお、値の範囲が座標値や色のコードを超えていてもエラーにはなりません。

以下のプログラムはランダムに赤い点を描画していきます。なお、描画されているのは内部の画面(仮想画面/オフスクリーン)ですので、点の描画後には「Send display data」ブロックを使って実際の液晶画面に表示(データを転送)する必要があります。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    LCD1IN8.DrawPoint(
    Math.randomRange(0, 160),
    Math.randomRange(0, 128),
    LCD1IN8.Get_Color(LCD_COLOR.RED),
    DOT_PIXEL.DOT_PIXEL_2
    )
    LCD1IN8.LCD_Display()
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

実際に動かすと思ったほど速くありません。より高速に処理するには、たくさん点を描画しておき、まとめて液晶画面にデータを転送します。以下のプログラムは20個の点を描画したら、まとめて液晶画面に転送するようになっています。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    for (let i = 0; i < 20; i++) {
        LCD1IN8.DrawPoint(
        Math.randomRange(0, 160),
        Math.randomRange(0, 128),
        LCD1IN8.Get_Color(LCD_COLOR.RED),
        DOT_PIXEL.DOT_PIXEL_2
        )
    }
    LCD1IN8.LCD_Display()
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

基本的なグラフィック描画(2)

 次に(3)の線の描画です。線を描画するには「Draw Line」ブロックを使います。開始座標と終了座標、線の色とサイズ、形状を指定します。線も点と同様に描画後には「Send display data」ブロックを使って液晶画面にデータを転送します。

 以下のプログラムはランダムな線をランダムな色で描画します。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    LCD1IN8.DrawLine(
        Math.randomRange(0, 160),
        Math.randomRange(0, 128),
        Math.randomRange(0, 160),
        Math.randomRange(0, 128),
        Math.randomRange(0, 65536),
        DOT_PIXEL.DOT_PIXEL_2,
        LINE_STYLE.LINE_SOLID
    )
    LCD1IN8.LCD_Display()
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

 (4)の四角形の描画です。四角形を描画するには「Draw Rectangle」ブロックを使います。線と同様に座標と色を指定します。なお、四角形は塗り潰すか、枠だけを描くかを指定することができます。枠の場合、線の太さを1〜4ドットの範囲で指定することができます。

 以下のプログラムはランダムな四角形をランダムな色で描画します。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    LCD1IN8.DrawRectangle(
    Math.randomRange(0, 160),
    Math.randomRange(0, 128),
    Math.randomRange(0, 160),
    Math.randomRange(0, 128),
    Math.randomRange(0, 65536),
    DRAW_FILL.DRAW_FULL,
    DOT_PIXEL.DOT_PIXEL_1
    )
    LCD1IN8.LCD_Display()
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

 (5)の正円の描画です。正円を描画するには「Draw Circle」ブロックを使います。線や四角形と同様に座標と色を指定します。なお、正円は塗り潰すか、枠だけを描くかを指定することができます。枠の場合、線の太さを1〜4ドットの範囲で指定することができます。

 以下のプログラムはランダムな正円をランダムな色で描画します。

 JavaScriptコードの場合、以下のようになります。

LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
basic.forever(function () {
    LCD1IN8.DrawCircle(
    Math.randomRange(0, 160),
    Math.randomRange(0, 128),
    Math.randomRange(10, 50),
    Math.randomRange(0, 65536),
    DRAW_FILL.DRAW_FULL,
    DOT_PIXEL.DOT_PIXEL_1
    )
    LCD1IN8.LCD_Display()
})

マイクロビットにプログラムを転送して実行すると以下のようになります。

明るさをグラフで表示する

 それではグラフィック描画機能を使って明るさをグラフで表示してみましょう。液晶画面は横160ドットあるので、明るさを左から右に縦棒グラフで表示していきます。明るい場合は棒グラフを長く表示し、暗い場合は短く表示します。
 まず、棒グラフのX座標を入れる変数を用意します。ここではxとしています。まず、(x,0)-(x,128)に黒い線を描画します。これは継続して明るさを示す棒グラフを表示した場合、すでに表示されている線を消去するためです。特に黒でなく白でも構いません。
 次に明るさを示す棒グラフを描きます。明るさは0〜255までの範囲の整数値です。液晶画面の座標は0〜128までなので明るさを2で割ればちょうど液晶画面サイズにおさまります。ただし、棒グラフを下側から伸びたように表示するには128から明るさを2で割った値を引く必要があります。
 そして、ここで注意しないといけないことがあります。旧ブロックエディタでは整数演算しかできないため明るさを2で割った結果は整数値になります。しかし、新ブロックエディタでは小数値になります。このため、この計算した値をDraw LineブロックのY座標に設定すると動作しません。そこで新ブロックエディタを使用している場合は「小数点以下四捨五入」ブロックを使って整数にする必要があります。
 次にX座標を1増やします。横の座標は0〜160なのでX座標を160で割った余りを変数に入れます。この処理はなくても動作するのですが、安全のため入れてあります。

 実際のプログラムは以下のようになります。

 JavaScriptコードの場合、以下のようになります。

let x = 0
LCD1IN8.LCD_Init()
LCD1IN8.LCD_Clear()
x = 0
basic.forever(function () {
    LCD1IN8.DrawLine(
    x,
    0,
    x,
    128,
    LCD1IN8.Get_Color(LCD_COLOR.BLACK),
    DOT_PIXEL.DOT_PIXEL_1,
    LINE_STYLE.LINE_SOLID
    )
    LCD1IN8.DrawLine(
    x,
    Math.round(128 - input.lightLevel() / 2),
    x,
    128,
    LCD1IN8.Get_Color(LCD_COLOR.RED),
    DOT_PIXEL.DOT_PIXEL_1,
    LINE_STYLE.LINE_SOLID
    )
    LCD1IN8.LCD_Display()
    x += 1
    x = x % 160
})

明るさだけでなく、3軸のずれをグラフで表示してみるのもよいでしょう。低速ですが水準器のようなものも作成できます。

著者 古籏一浩
プログラミングをベースにして面白そうなものはとりあえずやってみるというスタンス。複雑なものよりシンプルで楽しめるものが好み。最近は30年前に移植したゲーム(mz-700版 SPACE HARRIER)の話などを書いたりしています。
著者サイト:http://www.openspc2.org/