LoginSignup
2
5

More than 3 years have passed since last update.

懐かしのドット絵アニメをLEDマトリクスパネルに表示させてみた

Posted at

はじめに

LEDマトリクスパネルを買ってみたので、動作テストとしてドット絵アニメに挑戦してみました。
最終的に出来たのはこれ。

ff4_pic.jpg

LEDマトリクスパネル

本来は店舗等でたくさん並べて巨大なディスプレイを構成するものですが、1枚単位でも使えます。
1枚だと16x16~64x64ピクセル程度の表示能力しかありません。
LEDのピッチは2mm~10mmくらいまでいろいろあるようです。

自分は4mmピッチ(P4)の64x32ピクセルのパネルをAliexpressから購入。
信号用のフラットケーブルと電源コネクタも付属して、2000円弱で買えます。
(特に電源コネクタは)別に手に入れるのが大変そうなので、購入前に確認を。

海外通販に抵抗がある場合は、高いですが国内でも入手できそうです。

これらのパネルはどうやらHUB75というプロトコルで動いているようです。最終的にはライブラリに任せてしまうのですが、原理は一通り見ておきます。

参考記事

ハードウェア編

ドライバ基板制作

ドライバとしてESP32開発ボード(devkit)を使用してユニバーサル基板で組みました。
GPIO(出力で使えるピン)とパネルに接続するための16ピンコネクタをひたすら繋ぎます。

方眼紙に配線イメージを書いてから作業開始
lo.jpg

パネルの電源は5VなのでdevkitのUSBから取っても良いのですが、表示内容によっては数アンペア必要だそうです。今回は12V ACアダプターからDCDC(縦になっている小基板)で5Vに落としてdevkitおよびパネルの電源としています。

基板(表)
kiban1.jpg

基板(裏)
IMG_20210417_132259.jpg

"ガワ"制作

ホームセンターで買った木材を塗装してパネルに枠を付けました。
おしゃれガジェットっぽくなったぞ。

IMG_20210417_132857.jpg

のちのち動作モードを変更したくなるので、プッシュスイッチも2つ程付けました。

IMG_20210417_132905.jpg

ソフトウェア編

ライブラリインストール

HUB75の制御は以下のライブラリに任せます。

Arduinoのリポジトリに登録されているようなので、ライブラリマネージャからインストールしておきます。

lib_dl.png

ドット絵データ作成

画像からマイコンに読ませる配列データを作成するために、LCD image converterを利用します。

画面上をポチポチクリックして絵を描くこともできますし、Image -> Importで読み込みも可能。

lic.png

変換設定はこんな感じで。1ピクセルあたり16bitの情報で扱うので、R5G6B5を選んでBlock sizeを16bitにしておきます。

lic_c0.png
lic_c1.png

設定が終わったら、File -> Convertで書き出します。

書き出したファイルを開いてみると、配列データと構造体が定義されています。
このデータをそのまま使うとSRAMに展開されてしまうので、"PROGMEM"属性を追加してFlashから直接読むようにしておきます。

typedef struct {
   const uint16_t *data;
   uint16_t width;
   uint16_t height;
   uint8_t dataSize;
} tImage;

static const uint16_t image_data_img0[1024] PROGMEM = {
    0x0000, 0x0000, 0x0000, 0x0000,
    ~略~
};
const tImage img0 = { image_data_img0, 32, 32,
    16 };

アニメーションさせたい場合は複数の画像が必要なので、ここまでの手順を繰り返してデータを全て作っておきます。

描画プログラムの作成

#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include "sprites.h"

MatrixPanel_I2S_DMA *d = nullptr;

void drawRGBBitmap (int x, int y, const uint16_t bitmap[], int w, int h) {
  for(int j=0; j<h; j++) {
    for(int i=0; i<w; i++) {
      d->drawPixel(x+i, y+j, pgm_read_word(&bitmap[j*w+i]));
    }
  }
}

void setup() {
  // LED Matrix
  //                               R1, G1, B1, R2, G2, B2, A,  B,  C,  D,  E, LAT, OE, CLK};
  HUB75_I2S_CFG::i2s_pins _pins = {25, 26, 27, 21, 22, 23, 12, 16, 17, 18, -1, 32, 33, 15};
  HUB75_I2S_CFG mxconfig(
                          64,  // width
                          32,  // height
                           1,  // chain length
                       _pins   // pin mapping
  );
  d = new MatrixPanel_I2S_DMA(mxconfig);
  d->begin();
}

void loop() {
  // 1枚目
  d->flipDMABuffer();
  d->fillScreen(d->color444(0, 0, 0));  
  drawRGBBitmap(0, 0, img0.data, img0.width, img0.height);
  d->showDMABuffer();
  delay(500);

  // 2枚目
  d->flipDMABuffer();
  d->fillScreen(d->color444(0, 0, 0));  
  drawRGBBitmap(0, 0, img1.data, img1.width, img1.height);
  d->showDMABuffer();
  delay(500);

  // ここは好きなように変更
}

まずLCD image converterで作った画像データをincludeしておきます。
drawRGBBitmapは画像データを順次読み出して1ピクセル毎に描画する関数。
setup()内では基板に配線した通りに端子を定義してインスタンス生成。
loop()内ではdrawRGBBitmap関数を使って描画。
ダブルバッファになっているので、対象バッファ切り替え→描画→バッファ有効化のループにします。

おわりに

アニメーション表示はかわいいのですが、実用性は全くありません。今回使ったライブラリの描画バックエンドは界隈ではおなじみのAdafruits GFXのため、テキストや図形も自由自在に表示出来ます。とりあえず普段は時計と環境センサーの情報を表示させています。

lp.jpg

予算的にも3000~4000円で作れるので、一家に一台いかがでしょうか?

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5