Hello. I desperately need help.
I want to control a huidu D16 LED Matrix 32x32 with ESP32.
I created a code using GPT.
It lights a dot from 0,0 to 31,31 and then turns it off. I thought I could map the matrix by referencing the dot's continuous movement.
The problem lies here.
Both dots move simultaneously.
I've attached a video. (There was a mistake while filming, so it's rotated 90 degrees clockwise. Please note.)
Of course, I also purchased a controller from huidu, and that controller clearly displays the characters on the LEDs.
The LED Matrix itself isn't left-right.
I've been struggling with GPT for a week, but I can't seem to find an answer.
I need your advice.
#include <Arduino.h>
#include "soc/gpio_struct.h"
#include "soc/gpio_reg.h"
// ===== HUB75 핀맵 =====
#define PIN_R1 25
#define PIN_G1 26
#define PIN_B1 27
#define PIN_R2 14
#define PIN_G2 12
#define PIN_B2 13
#define PIN_A 18
#define PIN_B 5
#define PIN_C 19
#define PIN_D 16
#define PIN_CLK 4
#define PIN_LAT 22
#define PIN_OE 21
#define MATRIX_WIDTH 32
#define MATRIX_HEIGHT 32
// ===== GPIO 펄스 제어 =====
inline void clk_pulse() {
GPIO.out_w1ts = (1UL << PIN_CLK);
GPIO.out_w1tc = (1UL << PIN_CLK);
}
inline void lat_pulse() {
GPIO.out_w1ts = (1UL << PIN_LAT);
delayMicroseconds(1);
GPIO.out_w1tc = (1UL << PIN_LAT);
}
inline void oe_on() { GPIO.out_w1tc = (1UL << PIN_OE); }
inline void oe_off() { GPIO.out_w1ts = (1UL << PIN_OE); }
// ===== 행 주소 출력 =====
inline void set_row(uint8_t row) {
if (row & 0x01) GPIO.out_w1ts = (1UL << PIN_A); else GPIO.out_w1tc = (1UL << PIN_A);
if (row & 0x02) GPIO.out_w1ts = (1UL << PIN_B); else GPIO.out_w1tc = (1UL << PIN_B);
if (row & 0x04) GPIO.out_w1ts = (1UL << PIN_C); else GPIO.out_w1tc = (1UL << PIN_C);
if (row & 0x08) GPIO.out_w1ts = (1UL << PIN_D); else GPIO.out_w1tc = (1UL << PIN_D);
}
// ===== 전역 버퍼 (0=off, 1=on) =====
uint8_t framebuffer[MATRIX_HEIGHT][MATRIX_WIDTH] = {0};
// ===== 픽셀 설정 =====
void setPixel(uint8_t x, uint8_t y, bool on) {
if (x >= MATRIX_WIDTH || y >= MATRIX_HEIGHT) return;
framebuffer[y][x] = on ? 1 : 0;
}
void clearShiftRegister() {
// 모든 데이터 라인 0으로 세팅
GPIO.out_w1tc = (1UL << PIN_R1);
GPIO.out_w1tc = (1UL << PIN_G1);
GPIO.out_w1tc = (1UL << PIN_B1);
GPIO.out_w1tc = (1UL << PIN_R2);
GPIO.out_w1tc = (1UL << PIN_G2);
GPIO.out_w1tc = (1UL << PIN_B2);
for (int i=0; i<32; i++){
set_row(i);
for(int j=0; i<16; i++){
clk_pulse();
}
lat_pulse();
oe_on();
delayMicroseconds(50);
oe_off();
}
}
// ===== 한 줄 그리기 =====
void drawRow(uint8_t row) {
for (int col = 0; col < MATRIX_WIDTH; col++) {
bool r1=false, g1=false, b1=false;
bool r2=false, g2=false, b2=false;
int y1 = row;
int y2 = row + 16;
if (y1 < 32 && framebuffer[y1][col]) { r1=g1=b1=true; }
if (y2 < 32 && framebuffer[y2][col]) { r2=g2=b2=true; }
if(r1) GPIO.out_w1ts = (1UL << PIN_R1); else GPIO.out_w1tc = (1UL << PIN_R1);
if(g1) GPIO.out_w1ts = (1UL << PIN_G1); else GPIO.out_w1tc = (1UL << PIN_G1);
if(b1) GPIO.out_w1ts = (1UL << PIN_B1); else GPIO.out_w1tc = (1UL << PIN_B1);
if(r2) GPIO.out_w1ts = (1UL << PIN_R2); else GPIO.out_w1tc = (1UL << PIN_R2);
if(g2) GPIO.out_w1ts = (1UL << PIN_G2); else GPIO.out_w1tc = (1UL << PIN_G2);
if(b2) GPIO.out_w1ts = (1UL << PIN_B2); else GPIO.out_w1tc = (1UL << PIN_B2);
clk_pulse();
}
lat_pulse();
set_row(row);
oe_on();
delayMicroseconds(50);
oe_off();
}
// ===== 전체 프레임 그리기 =====
void drawFrame() {
for (int row = 0; row < 16; row++) {
drawRow(row);
}
}
// ===== 초기화 =====
void setup() {
pinMode(PIN_R1, OUTPUT); pinMode(PIN_G1, OUTPUT); pinMode(PIN_B1, OUTPUT);
pinMode(PIN_R2, OUTPUT); pinMode(PIN_G2, OUTPUT); pinMode(PIN_B2, OUTPUT);
pinMode(PIN_A, OUTPUT); pinMode(PIN_B, OUTPUT); pinMode(PIN_C, OUTPUT); pinMode(PIN_D, OUTPUT);
pinMode(PIN_CLK, OUTPUT); pinMode(PIN_LAT, OUTPUT); pinMode(PIN_OE, OUTPUT);
GPIO.out_w1ts = (1UL << PIN_OE);
Serial.begin(115200);
Serial.println("=== Mapping Test Start ===");
}
// ===== 메인 루프 =====
void loop() {
static int x = 0, y = 0;
static unsigned long lastChange = 0;
// 현재 픽셀만 ON
memset(framebuffer, 0, sizeof(framebuffer));
setPixel(x, y, true);
// 계속 화면 refresh
drawFrame();
// 2초마다 다음 좌표로 이동
if (millis() - lastChange > 37) {
lastChange = millis();
x++;
if (x >= MATRIX_WIDTH) {
x = 0;
y++;
if (y >= MATRIX_HEIGHT) y = 0;
}
Serial.printf("Now lighting (%d, %d)\n", x, y);
}
}

