Arduino
lcd
ArduinoIDE
SPI
ILI9341

【Arduino】Arduino UNOとカラーLCD(ILI9341)で値を「見」よう

はじめに

ここでは自分用の備忘録も兼ね、Arduino UNOとカラー液晶ディスプレイ(LCD)を用いてセンサーで得た値を見るまでを説明します。ここでは温湿度センサを用いています。

今回使用するモジュール

今回用いるモジュールは全て秋葉原にある店舗で購入しました。

  • Arduino UNO R3 (秋月電子通商)
  • カラー液晶 ILI9341 TJCTM24028-SPI 240x320 (aitendo)
  • 温湿度センサ AOSONG AM2320 (秋月電子通商)
  • 双方向汎用ロジックレベル変換 FXMA108 (秋月電子通商)

この他に10kΩ抵抗二つが必要になってきます。

カラーLCD ILI9341 TJCTM24028-SPI

今回使用するカラーLCDはaitendo直営店で手に入れた「ILI9341 TJCTM24028-SPI」です。

linecamera_shareimage.jpg
(↑裏面 特に何も考えず購入したため悪戦苦闘しました...)

裏にはSDカードの入るスペースもありますが、ここでは使用しません。
240x320の画質まで表示できるみたいです。
調べたらILI9341ベースであることがわかりました。
また、購入したものは画像右側中央の部分「J1」の箇所に素子がないためタッチパネルとしての使用は不可能でした。

※カラー液晶ディスプレイには多くの電流が流れるそうです。今回の回路作成ではarduinoから電源を引っ張っていますが、過電流を防ぐためにもなるべくarduinoとは別に外部電源を用いることを推奨します。

回路作成

早速回路を組んでいきます。
LCD - Arduino UNO間ではSPI通信という手法でデータが送られます。
が、難しいことは考えずとりあえず組んでいきます。

TFT_arduino.png
(↑fritzingによる回路モデル こんがらがりそう...)

IMG_9613.JPG
実際に組むとこんな感じに↑(回路組むの下手です...)

(ちなみに回路の写真に載っていたアクリル板のボードはOtaFabというところでレーザー加工で作成しました。OtaFabについて→FabLab)

※回路図に書き忘れていましたが、温湿度センサのSCL、SDAピンにはそれぞれ10kΩの抵抗でプルアップしてください!
Arduino UNOの電圧(5V)とLCDの動作電圧(3.3V)で異なるため、ロジックレベル変換モジュール(今回の場合FXMA108)が必要となってきます。くれぐれも5Vで動かさないこと!

ArduinoIDEでスケッチ

LCDにデータ(値とグラフ)を表示するためスケッチを書いていきます。ここではソースだけ載せます。完コピOKです。
パーツごとの仕様や詳しいことは仕様書やライブラリを読んでください。(温湿度センサーのデータ取得(I2C通信)は非常に難しいかもしれません。が、日本語のサイトもあるので頑張って見てください。)

LCD操作用に以下のライブラリを外部から使用しました。
- Adafruit_ILI9341
- Adafruit_GFX

Temperature_Humidity.ino
#include <SPI.h>
#include <Wire.h>

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

#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

unsigned char AM2320_DATA[8];
unsigned char AM2320_ADDR = 0x5c; // (0xb8 >> 1) and 0x7f

void getData() {
  Wire.beginTransmission(AM2320_ADDR);
  Wire.write(0x00);
  Wire.endTransmission();

  delayMicroseconds(1000);

  Wire.beginTransmission(AM2320_ADDR);
  Wire.write(0x03);
  Wire.write(0x00);
  Wire.write(0x04);
  Wire.endTransmission();

  delayMicroseconds(2000);

  Wire.requestFrom(0x5c, 8);

  for (int c = 0; Wire.available(); c++) {
    AM2320_DATA[c] = Wire.read();
  }
}

double temperature() {
  if (AM2320_DATA[4] & 0x80) {
    return (((AM2320_DATA[4]) & 0x7f) * 256) + AM2320_DATA[5] / 10.0;
  } else {
    return ((AM2320_DATA[4] * 256) + AM2320_DATA[5]) / 10.0;
  }
}

int humidity() {
  return (AM2320_DATA[2] * 256 + AM2320_DATA[3]) / 10;
}

void setup() {
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setRotation(3);

  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("Temperature and Humidity");
  tft.setCursor(120, 40);
  tft.println("degree Celsius");
  tft.setCursor(120, 60);
  tft.println("%");

  Wire.begin();
  pinMode(0xA0, INPUT);
}

void loop() {
  getData(); 

  double temp_c = temperature();
  static double p_temp_c = 0;
  int humid = humidity();
  static int p_humid = 0;
  static int Time = 60;
  static int HGraph = 240;
  static int TGraph = 240;

  if (temp_c != p_temp_c || humid != p_humid) {
    // Clear
    tft.setCursor(0, 40);
    tft.setTextColor(ILI9341_BLACK);
    tft.println(p_temp_c); 
    tft.setCursor(0, 60);
    tft.println(p_humid);

    // Print
    tft.setCursor(0, 40);
    tft.setTextColor(ILI9341_WHITE);
    tft.setTextSize(2);
    tft.println(temp_c);
    tft.setCursor(0, 60);
    tft.println(humid); 
  }


  tft.fillRect(Time, 140, 2, 100, ILI9341_BLACK);
  delay(1);
  tft.drawLine(Time, HGraph, Time + 1, 239 - humid, ILI9341_RED);
  tft.drawLine(Time, TGraph, Time + 1, 200 - (int)temp_c, ILI9341_BLUE);
  if (Time >= 320) {
    Time = 60;
  } else {
    Time += 1;
    HGraph = 239 - humid;
    TGraph = 200 - (int)temp_c;
  }

  delay(67);
  p_temp_c = temp_c;
  p_humid = humid;
}

スケッチ例に追加される「graphictest」を参考にするとうまくいくかと思います。
0xうんたらとかあるよぉ...と思われるかもしれませんがこれは温湿度センサーの通信部であり、仕様書など読み理解してしまえばどうということはない内容です。

最後に

自分自身arduinoもとより電子工作初心者ですが、割と簡単に液晶ディスプレイが操作できたのではないかと思います。Adafruit様のライブラリに感謝感激です。液晶は難しそう!といって切り捨てず、ぜひチャレンジして見てください。シリアルモニターとは全く違う世界が開けます。
次回はWiFiモジュールを使ってみたいと思います。