Arduino LCD Screenを使ってみる
最近は作った作品を紹介することが多かったのですが、やっぱり自分のできることを増やさないことには、同じようなものばかり作ることになってつまらないので、久々に新しいモジュールを使えるようにしたいと思います。
ということで、今回はArduino LCD Screenを使ってみたいと思います。画像表示ができるようになると色々楽しそうなので。
こちらによると、表示できるファイル形式はbmp(ビットマップ)形式のみで、解像度は160×128ピクセルとのことです。一応はArduino Esploraを意識した製品らしいのですが、他のArduinoでも使えるそうなので、まずはオーソドックスにArduino Unoで使ってみましょう。
まずはこちらのページに従って配線します。
うーん、ものすごい数のピンを使ってしまうなあ。。。
続いてソフト側の準備です。まずはとにもかくにもライブラリですが、こちらのページによると、どうやら自分の使っている開発環境(1.6.8)だと初めから組み込まれている模様です。
ということで、早速サンプルコードを書いていきたいと思います。サンプルコードの作成は、ほぼこちらの手順に沿っていきます。
コードを書く前に、表示する画像をMicro SDカードの最上位階層に保存しておきます。SDカードの方はFAT16かFAT32でフォーマットしておかなくてはならない模様。サンプルのビットマップ画像( “logo.bmp”)は上記のページに置かれています。
で、サンプルコードもほぼそのまま使います。こちらのページの一番最後にあるソースの中の、ファイル名が”arduino.bmp”になっているのを”logo.bmp”に変えただけです。
// include the necessary libraries #include <SPI.h> #include <SD.h> #include <TFT.h> // Arduino LCD library // pin definition for the Uno #define sd_cs 4 #define lcd_cs 10 #define dc 9 #define rst 8 TFT TFTscreen = TFT(lcd_cs, dc, rst); // this variable represents the image to be drawn on screen PImage logo; void setup() { // initialize the GLCD and show a message // asking the user to open the serial line TFTscreen.begin(); TFTscreen.background(255, 255, 255); TFTscreen.stroke(0, 0, 255); TFTscreen.println(); TFTscreen.println(F("Arduino TFT Bitmap Example")); TFTscreen.stroke(0, 0, 0); TFTscreen.println(F("Open serial monitor")); TFTscreen.println(F("to run the sketch")); // initialize the serial port: it will be used to // print some diagnostic info Serial.begin(9600); while (!Serial) { // wait for serial port to connect. Needed for native USB port only } // clear the GLCD screen before starting TFTscreen.background(255, 255, 255); // try to access the SD card. If that fails (e.g. // no card present), the setup process will stop. Serial.print(F("Initializing SD card...")); if (!SD.begin(sd_cs)) { Serial.println(F("failed!")); return; } Serial.println(F("OK!")); // initialize and clear the GLCD screen TFTscreen.begin(); TFTscreen.background(255, 255, 255); // now that the SD card can be access, try to load the // image file. logo = TFTscreen.loadImage("logo.bmp"); if (!logo.isValid()) { Serial.println(F("error while loading logo.bmp")); } } void loop() { // don't do anything if the image wasn't loaded correctly. if (logo.isValid() == false) { return; } Serial.println(F("drawing image")); // get a random location where to draw the image. // To avoid the image to be draw outside the screen, // take into account the image size. int x = random(TFTscreen.width() - logo.width()); int y = random(TFTscreen.height() - logo.height()); // draw the image to the screen TFTscreen.image(logo, x, y); // wait a little bit before drawing again delay(1500); }
では早速動かしてみましょう。
うん。特に問題なしです。
とりあえず使えることはわかったものの、何をどんな感じで表示できるのかがまだピンと来ていないので、一つずつ確認していきます。
まずは単純に画像を一枚表示させる、ということをやろうと思いますが、Arduinoのロゴマークだけ表示させていても面白くないので、自分でbmpファイルを用意することにします。
あんまり解像度が高くないので、ドット絵を表示するぐらいが丁度良いかと思い、bmp形式でファイルをエクスポート可能なPixenというドット絵エディタでマリオを描いてみました。
早速SDカードに入れて、以下のソースで表示させてみました。
#include <SPI.h> #include <SD.h> #include <TFT.h> // pin definition for the Uno #define sd_cs 4 #define lcd_cs 10 #define dc 9 #define rst 8 TFT TFTscreen = TFT(lcd_cs, dc, rst); PImage picture; void setup() { Serial.begin(9600); // initialize and clear the GLCD screen TFTscreen.begin(); TFTscreen.background(255, 255, 255); Serial.print(F("Initializing SD card...")); if (!SD.begin(sd_cs)) { Serial.println(F("failed!")); return; } Serial.println(F("OK!")); // now that the SD card can be access, try to load the // image file. picture = TFTscreen.loadImage("mario.bmp"); if (!picture.isValid()) { Serial.println(F("error while loading mario.bmp")); } // draw the image to the screen TFTscreen.image(picture, 0, 0); } void loop() { // don't do anything if the image wasn't loaded correctly. if (picture.isValid() == false) { return; } // draw the image to the screen // TFTscreen.image(picture, 0, 0); // wait a little bit before drawing again delay(1500); }
。。。しかし、表示されず。Arduinoのロゴマークだと表示されたので、ログ出力を確認してみたところ、以下の違いがありました。
// Arduinoロゴ画像 Initializing SD card...OK! File size: 6966 Image Offset: 54 Header size: 40 Bit Depth: 24 Image size: 48x48 // 自作画像 Initializing SD card...OK! File size: 81974 Image Offset: 54 Header size: 40 Bit Depth: 32 loadImage: invalid pixel format error while loading mario.bmp
どうやら24bitのbmpでないとダメみたいなのですが、Pixenの出力するbmpは32bitなので、24bitに変換してやる必要があります。幸い、Pixenの出力したbmpファイルをMacのプレビューで開き直し、プレビュー上でbmp形式指定で書き出すことで、24bitに変換することができました。
24bitに変換したbmpファイルをSDカードに置き直し、再度表示させてみたところ、今度は無事に表示されました。
うん、良い感じです。ちなみに画像サイズはディスプレイの解像度と同じ160×128にしています。
次に、「描画にどれぐらい時間がかかるのか?」の検証です。ボタン操作で2つの画像を切り替えられるようにしてみました。表示する画像のサイズは、どちらもディスプレイの解像度と同じ160×128です。
#include <SPI.h> #include <SD.h> #include <TFT.h> // pin definition for the Uno #define sd_cs 4 #define lcd_cs 10 #define dc 9 #define rst 8 #define CHANGE_PIN 5 TFT TFTscreen = TFT(lcd_cs, dc, rst); PImage picture; uint8_t last_button_state = HIGH; uint8_t button_state = HIGH; boolean isSmall = true; void setup() { Serial.begin(9600); pinMode(CHANGE_PIN, INPUT_PULLUP); // initialize and clear the GLCD screen TFTscreen.begin(); TFTscreen.background(255, 255, 255); Serial.print(F("Initializing SD card...")); if (!SD.begin(sd_cs)) { Serial.println(F("failed!")); return; } Serial.println(F("OK!")); // now that the SD card can be access, try to load the // image file. picture = TFTscreen.loadImage("mario1.bmp"); if (!picture.isValid()) { Serial.println(F("error while loading mario1.bmp")); } // draw the image to the screen TFTscreen.image(picture, 0, 0); } void loop() { // don't do anything if the image wasn't loaded correctly. if (picture.isValid() == false) { return; } button_state = digitalRead(CHANGE_PIN); if(last_button_state == HIGH && button_state == LOW){ if(isSmall){ picture = TFTscreen.loadImage("mario2.bmp"); if (!picture.isValid()) { Serial.println(F("error while loading mario2.bmp")); } TFTscreen.image(picture, 0, 0); }else{ picture = TFTscreen.loadImage("mario1.bmp"); if (!picture.isValid()) { Serial.println(F("error while loading mario1.bmp")); } TFTscreen.image(picture, 0, 0); } isSmall = !isSmall; } last_button_state = button_state; delay(20); }
結果はこんな感じになりました。
少なくとも最大サイズの画像の描画には2〜3秒はかかるようです。これだとアニメーションは無理そうだなあ。
最後に、「Arduino Pro miniでも動くのか?」 の確認です。自分は工作だとArduino Pro miniを使うことが多いので。
使ったPro miniは5V 16MHz版ですが、特にソースコードの変更も必要なく動かすことができました。よかったよかった。
ということで、Arduion LCD Screenを簡単にですが触ってみました。描画に時間がかかるという弱点はあるものの、DFPlayerと組み合わせることで、Arduinoで映像と音声をフォローできるようになるので、だいぶいろんなことができるようになるんじゃないかなーという気がしています。
ただ一つ注意が必要なのが、LCDライブラリのサイズがメチャメチャ大きいということです。例えば一番最初のサンプルコードは、Arduino Pro Mini向けにコンパイルすると、あんな短いコードでも
最大30,720バイトのフラッシュメモリのうち、スケッチが21,430バイト(69%)を使っています。
最大2,048バイトのRAMのうち、グローバル変数が1,025バイト(50%)を使っていて、ローカル変数で1,023バイト使うことができます。
という表示が出てきます。
そのため、Arduion LCD Screenだけを使うようならそこまで問題はないかもしれませんが、他にもライブラリのサイズが大きいようなモジュールを併用することになると、ちょっと問題になりそうです。
ディスカッション
コメント一覧
まだ、コメントがありません