はじめに
秋葉原の aitendo で以前に販売されていたマトリクスLEDパネルの表示プログラムを公開して欲しいとの要望があり、ESP32-DevKitCを使ったプログラムを作成したので、簡単な説明を加えてソースコードを公開します。勢いで購入してしまったけど使い方が分からないという方の参考になればと思います。
なお、このマトリクスLEDパネルはエレショップでも販売されているようです。
-
aitendo の商品ページ
ドットマトリック表示器(32x16)HD-0158-RG0019A
http://www.aitendo.com/product/14111 -
エレショップの商品ページ
32×16ドットマトリクスLEDパネル(赤/橙/緑) 32x16DOT-0158-DJK
https://eleshop.jp/shop/g/gEB8411/
ハードウェア
ESP32-DevKitCは3.3Vで動作するのに対してマトリクスLEDパネルは5Vでの動作と電圧が異なりますが、マトリクスLEDパネルの資料を見ると信号入力電圧のVinHの最小が2.4V、VinLの最大が0.8Vから、ESP32-DevKitCの信号出力で制御できそうです。
今回、ESP32-DevKitCとマトリクスLEDパネルのピンを以下のように接続して動作させました。
ESP32-DevKitC 信号名 | LEDパネルピン番号 | LEDパネル信号名 |
---|---|---|
IO12 | 11p | DR in |
IO13 | 8p | DG in |
IO32 | 6p | A0 in |
IO33 | 5p | A1 in |
IO15 | 4p | A2 in |
IO19 | 3p | A3 in |
IO25 | 9p | CLK in |
IO26 | 12p | ALE in |
IO27 | 10p | WE in |
IO14 | 1p | SE in |
IO18 | 2p | A/BB in |
GND | 7p | GND |
マトリクスLEDパネルの電源は以下の表のように**+5VとGNDをそれぞれつなぎます。
マトリクスLEDパネルの資料に誤りがあるようなので注意してください。+5VとGNDを逆につなぐとマトリクスLEDパネル**が破損する可能性があります。
LEDパネルピン番号 | LEDパネル信号名 | 機能 |
---|---|---|
1p | VDD | 駆動部電源(+5V) |
2p | GND | LED部GND |
3p | GND | LED部GND |
4p | VLED | LED部電源(+5V) |
5p | VLED | LED部電源(+5V) |
6p | Vss | 駆動部GND |
ちなみに、aitendo の商品ページ内からリンクされているファイルにマトリクスLEDパネルの回路図が含まれていて、そちらには正しいピン番号と信号名が記されていました。
また、エレショップの商品ページ内からリンクされている参考資料では注意書きが加えられています。
http://www.kyohritsu.jp/eclib/DIGIT/JNK/32x16dot0158.pdf
動作確認した環境
制御
マトリクスLEDパネルの制御は、多少間違いはあるものの aitendo の資料でもそれなりに動作させられると思いますが、エレショップの参考資料の方がより詳しく、間違いも訂正されていて分かり易いです。これらの資料に書かれている通りにピンを制御すれば、基本的に表示させることができると思います。(※)
ただし、強いて注意点を挙げるとすると、このマトリクスLEDパネルに使われているコントローラでは、表示データを保持するRAMを2面分持っていて、SE inピンやA/BB inピンのHやLの設定により制御方法が変わります。データを書き込む面(RAM)や表示する面(RAM)の制御を間違えると意図した表示となりません。
今回公開するプログラムでは、SE inを「L」にして自動切り替えモードで使いました。これは、データ書込み中はもう一方の面が表示され、A0 in~A3 inで指定する行アドレスが15から0(※)へ変わる際に表示面と書き換え面が自動で切り替わります。
----
※ エレショップの資料では注記が入っていて、行アドレス15にデータを書き込むと切り替わるとなっていますが、私の使ったaitendoで購入したパネルでは資料通りに行アドレス15から0へ変わる際に書き込んだデータが表示されるようになりました。マトリクスLEDパネルのロットなどにより挙動が違うのかもしれません。
今回のプログラムには行アドレス15へデータを書き込んだ後に意図的に行アドレスを0にする処理を入れてあります。どちらのマトリクスLEDパネルでも、このままで問題ないと考えています。
表示データ
今回のプログラムでは、赤色、緑色、橙色(赤色と緑色の同時発光)の3色それぞれに異なるデータを配列としてプログラム内に用意し、3秒ごとに切り替えて表示します。
表示色、表示するデータ、プログラム内での配列名は以下の表の通りです。
表示色 | 表示データ | 配列名(変数名) |
---|---|---|
赤 | "赤◎" | dat_buffer1 |
緑 | "★緑" | dat_buffer2 |
橙 | " 橙 " | dat_buffer3 |
表示間隔は、loop()関数の最終の以下のカッコ内の数字を変更することで早めたり、遅くしたりすることができます。数字の単位はミリ秒で、3000ミリ 秒 = 3 秒となります。
delay( 3000 );
ソースコード
今回のプログラムの全ソースコードを以下に記します。
ESP32-DevKitC用ですが、メモリサイズなどに問題がなければ、Arduino UNOなどへ容易に移植できると思います。
/*
* Copyright(C) by Yukiya Ishioka
*
* http://www.aitendo.com/product/14111
* http://aitendo3.sakura.ne.jp/aitendo_data/product_img/LED/HD-0158-RG0019A/HD-0158-RG0019A.rar
*
* https://eleshop.jp/shop/g/gEB8411/
* http://www.kyohritsu.jp/eclib/DIGIT/JNK/32x16dot0158.pdf
*
*/
# include <stdio.h>
# include <string.h>
/* ESP32 PANEL */
# define DRPIN 12 /* 11p */
# define DGPIN 13 /* 8p */
# define A0PIN 32 /* 6p */
# define A1PIN 33 /* 5p */
# define A2PIN 15 /* 4p */
# define A3PIN 19 /* 3p */
# define CLKPIN 25 /* 9p */
# define ALEPIN 26 /* 12p */
# define WEPIN 27 /* 10p */
# define SEPIN 14 /* 1p */
# define ABBPIN 18 /* 2p */
# define DEF_FONT_SIZE 16
# define DEF_DISP_WIDTH 32
int led_color;
unsigned char dat_buffer1[ DEF_FONT_SIZE ][ DEF_DISP_WIDTH ] = {
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};
unsigned char dat_buffer2[ DEF_FONT_SIZE ][ DEF_DISP_WIDTH ] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0 },
{ 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
};
unsigned char dat_buffer3[ DEF_FONT_SIZE ][ DEF_DISP_WIDTH ] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
};
void led_addr_wr( int a0, int a1, int a2, int a3 )
{
digitalWrite( A0PIN, a0 );
digitalWrite( A1PIN, a1 );
digitalWrite( A2PIN, a2 );
digitalWrite( A3PIN, a3 );
digitalWrite( ALEPIN, HIGH );
digitalWrite( WEPIN, HIGH );
digitalWrite( WEPIN, LOW );
digitalWrite( ALEPIN, LOW );
}
void setup( void )
{
int col, row;
int a0, a1, a2, a3;
/* init serial */
Serial.begin(115200);
Serial.println( "call setup()" );
pinMode( DRPIN, OUTPUT );
pinMode( DGPIN, OUTPUT );
pinMode( A0PIN, OUTPUT );
pinMode( A1PIN, OUTPUT );
pinMode( A2PIN, OUTPUT );
pinMode( A3PIN, OUTPUT );
pinMode( CLKPIN, OUTPUT );
pinMode( ALEPIN, OUTPUT );
pinMode( WEPIN, OUTPUT );
pinMode( SEPIN, OUTPUT );
pinMode( ABBPIN, OUTPUT );
digitalWrite( CLKPIN, LOW );
digitalWrite( ALEPIN, LOW );
digitalWrite( WEPIN, LOW );
digitalWrite( SEPIN, LOW );
digitalWrite( ABBPIN, LOW );
/* dummy address set */
led_addr_wr( LOW, LOW, LOW, LOW );
/* clear MATLED */
for( row=0 ; row<16; row++ ) {
for( col=0 ; col<DEF_DISP_WIDTH ; col++ ) {
digitalWrite( DRPIN, LOW );
digitalWrite( DGPIN, LOW );
digitalWrite( CLKPIN, HIGH );
digitalWrite( CLKPIN, LOW );
}
a0 = a1 = a2 = a3 = 0;
if( row & 0x1 ) a0 = 1;
if( row & 0x2 ) a1 = 1;
if( row & 0x4 ) a2 = 1;
if( row & 0x8 ) a3 = 1;
led_addr_wr( a0, a1, a2, a3 );
}
/* dummy address set */
led_addr_wr( LOW, LOW, LOW, LOW );
led_color = 0;
}
void loop( void )
{
int a0, a1, a2, a3;
int dr, dg;
int row, col;
int i;
unsigned char tmpchar;
unsigned char *buff1;
switch( led_color%3 ) {
case 1:
dr = 0;
dg = 1;
buff1 = (unsigned char *)dat_buffer2 ;
break;
case 2:
dr = 1;
dg = 1;
buff1 = (unsigned char *)dat_buffer3 ;
break;
case 0:
default:
dr = 1;
dg = 0;
buff1 = (unsigned char *)dat_buffer1 ;
break;
}
Serial.printf( "color DR=%d DG=%d\n", dr, dg );
for( i=0 ; i<16 ; i++ ) {
row = DEF_DISP_WIDTH * i;
for( col=0 ; col<DEF_DISP_WIDTH ; col++ ) {
if( buff1[ row + col ] ) {
digitalWrite( DRPIN, dr );
digitalWrite( DGPIN, dg );
} else {
digitalWrite( DRPIN, LOW );
digitalWrite( DGPIN, LOW );
}
digitalWrite( CLKPIN, HIGH );
digitalWrite( CLKPIN, LOW );
}
/* set access row position */
a0 = a1 = a2 = a3 = 0;
if( i & 0x1 ) a0 = 1;
if( i & 0x2 ) a1 = 1;
if( i & 0x4 ) a2 = 1;
if( i & 0x8 ) a3 = 1;
led_addr_wr( a0, a1, a2, a3 );
}
/* dummy address set */
led_addr_wr( LOW, LOW, LOW, LOW );
led_color++;
delay( 3000 ); /* delay 3000msec */
}
最後に
今回は表示データをあらかじめ配列としてプログラムに含めてプログラムをシンプルにすることで、プログラムの解析やESP32-DevKitC以外のボードへの移植を容易にしました。
プログラムは少し大きく複雑になりますが、表示させたい文字をプログラム内に定義することで表示用のデータへ変換して、マトリクスLEDパネルへ表示するプログラムも既にできています。実際のところ、先にそのプログラムをmatled_ai.inoとして作成し、今回紹介したプログラムがそこから派生したのでmatled_ai2.inoというファイル名になっています。
新しいプログラムは改造することで、任意の文字を表示することも容易になると思いますので、次回はこのプログラムを公開したいと考えています。
以上