●Arduino用ディスプレイ タッチスクリーンを使ってみる

Kuman Arduino用ディスプレイ タッチスクリーン 2.8 inch K60 というディスプレイを手に入れたので使ってみたいと思います。

Kuman Arduino用ディスプレイ タッチスクリーン 2.8 inch 320*240ピクセル LCD 16bit Arduino Nano Mega2560適用ディスプレイ K60

■表示するためのライブラリをインストールする

標準ライブラリで操作するには、ツールのライブラリを管理でライブラリマネージャを開きます。
adafruitで検索して、Adafruit GFX Library と Adafruit TFTLCD Library と Adafruit TouchScreen の3つのライブラリをインストールします。






以上で完了ですが、他の方法としては、購入後に教えてもらえるリンク先から圧縮ファイルをダウンロードして、
Arduino Demo_UNO&Mega2560 の中の Install libraries 内にある、 Adafruit_GFX と Adafruit_TFTLCD と TouchScreen の
3つのフォルダをパソコンの PC > ドキュメント > Arduino > libraries フォルダ内にコピーすることでもライブラリがインストールできます。


■文字を表示する

#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>

#define BLACK   0B0000000000000000
#define RED     0B1111100000000000
#define GREEN   0B0000011111100000
#define BLUE    0B0000000000011111
#define WHITE   0B1111111111111111

Adafruit_TFTLCD tft(A3,A2,A1,A0,A4);

void setup(void) {
  tft.reset();
  tft.begin(0x9341);//LCD制御用ICを指定
  tft.fillScreen(WHITE);
}

void loop(void) {
  tft.setCursor(10, 10);
  tft.setTextColor(BLACK);
  tft.setTextSize(4);
  tft.println("ABCDEFG");

  while (1);
}

実行すると次のように表示されるはずです。

まあ、プログラムが短いですから細かい説明は必要ないと思います。
必要なら、値をいろいろいじって確認してみてください。


▼グラフィックを描く

線を描くには、
tft.drawLine(10, 10, 100, 100, BLACK);
と追加すると描けますし、

円を描くには、
tft.drawCircle(100, 100,50,BLACK);
と追加すると描けます。


塗りつぶした円を描くには、
tft.fillCircle(100, 100,50,BLACK);
であり、

四角を描くには、
tft.drawRect(100,100,50,50,BLACK);
塗りつぶした四角を描くには、
tft.fillRect(100,100,50,50,BLACK);
であり、引数もなんとなく想像できます。

点を描くには、
tft.drawPixel(100,100,BLACK);
で1ピクセル毎に描いていくこともできます。


▼画面の座標を調べる

商品名には320×240ピクセルと書いてあるため、画面の座標を調べるために、次の2行で画面の端に円と点を描いてみました。

tft.drawCircle(240-1,320-1,50,BLACK);
tft.drawPixel(240-1,320-1,RED);

実行してみると、このようになりました。

これでLCDの向きと座標が確認できました。 ちなみに拡大してみると端が239:319であるとこが確認できます。



▼タッチパネルの座標を調べる

まずは、タッチパネルの値をパソコン側に送信するのみのプログラム用意しました。
#include <TouchScreen.h>

#define YP A3
#define XM A2
#define YM 9
#define XP 8

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {

  TSPoint p = ts.getPoint();

  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);

  Serial.print(p.x);
  Serial.print(" : ");
  Serial.print(p.y);
  Serial.print(" : ");
  Serial.println(p.z);

  delay(100);
}

タッチパネルに触れながらシリアルモニタで値を確認したところ、画面の座標とタッチパネルの座標の基準点が全く違う事と、 そもそも、スケールが違う事がわかりました。
タッチパネルの構造は抵抗膜タッチ方式で抵抗値をデジタル変換して1024の分解能で表示しているみたいです。
つまり、このような感じでした。

ちなみにZは押したときの圧力でした。


▼お絵描きソフトを書いてみる

以上の事柄から簡単なお絵描きソフトを書いてみる事にします。
しかし、まだ、ハードウェアとソフトウェアの座標が合ってない為にあまり上手く描けません。

#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <TouchScreen.h>

#define BLACK   0B0000000000000000
#define RED     0B1111100000000000
#define GREEN   0B0000011111100000
#define BLUE    0B0000000000011111
#define WHITE   0B1111111111111111

#define YP A3
#define XM A2
#define YM 9
#define XP 8

Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void) {
  tft.reset();
  tft.begin(0x9341);//LCD制御用ICを指定
  tft.fillScreen(WHITE);
}

void loop(void) {
  TSPoint p = ts.getPoint();
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.z > 10 && p.z < 1024) {
    int x = ((float)p.x / (float)1024) * 240;
    int y = ((float)(1024 - p.y) / (float)1024) * 320;
    tft.fillCircle(x, y, 5, BLACK);
  }
  delay(10);
}


実際に書いてみても、画面のふちの方は描画できず座標のスケールが間違っています。
プログラムの赤文字部分の修正が必要みたいです。


▼画面の座標とタッチパネルの座標を合わせる

タッチパネルの座標を合わせるには、画面の端をタッチして座標を取得する必要がありそうです。
そこで、プログラムを書き込んでタッチパネルの座標2ヶ所をペンで押して取得しました。
#include <TouchScreen.h>

#define YP A3
#define XM A2
#define YM 9
#define XP 8

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {

  TSPoint p = ts.getPoint();
  if (p.z > 10 && p.z < 1024) {
    Serial.print(p.x);
    Serial.print(" : ");
    Serial.println(p.y);
  }
  delay(500);
}


取得した座標をシリアルモニタで確認するとこのようになります。


取得した値を使って、先ほどのお絵描きソフトの赤文字部分を書き換えてみます。
#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>
#include <TouchScreen.h>

#define BLACK   0B0000000000000000
#define RED     0B1111100000000000
#define GREEN   0B0000011111100000
#define BLUE    0B0000000000011111
#define WHITE   0B1111111111111111

#define YP A3
#define XM A2
#define YM 9
#define XP 8

Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void) {
  tft.reset();
  tft.begin(0x9341);//LCD制御用ICを指定
  tft.fillScreen(WHITE);
}

void loop(void) {
  TSPoint p = ts.getPoint();
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.z > 10 && p.z < 1024) {
    int x = (((float)p.x - 124) / ((float)921 - 124)) * 240;
    int y = (((float)p.y - 95) / ((float)892 - 95)) * 320;
    y = 320 - y;
    tft.fillCircle(x, y, 5, BLACK);
  }
  delay(10);
}
これにより、ペンの位置と描画位置がだいたい一致するようになりました。


▼UNOでI2C通信も同時にできるようにする

LCDシールドをUNOに取り付けるとピンのほとんどを使用してしまいます。
I2Cで使用するA4ピンが画面表示で使用されていますし、なんとかI2C通信ができるようにならないものかと思いました。
そこで、TFTディスプレイとUNOの間をジャンパケーブルで接続してみます。

5V
GND
A0からA4
D2からD9

以上の15本の線をジャンパケーブルで接続したところ、画面もタッチパネルも動作することが確認できました。


I2CではA4とA5が必要なのですがA4ピンが画面に使用されています。
A4ピンが欲しいのでA4ピンに刺さっているケーブルを抜いて適当なデジタルピン0番に差し替えました。


差し替えたピンをソフトに反映させるために、プログラム上のTFTLCDの初期化部分で、ポートをA4からD0に変更します。
Adafruit_TFTLCD tft(A3, A2, A1, A0, A4);
の部分を探して第5引数を変更しました。
Adafruit_TFTLCD tft(A3, A2, A1, A0, 0);
その後、プログラムをボードに書き込むといままでと同じように画面もタッチパネルも動作しました。

空いたA4とA5ピンには、I2Cで使用できるか確認するために、大気圧センサーモジュールを使うで使用したI2Cで動作するセンサーを取り付けて値を画面表示しています。
A4にSDA、A5にSCLを接続しました。


以下I2C大気圧センサーモジュールと画面表示が同時にできるか確認するために使用したプログラムです。
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <Adafruit_GFX.h>
#include <Adafruit_TFTLCD.h>

#define BLACK   0B0000000000000000
#define RED     0B1111100000000000
#define GREEN   0B0000011111100000
#define BLUE    0B0000000000011111
#define WHITE   0B1111111111111111

Adafruit_TFTLCD tft(A3, A2, A1, A0,  0);

Adafruit_BMP085 bmp;

void setup() {
  Serial.begin(9600);
  if (!bmp.begin()) {
    while (1);
  }
  tft.reset();
  tft.begin(0x9341);//LCD制御用ICを指定
  tft.fillScreen(WHITE);
}

void loop() {
  tft.fillScreen(WHITE);
  tft.setCursor(10, 10);
  tft.setTextColor(BLACK);
  tft.setTextSize(4);
  tft.println(bmp.readTemperature());
  tft.println((double)bmp.readPressure() / 100);

  delay(1000);
}

ちなみに、配線が正しければUNOでもNANOでも同様に動作しました。



▲トップページ > マイコンなど