Description:
I am trying to control an LED panel using an ESP32.
The panel has a HUB75 connection and uses the following chips:
- SM16169SH
- INCD1018
Currently, I cannot even get the chip to turn on or display anything on the panel.
What I’ve tried:
- Basic ESP32 HUB75 libraries
- Attempted to send clock/data signals manually
- Checked wiring between ESP32 and HUB75
- Tried with 3V signals from the ESP32 and with the signals shifted to 5V with a SN74HCT245N
- I tried setting OE and CLK and LAT cycles, to get something running on the board, but didnt manage to
Problem:
- No LEDs light up, no output on the panel at all.
My questions:
- Does anyone have experience with the SM16169SH driver IC?
- Is there an initialization sequence required before the panel can display anything?
- Do I also need to configure the INCD1018 chip, and if so, how?
- Are there known working libraries for ESP32 + SM16169SH panels?
Hardware/Setup:
- ESP32
- LED Panel with HUB75 interface (80x40)
- SM16169SH + INCD1018 Chips
LED panel is powered with 5V and I am also using a SN74HCT245N to shift the 3V of the esp to 5V so that the panel gets the correct high/low signals.
I checked the Voltage after the SN74HCT245N, this was as expected (shifting between 0 and 5 Volts)
Code
As I did not manage to run anything i dont have any code except the mapping of the pins, which corresponds to my current wireing.
#define R1_PIN 14
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 25
#define G2_PIN 33
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19
#define C_PIN 32
#define D_PIN 12
#define LAT_PIN 18
#define OE_PIN 21
#define CLK_PIN 22
#define PANEL_WIDTH 80
#define PANEL_HEIGHT 40
I also have this script here
#include <WiFi.h>
#include <time.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "ESP32-VirtualMatrixPanel-I2S-DMA.h"
#include <Adafruit_GFX.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <WiFiClientSecure.h>
// —————— Wi‑Fi & Timezone ——————
const char* ssid = "";
const char* password = "";
const char* ntpServer = "";
const char* tzInfo = "";
// —————— Shelly BLE‑Gateway params ——————
const char* gatewayIp = "";
const char* sensorMac = "";
// —————— Panel geometry & pins ——————
#define PANEL_RES_X 80
#define PANEL_RES_Y 40
#define NUM_ROWS 1
#define NUM_COLS 1
#define R1_PIN 14
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 25
#define G2_PIN 33
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19
#define C_PIN 32
#define D_PIN 12
#define E_PIN -1
#define CLK_PIN 22
#define LAT_PIN 18
#define OE_PIN 21
#define VIRTUAL_MATRIX_CHAIN_TYPE CHAIN_TOP_LEFT_DOWN_ZZ
#define TEXT_SZ 1
#define CHAR_W (6*TEXT_SZ)
#define CHAR_H (8*TEXT_SZ)
// —————— VirtualPanel remap for 1/4‑scan ——————
class TenScanPanel : public VirtualMatrixPanel {
public:
using VirtualMatrixPanel::VirtualMatrixPanel;
protected:
VirtualCoords getCoords(int16_t x, int16_t y) override;
};
inline VirtualCoords TenScanPanel::getCoords(int16_t x, int16_t y) {
coords = VirtualMatrixPanel::getCoords(x, y);
if (coords.x < 0 || coords.y < 0) return coords;
const uint16_t subH = PANEL_RES_Y / 4;
coords.x += 16 * (1 + coords.x / 16);
if (((coords.y / subH) % 2) == 1) {
coords.x -= 16;
coords.y -= subH;
}
if (coords.y >= PANEL_RES_Y / 2) {
coords.y -= subH;
}
return coords;
}
// —————— Globals ——————
MatrixPanel_I2S_DMA *dma_display = nullptr;
TenScanPanel *tenPanel = nullptr;
// shared readings
volatile float currentTemp = NAN;
volatile float currentHum = NAN;
volatile float currentPrice = NAN; // cents per kWh
static StaticJsonDocument<1024> doc; // for Shelly JSON
static StaticJsonDocument<2048> adoc; // for aWattar JSON
static std::vector<uint8_t> dataBuf;
// —————— Base64 decoder ——————
static const char B64_CHARS[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
bool base64Decode(const String &in, std::vector<uint8_t> &out) {
int val = 0, valb = -8;
for (char c : in) {
if (isspace(c)) continue;
if (c == '=') break;
const char *p = strchr(B64_CHARS, c);
if (!p) return false;
val = (val << 6) + (p - B64_CHARS);
valb += 6;
if (valb >= 0) {
out.push_back(uint8_t((val >> valb) & 0xFF));
valb -= 8;
}
}
return true;
}
// —————— Display Task (every 1 s on Core 1) ——————
void displayTask(void *pvParameters) {
char timeBuf[9], buf[8];
for (;;) {
// local time
time_t now = time(nullptr);
struct tm ts;
localtime_r(&now, &ts);
snprintf(timeBuf, sizeof(timeBuf),
"%02d:%02d:%02d", ts.tm_hour, ts.tm_min, ts.tm_sec);
tenPanel->startWrite();
// — time centered —
{
uint16_t w = strlen(timeBuf)*CHAR_W;
uint16_t x = (PANEL_RES_X - w)/2;
uint16_t y = (PANEL_RES_Y - CHAR_H)/2;
tenPanel->fillRect(x, y, w, CHAR_H,
tenPanel->color565(0,0,0));
tenPanel->setCursor(x, y);
tenPanel->print(timeBuf);
}
tenPanel->endWrite();
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void setup() {
Serial.begin(115200);
// Wi‑Fi & NTP
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(300);
Serial.print('.');
}
Serial.println(" WiFi OK");
configTzTime(tzInfo, ntpServer);
// HUB75 DMA init
HUB75_I2S_CFG::i2s_pins pins = {
R1_PIN,G1_PIN,B1_PIN,
R2_PIN,G2_PIN,B2_PIN,
A_PIN,B_PIN,C_PIN,
D_PIN,E_PIN,
LAT_PIN,OE_PIN,CLK_PIN
};
HUB75_I2S_CFG cfg(PANEL_RES_X*2, PANEL_RES_Y/2, NUM_ROWS*NUM_COLS);
cfg.clkphase = false;
cfg.driver = HUB75_I2S_CFG::FM6126A;
dma_display = new MatrixPanel_I2S_DMA(cfg);
dma_display->setBrightness8(10);
if (!dma_display->begin()) {
Serial.println("DMA init failed!");
while (1) delay(1000);
}
// virtual panel
tenPanel = new TenScanPanel(*dma_display,
NUM_ROWS, NUM_COLS,
PANEL_RES_X, PANEL_RES_Y,
VIRTUAL_MATRIX_CHAIN_TYPE);
tenPanel->setTextColor(tenPanel->color565(50,50,50));
tenPanel->setTextSize(TEXT_SZ);
tenPanel->fillScreen(tenPanel->color565(0,0,0));
// start tasks
xTaskCreatePinnedToCore(displayTask, "Display", 4096, NULL, 1, NULL, 0);
}
void loop() {
// nothing here – all work in tasks
}
Which was working on another panel, that was using the ICN2037BP+ RUC7258D. This is not running on my panel with the SM16169SH.