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

10/nov/2012 新規
13/nov/2012 更新

漢字 LCD ライブラリの解説です。

  1. ワイド文字列とは
  2. 添付のサンプル・スケッチ
  3. サポートしている機能

・ワイド文字列とは

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 を10バイト占有
PROGMEM prog_char pstr[ ] = "日本語";
※プログラムメモリを10バイト占有
ワイド文字列wchar_t wstr[ ] = L"日本語";
※ SRAM を8バイト占有
PROGMEM prog_wchar pwstr[ ] = L"日本語";
※プログラムメモリを8バイト占有

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

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

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


・添付のサンプル・スケッチ

「漢字 LCD ライブラリ」には、9つのサンプル・スケッチが添付されています。
Arduino IDE の「ファイルメニュー」⇒「スケッチの例」⇒「KanjiLCD」で選択する事が可能です。
スケッチの例の選択方法

・klcd_graphic_demo1簡易グラフィック機能を表示するデモです。L/R スイッチを押すと、デモ画面が切り替わります。
・klcd_JIS_L3_char「漢字 LCD シールド」でサポートしている JIS 第三水準文字を表示します。L/R スイッチを押すと、次/前の画面に切り替わります。
・klcd_long_text長文(平成23年法律第2号「平成二十三年東北地方太平洋沖地震に伴う地方公共団体の議会の議員及び長の選挙期日等の臨時特例に関する法律」の本文の全文。法律は著作権法の保護対象外です。)を、ソフトで分割しながら表示させます。L スイッチを押すと、次の画面に進みます。禁則処理といった高度な処理はしていないので、レイアウト的に変な位置に句読点が表示されたりします。コンパイルすると約 11.7kB になります。
・klcd_long_text_wcharklcd_long_text のワイド文字版です。ほぼ全角文字だけの文章なので、コンパイルすると 9.2kB に縮まります。和文が多いと、ワイド文字の方が有利になる例です。
・klcd_mini_sketch「日本語で表示」と表示するだけの最小スケッチ例です。
・klcd_rocket_bitmap昭和チックな有人ロケットもどき(絵心ゼロの小生画)が、画面をゆっくりと横切ります。とてもショボいです。(下の画像参照)
・klcd_text_demo1「漢字 LCD シールド」の機能を説明するデモです。L/R スイッチを押すと、次/前の画面に切り替わります。14kB 弱なので、未確認ですがフラッシュが 16kB の Arduino Duemilanove 等でもデモできると思います。なお、デモで表示される文章に「組見本用創作文『問わずがたりの洋酒外史』JIS 第1水準バージョン」Copyright (C) 1990 by Akira Satoh [Directed by TYPE-LABO and NAVEL]を使用させて頂いております。
・klcd_text_demo1_wcharklcd_text_demo1 のワイド文字版です。プログラムの作り方が悪いせいで、全角文字が多いにも関わらず、コンパイル後のサイズが縮まっていません。作り方を変えれば、縮まると思いますが、プログラムが複雑になるので、そこまでやってません。
・klcd_wchar_str_opArduino IDE でワイド文字列を操作する方法のサンプルコードです。

小学生が書いたのか?と思うようなロケットもどきのビットマップ表示

・サポートしている機能

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

定数
定義コメント
KLCD_MAX_COLS16漢字 LCD シールドの最大桁数
KLCD_MAX_ROWS2漢字 LCD シールドの最大行数
KLCD_MAX_WIDTH128漢字 LCD シールドの最大グラフィック表示幅
KLCD_MAX_HEIGHT32漢字 LCD シールドの最大グラフィック表示高さ
KLCD_MAX_ENCODING6サポートしている符号化方式の数
KLCD_UTF16_BOML'\uFEFF'Byte Order Mark

符号化方式
定義コメント
KLCD_ENC_UTF80UTF-8 方式 : default
KLCD_ENC_UTF161UTF-16 方式 (BOM 自動判別) ※最初に KLCD_UTF16_BOM を送信する必要あり
KLCD_ENC_UTF16BE2UTF-16 方式 (Big Endian 固定)
KLCD_ENC_UTF16LE3UTF-16 方式 (Little Endian 固定)
KLCD_ENC_SJIS4シフトJIS 方式
KLCD_ENC_EUC_JP5EUC-JP 方式

エラーコード ※1〜4 は Wire ライブラリのエラーコードです
定義コメント
KLCD_ERR_NONE0正常
KLCD_ERR_TWI_BUFF_FULL1Wire ライブラリの送信バッファが一杯
KLCD_ERR_TWI_ADDR_NACK2TWI アドレス送信で NACK が返ってきた
KLCD_ERR_TWI_DATA_NACK3TWI データ送信で NACK が返ってきた
KLCD_ERR_TWI_OTHER_ERR4Wire ライブラリのその他のエラー
KLCD_ERR_BUSY0xF0漢字 LCD シールドが Busy なので、要求を処理できない
KLCD_ERR_TIME_OUT0xF1漢字 LCD シールドとの通信がタイムアウトした
KLCD_ERR_INVALID_PARAM0xFB引数が不正
KLCD_ERR_UNK_CMD0xFC漢字 LCD シールドでサポートしていないコマンド
KLCD_ERR_NOT_INIT0xFD初期化されていない
KLCD_ERR_UNKNOWN0xFF原因不明のエラーが発生した

typedef 定義
定義コメント
errCode_tuint8_tエラーコード。KLCD_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 の拡張機能
klcd.print(PSTR("文字列")); という風に使用します
PWSTR(s)(__extension__({static const wchar_t __c[ ] PROGMEM = (s); &__c[0];}))プログラムメモリ上のワイド文字列 ※avr/pgmspace.h の PSTR 定義のワイド文字版
C++ の標準仕様ではなく Arduino IDE の拡張機能
klcd.wprint(PWSTR(L"文字列")); という風に使用します


KanjiLCD クラスの public メンバー関数
関数名戻り値パラメータコメント
KanjiLCD無しuint8_t twiAddrコンストラクタ:漢字 LCD シールドの TWI(i2c) アドレス値を指定する
~KanjiLCD無し無しデストラクタ:現 Vesion では、特に何もしません
beginerrCode_tuint8_t cols,
uint8_t rows,
uint8_t enc = KLCD_ENC_UTF8,
uint8_t waitTime = 120
漢字 LCD シールドを初期化する。cols=16, rows=2 のみ指定可能。
正常に実行された場合は、画面クリア、カーソル位置 (0,0)、LCD 表示、カーソル非点滅、カーソル非表示、バックライト・ソフトOFF になる。
注意:漢字 LCD シールドは電源ONした直後、120ms ほど待たないと TWI 通信が開始できない。waitTime はその待ち時間(ミリ秒)。デフォルト値は 120 だが、この関数を呼び出す前に、別の処理で例えば 20ms 待っていれば、その分を差っ引いた 100 にしても構わない。
enderrCode_t無し終了処理。通常呼び出す事は無いでしょう
clearerrCode_t無し画面をクリアし、カーソル位置を (0,0) にする ※処理に約 60ms かかります
homeerrCode_t無し画面はそのままで、カーソル位置だけ (0,0) にする
setCursorerrCode_tuint8_t col,
uint8_t row
カーソル位置を設定: col=0〜15, row=0〜1 の範囲で指定 ※全角文字は偶数colのみ指定可能です
setEncodingerrCode_tuint8_t enc漢字 LCD シールドの符号化方式を変更する。何時でも変更できます。
KLCD_ENC_xxx のいずれかを指定します。範囲外の値を指定した時は KLCD_ERR_INVALID_PARAM エラーを返します。
noBlinkerrCode_t無しカーソル位置の文字を点滅させない
blinkerrCode_t無しカーソル位置の文字を点滅させる ※半角/全角に関係なく、常に全角文字単位で点滅されます。
noCursorerrCode_t無しカーソルを表示させない
cursorerrCode_t無しカーソルを表示させる ※半角/全角に関係なく、常に全角文字単位で表示されます。
noDisplayerrCode_t無しLCD を表示させない
displayerrCode_t無しLCD を表示させる
noBacklighterrCode_t無しLCD バックライトを OFF させる ※シールド上の DIPSW4 で、バックライト強制 ON モードにしている場合は、当コマンドに関係無く、バックライト ON されます
backlighterrCode_t無しLCD バックライトを ON させる ※シールド上の DIPSW4 で、バックライト強制 ON モードにしている場合は、当コマンドに関係無く、バックライト ON されます
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 関数から呼び出されます。通常、ユーザーが直接呼び出す事はありません
getStatuserrCode_t無し漢字 LCD シールドの現在の状態を取得する ※漢字 LCD シールドが Busy の場合、取得せずに KLCD_ERR_BUSY エラーを返します
getCursorColuint8_t無し現在のカーソル Col 位置 : 0〜15
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getCursorRowuint8_t無し現在のカーソル Row 位置 : 0〜1
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getEncodinguint8_t無し現在の符号化方式の状態 : KLCD_ENC_xxx のいずれかの値
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getLackedCodeuint8_t無し文字コード欠乏状態:0=充足中, 1=欠乏中
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getBlinkuint8_t無し現在の点滅の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getCursoruint8_t無し現在のカーソル表示の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getDisplayuint8_t無し現在の LCD 表示の状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getErroruint8_t無し現在の漢字 LCD シールドのエラーコード : KLCD_ERR_xxx のいずれかの値
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getLeftSWuint8_t無し現在の左スイッチの状態 : 0=OFF, 1=ON
※約10ms間隔で更新されるので、それよりも短い間隔で読み出しても、同じ値しか読み出せません
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getRightSWuint8_t無し現在の右スイッチの状態 : 0=OFF, 1=ON
※約10ms間隔で更新されるので、それよりも短い間隔で読み出しても、同じ値しか読み出せません
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getBacklightuint8_t無し現在のバックライトの状態 : 0=OFF, 1=ON
※直前に getStatus 関数を呼び出し、KLCD_ERR_NONE が返ってきたのを確認してから、呼び出してください
getKlcdTypeuint8_t無し漢字 LCD シールドのタイプ: 常に "BS21LAB-002" を意味する 0x02 が返される
getFirmVeruint8_t無し漢字 LCD シールドのファームウェアの Version 番号 (例: v1.2 の時は 0x12 になる)

KanjiLCD クラスの public メンバー関数:グラフィック描画
一旦、漢字 LCD コントローラ内の仮想画面(横128×縦32)に描いておいてから、flip 関数で一括して LCD へ転送する事で、初めて表示されます。
引数の x/x0/x1 は 0〜127、y/y0/y1 は 0〜31、color は 0 の時は消去、0 以外の時は描画、です。
注意1:文字を書くと、半角文字なら 16x8 単位、全角文字なら 16x16 単位で、その部分のグラフィックが消えます。つまり、文字とグラフィックは重ねられません。
注意2:激しく遅いです。過度の期待はしないように。
pseterrCode_tuint8_t x,
uint8_t y,
uint8_t color
仮想画面に点を描画
lineerrCode_tuint8_t x0,
uint8_t y0,
uint8_t x1,
uint8_t y1,
uint8_t color
仮想画面に線を描画
recterrCode_tuint8_t x0,
uint8_t y0,
uint8_t x1,
uint8_t y1,
uint8_t color
仮想画面に四角形(塗りつぶし)を描画
bitmaperrCode_tuint8_t x,
uint8_t y,
uint8_t size,
const uint8_t * bitmap
仮想画面に Bitmap(モノクロ8画素単位)を1ライン分転送:
x は8画素単位(0,8,16,...,120)の指定。
size は転送バイト数。画面右端を超える分の bitmap は無視される。
bitmap_PerrCode_tuint8_t x,
uint8_t y,
uint8_t size,
const prog_uint8_t * bitmap
bitmap が Program メモリ上にある場合は、こちらを使用してください
fliperrCode_tuint8_t x0,
uint8_t y0,
uint8_t x1,
uint8_t y1
仮想画面から LCD のグラフィック面に転送:ここで初めて LCD に表示される ※処理に最大約 60ms かかります

KanjiLCD クラスの 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) 2012 BS21 Lab, All rights reserved.