HUB75規格を深掘りしてみる
前回記事の紹介
前回の記事でLEDマトリックスディスプレイのデモを紹介しました.
ryosukeeeee.hatenablog.com
このLEDディスプレイに使われているHUB75という規格について解説します.
HUB75規格
HUB75には16本のピンがあります. 説明のためにピンを3つのグループにわけます.
グループ名 | ピン |
---|---|
Addr | ピンA,ピンB,ピンC,ピンD |
LED | ピンR1,ピンG1,ピンB1,ピンR2,ピンG2,ピンB2 |
Utils | ピンCLK,ピンLAT,ピンOE,ピンGND※ |
※GNDのみ3本ある
Addrはセクションの指定に用います.セクションについては後述します.
LEDは該当するLEDの色を指定するために用います.
Utilはその他の命令を送るために用います.もちろん,ピンGNDは接地です.
説明用の図
私が購入したこの商品を例にとりあげて説明します. 縦横のLEDの数は商品によって異なります. ディスプレイを使うときはデータシートを確認しましょう.
P5 RGB ピクセルパネルHDビデオディスプレイ LEDディスプレイモジュール 320x160 1 / 16s 64×32
- 出版社/メーカー: YANGTAO
- メディア:
- この商品を含むブログを見る
この商品は横64列,縦32行のLEDが並んでいます.
説明のためにすべてのLEDに下の図のように番号を振ります.
例えば,上から5行目,左から3列目のLEDは5-3と表記することにします.
Addrグループの役割
すべてのLEDを同時に点灯することはできません. なのでいくつかのセクションに分割し,人間の眼では認識できないほどの短い時間で点滅させるセクションを切り替えることでディスプレイ全体に映像を映し出します. すなわち,同時に点灯しているのは1つのセクションです.
この商品は2行分のLEDを1つのセクションを構成します. 全部で32行あるので16つのセクションに分けられます. 具体的には,
1,17行でセクション1,
2.18行でセクション2,
3.19行でセクション3,
・・・
16,32行でセクション16 といった具合です.
Addrグループのピンは点灯させるセクションを選択するために用いらます.
ABCDの4ビットでセクションを指定します.
LEDグループの役割
フルカラーのディスプレイなので,RGBのLEDのON・OFFを指定する必要があります.
R1,G1,B1で上半分側のLEDの色を指定します.
R2,G2,B2で下半分側のLEDの色を指定します.
加法混合になるので,RGB全部点灯すると白になります.
Utilグループの役割
ピンCLK,ピンLAT,ピンOEの役割は実際のコードを見てもらったほうがわかりやすいのでCのコードをみてください
gpio.h
/* -*- coding: utf-8 -*- */ #ifndef GPIO #define GPIO // ピン番号に名前をつける #define pinA 22 #define pinB 23 #define pinC 24 #define pinD 25 #define pinR1 11 #define pinR2 8 #define pinG1 27 #define pinG2 9 #define pinB1 7 #define pinB2 10 #define pinClock 17 #define pinOE 18 #define pinStrobe 4 // アドレスから特定のビットをとりだすビットマスク #define addressA 0b0001 #define addressB 0b0010 #define addressC 0b0100 #define addressD 0b1000 void setup(void); void allPinLow(void); #endif
gpio.c
/* -*- coding: utf-8 -*- */ #include "gpio.h" #include <stdio.h> #include <wiringPi.h> // GPIOの初期設定.すべてのピンを出力で使う. void setup(void) { pinMode(pinA, OUTPUT); pinMode(pinB, OUTPUT); pinMode(pinC, OUTPUT); pinMode(pinD, OUTPUT); pinMode(pinR1, OUTPUT); pinMode(pinR2, OUTPUT); pinMode(pinG1, OUTPUT); pinMode(pinG2, OUTPUT); pinMode(pinB1, OUTPUT); pinMode(pinB2, OUTPUT); pinMode(pinClock, OUTPUT); pinMode(pinOE, OUTPUT); pinMode(pinStrobe, OUTPUT); printf("setup done\n"); } // すべてのピンをLowにする void allPinLow(void){ digitalWrite(pinA, 0); digitalWrite(pinB, 0); digitalWrite(pinC, 0); digitalWrite(pinD, 0); digitalWrite(pinR1, 0); digitalWrite(pinR2, 0); digitalWrite(pinG1, 0); digitalWrite(pinG2, 0); digitalWrite(pinB1, 0); digitalWrite(pinB2, 0); digitalWrite(pinClock, 0); digitalWrite(pinOE, 0); digitalWrite(pinStrobe, 0); printf("all pin low\n"); }
main.c
/* -*- coding: utf-8 -*- */ #include <wiringPi.h> #include <stdio.h> #include "gpio.h" // ディスプレイの横幅 #define DISPLAY_WIDTH 64 // for文を繰り返す回数.点灯時間に相当する.大きい値にすれば点灯する時間が長くなる #define LOOPSIZE 1000000 int main(void) { int i, j, address; if(wiringPiSetupGpio() == -1) return 1; setup(); //GPIOの初期設定をする allPinLow(); //一度すべてのピンをLowにする for (j = 0; j < LOOPSIZE; j++) { address = j % 16; // jを16で割ったときの余り.0から15までの値をとる. // ディスプレイの横幅と同じ回数繰り返す for (i = 0; i < DISPLAY_WIDTH; i++) { // R1, G1, B1, R2, G2, B2に値を設定する. // iは列に相当する. // 試しに上半分は赤にする digitalWrite(pinR1, 1); // digitalWrite(pinG1, 1); // digitalWrite(pinB1, 1); // 下半分は緑にする // digitalWrite(pinR2, 1); digitalWrite(pinG2, 1); // digitalWrite(pinB2, 1); // pinClockをHighにすると,そのときのグループLEDの値がキャプチャされる digitalWrite(pinClock, 1); // 次に備えてLowにする digitalWrite(pinClock, 0); } // 前のセクションから移るためにLEDをオフにする digitalWrite(pinOE, 1); // どのセクションにデータを書き込むか設定する. digitalWrite(pinA, address & addressA); digitalWrite(pinB, address & addressB); digitalWrite(pinC, address & addressC); digitalWrite(pinD, address & addressD); // データがそろったのでLEDを光らせる digitalWrite(pinStrobe, 1); // 次に備えてLowにする digitalWrite(pinStrobe, 0); // 次に備えてLowにする digitalWrite(pinOE, 0); } allPinLow(); return 0; }
wiringPiを使ってるので-lwiringPiをつけてコンパイルします.
gcc -o main main.c gpio.c -lwiringPi
以下のコマンドで実行すると,ディスプレイが点灯します.
sudo ./main
ドット欠けしてますが,こんな風になるはず.
特定の列のLEDだけを点灯してみます. main.cを一部変更します.
main.c(一部抜粋)
// ディスプレイの横幅と同じ回数繰り返す for (i = 0; i < DISPLAY_WIDTH; i++) { // R1, G1, B1, R2, G2, B2に値を設定する. // iは列に相当する. if (i == 1 || i == 5 || i == 35) { digitalWrite(pinR1, 1); digitalWrite(pinG2, 1); } else { digitalWrite(pinR1, 0); digitalWrite(pinG2, 0); } // Clock High digitalWrite(pinClock, 1); // Clock Low digitalWrite(pinClock, 0); }
2列目,6列目,36列目のLEDが点灯してます.
特定の行のLEDだけを点灯してみます.
main.c(一部抜粋)
// ディスプレイの横幅と同じ回数繰り返す for (i = 0; i < DISPLAY_WIDTH; i++) { if (address == 3 || address == 15) { digitalWrite(pinR1, 1); digitalWrite(pinG2, 1); } else { digitalWrite(pinR1, 0); digitalWrite(pinG2, 0); } // Clock High digitalWrite(pinClock, 1); // Clock Low digitalWrite(pinClock, 0); }
4行目,16行目,20行目,32行目のLEDが点灯してます.
ソースコードはGithubにあげました.
github.com
参考資料
LEDドットマトリクスパネル HUB75規格について調べてみた - Qiita
https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf
https://learn.adafruit.com/32x16-32x32-rgb-led-matrix/how-the-matrix-works