「Raspberry Pi Pico」で「ILI9341」を使用した「液晶表示」と「タッチパネル」の使い方を、開発環境に「ArduinoIDE」を使って詳しく紹介します。
「ラズパイPico」の基本的な使用方法や「ArduinoIDE」を使用した開発環境の準備等は以下のリンクで詳しく紹介しています。
1.Raspberry Pi Picoとは
2.タッチパネル液晶表示器 ILI9341とは
3.配線図
・液晶表示のみの場合
・液晶表示+タッチパネルの場合
4.ライブラリの準備
5.簡単な「液晶表示」方法の確認
・動作紹介
・サンプルプログラム
・プログラムの詳細
6.お絵描きで「タッチパネル」の動作確認
・動作紹介
・サンプルプログラム
・プログラムの詳細
7.タッチパネル式操作表示器(GOT)
・動作紹介
・サンプルプログラム
8.まとめ
1.Raspberry Pi Picoとは
Raspberry Pi Pico(ラズパイ Pico)とは、イギリスのRaspberry Pi財団が開発したマイコンボードで、「Python」や「C言語」でプログラムすることができます。
本体基板上の入出力端子に、スイッチやセンサ、各種制御モジュール、通信モジュールを接続することで、それらをプログムによって制御することができ、プログラミング学習やホビー、組込み用途に最適です。
「ラズパイ Pico」の端子配列は以下のようになります。
(「Pico2」やWi-Fi通信機能搭載の「Pico W」もLED以外の基本的な端子配列は同じです。)
「ラズパイ Pico」の使い方や端子機能、開発環境の準備については、以下のリンク先で詳しく紹介しています。
2.タッチパネル液晶表示器 ILI9341とは
「ILI9341」とは、タッチパネル搭載のTFT液晶表示器で、今回使用するのは2.8インチ(320x240Pixel)のものです
外観は下画像のようになります。
今回購入したものの梱包状態は上画像になります。
タッチパネル機能のない(制御ICが実装されていない)ものもあるようなので、注意して購入しましょう。
タッチペンが付属していましたが、全てに付属はしてないかもしれません。なくてもいいと思いましたが、動作確認するとスマホのような精度はないので、タッチペンは必須と思いました。
ピンヘッダーは実装済みのものでした。
SDカードリーダーも実装されていますが、こちらの端子は未実装でした。
裏面にタッチパネルの制御ICが実装されています。
実装されてないものもあるようなので注意して購入しましょう。
今回実装されていた制御ICは「XPT2046」でした。
SDカードリーダーの使い方は、以下で詳しく紹介しています。
今回購入したものは以下のアマゾンのものです。
3.配線図
配線図について、液晶表示のみの場合と、液晶表示とタッチパネルを使う場合とで紹介します。
・液晶表示のみの場合
液晶表示だけを使用する場合の配線図は以下のようになります。
実際に配線した様子は下画像のようになります。
ブレッドボードを横に2枚連結して、ジャンパー線で接続しています。
配線部を拡大すると下画像のようになります。
・液晶表示+タッチパネルの場合
液晶表示とタッチパネルを使用する場合の配線図は以下のようになります。
液晶表示のみの場合の配線に、タッチパネルの配線4本を追加しています。
実際に配線した様子は下画像のようになります。
ブレッドボードを横に2枚連結して、ジャンパー線で接続しています。
配線部を拡大すると下画像のようになります。
ジャンパーリード配線でもできますが・・・
最初はジャンパーリード配線を使用して下画像のように動作確認していましたが、タッチパネル操作時にリード線に触れたり配線が揺れたりすると、接触不良で画面がチラついたり、暗くなったり、表示が真っ白になったりしたので、あまりおすすめできません。
半田付けするのが一番良いですが、動作確認には以下のようなブレッドボードやジャンパー線を使用して、確実に配線することをおすすめします。
4.ライブラリの準備
開発環境「ArduinoIDE」で使用するライブラリは以下になります。
事前にインストールしておいてください。
ライブラリ名 | 用途 | バージョン | 検索名 |
---|---|---|---|
Adafruit GFX Library | 文字フォントの指定や画面の チラツキ防止の「スプライト」用 | 1.11.1 | GFX |
Adafruit BusIO | Adafruit GFXライブラリを使用するために必要 | 1.16.2 | busio |
Adafruit ILI9341 | 液晶表示器ILI9341の制御用 | 1.6.1 | 9341 |
XPT2046_Touchscreen | タッチパネル制御用 | 1.4 | xpt paul |
ライブラリはプログラムの初めにヘッダーとして以下のように書いて呼び出して使用します。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ILI9341.h> // 液晶表示器 ILI9341 制御用ライブラリ
#include <XPT2046_Touchscreen.h> // タッチパネル制御用ライブラリ
「ArduinoIDE」のライブラリのインストール方法は以下のリンクで詳しく紹介しています。
5.簡単な「液晶表示」方法の確認
まずは基本的な液晶画面の表示方法を確認していきます。
・動作紹介
サンプルプログラムでは下画像のように、単純な文字表示と、変化する数値の確認を行なっています。
画面中央にはフォントを指定した文字を表示し、左上には電源ONからの経過時間をms単位で表示しています。
・サンプルプログラム
サンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ILI9341.h> // 液晶表示器 ILI9341 制御用ライブラリ
#include <Fonts/FreeSans18pt7b.h> // フォントを読み込み
#include <Fonts/FreeSans12pt7b.h>
#define TFT_WIDTH 320 // 画面幅
#define TFT_HEIGHT 240 // 画面高さ
#define TFT_SCK 18 // 液晶表示の SCK
#define TFT_MOSI 19 // 液晶表示の MOSI
#define TFT_DC 20 // 液晶画面の DC
#define TFT_RST 21 // 液晶画面の RST
#define TFT_CS 22 // 液晶画面の CS
// ILI9341ディスプレイのインスタンスを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST);
// スプライト(メモリ描画領域から一括表示)をcanvasとして準備
// 画面表示をtftではなくcanvasで指定して一括描画することでチラツキなく表示できる
GFXcanvas16 canvas(TFT_WIDTH, TFT_HEIGHT); // 16bitカラースプライト(オフスクリーンバッファ)
// 初期設定 ----------------------------------------
void setup() {
// SPI0初期設定
SPI.setTX(TFT_MOSI); // SPI0のTX(MOSI)
SPI.setSCK(TFT_SCK); // SPI0のSCK
// TFT初期設定
tft.begin(); // TFTを初期化
tft.setRotation(3); // TFTの回転を設定(0-3)
canvas.setTextSize(1); // テキストサイズを設定
}
// メイン -----------------------------------------
void loop() {
canvas.fillScreen(0x0000); // 背景色
// 文字表示
canvas.setCursor(48, 125); // 表示座標指定
canvas.setTextColor(0xFFFF); // テキスト色(文字色、背景色)※背景色は省略可
canvas.setFont(&FreeSans18pt7b); // フォント指定
canvas.println("Logikara Blog"); // 表示内容
// 電源ONからの経過時間カウント表示
canvas.setFont(&FreeSans12pt7b); // フォント指定
canvas.setCursor(0, 22); // 表示座標指定
canvas.print(millis()); // 経過時間をms単位で表示
// スプライト(メモリ内に描画した画面)をTFTに描画
tft.drawRGBBitmap(0, 0, canvas.getBuffer(), TFT_WIDTH, TFT_HEIGHT);
}
・プログラムの詳細
液晶表示器の初期設定
サンプルプログラムの「16行目」で以下のように、SPI通信の一部の端子を指定して、インスタンスを作成します。これによって「tft.〜」で指定して液晶表示の制御ができるようになります。
// ILI9341ディスプレイのインスタンスを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST);
初期設定の「25,6行目」で以下のように、SPI通信(SPI0)の標準の通信端子を指定します。
液晶表示器では「MOSI(データ送信)」と「SCK(クロック)」のみ使用し「MISO(データ受信)」はタッチパネルを使う場合に設定します。
// SPI0初期設定
SPI.setTX(TFT_MOSI); // SPI0のTX(MOSI)
SPI.setSCK(TFT_SCK); // SPI0のSCK
画面のチラツキ防止の「スプライト」
「20行目」で画面の「チラツキ」を防止するために、メモリ描画領域を一括表示する「スプライト」のインスタンスを、画面サイズを指定して作成しています。
// スプライト(メモリ描画領域から一括表示)をcanvasとして準備
// 画面表示をtftではなくcanvasで指定して一括描画することでチラツキなく表示できる
GFXcanvas16 canvas(TFT_WIDTH, TFT_HEIGHT); // 16bitカラースプライト(オフスクリーンバッファ)
「29〜31行目」で液晶画面の初期設定を行っています。
画面の初期化と画面表示方向の回転のみ「tft.〜」で指定していますが、以降の表示設定は「canvas.〜」で指定します。これによって、表示内容を一旦メモリ内の描画領域に描画します。
// TFT初期設定
tft.begin(); // TFTを初期化
tft.setRotation(3); // TFTの回転を設定(0-3)
canvas.setTextSize(1); // テキストサイズを設定
「50行目」でメモリ内の描画領域に描画した画面の内容を一括表示して、画面の「チラツキ」を抑える「スプライト」を行なっています。
// スプライト(メモリ内に描画した画面)をTFTに描画
tft.drawRGBBitmap(0, 0, canvas.getBuffer(), TFT_WIDTH, TFT_HEIGHT);
文字フォントの指定
文字フォントは使用しなくても表示はできますが、「ドット文字」のようになって見にくいので、フォントを指定することをおすすめします。
「3,4行目」で以下のように、ヘッダーファイルとしてフォント名を指定して読み込みます。
#include <Fonts/FreeSans18pt7b.h> // フォントを読み込み
#include <Fonts/FreeSans12pt7b.h>
「41,45行目」で以下のように「setFont(&フォント名)」で読み込んだフォント名を指定してフォントを設定します。
canvas.setFont(&FreeSans18pt7b); // フォント指定
canvas.setFont(&FreeSans12pt7b); // フォント指定
フォントは下画像のように「Adafruit_GFX_Library」内の「Fonts」フォルダ内にたくさんあります。
ファイル名がフォント名になるので、いろいろ読み込んで試してみてください。
6.お絵描きで「タッチパネル」の動作確認
タッチパネルの動作確認として、タッチ座標を取得して線を描く、お絵描きパネルで動作確認してみましょう。
・動作紹介
「サンプルプログラム」を書き込んで実行すると、下画像のように画面は真っ白な表示になります。
画面上をタッチペンでなぞると、線が描かれて文字や図形を描くことができます。
以下は当サイトのブログ名を書いてみたものです。
線はタッチ座標に円を連続して描画することで実現しています。
字が汚いのは置いといて・・・画面をなぞった通りにお絵描きができます。
線の太さは描画する円の半径を変えることで調節できます。
・サンプルプログラム
サンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ILI9341.h> // 液晶表示器 ILI9341 制御用ライブラリ
#include <XPT2046_Touchscreen.h> // タッチパネル制御用ライブラリ
#define TFT_WIDTH 320 // 画面幅
#define TFT_HEIGHT 240 // 画面高さ
#define TFT_ROTATION 3 // 画面の回転(タッチパネルの回転と合わせる)
#define COMMON_SCK 18 // 液晶表示とタッチパネル共通の SCK
#define COMMON_MOSI 19 // 液晶表示とタッチパネル共通の MOSI
#define TOUCH_MISO 16 // タッチパネルの MISO
#define TOUCH_CS 17 // タッチパネルの CS
#define TFT_DC 20 // 液晶画面の DC
#define TFT_RST 21 // 液晶画面の RST
#define TFT_CS 22 // 液晶画面の CS
XPT2046_Touchscreen ts(TOUCH_CS); // タッチパネルのインスタンスを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST); // ILI9341ディスプレイのインスタンスを作成
// 初期設定 ----------------------------------------
void setup() {
//SPI0設定
SPI.setTX(COMMON_MOSI); // SPI0のTX(MOSI)
SPI.setRX(TOUCH_MISO); // SPI0のRX(MISO)
SPI.setSCK(COMMON_SCK); // SPI0のSCK
//液晶画面初期設定
tft.begin(); // TFTを初期化
tft.setRotation(TFT_ROTATION); // TFTの回転を設定(0-3)
//タッチパネル初期設定
ts.begin(); // タッチパネル初期化
ts.setRotation(TFT_ROTATION); // タッチパネルの回転を設定(液晶画面と合わせる)
tft.fillScreen(ILI9341_WHITE); // 画面白色塗りつぶし
tft.fillRect(300, 1, 19, 18, ILI9341_DARKGREY); // 画面消去ボタン
// 出力端子初期設定
pinMode(LED_BUILTIN, OUTPUT); // LED用端子
digitalWrite(LED_BUILTIN, HIGH); // LED点灯(電源ランプ)
}
// メイン ------------------------------------------
void loop() {
if (ts.touched() == true) { // タッチされていれば
TS_Point tPoint = ts.getPoint(); // タッチ座標を取得
int16_t x = (tPoint.x-400) * TFT_WIDTH / (4095-550); // タッチx座標をTFT画面の座標に換算
int16_t y = (tPoint.y-230) * TFT_HEIGHT / (4095-420); // タッチy座標をTFT画面の座標に換算
// 円の連続で線を描画
tft.fillCircle(x, y, 2, 0x0A08); // タッチ座標に塗り潰し円を描画
// 描画エリア消去
if (x > 300 && y < 20) { // 画面右上角座標をタッチしたら
tft.fillScreen(ILI9341_WHITE); // 画面白色塗りつぶし
tft.fillRect(300, 1, 19, 18, ILI9341_DARKGREY); // 消去ボタン
}
}
}
・プログラムの詳細
初期設定
サンプルプログラムの「17,18行目」で以下のように、タッチパネルと液晶表示のインスタンスを作成します。これにより、タッチパネルは「ts.〜」、液晶表示は「tft.〜」でそれぞれの各種動作指定ができるようになります。
XPT2046_Touchscreen ts(TOUCH_CS); // タッチパネルのインスタンスを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST); // ILI9341ディスプレイのインスタンスを作成
「23〜25行目」の初期設定でSPI通信(SPI0)標準の通信端子を設定します。
「MOSI(データ送信)」と「SCK(クロック)」は共通で「MISO(データ受信)」はタッチパネルのみ使用します。
SPI.setTX(COMMON_MOSI); // SPI0のTX(MOSI)
SPI.setRX(TOUCH_MISO); // SPI0のRX(MISO)
SPI.setSCK(COMMON_SCK); // SPI0のSCK
初期設定の「29,33行目」で以下のように、液晶画面とタッチパネルの回転を設定しますが両方の回転方向は合わせる必要があります。
また、回転方向によって、表示とタッチ座標にズレが生じますので、回転方向ごとに補正する必要があります。
tft.setRotation(TFT_ROTATION); // TFTの回転を設定(0-3)
ts.setRotation(TFT_ROTATION); // タッチパネルの回転を設定(液晶画面と合わせる)
タッチ座標の取得、補正
「43,44行目」で以下のように、「ts.touched()」でタッチされているかどうかを確認し、タッチされていれば「ts.getPoint()」でタッチ座標(x,y)を取得します。
取得した座標は「tPoint.x」でx座標、「tPoint.y」でy座標を確認することができます。
if (ts.touched() == true) { // タッチされていれば
TS_Point tPoint = ts.getPoint(); // タッチ座標を取得
「45,46行目」で以下のように、液晶画面とタッチ座標の補正を行なっています。
補正値は個体によって異なると思うので、以下を参考に調整してください。
int16_t x = (tPoint.x-400) * TFT_WIDTH / (4095-550); // タッチx座標をTFT画面の座標に換算
int16_t y = (tPoint.y-230) * TFT_HEIGHT / (4095-420); // タッチy座標をTFT画面の座標に換算
画面の回転が「Rotation(1)」の場合は座標が増えるごとにズレ量も増えるという変化をしました。
この場合は補正が少々複雑になるため、以下参考までに載せておきます。
int16_t x = (tPoint.x –100) * TFT_WIDTH / (4095 – (tPoint.x /6));
int16_t y = (tPoint.y –100) * TFT_HEIGHT / (4095 – (tPoint.y /10));
塗りつぶし円の連続で線を描画
「49行目」で以下のように、取得したタッチ座標に塗りつぶし円を連続的に描画することで線を描いています。円の半径で線の太さが調節でき、色を変えると線の色を変更できます。
// 円の連続で線を描画
tft.fillCircle(x, y, 2, 0x0A08); // タッチ座標に塗り潰し円を描画
tft.fillCircle(x座標, y座標, 半径, 色);
タッチエリアの検出、画面消去
「52〜54行目」で以下のように、取得したタッチ座標の範囲を確認することで、タッチした位置によって動作を分岐させることができます。
サンプルプログラムでは画面の右上角部をタッチすることで画面を白色に塗りつぶして、描画した線を消去しています。
// 描画エリア消去
if (x > 300 && y < 20) { // 画面右上角座標をタッチしたら
tft.fillScreen(ILI9341_WHITE); // 画面白色塗りつぶし
tft.fillRect(300, 1, 19, 18, ILI9341_DARKGREY); // 消去ボタン
7.タッチパネル式操作表示器(GOT)
最後にタッチパネルを使用した操作表示器としての使い方を紹介します。
産業用途では「GOT(グラフィックオペレーションターミナル)」と呼ばれ「シーケンサ」と組み合わせて使用され、数万から十万以上するものもありますが、自作すれば数千円で製作でき、用途によっては機能的には十分だと思います。
・動作紹介
基本的な「GOT」の機能としては、「タッチボタン」と「データ表示」と思います。あとはスライドボリュームがあるといろいろな調整に使えると思うので、下画像のようなサンプル画面を作製しました。
動作確認のため、タッチ座標はタッチした時に常に表示されるようにしています。
上画像のように「ONボタン」にタッチすると左の「丸ランプ」が点灯します。
この時ラズパイPico本体のLEDを点灯させるようにしています。
「OFFボタン」にタッチすると「丸ランプ」は消灯し、ラズパイPico本体のLEDも消灯します。
上画像のようにスライドボリューム部にタッチすると、ツマミ部を移動させることができます。
上下に移動させることで画面上の数値が「0〜100」の範囲で変化して、LEDの明るさを調整できます。
写真では分かりにくいですがボリュームを下げて数値が小さくなるとLEDが暗くなり、「0」で消灯します。
・サンプルプログラム
サンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ILI9341.h> // 液晶表示器 ILI9341 制御用ライブラリ
#include <XPT2046_Touchscreen.h> // タッチパネル制御用ライブラリ
#include <Fonts/FreeSerifBold9pt7b.h> // フォントを読み込み
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>
#include <Fonts/FreeSansBold18pt7b.h>
#define TFT_WIDTH 320 // 画面幅
#define TFT_HEIGHT 240 // 画面高さ
#define TFT_ROTATION 3 // 画面の回転(タッチパネルの回転と合わせる)
#define COMMON_SCK 18 // 液晶表示とタッチパネル共通の SCK
#define COMMON_MOSI 19 // 液晶表示とタッチパネル共通の MOSI
#define TOUCH_MISO 16 // タッチパネルの MISO
#define TOUCH_CS 17 // タッチパネルの CS
#define TFT_DC 20 // 液晶画面の DC
#define TFT_RST 21 // 液晶画面の RST
#define TFT_CS 22 // 液晶画面の CS
XPT2046_Touchscreen ts(TOUCH_CS); // タッチパネルのインスタンスを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST); // ILI9341ディスプレイのインスタンスを作成
// スプライト(メモリ描画領域から一括表示)をcanvasとして準備
// 画面表示をtftではなくcanvasで指定して一括描画することでチラツキなく表示できる
GFXcanvas16 canvas(TFT_WIDTH, TFT_HEIGHT); // 16bitカラースプライト(オフスクリーンバッファ)
// 変数宣言
bool lampSignal = false; // ランプ点灯状態格納用
int16_t slideYValue = 55; // スライドボリュームY軸座標格納用
float volumeValue = 100; // スライドボリュームレベル換算値格納用
/******************** テキスト描画関数 ********************/
void drawText(int16_t x, int16_t y, const char* text, const GFXfont* font, uint16_t color) {
canvas.setFont(font); // フォント
canvas.setTextColor(color); // 文字色
canvas.setCursor(x, y); // 表示座標
canvas.println(text); // 表示内容
}
/******************** ボタン描画関数 ********************/
void drawButton(int x, int y, const char* label, const GFXfont* font, uint16_t bgColor, uint16_t labelColor) {
canvas.fillRect(x, y, 80, 80, ILI9341_DARKGREY); // 外枠
canvas.fillRect(x + 3, y + 3, 74, 74, ILI9341_WHITE); // 境界線
canvas.fillRect(x + 6, y + 6, 68, 68, bgColor); // 操作部
canvas.setFont(font); // 表示ラベル
// テキストの幅と高さを取得
int16_t textX, textY; // テキスト位置取得用
uint16_t textWidth, textHeight; // テキストサイズ取得用
canvas.getTextBounds(label, x, y, &textX, &textY, &textWidth, &textHeight);
// 中央揃えのための新しいx, y座標の計算
int16_t centeredX = x + (80 - textWidth) / 2; // xを中央へ
int16_t centeredY = y + (80 - textHeight) / 2 + textHeight; // yを下げて中央へ
canvas.setTextColor(labelColor); // 文字色
canvas.setCursor(centeredX, centeredY); // 新しいカーソル位置を設定
canvas.print(label); // テキストを描画
}
/***************** ランプ点灯状態更新関数 *****************/
void updateLamp() {
if (lampSignal == true) { // ランプ状態点灯なら
canvas.fillCircle(40, 190, 33, ILI9341_CYAN); // ランプ部点灯
analogWrite(LED_BUILTIN, (int)(volumeValue * 10.24)); // PWM出力開始
} else { // ランプ状態消灯なら
canvas.fillCircle(40, 190, 33, ILI9341_DARKGREY); // ランプ部消灯
analogWrite(LED_BUILTIN, 0); // PWM出力停止
}
}
// 初期設定 ----------------------------------------
void setup() {
Serial.begin(115200); // シリアル通信初期化
//SPI0設定
SPI.setTX(COMMON_MOSI); // SPI0のTX(MOSI)
SPI.setRX(TOUCH_MISO); // SPI0のRX(MISO)
SPI.setSCK(COMMON_SCK); // SPI0のSCK
//液晶表示初期設定
tft.begin(); // TFTを初期化
tft.setRotation(TFT_ROTATION); // TFTの回転を設定(0-3)
canvas.setTextSize(1); // テキストサイズ(倍率)
canvas.fillScreen(ILI9341_BLACK); // 背景色
//タッチパネル初期設定
ts.begin(); // タッチパネル初期化
ts.setRotation(TFT_ROTATION); // タッチパネルの回転を設定(液晶画面と合わせる)
// PWM初期設定
pinMode(LED_BUILTIN, OUTPUT); // LED用端子を出力設定
analogWriteFreq(1000); // PWM周波数
analogWriteRange(1024); // 分解能(10bit)
}
// メイン -----------------------------------------
void loop() {
canvas.fillScreen(ILI9341_BLACK); // 画面クリア
//タッチパネル処理
canvas.setTextColor(ILI9341_WHITE); // 文字色
canvas.setCursor(0, 26); // 座標設定
canvas.setFont(&FreeSans18pt7b); // フォント
if (ts.touched() == true) { // タッチされていれば
TS_Point tPoint = ts.getPoint(); // タッチ座標を取得
// タッチx座標をTFT画面の座標に換算
int16_t x = (tPoint.x-400) * TFT_WIDTH / (4095-550); // タッチx座標をTFT画面の座標に換算
int16_t y = (tPoint.y-230) * TFT_HEIGHT / (4095-420); // タッチy座標をTFT画面の座標に換算
// ボタンタッチエリア検出
if (x >= 91 && x <= 159 && y >= 156 && y <= 224) lampSignal = true; // 範囲内ならランプ状態を点灯へ
if (x >= 176 && x <= 244 && y >= 156 && y <= 224) lampSignal = false; // 範囲内ならランプ状態を消灯へ
// スライドボリューム 調整エリア検出
if (x >= 270 && x <= 315 && y >= 62 && y <= 216) { // 指定座標範囲内なら
slideYValue = y - 10; // ボリュームつまみ表示位置Y軸座標補正
volumeValue = 100.0 - ((float)slideYValue - 55.0) * 0.68; // ボリュームレベルの変化を0〜100の値に換算
volumeValue = (volumeValue > 100) ? 100 : (volumeValue < 0) ? 0 : volumeValue; // 100以上は100に、0以下は0でクランプ
}
canvas.printf("x=%d y=%d", x, y); // 座標表示
// Serial.printf("x=%d, y=%d\n", x, y); // シリアル出力確認用
} else { //タッチされていなければ座標表示なし
canvas.print("x= - y= -"); // 文字表示
}
// スライドボリュームレベル換算値表示
canvas.setCursor(262, 30); // 座標設定
canvas.printf("%.0f", volumeValue); // 値表示
// 線描画
canvas.drawFastHLine(0, 38, 260, ILI9341_WHITE); // 線(指定座標から平行線)
canvas.drawFastHLine(0, 39, 260, ILI9341_WHITE); // 線(指定座標から平行線)
canvas.drawFastVLine(120, 44, 43, ILI9341_PINK); // 線(指定座標から垂線)
canvas.drawFastVLine(121, 44, 43, ILI9341_PINK); // 線(指定座標から垂線)
canvas.drawFastHLine(0, 90, 260, ILI9341_WHITE); // 線(指定座標から平行線)
canvas.drawFastHLine(0, 91, 260, ILI9341_WHITE); // 線(指定座標から平行線)
canvas.drawFastHLine(0, 135, 260, ILI9341_WHITE); // 線(指定座標から平行線)
canvas.drawFastHLine(0, 136, 260, ILI9341_WHITE); // 線(指定座標から平行線)
// 文字描画(x, y, 内容, フォント, 文字色)
drawText(8, 60, "LCD Display", &FreeSerifBold9pt7b, ILI9341_GREEN); // 文字表示関数呼び出し
drawText(5, 80, "Touch Screen", &FreeSerifBold9pt7b, ILI9341_GREEN);
drawText(135, 77, "ILI9341", &FreeSans18pt7b, ILI9341_CYAN);
drawText(15, 125, "LogikaraBlog", &FreeSansBold18pt7b, ILI9341_ORANGE);
// ランプ描画(x, y, 半径, 色)
canvas.fillCircle(40, 190, 40, ILI9341_DARKGREY); // 外枠
canvas.fillCircle(40, 190, 36, ILI9341_WHITE); // 境界線
updateLamp(); // ボタン点灯状態更新関数呼び出し
// ボタン描画(x, y, ラベル, フォント, ボタン色, ラベル色)
drawButton(85, 150, "ON", &FreeSansBold12pt7b, ILI9341_GREEN, ILI9341_WHITE); // ONボタン
drawButton(170, 150, "OFF", &FreeSansBold12pt7b, ILI9341_RED, ILI9341_WHITE); // OFFボタン
// スライドボリューム描画
canvas.fillRect(265, 38, 55, 200, ILI9341_DARKGREY); // スライドエリア
canvas.fillRect(287, 48, 11, 182, ILI9341_WHITE); // 縦ライン枠
canvas.fillRect(290, 52, 5, 175, ILI9341_BLACK); // 縦ライン
canvas.fillRect(270, slideYValue, 45, 20, 0x0904); // ボリュームつまみ
canvas.fillRect(278, slideYValue + 8, 29, 3, ILI9341_RED); // ボリュームつまみライン
// スプライト(メモリ内に描画した画面)をTFTに描画
tft.drawRGBBitmap(0, 0, canvas.getBuffer(), TFT_WIDTH, TFT_HEIGHT);
}
8.まとめ
「Raspberry Pi Pico」で「ILI9341」を使用した「液晶表示」と「タッチパネル」の使い方を詳しく紹介しました。
開発環境に「ArduinoIDE」を使用し、液晶表示器やタッチパネル制御用の「ライブラリ」を使用することで、比較的簡単に画面表示やタッチパネルの動作確認を行うことができます。
今回は基本的な文字表示やフォント設定の確認から、画面表示のチラツキを防止する「スプライト」の方法を確認し、画面に線を描いて「お絵描き」しながら、タッチパネルの座標取得方法や、線の描画方法をサンプルプログラムで詳しく紹介しました。
最後に応用編として「タッチボタン」や「スライドボリューム」を画面上に配置してLEDを操作する「GOT(グラフィックオペレーションターミナル)」としての使い方まで紹介しました。
個人的には数千円で「GOT」としての機能が実現できるのがわかったことはかなりの収穫です^^
仕事で高価なGOTの導入に迷ったときはコレで十分ですね♪
タッチパネル液晶表示器の用途は幅広く、「PicoW」でネットワークと組み合わせればさらに色々な応用ができます。今年2025年は「生成AI」が猛威を振るう年になりそうなので、APIを使用して、画像から文字認識させて〜等、考え出すと面白くなりそうです。
いいものができたらまた紹介したいと思いますので、今年もどうぞよろしくお願いいたします。
コメント