BS21 Lab の製品 - Arduino 用 カナ LCD シールド - カナ LCD ライブラリの解説

1/aug/2014 新規
1/aug/2014 更新

カナ LCD ライブラリの解説です。
基本的には LiquidCrystal ライブラリと互換になるようにしていますが、一部、違いがあります。

  1. サポートしている画面サイズ
  2. ユーザー定義文字
  3. ワイド文字列とは
  4. サポートしている機能

・サポートしている画面サイズ

対応している画面は、1行、2行、4行のタイプのみです。

制御 IC である HD44780 (以下、互換 IC も含む)は、液晶モジュールの表示画面サイズとは無関係に、内部に 80 文字分の DDRAM メモリを持っています。 ただし、80 文字全部を一度に表示できるのは 20桁×4行の画面サイズのみで、それ以外では、80 文字は一気に表示できず、スクロールさせる必要があります。

<1行のタイプ>
本シールドの裏面の SJ2 をショート(short)させておく必要が有ります。
1行のタイプは、常に 80桁×1行になります。ただし、実際に表示されるのは、80桁中の一部分のみです。残りの桁は、左右にスクロールさせなければ見えませんので、注意して下さい。なお、80桁目と1桁目は繋がっているので、ループします。(ただし、実機を持っていないので確認していません)
例えば、液晶の表示画面サイズが8文字×1行の時は、以下の様になります。
80桁×1行
以下の begin 関数では、rows に 1 を指定してください。cols の指定は無視され、常に 80 として扱われます。
液晶画面の表示可能文字数に関わらず、常に 80桁まで文字が DDRAM メモリに書き込まれます。80桁目を超えると、自動的に 1桁目に戻ります。\r, \n でも1桁目に戻ります。

また、1行タイプのみ、フォントサイズが 5x8ドットのタイプと、5x10ドットのタイプの2種類があります。当然ながら、液晶モジュール自体が、そのフォントサイズに対応している必要があります(5x10ドットのタイプの液晶なら 5x8ドットのフォントも対応可能だが、逆は無理)。 5x10ドットの場合、SJ1 と SJ2 の両方をショート(short)させます。5x8ドットの場合は、SJ2 のみショート(short)させてください。
フォントサイズ対応する文字SJ1 の扱いコメント
5x8ドット185 文字(5x8ドット)+ユーザー定義の8文字SJ1 はオープン(open)5x10ドットのフォントは、下部が切れて表示されてしまいます。
5x10ドットg,j,p,q,y の5文字+185 文字(5x8ドット)+ユーザー定義の4文字SJ1 はショート(short)※実際には液晶部は 5x11 ドット分あるが、一番下のラインはカーソル表示専用の模様(実機がないので未確認)

<2行のタイプ>
本シールドの裏面の SJ2 をオープン(open)させておく必要が有ります。SJ1 の設定は無視されます。
2行のタイプは、常に 40桁×2行になります。ただし、実際に表示されるのは、40桁中の一部分のみです。例えば、SD1602H ならば、16桁×2行のみの表示です。 残りの桁は、左右にスクロールさせなければ見えませんので、注意して下さい。なお、40桁目と1桁目は繋がっているので、ループします。
例えば、液晶の表示画面サイズが8文字×2行の時は、以下の様になります。
40桁×2行
以下の begin 関数では、rows に 2 を指定してください。cols の指定は無視され、常に 40 として扱われます。
液晶画面の表示可能文字数に関わらず、2行とも常に 40桁まで文字が DDRAM メモリに書き込まれます。1行目の 40桁目を超えると、自動的に2行目の 1桁目に移動します。 2行目の 40桁目を超えると、自動的に1行目の 1桁目に戻ります。\r でその行の 1桁目に戻ります。\n で次の行の 1桁目に移動します。
また、フォントサイズは 5x8ドットのみです。HD44780 の仕様の制約で、5x10ドットは選べれません。

<4行のタイプ>
本シールドの裏面の SJ2 をオープン(open)させておく必要が有ります。SJ1 の設定は無視されます。
4行のタイプは、8桁×4行、10桁×4行、16桁×4行、20桁×4行、の4種類のみの対応です。(ただし、実機確認したのは 20桁×4行のみです)
以下の begin 関数では、rows に 4 を指定してください。cols には 8, 10, 16, 20 のいずれかを指定してください。
また、フォントサイズは 5x8ドットのみです。HD44780 の仕様の制約で、5x10ドットは選べれません。

4行のタイプでも内部的には 40桁×2行の扱いとなっており、液晶側のトリックにより、4行であるかの様な細工がなされています。
例えば、液晶の表示画面サイズが8文字×4行の時は、以下の様になります。
8桁×4行
3行目は、実際は1行目の8桁目以降が表示されています。同様に4行目は、実際は2行目の8桁目以降が表示されています。(16文字×2行の液晶を真ん中で切断して、右半分を下側に移動させた感じです。)
残りの部分も DDRAM メモリ的には存在するので、表示させようと思えば出来なくもないのですが、上記の表示トリックのせいで、スクロール時の挙動が、見かけ上、直感に反する変な挙動になります。 (実際は、8文字×4行の液晶としてではなく、16文字×2行の液晶として見れば、至極真っ当なスクロールの挙動をしています)

余りにも挙動が複雑すぎるので、本シールドでは、4行モードの時のスクロールの対応は断念しました。
begin 関数で指定した cols の値に従って、自動的に改行処理が行われます。各行とも常に cols 桁まで文字が DDRAM メモリに書き込まれます。 cols 桁目を超えると、自動的に次の行の 1桁目に移動します。4行目の cols 桁目を超えると、自動的に1行目の 1桁目に戻ります。\r でその行の 1桁目に戻ります。\n で次の行の 1桁目に移動します。
(この結果、cols×4 だけのDDRAM メモリしか使用しない事になりました。残りの DDRAM メモリは、存在はしてますが、一切使用されません)

なお、40桁×4行の物には対応していませんので注意して下さい。これは、ハード的に HD44780 が2個入っている為です。 本シールドで操作するのは常に1個だけなので、どちらか片方のみ、つまり40桁×2行としてしか操作できません。残り2行は何も表示されません。(それ以前にキャラLCD 接続のピン数が足らない)
本シールド2台あれば出来そうな気がするかもしれませんが、DB0〜DB7, RS の信号がバッティングするので、別途、selector (74157など) が 9bit 分、必要になると思います(試していません)。


・ユーザー定義文字

ユーザー定義文字は、8文字分あります。ただし、フォントサイズが 5x10ドットの時は、半分の4文字分になります。

本シールド電源 ON 直後は、日,月,火,水,木,金,土,♥(ハート記号) が設定されています。
createChar 関数を使って、ユーザーが自由に変更できます。(再度 begin 関数を呼び出すと、日,月,火,水,木,金,土,♥(ハート記号) に戻るので要注意)

ユーザー定義文字は、全角文字の'1'〜'8'か'@'〜'G'を指定すれば、表示させる事ができます。


・ワイド文字列とは

Arduino IDE では、通常の文字列("〜"と書かれている物)とは別に、ワイド文字列(L"〜"と書かれている物)というのが存在します。
通常の文字列では、ASCII は1文字1バイトですが、日本語(半角カナも含む)は1文字3バイトと、メモリ効率が悪くなります。 一方、ワイド文字列の場合、ASCII・ひらがな・カタカナ・カナに関係なく、1文字2バイトになります。この為、ASCII 文字が少なく、和文が多い文章では、ワイド文字列にした方がメモリ効率が良くなります。

ただし、Arduino IDE は、ワイド文字に対応した文字列操作関数を全くサポートしていませんので、単純に「カナ LCD シールド」に表示させる以上の事をさせようとすると、プログラム作成時に大きな制約を受けてしまいます。
この問題ですが、「カナ LCD ライブラリ」には、ワイド文字列⇒通常の文字列に変換するサポート関数(convertWCharToChar)が有りますので、これで回避してください。

また、「通常の文字列」と「ワイド文字列」の区別とは別次元で、「SRAM 上の文字列」と「プログラムメモリ上の文字列」の2種類が存在します。前者は SRAM 上に配置され、プログラムで自由に文字列の内容を変更できますが、後者は Arduino に書き込んだ後は変更できない(固定された)データとなります。この為、組み合わせ的には、以下の4種類の文字列が存在します。

SRAM 上の文字列
(書き換え可能)
プログラムメモリ上の文字列
(書き換え不可能)
通常の文字列char str[ ] = "カタカナ";
※ SRAM を13バイト占有
PROGMEM prog_char pstr[ ] = "カタカナ";
※プログラムメモリを13バイト占有
ワイド文字列wchar_t wstr[ ] = L"カタカナ";
※ SRAM を10バイト占有
PROGMEM prog_wchar pwstr[ ] = L"カタカナ";
※プログラムメモリを10バイト占有

「カナ LCD ライブラリ」でも、これら4種類の文字列に対応するように、4種類の print 関数が存在しますので、適宜、使い分けが必要となります。

SRAM 上の文字列プログラムメモリ上の文字列
通常の文字列print (str)print_P (pstr)
ワイド文字列wprint (wstr)wprint_P (pwstr)

ややこしいですねぇ。まあ、そんなに大量の文章を扱う訳で無い場合は、何も考えずに、SRAM 上の通常の文字列である char 配列を使っておけば、これらの問題は気にしなくても OK です。


・サポートしている機能

「カナ LCD ライブラリ」のサポートしている機能を、以下に列挙します。

定数
定義コメント
KANALCD_MAX_CHARDEFS8ユーザー定義文字の最大値
KANALCD_MAX_ENCODING6サポートしている符号化方式の数
KANALCD_UTF16_BOML'\uFEFF'Byte Order Mark

符号化方式
定義コメント
KANALCD_ENC_UTF80UTF-8 方式 : default
KANALCD_ENC_UTF161UTF-16 方式 (BOM 自動判別) ※最初に KANALCD_UTF16_BOM を送信する必要あり
KANALCD_ENC_UTF16BE2UTF-16 方式 (Big Endian 固定)
KANALCD_ENC_UTF16LE3UTF-16 方式 (Little Endian 固定)
KANALCD_ENC_SJIS4シフトJIS 方式
KANALCD_ENC_EUC_JP5EUC-JP 方式

画面モード:begin 関数の cols, rows で設定し、getScreenMode 関数で取得する
定義コメント
KANALCD_SM_80x10x0080桁×1行, フォント5x8 ※本シールド裏面の SJ2 がショート、SJ1 がオープンの時は、強制的にこのモードになる
KANALCD_SM_80x1L0x1080桁×1行, フォント5x10 ※本シールド裏面の SJ2 がショート、SJ1 もショートの時は、強制的にこのモードになる
KANALCD_SM_40x20x2040桁×2行, フォント5x8
KANALCD_SM_8x40x308桁×4行, フォント5x8
KANALCD_SM_10x40x4010桁×4行, フォント5x8
KANALCD_SM_16x40x5016桁×4行, フォント5x8
KANALCD_SM_20x40x6020桁×4行, フォント5x8

エラーコード ※1〜4 は Wire ライブラリのエラーコードです
定義コメント
KANALCD_ERR_NONE0正常
KANALCD_ERR_TWI_BUFF_FULL1Wire ライブラリの送信バッファが一杯
KANALCD_ERR_TWI_ADDR_NACK2TWI アドレス送信で NACK が返ってきた
KANALCD_ERR_TWI_DATA_NACK3TWI データ送信で NACK が返ってきた
KANALCD_ERR_TWI_OTHER_ERR4Wire ライブラリのその他のエラー
KANALCD_ERR_BUSY0xF0カナ LCD シールドが Busy なので、要求を処理できない
KANALCD_ERR_TIME_OUT0xF1カナ LCD シールドとの通信がタイムアウトした
KANALCD_ERR_INVALID_PARAM0xFB引数が不正
KANALCD_ERR_UNK_CMD0xFCカナ LCD シールドでサポートしていないコマンド
KANALCD_ERR_NOT_INIT0xFD初期化されていない
KANALCD_ERR_UNKNOWN0xFF原因不明のエラーが発生した

typedef 定義
定義コメント
errCode_tuint8_tエラーコード。KANALCD_ERR_xxx のいずれか。
※ただの uint8_t と記述するよりも errCode_t と記述した方が、意味が明確になるから。
prog_charchar PROGMEMプログラムメモリ上の文字 ※実際は avr/pgmspace.h で定義されています
prog_wcharwchar_t PROGMEMプログラムメモリ上のワイド文字 ※avr/pgmspace.h で定義されている prog_char のワイド文字版

#define 定義
定義名定義内容コメント
PSTR(s)(__extension__({static const char __c[ ] PROGMEM = (s); &__c[0];}))プログラムメモリ上の文字列 ※実際は avr/pgmspace.h で定義されています。
C++ の標準仕様ではなく Arduino IDE の拡張機能
kanalcd.print(PSTR("文字列")); という風に使用します
PWSTR(s)(__extension__({static const wchar_t __c[ ] PROGMEM = (s); &__c[0];}))プログラムメモリ上のワイド文字列 ※avr/pgmspace.h の PSTR 定義のワイド文字版
C++ の標準仕様ではなく Arduino IDE の拡張機能
kanalcd.wprint(PWSTR(L"文字列")); という風に使用します


KanaLCD クラスの public メンバー関数 ※ 互換="変更" は LiquidCrystal ライブラリと違いがある関数。 互換="追加" は LiquidCrystal ライブラリには無い関数。
関数名互換戻り値パラメータコメント
KanaLCD変更無しuint8_t twiAddrコンストラクタ:カナ LCD シールドの TWI(i2c) アドレス値を指定する
~KanaLCD無し無しデストラクタ:現 Vesion では、特に何もしません
begin変更errCode_tuint8_t cols,
uint8_t rows,
uint8_t enc = KANALCD_ENC_UTF8,
uint8_t waitTime = 80
カナ LCD シールドを初期化する。cols と rows は上記を参照。
正常に実行された場合は、画面クリア、カーソルと画面スクロールをホーム位置、進行方向:左から右、自動スクロールOFF、LCD 表示、カーソル非点滅、カーソル非表示、バックライト・ソフトOFF になる。
注意:カナ LCD シールドは電源ONした直後、80ms ほど待たないと TWI 通信が開始できない。waitTime はその待ち時間(ミリ秒)。デフォルト値は 80 だが、この関数を呼び出す前に、別の処理で例えば 20ms 待っていれば、その分を差っ引いた 60 にしても構わない。
enderrCode_t無し終了処理。通常呼び出す事は無いでしょう
clearerrCode_t無し画面をクリアし、カーソルと画面スクロールをホーム位置にする ※処理に約 1.72ms かかります
homeerrCode_t無し画面はそのままで、カーソルと画面スクロールをホーム位置にする ※処理に約 1.72ms かかります
setCursorerrCode_tuint8_t col,
uint8_t row
カーソル位置を設定: col=0〜79, row=0〜3 の範囲で指定(実際は上記制約有り)
setEncoding追加errCode_tuint8_t encカナ LCD シールドの符号化方式を変更する。何時でも変更できます。
KANALCD_ENC_xxx のいずれかを指定します。範囲外の値を指定した時は KANALCD_ERR_INVALID_PARAM エラーを返します。
noBlinkerrCode_t無しカーソル位置の文字を点滅させない
blinkerrCode_t無しカーソル位置の文字を点滅させる
noCursorerrCode_t無しカーソルを表示させない
cursorerrCode_t無しカーソルを表示させる
noDisplayerrCode_t無しLCD を表示させない
displayerrCode_t無しLCD を表示させる
noBacklighterrCode_t無しLCD バックライトを OFF させる ※シールド上の DIPSW3 で、バックライト強制 ON モードにしている場合は、当コマンドに関係無く、バックライト ON されます
backlighterrCode_t無しLCD バックライトを ON させる ※シールド上の DIPSW3 で、バックライト強制 ON モードにしている場合は、当コマンドに関係無く、バックライト ON されます
scrollDisplayLefterrCode_t無し表示内容は変更せずに、画面表示を1文字分だけ左スクロールさせる
scrollDisplayRighterrCode_t無し表示内容は変更せずに、画面表示を1文字分だけ右スクロールさせる
moveCursorLeft追加errCode_t無し表示内容は変更せずに、カーソルを1文字分だけ左移動させる
moveCursorRight追加errCode_t無し表示内容は変更せずに、カーソルを1文字分だけ右移動させる
leftToRighterrCode_t無し左から右へカーソルが進む:デフォルト
rightToLefterrCode_t無し右から左へカーソルが進む
autoscrollerrCode_t無し自動スクロールさせる
noAutoscrollerrCode_t無し自動スクロールさせない:デフォルト
createCharerrCode_tuint8_t index,
const uint8_t font_data[8]
ユーザー定義文字フォント(5x8dots)を設定: index=0〜7 の範囲
printsize_tconst __FlashStringHelper * ifshプログラムメモリ上の文字列を表示する?
※__FlashStringHelper を調べてみたのですが、これといった説明が見つかりませんでした。詳細不明です。
printsize_tconst String & ss を表示する
printsize_tconst char str[ ]str を表示する
printsize_tchar cc を表示する
printsize_tunsigned char b,
int base = DEC
b を base に従って表示する
printsize_tint n,
int base = DEC
n を base に従って表示する
printsize_tunsigned int n,
int base = DEC
n を base に従って表示する
printsize_tlong n,
int base = DEC
n を base に従って表示する
printsize_tunsigned long n,
int base = DEC
n を base に従って表示する
printsize_tdouble n,
int digits = 2
n を digits の桁で表示する?
printsize_tconst Printable & xPrintable 派生クラスの printTo メンバー関数を呼び出す
printlnsize_t無し改行だけする
printlnsize_tconst __FlashStringHelper * ifshプログラムメモリ上の文字列を表示する?+改行処理
※__FlashStringHelper を調べてみたのですが、これといった説明が見つかりませんでした。詳細不明です。
printlnsize_tconst String & ss を表示する+改行処理
printlnsize_tconst char str[ ]str を表示する+改行処理
printlnsize_tchar cc を表示する+改行処理
printlnsize_tunsigned char b,
int base = DEC
b を base に従って表示する+改行処理
printlnsize_tint n,
int base = DEC
n を base に従って表示する+改行処理
printlnsize_tunsigned int n,
int base = DEC
n を base に従って表示する+改行処理
printlnsize_tlong n,
int base = DEC
n を base に従って表示する+改行処理
printlnsize_tunsigned long n,
int base = DEC
n を base に従って表示する+改行処理
printlnsize_tdouble n,
int digits = 2
n を digits の桁で表示する?+改行処理
printlnsize_tconst Printable & xPrintable 派生クラスの printTo メンバー関数を呼び出す+改行処理
print_Psize_tconst prog_char * pstrプログラムメモリ上の文字列を表示する
wprintsize_twchar_t wchワイド文字(UTF-16)を1文字表示する
wprintsize_tconst wchar_t * wstrSRAM 上のワイド文字列(UTF-16)を表示する
wprint_Psize_tconst prog_wchar * pwstrプログラムメモリ上のワイド文字列(UTF-16)を表示する
writesize_t...print 関数から呼び出されます。通常、ユーザーが直接呼び出す事はありません
write_Psize_t...print_P 関数から呼び出されます。通常、ユーザーが直接呼び出す事はありません
getStatus追加errCode_t無しカナ LCD シールドの現在の状態を取得する ※カナ LCD シールドが Busy の場合、取得せずに KANALCD_ERR_BUSY エラーを返します
getCursorCol追加uint8_t無し現在のカーソル Col 位置 : 0〜79
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getCursorRow追加uint8_t無し現在のカーソル Row 位置 : 0〜3
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getScreenMode追加uint8_t無し現在の画面モードの状態 : KANALCD_SM_xxx のいずれかの値
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getEncoding追加uint8_t無し現在の符号化方式の状態 : KANALCD_ENC_xxx のいずれかの値
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getLackedCode追加uint8_t無し文字コード欠乏状態:0=充足中, 1=欠乏中
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getBlink追加uint8_t無し現在の点滅の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getCursor追加uint8_t無し現在のカーソル表示の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getDisplay追加uint8_t無し現在の LCD 表示の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getCursorDir追加uint8_t無し現在のカーソル進行方向の状態 : 0=RtoL(右から左), 1=LtoR(左から右)
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getAutoScroll追加uint8_t無し現在の自動スクロールの状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getError追加uint8_t無し現在のカナ LCD シールドのエラーコード : KANALCD_ERR_xxx のいずれかの値
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getLeftSW追加uint8_t無し現在の左スイッチの状態 : 0=OFF, 1=ON
※約10ms間隔で更新されるので、それよりも短い間隔で読み出しても、同じ値しか読み出せません
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getRightSW追加uint8_t無し現在の右スイッチの状態 : 0=OFF, 1=ON
※約10ms間隔で更新されるので、それよりも短い間隔で読み出しても、同じ値しか読み出せません
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getBacklight追加uint8_t無し現在のバックライトの状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KANALCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getKlcdType追加uint8_t無しカナ LCD シールドのタイプ: 常に "BS21LAB-015" を意味する 0x0F が返される
getFirmVer追加uint8_t無しカナ LCD シールドのファームウェアの Version 番号 (例: v1.2 の時は 0x12 になる)

KanaLCD クラスの public メンバー変数
変数名コメント
resuint8_tprint 関数等でエラー発生時の詳細を知る為に使用できます


グローバル関数
文字コード変換サービス関数
Arduino IDE には、ワイド文字(UTF-16)に対応した文字列操作関数が存在しないので、これらのサービス関数にて、ワイド文字列から通常の文字列(UTF-8)に変換してから、文字列操作すると良いでしょう。
buffer は、変換後の UTF-8 文字列を格納するのに十分なサイズである必要があります。だいたい UTF-16 文字列の総バイト数の1.5倍+αが目安です。
注意:バッファあふれのチェックはしていませんので、注意してください。
関数名戻り値パラメータコメント
convertWCharToCharsize_tchar * buffer,
const wchar_t * wstr
SRAM 上の UTF-16 文字列 wstr を、UTF-8 文字列 buffer に変換します。変換後のバイト数を返します。
convertWCharToChar_Psize_tchar * buffer,
const prog_wchar * pwstr
プログラムメモリ上の UTF-16 文字列 pwstr を、UTF-8 文字列 buffer に変換します。変換後のバイト数を返します。


Arduino 用 カナ LCD シールドに戻る

Copyright (C) 2014 BS21 Lab, All rights reserved.