8pinの32ビットマイコンSTM32C011J4M7につないだ8x8RGBフルカラーLEDマトリックス(WS2812B)で数字フォントを表示してみました。


LEDマトリックスには3Dプリンターで作成したメッシュをつけ,コピー用紙とアクリル板の2枚のフィルター?を被せて表示をくっきりさせています。





8x8と4x6の数字フォントを表示して縦横にスクロールさせた動画です(^^)。





NeoPixel(WS2812B)系のLEDは数珠つなぎに接続していくので,マトリックスではLEDがジグザグに配列されているものが多いですね。

私は頭が混乱するので(^^;;;; ,XY直交座標系の仮想マトリックスをバッファーとして作り,まずはそこに表示データを書き込んでいます。そして,表示の際はデーターをシリアルの順番に並ばせて出力する,という手を使っています。

今回の直交座標系のバッファーとシリアルにつながれたLEDの順番はそれぞれ下図のようになっています。


NeoPixel系は各LEDにデータが記憶されるので,シリアル通信の出力の時だけ一定の速度が要求されますが,バッファ書き込みやデータ変換は特に時間に縛られることなく処理ができます。



なお,数字のフォントは8x8ドットと4x6ドットのものを表計算ソフトで作り,数字だけなので,数値をプログラムにコピペして使ってみました。

下図は”9”の作成部で,8x8ドットのフォントの1文字は8byteで構成します。今回はバッファのXY座標系を意識して,表に向かって左からbit0,bit1----bit7 としましたが,,,LCDなどのフォントデータとは逆ですね(^^;;;;;;;。







フォントの書体のチェックとして上の動画のプログラムがとにかく動いたのでメモしておきます。


// STM32C011 NeoPixel 8x8 Test_1

// RGB_LED: 8x8
const unsigned int X_max = 8; // LED Matrix
const unsigned int Y_max = 8;

const unsigned int Led_max = X_max*Y_max; // number of LED
const byte c_order[]={1,0,2}; // send GRB, R:1, G:0, B:2

byte bData[X_max][Y_max][3]; // Data Buffer
byte aData[Led_max][3]; // Serial data for output

// Font of Number
byte nFont_8x8[10][8]={{0,112,136,200,168,152,136,112},{0,32,48,32,32,32,32,112},
{0,112,136,128,64,32,16,248},{0,248,64,32,64,128,136,112},
{0,64,96,80,72,248,64,64},{0,248,8,120,128,128,136,112},
{0,96,16,8,120,136,136,112},{0,248,128,64,32,16,16,16},
{0,112,136,136,112,136,136,112},{0,112,136,136,240,128,64,48}};
byte nFont_4x6[10][6]={{0,14,10,10,10,14},{0,4,6,4,4,4},{0,14,8,4,2,14},{0,14,8,14,8,14},
{0,10,10,14,8,8},{0,14,2,14,8,14},{0,14,2,14,10,14},{0,14,8,4,4,4},
{0,14,10,14,10,14},{0,14,10,14,8,14}};

void setup() {
pinMode(PA8, OUTPUT);

// LED All Clear
allset(0,0,0);
show_Data();
delay(500);
}

// ************************************************************************************

void loop(){
byte bbr=0x4F; // Brightness // Basic Colors setting
// R, G, B, R+G, R+B, G+B, R+G+B
byte base_Color[7][3]={{bbr,0,0},{0,bbr,0},{0,0,bbr},
{bbr,bbr,0},{bbr,0,bbr},{0,bbr,bbr},{bbr,bbr,bbr}};

int waitms=3000;

for (byte i=0; i<7; i++){ // Show Basic Colors 1
allset(base_Color[i][0],base_Color[i][1],base_Color[i][2]);
show_Data();
delay(waitms);
}

for(int i=0; i< Y_max; i++){ // Show Basic Colors 2
for (int j=0; j< X_max; j++){
byte pc=(X_max*i+j)%7; // point color
p_set (j, i,base_Color[pc][0],base_Color[pc][1],base_Color[pc][2]);
}
show_Data();
}
delay(waitms);

// Fill buffer blue
allset(0,0,0x4F);
show_Data();

/* Set 8x8 dot Font ---LEFT Scroll---
(font number; start point x,y; front color r,g,b; back color r,g,b)*/
for (int x=8; x>-73; x--){
for(int n=0; n<10;n++){
dotSet_8x8_F (n,x+n*8,0,0x4F,0x4F,0x4F,0,0,0x4F);
}
show_Data();
delay(250);
}
delay(waitms);

// Fill buffer white
allset(0x1F,0x1F,0x1F);
show_Data();

/* Set 8x8 dot Font --- UP Scroll---
(font number; start point x,y; front color r,g,b; back color r,g,b)*/
for (int y=8; y>-73; y--){
for(int n=0; n<10;n++){
dotSet_8x8_F (n,-1,y+n*8,0x3F,0,0,0x1F,0x1F,0x1F);
}
show_Data();
delay(250);
}
delay(waitms);


// Fill buffer Blue
allset(0,0,0x3F);
show_Data();

/* Set 4x6 dot Font ---LEFT Scroll---
(font number; start point x,y; front color r,g,b; back color r,g,b)*/
for (int x=8; x>-33; x--){
for(int n=0; n<10;n++){
dotSet_4x6_F (n,x+n*4,1,0x3F,0x3F,0x3F,0,0,0x3F);
}
show_Data();
delay(250);
}
delay(waitms);


// Fill buffer white
allset(0x1F,0x1F,0x1F);
show_Data();

/* Set 4x6 dot Font --- UP Scroll---
(font number; start point x,y; front color r,g,b; back color r,g,b)*/
for (int y=8; y>-53; y--){
for(int n=0; n<10;n++){
dotSet_4x6_F (n,2,y+n*6,0x4F,0,0,0x1F,0x1F,0x1F);
}
show_Data();
delay(250);
}
delay(waitms);

} // loop End

// *************************************************************************************************


// bData, Make all LEDs the same color

void allset (byte r,byte g,byte b){
for(int i=0; i< X_max; i++){
for (int j=0; j< Y_max; j++){
bData[i][j][0]=r;
bData[i][j][1]=g;
bData[i][j][2]=b;
}
}
}


// bData, Make a LED the color

void p_set (int x, int y, byte r, byte g, byte b){
if (x>=0 && x< X_max && y>=0 && y< Y_max){
bData[x][y][0]=r;
bData[x][y][1]=g;
bData[x][y][2]=b;
}
}

// Set 8x8 dot Font (font number;start point x,y; front color r,g,b; back color r,g,b)

void dotSet_8x8_F (int n,int x,int y,byte fr,byte fg,byte fb,byte br,byte bg,byte bb){
int px, py;
for (int i=0; i<8; i++){
py=y+i;
for (int j=0; j<8; j++){
px=x+j;
if (bitRead(nFont_8x8[n][i],j) > 0){
p_set (px, py, fr, fg, fb);
}else {
p_set (px, py, br, bg, bb);
}
}
}
}


// Set 4x6 dot Font (font number;start point x,y; front color r,g,b; back color r,g,b)

void dotSet_4x6_F (int n,int x,int y,byte fr,byte fg,byte fb,byte br,byte bg,byte bb){
int px, py;
for (int i=0; i<6; i++){
py=y+i;
for (int j=0; j<4; j++){
px=x+j;
if (bitRead(nFont_4x6[n][i],j) > 0){
p_set (px, py, fr, fg, fb);
}else {
p_set (px, py, br, bg, bb);
}
}
}
}


// Show the data

void show_Data(){
bData_to_aData(); // Send data to Serial buffer
sendData(); // Serial output to LEDs
}


void bData_to_aData(){
for (int i=0; i< Led_max; i++){
int x,y;
y=i/X_max;
if (y % 2 > 0){
x=i % X_max;
}else{
x=X_max-(i % X_max)-1;
}
aData[i][0]=bData[x][y][0];
aData[i][1]=bData[x][y][1];
aData[i][2]=bData[x][y][2];
}
}


void sendData(){
noInterrupts();
for (byte numLed=0; numLed<Led_max; numLed++){ //led
for (byte rgbLed=0; rgbLed <3; rgbLed++){ // G-R-B
byte a=aData[numLed][c_order[rgbLed]]; // set 1byte
for (byte i=0; i<8; i++){ // loop bit:7---0
if ((a & 0x80) >0){ // *** if bit=1 ***
for (int i=0; i<3; i++){ // High_long
for (int j=0; j<8; j++){
digitalWriteFast(PA_8, HIGH);
}
}
for (int i=0; i<2; i++){ // Low_short
for (int j=0; j<8; j++){
digitalWriteFast(PA_8, LOW);
}
}
}else{ // *** if bit=0 ***
for (int i=0; i<2; i++){ // High_short
for (int j=0; j<8; j++){
digitalWriteFast(PA_8, HIGH);
}
}
for (int i=0; i<3; i++){
for (int j=0; j<8; j++){
digitalWriteFast(PA_8, LOW); // Low_long
}
}
}
a=a*2; // set bit7
} // next bit
} // next byte(G-R-B)
} // next LED
interrupts();
}







なんかごちゃごちゃと長くなってきていますが,STM32C011のプログラムメモリとRAMはまだまだ余裕があります。

ArduinoでもI2CやUARTを使わないと本来のメモリの大きさが実感できますね。もう少しこれらライブラリがコンパクトになるのを待つか,,自前でなんとかするかですかね(^^;;;;;;;;。