この記事は、こういった声をサポートしていきます!
Arduino初心者歓迎シリーズ:機器導入、文法編、実践①、実践②、実践③(今ここ)、実践④
・Arduinoやってみたいけど、よくわかんないや!
・順番に手取り足取り教えてほしい!
このページで学べること
Arduinoでディスプレイを使用する方法を学び、テキストを表示するプログラムを作成します。また、シリアル(I2C)通信を使用してキャラクタディスプレイに表示されたテキストを確認するプログラムも作成します。
ディスプレイどんなもの?
ひとつディスプレイといっても下記写真のように色々と種類があります。
キャラクタディスプレイ
今回使用するのは、文字を表示するには簡単なキャラクターディスプレイを使います。文字(キャラクタ)の表示に特化したディスプレイです。今回のはLCDの16文字2行タイプ。型式は1602A
このタイプは、1文字を点々(ドット)で表します。横5×縦8の点々です。
英数字と登録された記号が、フォントとしてパーツに入ってます。
なので漢字は基本使えないです。カタカタはいけるの多いです。
用意されたフォントではなく、自前で用意すれば好きな風にもできはします。
ちょっと難易度は高しです。
LCDは画面自体は光らないです。
買うときはバックライトの有無を確認するのと、何文字の何行か、背景や文字の色も確認しましょう。
通信方式は、よくわからんならI2Cと書かれたものを使用しましょう。電源の±とSCLとSDAという2本で計4本だけで使うことができます。
I2Cじゃない8ビット(16もある)パラレル通信というデータ線だけて8本必要なやつもありますので製品名をよく確認。
今回使うものは、
元はパラレル通信用の物を、I2Cで使えるように変換モジュールがくっついているものです。
OLEDディスプレイ(紹介のみ)
最初のディスプレイ画像の下段右2個は有機EL(OLED)というディスプレイです。
文字以外にもいろいろと表示できますが
その分の制御はキャラクタディスプレイより、複雑になります。
でも、ライブラリ引き当てれば、あら不思議。文字表示する分には簡単です。
一文字を5×8で表すというよりは、今回サンプルで載せている0.91inchサイズの128×32pixelというスペックだと、1画面を128×32の小さい点で表現します。さっきのキャラクタより細かいです。
制御コントローラーはSSD1306。Aruduinoのライブラリで検索するとAdafruit_SSD1306というものがヒットします。ほかのサイズもそろってる。ライブラリはAdafruitの使っとけば間違いなし
LCDと違って、画面が光るので、バックライトはないです。
発光する色味は大体単色(2色もあるにはある)で白、青、黄あたり。
TFTディスプレイ(紹介のみ)
最初のディスプレイ画像の左上のディスプレイがTFTディスプレイ
フルカラーが特徴。難易度は一番高い。タッチセンサ同梱のものもあり、汎用性が高い。
制御コントローラが色々ある。安い製品はコントローラがよくわからんのもあったりと、ちょっとやっかい。
画面大き目、色味もあるので、I2Cだと表示が遅くなりがち。
このTFTタイプまで来ると、2.8inchあったりと240×320の点々で表現できるので画数ある漢字も表現できる。
ただフォントを用意しないといけない。フォント何文字分用意するかによるけど、いっぱい用意するとその分容量取られる。
LCDディスプレイにテキストを表示する
色々書きましたが、一番簡単なキャラクタディスプレイを実際に使ってみましょう
試しに1分固定の時間設定とLEDを用いたアラーム通知を備えたキッチンタイマーを作成します。
Arduinoキッチンタイマーの作成ガイド
ステップ1: 準備
Arduinoを始める前に、以下のものが必要です:
- Arduinoボード
- LCDディスプレイ (I2C接続)
- LED
- ジャンパーワイヤー
ステップ2: ライブラリの追加
Arduino IDEを開き、「スケッチ」 -> 「ライブラリをインクルード」 -> 「ライブラリマネージャ…」と進み、”LiquidCrystal_I2C”を検索してインストールします。
初めて使うライブラリは、「ファイル」 -> 「スケッチ例」-> 「インストールしたやつを選択」
これで、どんな感じで使うのかを見てみると良いかなと思います。
次のスケッチでは、LCDに初期メッセージを表示し、1分の待機後にGPIO13に繋いだLEDを点灯させます。経過後にタイムアップメッセージを表示し、LEDを消灯します。
#include <LiquidCrystal_I2C.h>
// LCD関連の設定
LiquidCrystal_I2C lcd(0x27, 16, 2);
// LEDピンの設定
const int ledPin = 13;
void setup() {
lcd.init(); // LCDの初期化
lcd.backlight(); //バックライト点灯
lcd.setCursor(1,0); //書き始めの位置を指定
lcd.print("Kitchen Timer");
// LEDピンの設定
pinMode(ledPin, OUTPUT);
}
void loop() {
// 1分の待機
delay(60000)
// LED点灯
digitalWrite(ledPin, HIGH);
delay(500); // LED点灯時間
// LCDに終了メッセージ表示
lcd.clear();
lcd.print("Time's up!");
// LED消灯
digitalWrite(ledPin, LOW);
}
ステップ3: コードの理解
#include <LiquidCrystal_I2C.h>
: LCDライブラリをインクルードします。LiquidCrystal_I2C lcd(0x27, 16, 2);
: I2CアドレスとLCDの行数および列数を指定してLCDオブジェクトを作成します。I2Cアドレスは物によって違いますのでお持ちの装置のマニュアルを確認してね。const int ledPin = 13;
: LEDが接続されたデジタルピンの番号を指定します。
残りのコードは、1分ごとにLCDにメッセージを表示し、LEDを点灯させる簡単なキッチンタイマーの動作を実現しています。行数は多くないので、一行ずつゆっくり読んでいってください。
ステップ4: コードの書き換え
試しに、キッチンタイマーの設定時間を変えれるようにしてみましょう
次のスケッチでは、起動時にスイッチが押されてると、その間、設定時間が加算され、LCDに新しい時間が表示されます。設定時間は1分~5分のサイクルで変更されます。スイッチを離すとタイマー開始。
タイマーの基本動作は変わりませんが、設定時間を変更できるようになりました。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int ledPin = 13;
const int switchPin = 2; // スイッチが接続されたデジタルピンの番号
int timerDuration = 1; // タイマーの初期設定時間(1分)
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Kitchen Timer");
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
}
void loop() {
// スイッチが押されている間、設定時間を変更していく
while(!digitalRead(switchPin)){
if (digitalRead(switchPin) == LOW) {
if (timerDuration == 5) {
timerDuration = 1;
} else {
timerDuration = timerDuration + 1;
}
lcd.clear();
lcd.print("Timer set: " + String(timerDuration) + " min");
delay(3000); // 1秒待機してLCD表示を確認
}
}
lcd.clear();
lcd.print("Timer set: " + String(timerDuration) + " min");
lcd.setCursor(0,1); //書き始めの位置を指定
lcd.print("CountDown Now...: ");
for(int i=0; i<timerDuration; i++){
delay(60000); // 1分待機
}
lcd.clear();
lcd.print("Time's up!");
digitalWrite(ledPin, LOW);
while(digitalRead(switchPin)){}
}
もういっちょ。次のスケッチではカウントダウン中の残り時間が分かるようにしてみます。
今何分か知りたいですもんね。
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int ledPin = 13;
const int switchPin = 2; // スイッチが接続されたデジタルピンの番号
int timerDuration = 1; // タイマーの初期設定時間(1分)
void setup() {
lcd.init();
lcd.backlight();
lcd.print("Kitchen Timer");
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
}
void loop() {
// スイッチが押されている間、設定時間を変更していく
while(!digitalRead(switchPin)){
if (digitalRead(switchPin) == LOW) {
if (timerDuration == 5) {
timerDuration = 1;
} else {
timerDuration = timerDuration + 1;
}
lcd.clear();
lcd.print("Timer set: " + String(timerDuration) + " min");
delay(3000); // 1秒待機してLCD表示を確認
}
}
lcd.clear();
lcd.print("Timer set: " + String(timerDuration) + " min");
lcd.setCursor(0,1); //書き始めの位置を指定
lcd.print("CountDown Now");
delay(1000); // 1秒待機
lcd.print(".");
delay(1000); // 1秒待機
lcd.print(".");
delay(1000); // 1秒待機
lcd.print(".");
delay(1000); // 1秒待機
digitalWrite(ledPin, HIGH);
for(int i=0; i<timerDuration; i++){
for(int ii=0; ii<60; ii++){
delay(1000); // 1秒待機
lcd.clear();
lcd.print("Time left: " + String((timerDuration-1)-i) + ":"+ String(59-ii));
}
}
lcd.clear();
lcd.print("Time's up!");
digitalWrite(ledPin, LOW);
while(digitalRead(switchPin)){}
}
今回の適当な感じのタイマーなら、割と簡単に作ることができます。
しかし、正確な時間を刻もうとすると、RTC(リアルタイムクロック)モジュールという部品を使うのが
無難と思います。
delay関数は便利なのですが、時計のように正確に刻むという点の細かいこというと少しずつずれます。今回のようにFor文で繰り返して積算で1分とか5分を作っていくとなおのこと。
おまけ
おまけに、別のキャラクタディスプレイ「AQM1602XA(コントローラはST7032)」
ライブラリマネージャでST7032を検索すると
LCD_ST7032とST7032_asukiaaaの2個が記事執筆時点で引っかかります。
ST7032_asukiaaaというライブラリは、何もいじらずにサンプルスケッチが動きました。
LCD_ST7032は、データ書き込みの指定が私の使用しているものには合わなく、コントラストMax状態(調整きかない)になりました。
中身を見てみると、49行目がCNTRBIT_CO(0x80)と記載されており、仕様が不一致していましたので、CNTRBIT(0x00)に変更し動くようになりました。ライブラリがあれば簡単ですが、なくてもデータシートに仕様がかいてあったり、サンプル乗ってたりするので、困ったら開いてみましょう。
この製品は秋月電子が販売しているものです。
この記事で使用した1602Aはケースに組込み易く、取り扱いやすい基板に乗っかていて4隅に穴も開いていて、ケースにすぐに取り付けれるようになっています。
AQM1602XAはディスプレイが薄く、省スペースなタイプです。
バックライトはありません。
これはパラレルもシリアルのI2C通信も対応していますが、本体の端子のピッチが2.54じゃないです。それをI2C通信に必要な分にしてピッチ変換の基板がくっつけて販売されています。便利ですね。
おわりに
いかがだったでしょうか。
I2Cのシリアル通信のものは線もすくないので、非常に敷居は低いかなと思います。
キャラクタディスプレイは、自由度は低いですけど、その分で、ほかのものより制御はしやすいです。
キャラクタディスプレイを足掛かりに、ぜひ他のOLEDとかTFTにも挑戦してみてください。
コメント