電光掲示板に文字が流れていくやつって、ちょっと作ってみたくなりますよね。
いつかやろうと思ってるだけじゃ進まないので、気合を入れてやりました!
8x8のLEDドットマトリクスが4つ連結されたデバイス。
LED点灯にはMAX7219というドライバが使用されています。
EPS32は他のことで使用中でしたので、久々にArduino UNOを引っ張り出してきました。
まずは動いている様子をご覧ください。
推しの真野あゆみさん(スワローズファン)のイベントに持っていこうかな…なんて考えながら作りました(笑)
文字の隙間が少し気になる箇所があるけど、一応動きました。
5本のピンとArduinoの接続は下記のようにしました。
Vcc = 5V
GND = GND
DIN = D11
CS = D10
CLK = D13
Arduinoライブラリは、「MD_MAX72xx」と「MD_Parola」を使用しました。
英語の文字は、標準フォントを使用。
ひらがなとカタカナは、手書きです。
手書きの表示は以前やったことがあるので、この応用。
こんな感じでExcelに下書きをして・・・
縦の列で16進数に変換します。
このとき、下から数えていきます。
例えば「す」の一番左端は、下から数えると「00000100」なので、「0x04」という感じ。
これをひたすら文字数分数えていきます。
出来たら、入力していきます。
大まかなプログラムは生成AIに作らせたのですが、ひらがなとカタカナの表示がどうしてもうまくいかずに手作業となりました。
フォントライブラリを使用することも考えましたが、Arduinoの容量をオーバーしてしまったので断念。
EPS32で再挑戦したいところです。
参考までに、プログラムを記載しておきます。
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define CS_PIN 10
MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
struct CustomChar {
char key;
uint8_t data[9];
};
//==================================================
// MAX7219用フォント
// 形式:
// {幅, 列1, 列2, 列3 ...}
//==================================================
const CustomChar myFonts[] = {
// す
{'s', {8, 0x04, 0x04, 0x14, 0xAC, 0x7E, 0x04, 0x04, 0x00}},
// わ
{'w', {8, 0x48, 0x28, 0xFE, 0x08, 0x84, 0x84, 0x78, 0x00}},
// ほ
{'h', {8, 0xFE, 0x00, 0xCA, 0xCA, 0x7E, 0x4A, 0x8A, 0x00}},
// ー
{'-', {8, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00}},
// ま
{'m', {8, 0x00, 0xD4, 0xD4, 0xD4, 0xFE, 0x54, 0x94, 0x00}},
// の
{'n', {8, 0x30, 0x48, 0x24, 0x9C, 0x84, 0x48, 0x30, 0x00}},
// し
{'i', {8, 0x00, 0x7E, 0x80, 0x80, 0x80, 0x40, 0x00, 0x00}},
// り
{'r', {8, 0x00, 0x0E, 0x80, 0x80, 0x40, 0x3E, 0x00, 0x00}},
// イ
{'v', {8, 0x00, 0x20, 0x20, 0x10, 0xF8, 0x04, 0x02, 0x00}},
// ベ
{'b', {8, 0x20, 0x10, 0x08, 0x10, 0x24, 0x40, 0x44, 0x00}},
// ン
{'e', {8, 0x00, 0x82, 0x84, 0x80, 0x40, 0x20, 0x18, 0x00}},
// ト
{'t', {8, 0x00, 0x00, 0xFE, 0x10, 0x10, 0x20, 0x00, 0x00}},
// お
{'o', {8, 0x44, 0xA4, 0xFE, 0x14, 0x90, 0x94, 0x68, 0x00}},
// め
{'x', {8, 0x60, 0x9C, 0x70, 0xA8, 0x1E, 0x88, 0x70, 0x00}},
// で
{'d', {8, 0x00, 0x04, 0x04, 0x34, 0x4A, 0x86, 0x8A, 0x00}},
// と
{'y', {8, 0x00, 0x40, 0xAE, 0x90, 0x90, 0x88, 0x80, 0x00}},
// う
{'u', {8, 0x00, 0x10, 0x8A, 0x8A, 0x4A, 0x30, 0x00, 0x00}},
// !
{'!', {8, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x00}}
};
void setup()
{
myDisplay.begin();
myDisplay.setIntensity(1);
myDisplay.displayClear();
for (uint8_t i = 0; i < sizeof(myFonts) / sizeof(CustomChar); i++) {
myDisplay.addChar(
myFonts[i].key,
myFonts[i].data
);
}
}
void loop()
{
if (myDisplay.displayAnimate()) {
static uint8_t state = 0;
switch (state) {
case 0:
myDisplay.displayText(
"MANO",
PA_CENTER,
100,
2000,
PA_PRINT,
PA_NO_EFFECT
);
state++;
break;
case 1:
// すわほー
myDisplay.displayText(
"swh-",
PA_CENTER,
100,
2000,
PA_PRINT,
PA_NO_EFFECT
);
state++;
break;
case 2:
// まのしりイベントおめでとう!
myDisplay.displayText(
"mnir vbet oxdyu!",
PA_LEFT,
50,
2000,
PA_SCROLL_LEFT,
PA_SCROLL_LEFT
);
state = 0;
break;
}
}
}







