LoginSignup
11
11

More than 3 years have passed since last update.

M5Stack で LEDマトリクスパネル (HUB-75) を光らせる

Last updated at Posted at 2020-12-11

いわゆる HUB75 という規格のLEDパネルを M5Stack で光らせます。光らせて何かをするというより、LED Matrix Panel の光る仕組みについて実験してみたという主旨です。

image.png

参考

HUB75 LED Matrix Panel

屋外の高いところとかに、輝度がやや高めの LED ディスプレイがあったら、だいたいこの規格の LED パネルが使われています(多分)。最近は国内でも簡単に購入できるようになりました。そこそこの輝度があって、制御に必要な機器もそれなりの値段で入手できることから、業務用としてはかなり広く使われているという印象です。

HUB75 の仕様については、下記の記事で詳しく書かれているので、ここでは要点だけ書きます。

なお、64x64 のパネルの場合は HUB75E という、HUB75 を拡張した規格が使われていることが多いようです。HUB75E では GND ピンをひとつ潰して、代わりに列を指定するための E ピンが追加されています。ABCDE の 5bit で指定することで、32列 (x2=64列) 指定できます。

使ったもの

  • M5Stsck
  • 32x64 LED Matrix Panel (HUB75)
  • 30A/5V 安定化電源

LED Matrix Panel は、同じ見た目をしていても、信号回りの仕様(ピン配置、HIGH/LOWの解釈)が異なることがあるようです。

結線

image.png

  • LED Matrix のピン名: M5Stack の GPIO
  • A: 18
  • B: 19
  • C: 21
  • D: 22
  • R1: 16
  • G1: 26
  • B1: 17
  • CLK: 2
  • OE: 23
  • LAT: 5

実際に結線しようとしてから気がつきましたが、M5Stack のデフォルトで出ているピンだけだと、微妙にピン数が足りなくて R2,G2,B2 に結線できませんでした。無理矢理出して足りるようにすることもできますが、実験なのでとりあえず今回は R2,G2,B2 は無しでやりました。このため、パネルの上半分しか光りません。

M5Stack の 18 と 19 のピンは LCD に使われているため、LED パネルを光らせている間に LCD を動かすとバグります。1, 3 のピンはシリアル通信に使われており、35, 36 は input only なので今回の用途には使えません。

なお LED Matrix Panel は 5V 動作ですが、M5Stack の 3.3V の出力を直接入れても問題なく動作するようです。

image.png

だいぶん粗いですが、こんな結線でも光りました。ただし、ちょっとでも触るとノイズがのってちらつきます。

全点灯プログラム

実験なので、いろいろしやすいように Arduino で書いてみました。PIN_R1, PIN_G1, PIN_B1 を HIGH にしたり LOW にしたりすると、色を変えられます。


#define PIN_A   18
#define PIN_B   19
#define PIN_C   21
#define PIN_D   22
#define PIN_R1  16
#define PIN_G1  26
#define PIN_B1  17
#define PIN_CLK 2
#define PIN_OE  23
#define PIN_LAT 5

void setup() 
{

  pinMode( PIN_A, OUTPUT );
  pinMode( PIN_B, OUTPUT );
  pinMode( PIN_C, OUTPUT );
  pinMode( PIN_D, OUTPUT );
  pinMode( PIN_R1, OUTPUT );
  pinMode( PIN_G1, OUTPUT );
  pinMode( PIN_B1, OUTPUT );
  pinMode( PIN_CLK, OUTPUT );
  pinMode( PIN_OE, OUTPUT );
  pinMode( PIN_LAT, OUTPUT );

  digitalWrite( PIN_A, LOW );
  digitalWrite( PIN_B, LOW );
  digitalWrite( PIN_C, LOW );
  digitalWrite( PIN_D, LOW );
  digitalWrite( PIN_R1, LOW );
  digitalWrite( PIN_G1, LOW );
  digitalWrite( PIN_B1, LOW );
  digitalWrite( PIN_LAT, LOW );

  // OE のみ HIGH で OFF になる
  digitalWrite( PIN_OE,  HIGH );
  digitalWrite( PIN_CLK, LOW );
}

void loop() 
{
  int i = 0;
  char d = 0;

  for ( d = 0; d < 16; d++ ){

    // ラッチはこのタイミングで HIGH にする必要があるぽい
    digitalWrite( PIN_LAT, HIGH ); 

    // (R=1,G=1,B=1) 
    digitalWrite( PIN_R1, HIGH );
    digitalWrite( PIN_G1, HIGH );
    digitalWrite( PIN_B1, HIGH );

    // R2,G2,B2 も結線できている場合
    // digitalWrite( PIN_R2, HIGH );
    // digitalWrite( PIN_G2, HIGH );
    // digitalWrite( PIN_B2, HIGH );

    // RGB データ (R=1,G=1,B=1) を 64ibt 分転送する
    for ( i = 0; i < 64; i++ ){
      digitalWrite( PIN_CLK, HIGH );
      digitalWrite( PIN_CLK, LOW );
    }

    // LED を消灯する (データ転送時のちらつきを防ぐ)
    digitalWrite( PIN_OE, HIGH );

    // LED パネルの光らせる列を 4bit で指定する
    digitalWrite( PIN_A, ( d & 1 ) );
    digitalWrite( PIN_B, ( d & 2 ) >> 1);
    digitalWrite( PIN_C, ( d & 4 ) >> 2);
    digitalWrite( PIN_D, ( d & 8 ) >> 3);

    // 4bit で指定した列に RGB データを転送する
    digitalWrite( PIN_LAT, LOW );

    // LED を点灯する
    digitalWrite( PIN_OE,  LOW );

  }
}

中間色点灯プログラム

LED が点灯する時間の長さを調整することで、中間色を表現してみるテストです。

// setup() と #define は上のプログラムと同じなので省略

// 色調(階調)の設定
inline void SET_RGB( char r, char g, char b, int j ){
    digitalWrite( PIN_R1, r > j ? HIGH : LOW );
    digitalWrite( PIN_G1, g > j ? HIGH : LOW );
    digitalWrite( PIN_B1, b > j ? HIGH : LOW );
}

char d = 0;
void loop()
{
  int i = 0;
  int j = 0;

  for ( j = 0; j < 16; j++ ){ // RGB 16 階調 (16x16x16=4096色)
    for ( d = 0; d < 16; d++ ){
      digitalWrite( PIN_LAT, HIGH );

      for ( i = 0; i < 64; i++ ){
        SET_RGB( d, i/4, 15-d, j );
        digitalWrite( PIN_CLK, HIGH );
        digitalWrite( PIN_CLK, LOW );
      }

      digitalWrite( PIN_OE, HIGH );

      digitalWrite( PIN_A, ( d & 1 ) );
      digitalWrite( PIN_B, ( d & 2 ) >> 1);
      digitalWrite( PIN_C, ( d & 4 ) >> 2);
      digitalWrite( PIN_D, ( d & 8 ) >> 3);

      digitalWrite( PIN_LAT, LOW );

      digitalWrite( PIN_OE,  LOW );

    }
  }
}

240MHz 動作なら 256 階調でもできそうなのですが、上記のプログラムで 256 階調にするとちらつきました。16 階調くらいにして、ようやくちらつかなくなりました。真面目に 256 階調やるなら、やはり DMA などを使う必要がありそうです。

結論

いろいろ中途半端になってしまったので、ESP32 でもうちょっと真面目に書いて情報追記しときます(いつ?)。

11
11
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
11
11