dot_matrix_LED_drive

LEDドットマトリクス駆動

横32dot、縦16dotのドットマトリクスLED表示を使ったネタです。

/media/uploads/morita/image_20140531234905a.jpg

mbed用にドライブライブラリを用意しました。

ライブラリを使用したデモです。
キャラクター表示動作確認デモ
加速度センサーを使った波形表示デモ
mbedの文字を跳ね返りながら表示するデモ

  • dot表示ボードについて

市販品がいろいろ出ていますが、デジットから入手したものを使用しています。 dotマトリクス表示モジュールにドライバー回路を自作しても動作すると思います。

  • 表示ボードの構成

表示のコントロール用として、データ線が3本、クロック線が1本、ラッチ線が1本、エネーブル線が1本出ています。
表示データはクロックに同期させて、16bit分をシリアルに送る方法となっています。
今回利用したモノは横32dotですが、左右に2分割されており、各16dotを別々に送り込む形式になっています。
表示データ用のシフトレジスタICですが、内部は、16bitシリアルINパラレルアウトのシフトレジスタ、16bitパラレルラッチ、16回路のドライバーで構成されています。
シリアルINに入力したデータは、一回のクロックにより、INデータ->b0->b1->b2...b14->b15と転送されます。
16回の操作で、b0からb15にデータが揃います。
最初のクロックでシフトINされたデータは最終的にはb15に到達し、最後の16個目のクロックでシフトINしたデータはb0に置かれる事になります。

/media/uploads/morita/d3216_pic1.jpg

  • 表示の仕組み

dotのON/OFF情報は、横方向の16dot×2と、縦方向16列を同時に選択する方式で、交点の点灯、消灯を横方向のbitで指定します。
縦方向は16ですので、デコードされていれば4bitで選択可能ですが、使用したものは、16bitのシフトレジスタにそのままつながっています。
(あまり意味がありませんが多重選択も可能)
通常は、1スキャン毎にどれかのbitを1にしたデータを送り込む事になります。

手順で書くと、
1、左側16dot分の表示データ、右側16dot分の表示データ、縦方向の光らせたい列のデータの計3組、おのおの16bit分を用意します。
2、3組のデータをシリアル送り(クロックは共通)で16bit分転送します。
3、ラッチ信号を使って、今送り込んだデータを表示にまわします。
上記の手順は、横1本分ですので、上から下に(下から上でも良い)順に表示を行えば、全体が光って見える算段となっています。

このように、16回の操作で面全体が表示され仕組みですが、メモリは搭載されておらず、目の残像効果で全てのドットを表示します。
このため、表示を維持する間は、データ送信を止める事はできません。

表示としての、ちらつきの限界は50Hz程度です。16行の表示にかかる時間はそのまま倍数になりますので、データを送る間隔は16倍速くなければなりません。
50Hzの場合は16を乗算して、800Hzとなります。
この表示データを送る間隔は、普通に表示できる最低更新レートになります。
しかし、50Hzの更新では、視線の移動などで、ちらつきが気になります。
速くする、たとえばレートを400Hzくらいにすると劇的に改善されますが、400Hzだと16スキャン分で6.4KHz必要になります。
この速度はARMプロセッサの割り込みで、問題なく扱う事ができます。
ライブラリの初期値は200uS間隔、5KHzとしていますので、更新レートは312.5Hzになります。

  • 実際の転送方法

データの転送はSPIとほとんど同じですが、3組のデータを1つのクロックで転送するSPIの内蔵ペリフェラルは無い(多分?)と思われますので、ソフトで実行します。
使用した表示ボードの最大転送速度は10Mbpsなので、CPUの実行速度とIOの更新速度によっては、waitの挿入が必要になるかも知れません。
1回の割り込みで1行を表示する事として、タイマー割り込みで処理します。
16回の割り込みで1面の表示になります。

  • ハードの用意

表示ボードを購入してくる(デジットで売られているのは出物なので安かった)のが簡単ですが、16*16dotマトリクスのLED表示モジュールが販売されているので、シフトレジスタとドライバを組み合わせて作成する事もできます。
データ送りがシリアルのため、出力ポートが6本(5本でも可能)あれば駆動できます。
シフトレジスタの信号形式は、CMOSゲートのHC4094とほぼ同じですが、一からハードを作るとなるとドライバICも必要となるため、配線がちょっと厄介かもしれません。
デジット販売の表示基板でも結線するのが面倒と言う方は、共立電子から上記の表示ボードをArudinoに接続するシールドが売られています。
nucreo系、KL系のCPUボードなら、そのまま差し込めば接続が完了します。

  • 結線

表示ライブラリのコンストラクタに、接続しているピン情報を渡して初期化する方法を取っています。
結線時に使用したポートの名前を使用します。

コンストラクタ KP1632D(PinName BD7851_COM, PinName BD7851_CA, PinName BD7851_CB, PinName BD7851_CLK, PinName BD7851_LT, PinName BD7851_ENB=NC, uint16_t period=200);

出力になればどのポートでもかまいませんが、面倒だったので、上記の共立電子製Arudinoシールドの番号でdemoを作っています。
この場合のピン指定は(D7,D9,D10,D6,D5,D4)となります。
nucreo系KL系(KL25で確認)ではArudino互換端子用に、名前をArudino名定義されていますので、そのままD??の番号で渡せます。
他のmbedにバラ結線した場合はピン名で指定しなければなりません。

引数名と信号の関係は

  • PinName BD7851_COM ⇒ 縦の行位置指定用シフトレジスタのデータ
  • PinName BD7851_CA ⇒ 横の左側表示用シフトレジスタのデータ
  • PinName BD7851_CB ⇒ 横の右側表示用シフトレジスタのデータ
  • PinName BD7851_CLK ⇒ 全シフトレジスタ共通のシフトクロック
  • PinName BD7851_LT ⇒ パラレルラッチのラッチ信号
  • PinName BD7851_ENB ⇒ 表示のON/OFF線

BD7851_ENBは全体の表示をON/OFFさせるエネーブル線の制御ですが、表示したまま(前記の表示基板では、GNDに接続すると表示ON)にしていますので、ハード結線で固定してしまう場合や、そもそもそんな線が無い場合は省略とします。
最後の数値は割り込みの間隔をμSで指定する引数で、無指定の場合は200μSになります。

パブリックメンバにある
flame_buf pbuf[16];
flame_buf abuf[16];
bool tranfer_sw;
ですが、pbuf[]は32bitの表示データ保持メモリになっています。割り込みはこのメモリ内容を絶えず表示ボードに送り続けます。
このメモリに表示データを書き込めば、そのまま表示されます。

少し変わったところでは、abuf[]とtranfer_swを持っている所です。
abufはpbufと同じサイズのメモリですが、abufに書き込んだデータはそのままでは表示されません。
tranfer_sw=true;とする事でpbufにコピーされ、表示になります。
この様になっているのは、pbufへの書き込みが、即時反映で早い動作になる反面、表示とは非同期で書き換わりが発生するため、表示を高速で動かす様な動作では切り替わり点が不定で変な表示になります。
一方、abufに書き込んだ後、tranfer_swを操作する方法は16行目の表示が終わった瞬間に更新が行われるため、表示途中では書きかわりません。
欠点は、最悪1面の表示時間分、待たなければならない点です。この時間はデフォルトで3.2mSになります。
このため、頻繁に書き込む場合はtranfer_sw==falseの確認を行わないと、一回分の表示が飛ばされてしまう事があります(高速書き換えでは飛ばされても実害無いですが)

  • その他

表示ライブラリは5x7dotのASCIIコード用キャラジェネを持っており、5文字2行の表示が行えます。
streamクラスを継承していますので、printf文を使う事ができますが、かなりのRAMを消費します。
mbed(あるいは同系のARMプロセッサ)の容量によっては、メモリ不足が発生すると思います。


Please log in to post comments.