Arduino Nanoで2.4インチ 240x320 TFTディスプレイのタッチパネルを使ってみる
はじめに
- これまでにArduino Nanoで2.4インチディスプレイを動かしてみた。
- 今回は、いよいよ残りのタッチパネル機能を使ってみる。
サンプルコード
- とりあえずメーカー提供のサンプルコードを実行してみる。
- スケッチ例 --> MCUFRIEND_kbv --> Touch_shield_new
実行結果
- とりあえずメーカー提供のサンプルコードを実行してみる。
- スケッチ例 --> MCUFRIEND_kbv --> Touch_shield_new
実行結果
- 普通に起動するとこんな感じで「キャリブレーションをしろ」というメッセージが表示される。
- 何をどうキャリプレーションしたらいいか分からないので、ひとまず適当に"EXIT"の部分にタッチすると、お絵描き画面モードに切り替わる。
- ただ、画面をタッチすると反応はするものの、見当違いの位置に描画されてしまう。
- 丸を描こうとしてもズレズレで丸にならない。
- なるほど、タッチ検出領域がどこからどこまでかってのを最初にキャリブレーションしろって事ね。
- ちなみにシリアルモニタにはこんなメッセージが出る。
- どうやら今の設定はもっと大きなサイズの液晶ディスプレイ用らしい。
Most Touch Screens use pins 6, 7, A1, A2
But they can be in ANY order
e.g. right to left or bottom to top
or wrong direction
Edit name and calibration statements
Please Calibrate.
ID=0x9797
Screen is 240x320
Calibration is:
LEFT = 907 RT = 136
TOP = 942 BOT = 139
Wiring is always PORTRAIT
YP=15 XM=16
YM=7 XP=6
キャリブレーション
という事で、ちゃんとキャリブレーションする。
- 再起動して、さっきのキャリブレーション画面の状態にする。
- この状態で画面を適当にぽちぽちタッチすると、タッチした位置の座標が逐次表示される。
- なるほど、これをメモっておくのね。
という事で、画面右上の隅をタッチ。
(ここでx, yの座標をメモ)
次は、左下の隅をタッチ。
(ここでもx, yの座標をメモしておく)
これで四隅の座標が取れたので、
サンプルコードの以下の部分をこんな感じに書き換えてリコンパイル。
//const int XP=6,XM=A2,YP=A1,YM=7; //ID=0x9341
//const int TS_LEFT=907,TS_RT=136,TS_TOP=942,TS_BOT=139;
/******************************************************
* MCUFRIEND 0x9797 configration
*******************************************************/
const int XP=6,XM=A2,YP=A1,YM=7; //240x320 ID=0x9797
const int TS_LEFT=182,TS_RT=893,TS_TOP=858,TS_BOT=210;
- なかなか画面の隅を狙ってタッチするのが難しいので、ギリギリまで攻めた数値ではない。
- 数字はだいたいこんな感じ、って制度なので時間があったらもっと精度よく決められるのかも。
キャリブレーション後のコード
- 最終的に完成したコードはこれ。
// the regular Adafruit "TouchScreen.h" library only works on AVRs
// different mcufriend shields have Touchscreen on different pins
// and rotation.
// Run the TouchScreen_Calibr_native sketch for calibration of your shield
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft; // hard-wired for UNO shields anyway.
#include <TouchScreen.h>
char *name = "Please Calibrate."; //edit name of shield
//const int XP=6,XM=A2,YP=A1,YM=7; //ID=0x9341
//const int TS_LEFT=907,TS_RT=136,TS_TOP=942,TS_BOT=139;
/******************************************************
* MCUFRIEND 0x9797 configration
*******************************************************/
const int XP=6,XM=A2,YP=A1,YM=7; //240x320 ID=0x9797
const int TS_LEFT=182,TS_RT=893,TS_TOP=858,TS_BOT=210;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
TSPoint tp;
#define MINPRESSURE 200
#define MAXPRESSURE 1000
int16_t BOXSIZE;
int16_t PENRADIUS = 1;
uint16_t ID, oldcolor, currentcolor;
uint8_t Orientation = 0; //PORTRAIT
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
void show_Serial(void)
{
Serial.println(F("Most Touch Screens use pins 6, 7, A1, A2"));
Serial.println(F("But they can be in ANY order"));
Serial.println(F("e.g. right to left or bottom to top"));
Serial.println(F("or wrong direction"));
Serial.println(F("Edit name and calibration statements\n"));
Serial.println(name);
Serial.print(F("ID=0x"));
Serial.println(ID, HEX);
Serial.println("Screen is " + String(tft.width()) + "x" + String(tft.height()));
Serial.println("Calibration is: ");
Serial.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT));
Serial.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT));
Serial.println("Wiring is always PORTRAIT");
Serial.println("YP=" + String(YP) + " XM=" + String(XM));
Serial.println("YM=" + String(YM) + " XP=" + String(XP));
}
void show_tft(void)
{
tft.setCursor(0, 0);
tft.setTextSize(1);
tft.print(F("ID=0x"));
tft.println(ID, HEX);
tft.println("Screen is " + String(tft.width()) + "x" + String(tft.height()));
tft.println("");
tft.setTextSize(2);
tft.println(name);
tft.setTextSize(1);
tft.println("PORTRAIT Values:");
tft.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT));
tft.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT));
tft.println("\nWiring is: ");
tft.println("YP=" + String(YP) + " XM=" + String(XM));
tft.println("YM=" + String(YM) + " XP=" + String(XP));
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor((tft.width() - 48) / 2, (tft.height() * 2) / 4);
tft.print("EXIT");
tft.setTextColor(YELLOW, BLACK);
tft.setCursor(0, (tft.height() * 6) / 8);
tft.print("Touch screen for loc");
while (1) {
tp = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) continue;
if (tp.x > 450 && tp.x < 570 && tp.y > 450 && tp.y < 570) break;
tft.setCursor(0, (tft.height() * 3) / 4);
tft.print("tp.x=" + String(tp.x) + " tp.y=" + String(tp.y) + " ");
}
}
void setup(void)
{
uint16_t tmp;
tft.reset();
ID = tft.readID();
tft.begin(ID);
Serial.begin(9600);
show_Serial();
tft.setRotation(Orientation);
tft.fillScreen(BLACK);
show_tft();
BOXSIZE = tft.width() / 6;
tft.fillScreen(BLACK);
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
currentcolor = RED;
delay(1000);
}
void loop()
{
uint16_t xpos, ypos; //screen coordinates
tp = ts.getPoint(); //tp.x, tp.y are ADC values
// if sharing pins, you'll need to fix the directions of the touchscreen pins
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) {
// most mcufriend have touch (with icons) that extends below the TFT
// screens without icons need to reserve a space for "erase"
// scale the ADC values from ts.getPoint() to screen values e.g. 0-239
//
// Calibration is true for PORTRAIT. tp.y is always long dimension
// map to your current pixel orientation
switch (Orientation) {
case 0:
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());
break;
case 1:
xpos = map(tp.y, TS_TOP, TS_BOT, 0, tft.width());
ypos = map(tp.x, TS_RT, TS_LEFT, 0, tft.height());
break;
case 2:
xpos = map(tp.x, TS_RT, TS_LEFT, 0, tft.width());
ypos = map(tp.y, TS_BOT, TS_TOP, 0, tft.height());
break;
case 3:
xpos = map(tp.y, TS_BOT, TS_TOP, 0, tft.width());
ypos = map(tp.y, TS_LEFT, TS_RT, 0, tft.height());
break;
}
// are we in top color box area ?
if (ypos < BOXSIZE) { //draw white border on selected color box
oldcolor = currentcolor;
if (xpos < BOXSIZE) {
currentcolor = RED;
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 2) {
currentcolor = YELLOW;
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 3) {
currentcolor = GREEN;
tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 4) {
currentcolor = CYAN;
tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 5) {
currentcolor = BLUE;
tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 6) {
currentcolor = MAGENTA;
tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, WHITE);
}
if (oldcolor != currentcolor) { //rub out the previous white border
if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
if (oldcolor == GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
if (oldcolor == CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
if (oldcolor == BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
}
}
// are we in drawing area ?
if (((ypos - PENRADIUS) > BOXSIZE) && ((ypos + PENRADIUS) < tft.height())) {
tft.fillCircle(xpos, ypos, PENRADIUS, currentcolor);
}
// are we in erase area ?
// Plain Touch panels use bottom 10 pixels e.g. > h - 10
// Touch panels with icon area e.g. > h - 0
if (ypos > tft.height() - 10) {
// press the bottom of the screen to erase
tft.fillRect(0, BOXSIZE, tft.width(), tft.height() - BOXSIZE, BLACK);
}
}
}
実行結果
// the regular Adafruit "TouchScreen.h" library only works on AVRs
// different mcufriend shields have Touchscreen on different pins
// and rotation.
// Run the TouchScreen_Calibr_native sketch for calibration of your shield
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft; // hard-wired for UNO shields anyway.
#include <TouchScreen.h>
char *name = "Please Calibrate."; //edit name of shield
//const int XP=6,XM=A2,YP=A1,YM=7; //ID=0x9341
//const int TS_LEFT=907,TS_RT=136,TS_TOP=942,TS_BOT=139;
/******************************************************
* MCUFRIEND 0x9797 configration
*******************************************************/
const int XP=6,XM=A2,YP=A1,YM=7; //240x320 ID=0x9797
const int TS_LEFT=182,TS_RT=893,TS_TOP=858,TS_BOT=210;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
TSPoint tp;
#define MINPRESSURE 200
#define MAXPRESSURE 1000
int16_t BOXSIZE;
int16_t PENRADIUS = 1;
uint16_t ID, oldcolor, currentcolor;
uint8_t Orientation = 0; //PORTRAIT
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
void show_Serial(void)
{
Serial.println(F("Most Touch Screens use pins 6, 7, A1, A2"));
Serial.println(F("But they can be in ANY order"));
Serial.println(F("e.g. right to left or bottom to top"));
Serial.println(F("or wrong direction"));
Serial.println(F("Edit name and calibration statements\n"));
Serial.println(name);
Serial.print(F("ID=0x"));
Serial.println(ID, HEX);
Serial.println("Screen is " + String(tft.width()) + "x" + String(tft.height()));
Serial.println("Calibration is: ");
Serial.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT));
Serial.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT));
Serial.println("Wiring is always PORTRAIT");
Serial.println("YP=" + String(YP) + " XM=" + String(XM));
Serial.println("YM=" + String(YM) + " XP=" + String(XP));
}
void show_tft(void)
{
tft.setCursor(0, 0);
tft.setTextSize(1);
tft.print(F("ID=0x"));
tft.println(ID, HEX);
tft.println("Screen is " + String(tft.width()) + "x" + String(tft.height()));
tft.println("");
tft.setTextSize(2);
tft.println(name);
tft.setTextSize(1);
tft.println("PORTRAIT Values:");
tft.println("LEFT = " + String(TS_LEFT) + " RT = " + String(TS_RT));
tft.println("TOP = " + String(TS_TOP) + " BOT = " + String(TS_BOT));
tft.println("\nWiring is: ");
tft.println("YP=" + String(YP) + " XM=" + String(XM));
tft.println("YM=" + String(YM) + " XP=" + String(XP));
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor((tft.width() - 48) / 2, (tft.height() * 2) / 4);
tft.print("EXIT");
tft.setTextColor(YELLOW, BLACK);
tft.setCursor(0, (tft.height() * 6) / 8);
tft.print("Touch screen for loc");
while (1) {
tp = ts.getPoint();
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) continue;
if (tp.x > 450 && tp.x < 570 && tp.y > 450 && tp.y < 570) break;
tft.setCursor(0, (tft.height() * 3) / 4);
tft.print("tp.x=" + String(tp.x) + " tp.y=" + String(tp.y) + " ");
}
}
void setup(void)
{
uint16_t tmp;
tft.reset();
ID = tft.readID();
tft.begin(ID);
Serial.begin(9600);
show_Serial();
tft.setRotation(Orientation);
tft.fillScreen(BLACK);
show_tft();
BOXSIZE = tft.width() / 6;
tft.fillScreen(BLACK);
tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
currentcolor = RED;
delay(1000);
}
void loop()
{
uint16_t xpos, ypos; //screen coordinates
tp = ts.getPoint(); //tp.x, tp.y are ADC values
// if sharing pins, you'll need to fix the directions of the touchscreen pins
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
// we have some minimum pressure we consider 'valid'
// pressure of 0 means no pressing!
if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) {
// most mcufriend have touch (with icons) that extends below the TFT
// screens without icons need to reserve a space for "erase"
// scale the ADC values from ts.getPoint() to screen values e.g. 0-239
//
// Calibration is true for PORTRAIT. tp.y is always long dimension
// map to your current pixel orientation
switch (Orientation) {
case 0:
xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());
break;
case 1:
xpos = map(tp.y, TS_TOP, TS_BOT, 0, tft.width());
ypos = map(tp.x, TS_RT, TS_LEFT, 0, tft.height());
break;
case 2:
xpos = map(tp.x, TS_RT, TS_LEFT, 0, tft.width());
ypos = map(tp.y, TS_BOT, TS_TOP, 0, tft.height());
break;
case 3:
xpos = map(tp.y, TS_BOT, TS_TOP, 0, tft.width());
ypos = map(tp.y, TS_LEFT, TS_RT, 0, tft.height());
break;
}
// are we in top color box area ?
if (ypos < BOXSIZE) { //draw white border on selected color box
oldcolor = currentcolor;
if (xpos < BOXSIZE) {
currentcolor = RED;
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 2) {
currentcolor = YELLOW;
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 3) {
currentcolor = GREEN;
tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 4) {
currentcolor = CYAN;
tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 5) {
currentcolor = BLUE;
tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, WHITE);
} else if (xpos < BOXSIZE * 6) {
currentcolor = MAGENTA;
tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, WHITE);
}
if (oldcolor != currentcolor) { //rub out the previous white border
if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
if (oldcolor == GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, GREEN);
if (oldcolor == CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, CYAN);
if (oldcolor == BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, BLUE);
if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, MAGENTA);
}
}
// are we in drawing area ?
if (((ypos - PENRADIUS) > BOXSIZE) && ((ypos + PENRADIUS) < tft.height())) {
tft.fillCircle(xpos, ypos, PENRADIUS, currentcolor);
}
// are we in erase area ?
// Plain Touch panels use bottom 10 pixels e.g. > h - 10
// Touch panels with icon area e.g. > h - 0
if (ypos > tft.height() - 10) {
// press the bottom of the screen to erase
tft.fillRect(0, BOXSIZE, tft.width(), tft.height() - BOXSIZE, BLACK);
}
}
}
- 正しくタッチ位置も検出できるようになり、文字が書けるようになった。
- 各色使い分けられるし、これでちょっとしたゲームも作れちゃいそう。
- ただ、文字を書くにはちょっと精度が悪いので、ボタンを表示してテキストを表示するとかが良さげ。
- センサから取得した測定値をいい感じで表示するもの良い。
- イケてるタッチUI付きのWebRadioでも作ってみようかな。
Author And Source
この問題について(Arduino Nanoで2.4インチ 240x320 TFTディスプレイのタッチパネルを使ってみる), 我々は、より多くの情報をここで見つけました https://qiita.com/Nabeshin/items/587257f447c5b8b3912b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .