Arduinoを使って8X8マトリクスLEDに日本語テキスト文字を表示する

by ボクにもわかる地上デジタル

[Arduino Menu] [XBee Menu] [地デジ Menu]


 

はじめに

 このページではArduinoから直接(制御ICなどを使用しないで)マトリクスLEDにテキスト文字(アルファベットと数字)を表示する方法について説明します。ひらがな、カタカナ、一部の漢字の表示方法についても説明します。日本語表示については上の動画を、製作例とサンプルスケッチは以下は動画を再生してみて下さい。

 
Arduinoシールド製作例(左)とブレッドボード上での製作例(右)

※高速点滅しながらスクロールしており、きれいに撮影できませんでした。(実物はもっと見やすい)

マトリクスLEDの表示方式

 マトリクスLEDに文字を表示する際、一般的にダイナミック点灯と呼ばれる点灯方式を使用します。ダイナミック点灯方式ではマトリクスLEDの1列ずつを一瞬だけ点灯制御する方式で、その他の画素は残像で見える方式です。(ブラウン管の走査線にも似ています。)
 今回はそのダイナミック点灯をArduinoマイコンから直接ドライブする方式を用います。つまりArduinoがマトリックスLEDの制御用ドライバとして動作します。他にもマイコンをマトリクスLED側に内蔵してI2Cなどのシリアルインタフェースを持つ商品や論理回路などによって独自のパラレルやシリアル転送方式で表示する高機能なマトリクスLEDモジュールも売られています。
 直接ドライブ方式の利点は安価であることです。マトリクスLEDは秋月で200円で売られており、負荷抵抗や基板代、コネクタ代など合わせてもしれてます。欠点は列方向と行方向でそれぞれ8信号の計16信号をマトリクスLEDの表示だけで使用してしまうことです。19本の端子の実に84%を使ってしまうのです。
 さらに、文字フォントを自分でいちいち作成して表示するのは手間がかかるので、アルファベットと数字のフォントはフリーのものを流用することでスケッチ内ではテキスト文字の入力で表示し、スクロール表示するようにしました。
 Arduinoのメインプログラムを定義する関数loop()内のわずか3行で、表示を実行します。ここに自由にプログラムを追加すれば、例えば、XBeeで受信したテキスト文字を表示することも簡単です。


シールドの製作例(実際の点灯状態は、もっと良好です。)

アノードコモンとカソードコモン

 LEDには極性があり、アノードからカソードに電流が流れた時に点灯します。全てのLEDの端子をマトリクスLEDから取り出すのは無駄なので、アノードもしくはカソードのどちらか片方を1つの端子に集めて共通端子にするのが一般的です。数字を表示する「7セグメントLED」ではアノードを集めたタイプをアノードコモン、カソードを集めたタイプをカソードコモンと呼びます。

 以下の話は少しややこしいので、マトリクスLEDには極性に起因したA方式とB方式の2種類があると理解していただいていれば、次の節に進んでもらって結構です。
 8X8マトリクスLEDにおいても、行か列の8個のLEDのアノードもしくはカソードを集めて一つのコモン端子に接続されています。ところが、その集めた共通のコモン端子も8個あり、回路的にはコモン端子と呼べる端子がどちらも対等になっていまいます。そこで列(COL側)がアノードコモンとなっているタイプをAタイプ、行(ROW側)がアノードコモンとなっているタイプをBタイプと呼んで区別します。

マトリクスLEDにおける極性(アノードコモンとカソードコモン)
部品名 タイプ COL側コモンの時 ROW側コモンの時
OSL641501-ARA Aタイプ COL側アノードコモン ROW側カソードコモン
OSL641501-BRA Bタイプ COL側カソードコモン ROW側アノードコモン

 つまり、アノードコモンなのかカソードコモンなのかは使い方次第です。列(COL)ごとに点灯させる場合、COL側コモンとなりAタイプのマトリクスLEDをアノードコモンと呼ぶことになりますが、同じ部品でも行(ROW側)ごとに表示を行う場合はカソードコモンと呼びます。とても、ややこしいので、Aタイプ、Bタイプと呼ぶほうが良いでしょう。

ハードウェアの製作A(ブレッドボード)

 マトリクスLEDは秋月で売られている「OSL641501-ARA」や「OSL641501-BRA」の他、ダイナミック点灯に対応しているものであれば、(おそらく)どれでも良いと思います。ただし、OSL641501-BRAのようなアノードコモン(Bタイプ)やピン配列が異なっていてもスケッチに少しだけ追記が必要です。
 当方のスケッチでは列(COL側)がコモンになります。LEDの電流制限用の抵抗は行(ROW側)に入れてください。このような説明は上記やArduinoのサイトにも書かれていませんのでした。間違えると画素によって明るさが違ってしまいます。
 秋月で売られているOSL641501-ARAやOSL641501-BRAの他、多くのマトリクスLEDには部品の4辺に凹または凸があり、並べて接続した時に位置がずれないように工夫されています。このうち2辺の凸部が左側と下側にくるように配置した時に左下のピン番号が1番ピンで右に向かって8番ピンまであります。9番ピンから16番ピンは上側列の右から順に振られます(全てLED点灯面から見た時の方向)。詳しくは下図を参照してください。


マトリクスLEDの直接ドライブ方式の回路図

マトリクスLEDのArduino用スケッチ

マトリクスLEDのArduino用スケッチ

#include "FrequencyTimer2.h"

#define DISPLAY_COLS  240   // 表示用のバッファサイズ 最大256-16
#define LED_COMMON   1    // LEDの極性。カソードがROW側(Aタイプ)は0、COL側(Bタイプ)は1

const static
//       /*LED  */ -- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
byte pins[17]= /*Arduino*/ {-1, 5, 4, 3, 2,14,15,16,17,13,12,11,10, 9, 8, 7, 6};

const static
byte cols[8] = {pins[13],pins[ 3],pins[ 4],pins[10],pins[ 6],pins[11],pins[15],pins[16]};
const static
byte rows[8] = {pins[ 9],pins[14],pins[ 8],pins[12],pins[ 1],pins[ 7],pins[ 2],pins[ 5]};

byte col = 0;
byte leds[DISPLAY_COLS];
byte pattern=0;
byte pattern_max=0;

void setup() {
  byte i;
  for(i=1;i<=16;i++) pinMode(pins[i], OUTPUT);      // sets the pins as output
  for(i=1;i<= 8;i++) digitalWrite(cols[i - 1], LOW);   // set up cols and rows
  for(i=1;i<= 8;i++) digitalWrite(rows[i - 1], LOW);
  clearLeds();
  FrequencyTimer2::disable();               // Turn off toggling of pin 11
  FrequencyTimer2::setPeriod(2000);            // Set refresh rate
  FrequencyTimer2::setOnOverflow(display);        // Set interrupt routine to be called
  setPattern("Hello! I'm Arduino.");
}

void loop() {
  pattern = ++pattern;
  if(pattern > pattern_max)pattern=0;
  delay(75);
}

void clearLeds() {
  for(int i = 0; i < DISPLAY_COLS; i++) leds[i] = 0x00;  // Clear display array
}

void setPattern(char *s) {
  int i=0,j;
  pattern=0;
  while(s[i] != '\0' && pattern < DISPLAY_COLS-8){
    pattern += Font_Draw(s[i],pattern,-1);
    i++;
  }
  pattern_max = pattern+16;
  pattern=0;
}

void display() {
  byte row;
  digitalWrite(cols[col], LED_COMMON);          // Turn whole previous column off
  col++;
  if (col == 8) col = 0;
  
  for (row = 0; row < 8; row++) {
    if( col+pattern >= 8 &&
      col+pattern < pattern_max-8 &&
      (leds[col+pattern-8]>>row)&1 == 1  ){
      digitalWrite(rows[row], LED_COMMON);      // Turn on this led
    } else digitalWrite(rows[row], !LED_COMMON);
  }
  digitalWrite(cols[col], !LED_COMMON);          // Turn whole column on at once
}

動作確認用のサンプルスケッチのダウンロード

ダウンロード:マトリクスLEDのArduino用スケッチ「matrix1.zip

 ダウンロードしたZIPを展開し、FrequenctTimer2フォルダを「...\Arduino\libraries」フォルダへコピーしてからArduino IDEを起動し、スケッチ本体「matrix1.ino」を開きます。
 スケッチ「matrxi_serial.ino」の方はシリアル(9600baud)で受信したテキストをスクロール表示します。

 ハードウェアによってスケッチの変更が必要です。#define LED_COMMON、byte pins、byte cols、byte rowsの内容を必ず確認してください。(リリースするたびに変更する可能性があります。)

スケッチの変更部分
変更部分 条件 記述内容
#define
byte pins
LED=Aタイプ 0
LED=Bタイプ 1
const static
LED_COMMON
ブレッド試作 -1, 5, 4, 3, 2,14,15,16,17,13,12,11,10, 9, 8, 7, 6
シールド製作 -1,13,12,11,10,14,15,16,17, 2, 3, 4, 5, 6, 7, 8, 9

 なお、使用しているFrequenctTimer2ライブラリはArduino LeonardoなどATmega32u4を搭載したマイコンボードでは動作しません。Arduino Uno, DuemilanoveなどATmega328Pを搭載したマイコンボードを使用してください。

ハードウェアの製作B(シールドの製作)

 次にArduino用シールドの製作例です。使用する部品は全て秋月電子通商で手に入ります。配線はシールドのパターンを引き回しやすいようにブレッドボードの配線とは異なる配線を行いました。

Arduino用マトリクスLEDシールドの部品リスト
部品名 参考単価 数量 参考価格
マトリクスLED 8x8ドット OSL641501-ARA 200円 1個 200円
Arduino用ユニバーサル基板 200円 1個 200円
ピンヘッダ(オス) 1X40 (40P) 40円/40ピン 28ピン 28円
丸ピンICソケット(シングル20P) 60円/20ピン 16ピン 48円
抵抗 100Ω 100円/100個 10個 10円
合計 486円


表面のパターン図例


裏面のパターン図例

 LEDへの配線パターンの変更に伴い、スケッチのpins定義の箇所を以下のように書き換えます。

   変更前:byte pins[17]= /*Arduino*/ {-1, 5, 4, 3, 2,14,15,16,17,13,12,11,10, 9, 8, 7, 6};
   変更後:byte pins[17]= /*Arduino*/ {-1,13,12,11,10,14,15,16,17, 2, 3, 4, 5, 6, 7, 8, 9};

日本語表示(ひらがな、かたかな、少しの漢字)用 Arduino スケッチ

 以上の製作品で日本語表示を行うためのArduinoスケッチを紹介します。このスケッチを使うと、ひらがな、カタカナ、そして一部の漢字を表示することが可能です。スケッチは以下からダウンロードします。ダウンロードしたファイルにはライブラリが含まれます。「FrequenctTimer2」と「Time」フォルダを「...\Arduino\libraries」フォルダへコピーしてからArduino IDEを起動してください。起動後にスケッチ本体「matrix_kanji.ino」を開きます。そして前述のスケッチ内のpins定義を製作したハードウェアに合わせて変更します。

ダウンロード:日本語表示マトリクスLEDのスケッチ「matrix_kanji.zip

 スケッチをArduinoに書き込むと自動的に日本語フォントがArduino内のEEPROMに書き込まれます。日本語文字は1バイトのひらがな文字とカタカナ文字が中心ですが、少しだけ漢字も含まれます。以下にコード表を示します。(あまり使わない記号などで表示されない文字があります。)

日本語マトリクスLEDの文字コード表

    |   00 10 20 30 40 50 60 70 80 90 A0 B0 C0 D0 E0 F0
----+---------------------------------------------------
00  |   NL DE SP 0 @ P ‘ p 値 温 □ ー た み □ □ 
01  |   SH D1 ! 1 A Q a q 月 湿 。 あ ち む □ □ 
02  |   SX D2 ” 2 B R b r 火 照 「 い つ め □ □ 
03  |   EX D3 # 3 C S c s 水 明 」 う て も □ □ 
04  |   ET D4 $ 4 D T d t 木 電 、 え と や □ □ 
05  |   EQ NK % 5 E U e u 金 気 ・ お な ゆ □ □ 
06  |   AK SN & 6 F V f v 土 圧 を か に よ □ □ 
07  |   BL EB ’ 7 G W g w 日 池 ぁ き ぬ ら □ □ 
08  |   BS CN ( 8 H X h x 年 測 ぃ く ね り □ □ 
09  |   HT EM ) 9 I Y i y 時 定 ぅ け の る □ □ 
0A  |   LF SB * : J Z j z 分 室 ぇ こ は れ □ □ 
0B  |   HM EC + ; K [ k { 秒 計 ぉ さ ひ ろ □ 今 
0C  |   CL → , < L ¥ l | 円 刻 ゃ し ふ わ □ 天 
0D  |   CR ← − = M ] m } 度 中 ゅ す へ ん □ 地 
0E  |   SO ↑ . > N ^ n  ̄ 外 上 ょ せ ほ ゛ □ 切 
0F  |   SI ↓ / ? O _ o DL 内 下 っ そ ま ゜ UT 入 

 表示したい文字を文字列変数rxに格納すると、表示内容を変更することが出来ます。例えばsetup()関数内のsprintfを書き換えます。文字は全て半角(1バイト文字)です。Windowsであれば全角で入力してF8を押すと半角文字に変換できます。また、表示はひらがなになります。カタカナを表示したい場合は文字を"{"と"}"でくくります。漢字を表示したい場合は"{"と"}"の間に16進数で文字コードを入れます。

日本語表示部のスケッチ書き換え
表示内容 命令
123ABCdef sprintf(rx,"123ABCdef");
あいうえおかきくけこ sprintf(rx,"アイウエオカキクケコ");
ひらがなカタカナ sprintf(rx,"ヒラガナ{カタカナ}");
ボクにもわかる地上デジタル sprintf(rx,"{ボク}ニモワカル{FD}{9E}{デジタル}");
ボクにもわかる地上デジタル sprintf(rx,"{ボク}ニモワカル%c%c{デジタル}",(char)0xFD,(char)0x9E);

読めない場合はこちら

 日本語フォントは一度、Arduinoに書き込めば、以降は書き込む必要がありません。スケッチ「matrix_kanji.ino」と同じフォルダ内「font.ino」の「EEPROM_WRITE」の#defineを消去すると、以降は書き込みを実行しなくなり、スケッチのプログラムサイズを1400バイトほど節約することが出来ます。ただし、新しいArduinoを使用する場合は、再度、書き込みが必要ですので、EEPROM_WRITEの定義を戻す(#define EEPROM_WRITEを追加する)必要があります。

 シリアルで入力した文字を表示することが出来ます。さらに[ESC][T]に続いて「19:12」のように時刻を入力すると、以降、時計として時刻を表示し続けます。ただし、Arduino上の水晶クロックは時計用ではないので、あまり正確な時計ではありません。例えば、パソコンを起動するたびにデータを送るなどの工夫が必要です。

時計設定フォーマット
時刻 送信シリアルデータ
0:00 [ESC][T][0][0][:][0][0]
AM 6:30 [ESC][T][0][6][:][3][0]
PM 6:30 [ESC][T][1][8][:][3][0]

 なお、ArduinoマイコンにはArduino Uno, DuemilanoveなどのATmega328Pを搭載したマイコンボードを使用してください。(Arduino Leonardoでは動作しません。)

日本語フォント(美咲フォント)

 ここでは日本語フォントに美咲フォントを使用しました。詳しくはスケッチ「font.ino」中の参考文献に記しています。Arduinoで使いやすいようにフォントの変換を行うユーティリティについてはダウンロードした「参考資料_Fontx2Util」フォルダを参照してください。

秋月電子32X16ドットLED電光掲示板用拡張表示ユニット

 最後に秋月電子通商で販売されていた32X16ドットLED電光掲示板用拡張表示ユニットとArduinoとを接続して、上段に時刻表示を、下段にテキスト文字がスクロールする置時計を製作します。
 ただし、秋月電子通商で販売されていたマトリクスLED C-2AAOSRDTを2つ用いた「32×16ドットLED電光掲示板用拡張表示ユニット(¥2,500)」( 32×16ドットLEDマトリクス表示装置パーツセット)は2014年3月頃に販売終了し、互換性の無いAdafruit製の「RGBフルカラードットマトリクスLEDパネル」(¥2,880)へ移行してしまいました。
 テキスト文字はシリアルで受信します。シリアル(Digital 0番ピン=RXと1番ピン=TX)にXBeeモジュールを接続すれば、遠隔で表示文字を変更することも出来ます。


 マトリクスLEDのドライバは、これまでのサンプルで使用した8X8ドット用の画面(画像データ)を参考文献「なんでも作っちゃう、かも。」へ転送する2重構造になっています。メモリーの無駄使いではありますが、秋月用のフォーマットに変換する部分を他力に頼ったので、とりあえず動くものを1時間ほどで完成させることが出来ました。Arduino用のライブラリは多くの人が配布しており、それらを流用させていただくことで、てっとり早く動くものが出来上がります。フォントは前のサンプルと同じ美咲フォントです。

ダウンロード:秋月電子32X16マトリクスLED時計のスケッチ「matrix_clock.zip

 ダウンロードしたスケッチはREADME.txtにしたがってインストールしてください。また、「matrix_clock.ino」内の下記の部分は秋月表示ユニットとArduinoとの接続ピンの定義です。左から順にDigital 2番ピン=SIN 1、Digital 3番ピン=SIN 2、Digital 4番ピン=SIN 3、Digital 5番ピン=CLOCK、Digital 6番ピン=LATCH、Digital 7番ピン=STROBEに接続することを示しています。

AkiMatrix myMatrix = AkiMatrix(2,3,4,5,6,7);

参考文献

  ・http://playground.arduino.cc/Main/DirectDriveLEDMatrix
  ・http://playground.arduino.cc/uploads/Main/Matrix.gif
  ・趣味的工作日誌 http://www.surveytec.com/cgi-bin/diarypic/diary.cgi?no=32
  ・なんでも作っちゃう、かも。http://arms22.blog91.fc2.com/blog-entry-220.html
  ・Arduinoをはじめよう (Massimo Banzi著 船田功訳 オライリージャパン)
  ・Arduino 日本語リファレンス http://www.musashinodenpa.com/arduino/ref/


Arduinoメインメニューへ戻る

XBeeメインメニューへ戻る

地デジトップへ戻る


秋月電子 Arduino互換ボードの使い方

Arduinoで湿度を測定する

Arduino用液晶シールド

Arduino 赤外線リモコンコード解析

Arduino用Wi-Fi無線LAN

Arduino用 EasyVR Shield で音声認識

ArduinoとXBeeとの接続