「せっかくArduinoでガジェットを作ったのに、操作がボタン1個だけで味気ない…」そんな悩みを抱えていませんか?

実は、タッチパネル付きのTFT液晶(ILI9341)を使うと、スマホのような直感的なタッチUIをArduinoで実現できるんです。画面をタップしてメニューを操作したり、スライダーで値を変えたり——そんなリッチなガジェットが自作できますよ!

今回はILI9341搭載のタッチパネルTFT液晶をArduino UNOに接続して、タッチ対応のメニューUIをゼロから実装する方法を解説します。回路図・ライブラリ導入・スケッチまで一気にまとめましたので、ぜひ最後まで読んでみてください 😊

📦 必要なパーツ

Arduino TFT touchscreen
Arduino TFT touchscreen / Photo by Chengxin Zhao via Pexels

まず用意するものを確認しておきましょう。

  • Arduino UNO(またはUNO R4 MINIMA)
  • 2.4インチ TFT液晶モジュール(ILI9341 + XPT2046タッチコントローラー内蔵)
  • ジャンパーワイヤー(オス→メス 8本程度)
  • ブレッドボード(任意)

ILI9341モジュールはSPI接続タイプが主流です。タッチ機能はXPT2046というICが担当しており、同じSPIバスを共有して使います。Amazonや秋月電子で「2.4インチ TFT タッチ」と検索すると見つかります。

🔌 配線(回路図)

ILI9341はSPI接続です。Arduino UNOとの接続は以下のとおりです。

TFTモジュールのピン Arduino UNOのピン 用途
VCC 5V(または3.3V) 電源
GND GND グラウンド
CS(LCD CS) D10 液晶チップセレクト
RESET D9 リセット
DC / RS D8 データ/コマンド切替
MOSI / SDI D11 SPI データ送信
SCK / CLK D13 SPI クロック
LED / BL 3.3V または D3 バックライト
T_CS D4 タッチチップセレクト
T_IRQ D2 タッチ割り込み(任意)
MISO D12 SPI データ受信(タッチ用)

⚠️ 注意:モジュールによってピン名が微妙に異なる場合があります。データシートを必ず確認してください。SDO/MISO が別ピンに分かれているタイプもあります。

📚 ライブラリのインストール

Arduino IDEのライブラリマネージャーから以下の2つをインストールします。

  1. Adafruit ILI9341(液晶描画用)
  2. Adafruit GFX Library(グラフィックス基盤)
  3. XPT2046_Touchscreen(タッチ読み取り用/作者:Paul Stoffregen)

「ツール → ライブラリを管理」から各ライブラリ名で検索してインストールすればOKです。依存関係のライブラリも一緒にインストールするよう促されたら「全てインストール」を選びましょう。

🖥️ まずは画面に文字と図形を描いてみる

配線とライブラリが準備できたら、まず表示確認から始めましょう。以下のスケッチをArduinoに書き込んでみてください。

#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>

// ピン定義
#define TFT_CS   10
#define TFT_DC    8
#define TFT_RST   9

// TFTオブジェクトを作成
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

void setup() {
  tft.begin();               // TFT初期化
  tft.setRotation(1);        // 横向き表示(0〜3で回転変更可)
  tft.fillScreen(ILI9341_BLACK); // 画面を黒で塗りつぶす

  // 白色でテキスト表示
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);        // 文字サイズ(1〜6)
  tft.setCursor(20, 20);
  tft.println("Hello, TFT!");

  // 青い四角形を描画
  tft.fillRect(20, 60, 100, 40, ILI9341_BLUE);

  // 赤い円を描画
  tft.fillCircle(200, 80, 30, ILI9341_RED);
}

void loop() {
  // 今はここは空でOK
}

ポイントをまとめるとこんな感じです。

  • setRotation(1) で横向きに。0が縦、1が横(左向き)、3が横(右向き)
  • fillScreen() で背景色を一発塗り
  • fillRect(x, y, 幅, 高さ, 色) で塗りつぶした四角形
  • 色定数は ILI9341_RED / ILI9341_BLUE / ILI9341_WHITE などが使える

画面に文字と図形が表示されればOKです ✅ 表示されない場合は配線を見直しましょう。

👆 タッチ座標を読み取ってみる


次にタッチパネルから座標を読み取るスケッチを試してみましょう。

#include <XPT2046_Touchscreen.h>
#include <SPI.h>

#define TOUCH_CS  4
#define TOUCH_IRQ 2

// タッチスクリーンオブジェクト
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ);

void setup() {
  Serial.begin(9600);
  ts.begin();                // タッチ初期化
  ts.setRotation(1);         // 液晶の回転に合わせる
  Serial.println("Touch the screen!");
}

void loop() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();  // タッチ座標を取得
    // 生の座標をシリアルモニタに出力
    Serial.print("X=");
    Serial.print(p.x);
    Serial.print(" Y=");
    Serial.print(p.y);
    Serial.print(" Z=");
    Serial.println(p.z);         // Z(圧力)値
    delay(100);
  }
}

シリアルモニタを開いて(9600bps)、画面をタップしてみてください。X・Y・Zの値が流れてきたらタッチの取得成功です!

ひとつ注意点があります。XPT2046が返す座標は生の値(0〜4095程度)で、液晶の画素座標(320×240)とは異なります。次のセクションで変換方法も含めて実装します。

🎛️ タッチUI付きメニューを実装する

いよいよ本題です!画面に3つのボタンを表示して、タップした場所に応じて処理を切り替えるタッチメニューを実装しましょう。

#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>
#include <SPI.h>

// ピン定義
#define TFT_CS   10
#define TFT_DC    8
#define TFT_RST   9
#define TOUCH_CS  4
#define TOUCH_IRQ 2

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ);

// 画面サイズ(横向き)
#define SCREEN_W 320
#define SCREEN_H 240

// タッチ座標→液晶座標のマッピング(要キャリブレーション)
#define TOUCH_X_MIN  300
#define TOUCH_X_MAX  3800
#define TOUCH_Y_MIN  300
#define TOUCH_Y_MAX  3800

// ボタンの定義(x, y, 幅, 高さ)
struct Button {
  int x, y, w, h;
  const char* label;
  uint16_t color;
};

// 3つのメニューボタン
Button buttons[] = {
  {20,  60, 280, 40, "LED ON",    ILI9341_GREEN},
  {20, 110, 280, 40, "LED OFF",   ILI9341_RED},
  {20, 160, 280, 40, "INFO",      ILI9341_CYAN}
};
const int BTN_COUNT = 3;

// タッチ座標を液晶のピクセル座標に変換
int mapTouch(int val, int minVal, int maxVal, int screenSize) {
  return map(val, minVal, maxVal, 0, screenSize);
}

void drawMenu() {
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.setCursor(20, 20);
  tft.println("Select Menu:");

  for (int i = 0; i < BTN_COUNT; i++) {
    Button& b = buttons[i];
    tft.fillRoundRect(b.x, b.y, b.w, b.h, 8, b.color); // 角丸ボタン
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(2);
    tft.setCursor(b.x + 10, b.y + 12);
    tft.print(b.label);
  }
}

void handleButton(int idx) {
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.setCursor(10, 10);

  if (idx == 0) {
    tft.println("LED: ON");
    digitalWrite(LED_BUILTIN, HIGH); // D13のLEDを点灯
  } else if (idx == 1) {
    tft.println("LED: OFF");
    digitalWrite(LED_BUILTIN, LOW);  // D13のLEDを消灯
  } else if (idx == 2) {
    tft.println("Arduino TFT UI");
    tft.setCursor(10, 40);
    tft.println("ILI9341 + XPT2046");
    tft.setCursor(10, 70);
    tft.println("Touch Menu Demo");
  }

  // 2秒後にメニューに戻る
  delay(2000);
  drawMenu();
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  tft.begin();
  tft.setRotation(1);
  ts.begin();
  ts.setRotation(1);
  drawMenu(); // 最初にメニューを描画
}

void loop() {
  if (!ts.touched()) return;

  TS_Point p = ts.getPoint();

  // 生座標 → 液晶ピクセル座標に変換
  int px = mapTouch(p.x, TOUCH_X_MIN, TOUCH_X_MAX, SCREEN_W);
  int py = mapTouch(p.y, TOUCH_Y_MIN, TOUCH_Y_MAX, SCREEN_H);

  // どのボタンが押されたか判定
  for (int i = 0; i < BTN_COUNT; i++) {
    Button& b = buttons[i];
    if (px >= b.x && px <= b.x + b.w &&
        py >= b.y && py <= b.y + b.h) {
      handleButton(i);
      break;
    }
  }
  delay(150); // チャタリング防止
}

このスケッチのポイントはここです!

  • Button構造体でボタンの位置・サイズ・ラベル・色をまとめて管理
  • fillRoundRect() で角丸ボタンを描画(見た目がぐっと良くなります)
  • mapTouch() でXPT2046の生座標を画面座標に変換
  • タップした座標がどのボタン範囲内かを for ループで総当たり判定
  • 処理後2秒でメニューに自動復帰

🔧 タッチがズレる場合はキャリブレーションを


タッチした場所と反応する座標がズレる場合は、キャリブレーションが必要です。

先ほどのタッチ座標確認スケッチを使って、画面の「左上・右上・左下・右下」をタップしたときのX・Zの生座標を記録してください。その最小値・最大値を TOUCH_X_MIN / TOUCH_X_MAX / TOUCH_Y_MIN / TOUCH_Y_MAX に設定すればOKです。

また、液晶の setRotation() とタッチの setRotation()同じ値にすることも重要です。ここがズレているとX・Y軸が入れ替わったりします。

💡 応用アイデア

このタッチUIベースを作ってしまえば、あとは処理を差し替えるだけでいろんなガジェットに応用できます。

  • 🌡️ 温湿度モニター:DHT22の値をリアルタイム表示して、タップで単位切替(℃/℉)
  • 🔊 音量コントローラー:スライダーUIを実装してPWMで音量を制御
  • 💡 スマートライト:カラーパレットで色を選択してLEDの色を変える
  • ⏱️ タイマーガジェット:「+」「−」ボタンで分数を設定してカウントダウン

Button構造体の配列にメニュー項目を追加するだけで、どんどん画面を拡張できますよ 😊

まとめ

今回はArduinoとILI9341タッチパネルTFT液晶を使って、タッチUI付きメニューを実装する方法を解説しました。

ポイントをおさらいすると——

  • ILI9341(表示)+ XPT2046(タッチ)のSPI接続が基本構成
  • Adafruit ILI9341・GFX・XPT2046_Touchscreenの3ライブラリを使う
  • タッチ座標は生値なのでmapで変換+キャリブレーションが必要
  • Button構造体でボタンを管理すると追加・変更がラクになる

「スケッチ書いて基板に積むだけ」のシンプルさで、スマホのようなUIが作れるのがArduino電子工作の醍醐味ですよね。ぜひ手を動かして試してみてください!次はセンサーの値をリアルタイムでグラフ表示するUIにも挑戦してみましょう 🚀

📡 Arduinoをもっと深く学ぼう!

Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。

Arduinoロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。