Arduino しようぜ!パラレルLCD編

「Arduino しようぜ!」の5回目、パラレルLCD実践編です。(「Arduino しようぜ!」は大谷選手の「野球しようぜ!」へのオマージュです。)
Arduino IDEでスケッチを作成して、パラレルLCDディスプレイに文字を表示します。
今回は、自宅にあった12種類のLCDを紹介しています。

(前回のOLEDに文字を表示するソフトウエア実践編は、以下をクリック)

ハードウエア

LCDの種類

ここでいう「LCD(Liquid Crystal Display:液晶ディスプレイ)」には、キャラクタとグラフィックの2種類があります。
キャラクタは文字数が決まった表示機です。1行に16文字などと決まりがあります。
グラフィックは細かなドットが集まった表示機で、ドットの集まりで文字表示はもちろん、好きな図形や絵なども表示できます。前回のOLEDもグラフィックです。
今回、使用するのはキャラクタのLCDです。

左 キャラクタ、 右 グラフィック

キャラクタLCDにもインターフェースで2種類あります。
OLEDの時に使用したI2Cと、パラレルです。

パラレル接続のLCDは、下図のように多数の配線が必要ですが、動作の理解はこちらが楽です。
(パラレルLCDの例)

この後の項目で、自宅にあった12種類のLCDを紹介しています。ただし、動作が確認できなかったものもあります。
(データシートを見るのが面倒なので、忘備録としてまとめてみました。適宜、修正・加筆をします。)

パラレルLCD

パラレルLCDは「○○1602」と呼ばれる、型番+数字4桁の物が多いです。
通常、後ろの4桁の数字を見れば、文字数と行数が分かります。
「1602」は16文字✕2行です。「2004」ならば20文字✕4行ですね。
パラレルLCDには基盤の形でも2種類あり、国内でよく見る左に2列の端子があるタイプと、海外でよく見る上部に1列の端子が並ぶタイプがあります。

ドライバIC

パラレルLCDには、ほぼ間違いなく1980年代に発売された日立製のドライバIC「HD44780」(現在は互換品)が使われています。
このICの搭載フォントにはカタカナが含まれており、互換ICもそのままコピーして製造されているので、中華製のドライバICでもカタカナが表示できます。
現在販売されているパラレルLCDの裏には、パッケージ化された互換ICが付いています。
(「SC1602BSLB」の例)

古いLCDでは基盤裏には、日立純正の「HD44780」が付いています。(写真右)
こちらの拡張ICには「HD44100」ではなく三洋の「LC7930」が2個、使われています。(写真中央と左側)

動作の解説

ドライバIC「HD44780」の入力は、「RS」「R/W」「E」の3つの制御線と「DB0」~「DB7」までの8本のデータ線があります。
制御線でタイミングを、データ線で文字のデータを送ります。
このIC1つでLCDに8文字✕2行(16文字)の表示ができます。
(LCDを横に組み合わせると、16文字✕1行に出来ます。)

これは、誤解を恐れずに例えると電車です。
モータが付いた、16人乗り(8✕2)の動力車が「HD44780」です。
(電車の絵は「いらすとや」さんより)

では、16文字✕2行のLCDは、どうやって実現しているのでしょうか?
動力のない電車(HD44100)を1両、牽引します。
すると、合計で32人(16✕2)乗車できます。

実際のドライバICの動作を簡略化して説明すると、下図のようになります。
「HD44780」1つでは、文字データの受け取りと、LCDへ8✕2の16文字が制御可能です。

下図は、拡張IC(HD44100等)を追加して、16文字✕2行にしている状態です。
拡張ICは、外部との入出力は持たず、LCDへの表示に特化することで小型・簡略化されています。
(「24文字✕2行」のLCDならば、合計48なので「HD44780」と拡張ICが2つ 16+16+16で実現しています。)

「2004A」のように20文字✕4行(合計80文字)を実現するためには、動力のない電車(HD44100)を合計4両牽引すると、「HD44780」の16に加えて、拡張IC分が +16+16+16+16で80になります。(下図参照)
ドライバIC「HD44780」は、最大で80の文字データを保持できるので、20文字✕4行 80が最大の文字数になります。
これ以上の文字を表示するには、基板上にもう1つ「HD44780」を追加します。

ところで、「16文字✕1行」や「16文字✕2行」の商品は理解できるのですが、「20文字✕2行」は合計40で16で割り切れません。内部でなにか特殊なことをしているのでしょうか?

使用上の注意事項

1 左に端子が並ぶタイプのLCDには、電源の極性が逆のものがあり、逆につなぐと即壊れます。(注意!)

2 電源は+5 Vと+3.3 Vの物があります。3.3 V仕様の最大電圧は4.5 V程度なので5 Vでは使えません。購入時には注意しましょう。(実際には使えるものもあるので、自己責任で。)

3 コントラスト調整には、半固定抵抗などがよく使われますが、ダイオードを使用すると調整いらずで簡単です。1S1588、1S2076A、1N4148など定番の小信号ダイオードをPin 3につなげばOKです。

4 少し古い資料では、4 bitモード(データ線を4本で使用するモード)で、使用しないG0~G3をGNDにつなぐ例が見られますが、ドライバICのデータシートには「オープンにする。」と書かれています。

5 「E(Enable) : Pin 6」は、信号の安定のために10 k ~ 100 kΩ程度の抵抗でプルダウンしておきます。

6 「RW(Read/Write):Pin 5」は、読み込みに使用しないので通常はGNDにつなぎます。

7 RS は Resistor Selectの略です。「E」端子とともにArduinoにつなぐ制御線です。

標準的なつなぎ方
(「ZJM162A」の例です。「SC1602BSLB」は電源端子が逆になります。)

実際のパラレルLCD

SC1602BSLB

16文字✕2行
秋月電子のバックライト付きLCDです。
販売コード:100038
(電源をよく確認してください。たまにVDDとVSS端子が逆のものがあります。)
端子番号は、基盤の裏から見た場合

ZJM162A

16文字✕2行
海外の製作例で定番のLCDです。
aitendoの型番:ZJM162A

PX1602

16文字✕2行
aitendoの型番:ZJM162A
動作電圧:3.3 V

aitendoで購入したLCDですが、ちょっと特殊なLCDです。ケーブルは1 mmピッチ20ピンのFFCで、コントラスト調整端子(VO)がありません。
表示部の下に4つのLEDが付いています。(左から、赤 緑 赤 赤 )
バックライトはELシートだそうです。専用駆動ICが必要になるので、点灯の確認は出来ていません。

L2432

24文字✕2行
(スケッチでは、lcd.begin(24, 2); とします。)

コネクタは「SC1602BSLB」と同じ、左側の縦2列です。
注意:GNDはPin 1、VDD(+5 V) がPin 2です。

SC2004

20文字✕4行
(スケッチでは、lcd.begin(20, 4); とします。)

コネクタは「SC1602BSLB」と同じ、左側の縦2列です。
注意:GNDはPin 1、VDD(+5 V) がPin 2です。

2004A

20文字✕4行
(スケッチでは、lcd.begin(20, 4); とします。)

コネクタは「ZJM162A」と同じ、上側の横1列です。

LM032L

20文字✕2行
(スケッチでは、lcd.begin(20, 2); とします。)

コネクタは「SC1602BSLB」と同じ、左側の縦2列です。
注意:GNDはPin 1、VDD(+5 V) がPin 2です。
(今回、動作テストをしたら表示が不良になっていました。)

DM2020

懐かしの亜土電子で入手したようです。(記憶があいまい)
20文字✕1行

コネクタは「SC1602BSLB」と同じ、左側の縦2列ですが、ピンが全く違います。
基盤の裏をよく見ると。日立のドライバICではなく、NECのuPD7228が2つ付いています。
1つのICで10文字分を制御するそうで、制御線が6本(クロックの供給も必要)、データ線が4本という独自仕様だそうです。
Arduino用のライブラリを作られた方も見つけたのですが、クロックはハード的に作成して供給されているようで、今回はArduinoで動かすのはあきらめました。
(これの1つ後のDM2021なら、「SC1602BSLB」と同様に使えます。)

端子は未確認の情報です。動作したら追記します。

LM162

16文字✕2行
コネクタは「SC1602BSLB」と同じ、左側の縦2列です。
注意:GNDはPin 1、VDD(+5 V) がPin 2です。

LM016

16文字✕2行
コネクタは「ZJM162A」と同並びですが、下側の横1列です。
(非常に古いLCDなので、文字が薄くなっています。)

ZJM161A

16文字✕1行
ただし、内部では8文字✕2行で、9文字目は2行目扱いです。
(スケッチでは、16 X 1の lcd.begin(16, 1);ではなく、8 X 2の lcd.begin(8, 2); とします。)

コネクタは「ZJM162A」と同じ、上側の横1列です。

WD-A1601M

16文字✕1行
これも、内部では8文字✕2行で、9文字目は2行目扱いです。
(スケッチでは、16 X 1の lcd.begin(16, 1);ではなく、8 X 2の lcd.begin(8, 2); とします。)

コネクタは「ZJM162A」と同じ、上側の横1列です。aitendoの商品はコネクタ付きで、赤線を上にして次のような配線になります。
(aitendoの2列x7P IDCコネクタの端子)

基板上の端子

aitendoで付属するコネクタの端子

ソフトウエア

ライブラリの読み込み

パラレルLCDには、日立製のドライバIC「HD44780」または互換品が使われています。これのICを動かすためのライブラリは「LiquidCrystal」です。
OLEDやI2CのLCDとちがって、パラレルLCDに文字を表示する「LiquidCrystal」ライブラリは標準で入っているので、ライブラリ追加のための手順は必要ありません。

LCDテスト用スケッチ

LCDテスト用のスケッチを読み込みます。
「ファイル」「スケッチ例」、「Arduino UNO用のスケッチ例」の「LiquidCrystal」から「HelloWorld」を選びます。

ちょっと長いスケッチになりますが、下がLCDテスト用のスケッチの内容です。
最初のコメントには、「この例で使っているライブラリは、日立のHD44780を使った16文字✕2行のLCDなら、どれでもOK」的なことが書かれています。
詳細はこの後、解説します。

/*
  LiquidCrystal Library - Hello World

 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.

 This sketch prints "Hello World!" to the LCD
 and shows the time.

  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 modified 7 Nov 2016
 by Arturo Guadalupi

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystalHelloWorld

*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

LCDの接続試験

スケッチ内の配線に従ってArduinoとLCDをつなぎます。
(「ZJM162A」の例です。「SC1602BSLB」は電源端子が逆になります。)

図のとおりにArduinoとLCDをつないだら、「検証」してエラーが出ないことを確認して「書き込み」をします。
コントラスト調整にはダイオードを使っているので、無調整で問題なく表示が出るはずです。
表示されない場合は、配線を再確認してください。
正常であれば、1行目に「Hello World」が表示され、2行目の数字がカウントアップされます。

LCDテスト用スケッチの内容説明

OLEDと同じ様に、各項目の細部を確認しながら、必要なものを「void setup() {」に記載します。
いらないものを削除する前に、書いてある内容を説明します。

#include <LiquidCrystal.h>
LCD用のライブラリを読み込む設定です。消してはいけません。

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
「const」は「constant(定数)」の略で、書き換え禁止の設定をします。
LCDの端子番号を設定したのに、他のところで勝手に変えられたら困るので、「const」を使います。
なお、「const」で付ける名前(ここでは「rs」など)は小文字を使い、「#define」で使う大文字の名前と区別します。
「int」は「integer type」の略で、整数を入れる入れ物を準備します。
次の行でLCDの端子を設定するために、分かりやすい名前を決めています。
例えば、rs(という名前の整数の入れ物)と書かれた部分は「12」と読み替えられます。

LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
LCDの各端子とArduinoの接続先を指定するための設定です。

lcd.begin(16, 2);
LCDをカッコ内の文字数と行数で初期化します。
ここでは、LCDのクリアと行初への移動の処理が含まれています。

lcd.print(“hello, world!”);
LCDに「Hello World」と表示させます。
「”」で表示したい文字を囲みます。表示できるのは半角英数字のみです。

void loop()内の処理は、一定間隔で数字を増やして表示する処理です。
名前を表示するには必要ないので消去します。

LCD表示の命令

上でも若干説明しましたが、よく使うLCDの命令は次のとおりです。

LiquidCrystal (rs,rw,enable,d0,d1,d2,d3,d4,d5,d6,d7)
rwはGNDにつないでいるので省略できます。
d0~d7の部分は、今回は、4bit(データ配線が4本)なので「d0~d3」までは省略しています。ここに「d0~d7」のピン設定を書けば8bit(データ線が8本)モードに自動でなります。
(Arduino側のデータ線を8本用意するのは大変なので、通常は4bitモードで使います。)
なお、スケッチの上の行を省略して、
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
と直接指定することも出来ますが、コメントに書いておかないと何を指定しているのかが分からなくなります。

.clear()
LCDを消去してカーソルを0.0へ移動します。

.setCursor(col, row)
指定位置へカーソルを移動します。

.print(data)
「”」で囲んだ文字を表示します。

.write(data)
1バイトのデータを文字に変換して表示します。

.cursor()
文字位置にカーソルを表示します。消すのは「.noCursor()」

.blink()
文字を点滅します。点滅停止は「.noBlink()」

その他にも、文字のスクロールや文字方向の変換、ユーザが作った文字(外字)の表示などが出来ます。

名前の表示

LCDテスト用スケッチをコピペして、LCDに名前を表示するスケッチを作成します。
こんな感じになります。(「Hello World」は「Yatte Miyoh!」と書き換えました。)
基本的にコメントは消しましたが、ピンの設定の部分は残しました。

/*
  接続回路:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
*/

#include <LiquidCrystal.h>

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  lcd.begin(16, 2); // LCDの表示文字数と桁数

  lcd.print("Yatte Miyoh!");
}

void loop() {
}

SC1602BSLB

書き換えが終了したら、「検証」してエラーがなければ「書き込み」をします。
今度は、1行目に「Yatte Miyoh!」(名前)だけが表示されます。

ZJM162A

配線を取り替えて、「ZJM162A」をArduinoにつなぎます。
これも問題なく表示されました。

PX1602

次は「PX1602」です。ケーブルがフラットのFFCなので、変換基盤を使いました。
このパラレルLCDは3.3 V用なので、Arduinoの3.3 Vから電源を取ります。
多分、皆さんがやっても同じ用に黒豆腐になると思います。(aitendoのHPでは正常に表示されていますが。)

Pin 1はaitendoのHPではNCと書かれていますが、「コントラスト調整端子?」ではないかと試しましたがダメでした。
しかたがなく、ドライバIC「KS0066」の動作電圧は3 Vモードで2.7~4.5 Vなので、VDDを調整してみました。
抵抗で分圧しても良いのですが、今回はArduinoからの+5 Vで定番レギュレータ「TL431」を使って可変電圧を作って試験しました。
4.5 Vから下げていって、3.2 V以下でちょうど良いコントラストになりました。(微妙)

ついでに、基盤に付いている4個のLEDも全部点灯させてみました。
個人的には、左端が緑LEDなら電源表示にちょうど良いなと。
コントラスト調整の手間さえなければ、組み込む時に、LEDを別に準備しなくて良いのは便利そうです。

電源の接続間違い防止

何度も繰り返し書いていますが、電源端子を間違うと最悪の場合、LCDは一発で壊れてしまいます。
具体例が下図です。

だいぶ前に間違って「Pin1にGND」を「Pin2に+5 V」を接続したら壊れて、右半分が正常に表示されなくなりました。(拡張ドライバICが壊れたのだと思います。)
接続には気をつけましょう。
基本的には、この電源端子さえ気をつければ、他の端子は同じ並びになっています。

配線をする前に、基板上の明らかにGNDにつながっている部分とPin1とPin2の導通を確認すれば、間違うことがないのでオススメです。
(データシートで確認するのが大前提ですが・・・)

コメント