次はSTM32ボードを積極的に使ていきたい(22) グラフィック液晶(3)
グラフィック液晶搭載タッチスクリーン利用の調査
前回の続きです。
利用することが出来ます。
裏側のICを調べると、XPT2046というタッチスクリーン・コントローラが搭載されていました。
幸いにして、Arduino STM32には標準でXPT2046用のライブラリが提供されています。
・Serasidis_XPT2046_touch - A simple XPT2046 Touch Screen library for STM32 micro-controllers
Adafruit_ILI9341_STMライブラリのサンプルスケッチ touchpaint.inoを修正して
簡単なお絵描きプログラムを作成してみました。
オリジナルのtouchpaint.inoはAdafruit製のグラフィック液晶モジュール用で
コントローラにSTMPE610を使っていることを前提としているので、そのままでは動きません。
コントローラー周りをXPT2046対応に修正しました。
XPT2046はSPIインタフェースで利用しますが、液晶パネルの制御にもSPIを利用してます。
そのため、2つあるSPIバスをそれぞれに割り当てました。
液晶パネルの表示にSPI1、XPT2046にSPI2を利用しました。
接続図

結線表
/*************************************************** This is our touchscreen painting example for the Adafruit ILI9341 Shield ----> http://www.adafruit.com/products/1651 Check out the links above for our tutorials and wiring diagrams These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional) Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution ****************************************************/ // 2018/06/25,たま吉さん, XPT2046コントローラー対応 #include <SPI.h> #include <Adafruit_GFX_AS.h> // Core graphics library #include <Adafruit_ILI9341_STM.h> #include <XPT2046_touch.h> // This is calibration data for the raw touch data to the screen coordinates #define TS_MINX 600 #define TS_MINY 440 #define TS_MAXX 3460 #define TS_MAXY 3460 // TFT制御用ピン #define TFT_CS PA0 #define TFT_RST PA1 #define TFT_DC PA2 // タッチパネルCSピン #define CS_PIN PA3 SPIClass SPI_2(2); Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); XPT2046_touch ts(CS_PIN, SPI_2); // Chip Select pin, SPI port // Size of the color selection boxes and the paintbrush size #define BOXSIZE 40 #define PENRADIUS 3 int oldcolor, currentcolor; void setup(void) { Serial.begin(115200); Serial.println(F("Touch Paint!")); // tft.begin(SPI_2); tft.begin(); tft.fillScreen(ILI9341_BLACK); ts.begin(); Serial.println("Touchscreen started"); // make the color selection boxes tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED); tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW); tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN); tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN); tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE); tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA); // select the current color 'red' tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); currentcolor = ILI9341_RED; } void loop() { // Retrieve a point TS_Point p = ts.getPoint(); if ( (p.z <=800) || (p.z > 3000)) return; int16_t tmp = p.x; p.x = p.y; p.y = tmp; Serial.print("Z = "); Serial.print(p.z); Serial.print(" X = "); Serial.print(p.x); Serial.print(" Y = "); Serial.print(p.y); // Scale from ~0 ~ TS_MAXX to tft.width using the calibration #'s p.x = tft.width() - map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); Serial.print("("); Serial.print(p.x); Serial.print(", "); Serial.print(p.y); Serial.println(")"); if (p.y < BOXSIZE) { oldcolor = currentcolor; if (p.x < BOXSIZE) { currentcolor = ILI9341_RED; tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 2) { currentcolor = ILI9341_YELLOW; tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 3) { currentcolor = ILI9341_GREEN; tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 4) { currentcolor = ILI9341_CYAN; tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 5) { currentcolor = ILI9341_BLUE; tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 6) { currentcolor = ILI9341_MAGENTA; tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } if (oldcolor != currentcolor) { if (oldcolor == ILI9341_RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED); if (oldcolor == ILI9341_YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW); if (oldcolor == ILI9341_GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN); if (oldcolor == ILI9341_CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN); if (oldcolor == ILI9341_BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE); if (oldcolor == ILI9341_MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA); } } if (((p.y - PENRADIUS) > BOXSIZE) && ((p.y + PENRADIUS) < tft.height())) { tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor); } }
スケッチを書き込んで実行すると、簡単なお絵描きが出来ます。
ただし、若干座標位置、描画可能範囲がずれいます。
下記の図は、実行中のシリアル出力です。
xの値がマイナスの値になっちゃっています。
#define TS_MINX 600 #define TS_MINY 440 #define TS_MAXX 3460 #define TS_MAXY 3460
タッチスクリーンでは、x、yの座標と圧力zを12ビットのアナログ値で測定しています。
12ビットなので0~4095の範囲のなります。
定義した上記の値は、描画領域の上下左右の境界部分の値です。
この値を実際の320x240ドットの範囲にスケール変換して座標を得ています。
測定した値が正しくないために、取得した座標にずれが生じてしまっているようです。
もう少し厳密に測定する必要がありそうです。
液晶パネル上に被膜抵抗(タッチスクリーン)が張り付いていて、その上を押すと
0~4095の値が 得られるわけですが、タッチスクリーンは液晶の描画範囲の外側も含んでいます。
個々のモジュールでは、タッチスクリーンを貼った具合(ずれ等)は微妙に異なります。
ですので、個々のモジュール毎に描画の上下限範囲の値を測定する
キャリブレーションが必要となります。
キャリブレーション設定支援のスケッチなんかも必要ですね。
« 次はSTM32ボードを積極的に使ていきたい(21) グラフィック液晶(2) | トップページ | 次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4) »
「arduino」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Zorin OSでArduino Uno互換機(CH340)が認識しない(2025.01.19)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- Arduino用 SKK日本語変換ライブラリの開発 その1(2024.12.28)
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
「表示器制御関連」カテゴリの記事
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
- Arduino用 美咲フォントライブラリを更新しました(2024.03.21)
- Raspberry Pi Pico(MicroPython)でLEDドットマトリックスを使ってみる(2024.03.14)
- Raspberry Pi Pico MicroPython用のマルチフォントライブラリ(2023.02.09)
- MicroPython(Raspberry Pi pico)で8x8ドットNeoPixcel文字表示(2023.02.08)
「ARM」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- PocketGoで遊んでみる(1)(2020.03.24)
- Arduino用 MML文演奏ライブラリの作成 その1(2019.04.01)
- BluePillボードで4桁7セグLEDの制御(2019.03.21)
「STM32」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- 「Arduino STM32 リファレンス 日本語版」が2万アクセス突破!(2021.03.26)
- SPI接続フラッシュメモリモジュールを入手しました(2020.05.13)
- Arduino STM32でキャラクタ液晶ディスプレイを使う(2019.06.01)
« 次はSTM32ボードを積極的に使ていきたい(21) グラフィック液晶(2) | トップページ | 次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4) »
コメント