キャラクターLCDやドットマトリクス等の半角カタカナをサポートしているデバイスでカタカナを出力する際、Arduinoのスケッチにそのまま半角カタカナで記述しても文字化けするため、エスケープコードで16進数を書く必要がある。
lcd.print("\xba\xdd\xc6\xc1\xca");
ArduinoのスケッチはユニコードになっているがLCDキャラクターディスプレイはShift-JISのためそのままでは扱えない為である。スケッチのinoファイルをShift-JISで作成し、Arduino IDEで開いてビルド・書き込みも可能だが、Arduino IDE上の表示では豆腐文字になるし、上書きするとデータが壊れる為実用的ではない。
そこで、1602の半角カタカナのみの対応であるが、簡易的にユニコードをShift-JISに変換する関数を作成した。
char jpconv[64];
char* jp(char *text) {
char *cur = &jpconv[0], *chk = text;
while (*chk != 0) {
if ((*chk & 0xff) == 0xef && (*(chk+1) & 0xbc) == 0xbc) {
*cur = (*++chk & 0x02) << 5;
*cur++ = *++chk + *cur;
} else
*cur++ = *chk;
chk++;
}
*cur = 0;
return jpconv;
}
このコードで半角カタカナが実行時ユニコードからShift-JISに変換される。使い方としては、例えば1602キャラクターディスプレイにカタカナを表示する場合の例は以下になる。文字列を jp() で囲むだけ。
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char jpconv[64];
char* jp(char *text) {
char *cur = &jpconv[0], *chk = text;
while (*chk != 0) {
if ((*chk & 0xff) == 0xef && (*(chk+1) & 0xbc) == 0xbc) {
*cur = (*++chk & 0x02) << 5;
*cur++ = *++chk + *cur;
} else
*cur++ = *chk;
chk++;
}
*cur = 0;
return jpconv;
}
void setup() {
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(jp("カンタンニホンゴ"));
}
void loop() {
}
カタカナは下記コードの範囲に対応。句読点濁点括弧などすべて半角で入力する事。Windowsであれば文字入力後 Ctrl + O で半角になる。
スケッチの簡単な解説。1602のLCD等はASCIIコードで文字列を扱っており、1文字1バイトで0~255の数字で文字を指定する。上記カタカナは0xa1~0xdfの範囲である。
Arduinoのスケッチはユニコードで文字を扱う為、半角英数はASCIIコードと同じだが半角カタカナは3バイト構成となっている。以下の様な表になる。
文字 | ユニコード | ASCII |
。 | ef bd a1 | a1 |
「 | ef bd a2 | a2 |
」 | ef bd a3 | a3 |
、 | ef bd a4 | a4 |
・ | ef bd a5 | a5 |
ヲ | ef bd a6 | a6 |
ァ | ef bd a7 | a7 |
ィ | ef bd a8 | a8 |
ゥ | ef bd a9 | a9 |
ェ | ef bd aa | aa |
・・・ | ||
ソ | ef bd bf | bf |
タ | ef be 80 | c0 |
チ | ef be 81 | c1 |
ツ | ef be 82 | c2 |
・・・ | ||
ロ | ef be 9b | db |
ワ | ef be 9c | dc |
ン | ef be 9d | dd |
゙ | ef be 9e | de |
゚ | ef be 9f | df |
カタカナはefで始まり、bdが続く場合3バイト目がそのままASCIIコード。beが続く場合は3バイト目に0x40を足した数がASCIIコードなる。
処理としては、一文字ずつ調べて行って0xefでなければそのままコピー、0xefなら次のバイトを見て0xbdであればその次をそのままコピー、0xbeならその次に0x40を足してコピーして変換した文字列を作成する。その処理をコンパクトにまとめたのが上記関数になる。