フォト
2025年4月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
無料ブログはココログ

« 次はSTM32ボードを積極的に使ていきたい(21) グラフィック液晶(2) | トップページ | 次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4) »

2018年6月25日 (月)

次はSTM32ボードを積極的に使ていきたい(22) グラフィック液晶(3)

グラフィック液晶搭載タッチスクリーン利用の調査

前回の続きです。

グラフィック液晶モジュールのタッチスクリーンの利用を調査しました。

Dscn8344

私が所有しているグラフィック液晶モジュールには、タッチスクリーンを
利用することが出来ます。

裏側のICを調べると、XPT2046というタッチスクリーン・コントローラが搭載されていました。

03

このコントローラーはTI社のTSC2046と同等のようで、探すと日本語のデータシートがあります。

幸いにして、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を利用しました。

接続図
01

結線表

02

スケッチ
/***************************************************
  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、yです。
xの値がマイナスの値になっちゃっています。

04

プログラム内の下記の箇所で、描画範囲部分のスクリーン位置を実測値にて設定しています。
#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」カテゴリの記事

表示器制御関連」カテゴリの記事

ARM」カテゴリの記事

STM32」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

« 次はSTM32ボードを積極的に使ていきたい(21) グラフィック液晶(2) | トップページ | 次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4) »