Monochrome 32*16 P10 HUB12 LED matrix control with ESP32

Hi, I have 3 variants of displays at home. Versions 1 and 2 of the outer version 3 are the inner inverted. They all work well with the DMD3 library. The mapping you have right just is the wrong timing. I will try to put pullup or down resistors on the outputs for edge banding. The DMD3 library is slow and ESP32 with a web server is not enough to refresh the display. That’s why I want to use the smartmatrix library. You have an inverted implementation in your library for use in version 3. I bought the displays on aliexpress and ebay over the course of two years.

Otherwise, I’m glad you’re developing this library. I will support you.

Unfortunately, I only had two links to insert.

version 2

Hi René, thanks for your donation which motivated me to dig out my HUB75 panels and bare ESP32 to connect up the panels and see what’s going on. I was able to reproduce some of the issues here, and found a fix:


It looks like sometimes the clock needs to be inverted. I’m not sure if that’s the case on all hardware setups, but it helped with the panels I have here and a bare ESP32.

For your version 3, it looks like you don’t need the inversion on the data line. You can do a quick fix for now, just comment out the code that inverts R1. There’s two places in the code with inversion:

Hope that helps, LMK if you’re still seeing issues.

I have also tried using this:

And it changed this:

to this:

And also with that additional config it shows some kind of flicker, but not much in terms of different LEDs being lit up.

I assume that the other piece of advice with the editing of the files is just for the inverted panel and wouldn’t help in my case. So what you see is the result of just adding that to the config.


@BodoMinea I think you have a different issue with your panel. I can’t reproduce it here. If you can get me a sample of your panel (I’m in the UK) or let me know where you got it, I can try to reproduce the issue.

(I didn’t see your other post update when I posted this, maybe you’ve gotten it to work now?)

Nope, that’s another type of panel. HUB75 and RGB. There are two separate topics for the two types I am testing. For those I found the control voltage to be the issue and my level shifts to not be working. Will investigate the shifters you pointed me to, otherwise the issue is software-wise closed as the library is driving them as intended.

But the panels we´re talking about here are HUB12, monochrome and 3v3 friendly (tested with rpi-rgb-led-matrix on Pi 1, 3 and 4, directly connected) but light up the wrong pixels - as seen in the above pictures/videos.

I currently cannot obtain the information regarding their sourcing (I didn’t buy those myself) and also cannot send you one because I am not at my office until later next week. When I get back there I will do that and also test multiple panels I have (I think I also have some red ones with the same arrangement, or at least some red ones that are tested with rpi-rgb-led-matrix as working), test all hardware combinations and if I don’t uncover anything I’ll ask for your details in order to have one delivered to you.

@BodoMinea you might want to lower the clock speed to see if that helps:

Apologies if I already suggested this or you already tried this, I have limited time to help out with these things and can’t keep all the details in my head.

Hi, thank you for your reply. The patch does not work on any version of the display. Also version 3 after pixel negation behaves the same. It is not visible without negation. I also reduced ESP32_I2S_CLOCK_SPEED - nothing. Can I invert a font written with USE_ADAFRUIT_GFX_LAYERS? So I don’t know what to do next.

@renda71 So SMARTMATRIX_OPTIONS_ESP32_INVERT_CLK doesn’t work on any version of the display? What changes if anything?

It doesn’t make any sense that removing pixel negation on version 3 doesn’t change anything. It should invert the pixels on all panels, and you could verify that with one of your other panels.

Can I invert a font written with USE_ADAFRUIT_GFX_LAYERS?

You can make the font color black, and set the background to white. You may find it useful to disable color correction on the layers so that the exact colors you set are sent to the panel instead of applying color (gamma) correction.

@renda71 while I have the HUB12 panels pulled out I’m trying to add support to Teensy 4. The panels I have require OE to be inverted, which isn’t easy to do, so I haven’t done it yet. The result looks inverted like your version 3 video. You may want to try combinations of enabling and disabling OE, R1, and CLK inversion to try to get your version 3 working.

I tried that at an earlier stage, only the ‘flicker’ changes, but the wrong lit up pixels are still at their places.

No worries :slight_smile: I know you’re doing your best to support the widest range of panels but sometimes the Chinese manage to surprise us all.

I am sorry. I described it incorrectly. My English is bad. So after changing (SMARTMATRIX_OPTIONS_ESP32_INVERT_CLK) display versions 1 and 2, the mapping test is unchanged. The version 3 display has changed. This display is inverted hardware. I wanted to try to change it, so my question in the previous post. I can’t change the color of the text. I am doing something wrong.


#include <Wire.h>
#include <MatrixHardware_ESP32_V0.h>
#include <SmartMatrix.h>
#include <Fonts/FreeMonoBoldOblique12pt7b.h>

#define COLOR_DEPTH 24                  // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 32;        // known working: 32, 64, 96, 128
const uint8_t kMatrixHeight = 32;       // known working: 32 (untuk 1 baris), 64 (untuk 2 baris)
const uint8_t kRefreshDepth = 24;       // known working: 24, 36, 48
const uint8_t kDmaBufferRows = 2;       // known working: 2-4, use 2 to save memory, more to keep from dropping frames and automatically lowering refresh rate
const uint8_t kPanelType = SMARTMATRIX_HUB12_16ROW_32COL_MOD4SCAN;   // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels
//const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_HUB12_MODE);      // see for options

const uint8_t kIndexedLayerOptions = (SMARTMATRIX_OPTIONS_HUB12_MODE);
SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_INDEXED_LAYER(indexedLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kIndexedLayerOptions);

const uint8_t kMonoLayerOptions = (SM_GFX_MONO_OPTIONS_NONE);
const rgb24 defaultBackgroundColor = {0,0,0};

void setup() {
  //indexedLayer.fillScreen(0xff); //  this works background is off
  indexedLayer.setTextColor(0x0000); //  the color setting does not work to change the invert pixel
  indexedLayer.drawString(0, -7, 0, "He"); // Tes Vertikal

void loop() 


You’re using the indexed layer which is more complicated. It only has two colors: 0 and 1. 0 is transparent. 1 is whatever color you set with indexedLayer.setIndexedColor().

This code won’t work, 0xff isn’t a valid indexed color for this layer: indexedLayer.fillScreen(0xff);

This code sets the layer color to black:

indexedLayer.setIndexedColor(1, {0,0,0});

indexedLayer.setTextColor(0x0000) doesn’t work as you intended as you’re setting the color to index 0 which is transparent.

This code draws text to the screen with indexed color 1, which is black:

indexedLayer.drawString(0, -7, 1, "He");

You can’t see it though because the transparent pixels see through to the default black color underneath, and you can’t change the default color. You’ll need to add another layer underneath, that could be backgroundLayer, or it could be another indexedLayer with index color 1 set to white, and the screen filled with indexed color 1.

I hope this is not too confusing.

I’m not sure what to suggest for your panels 1 and 2. If you paste the code that you used to test SMARTMATRIX_OPTIONS_ESP32_INVERT_CLK I might be able to spot a bug. e.g. this is incorrect: const uint8_t kIndexedLayerOptions = (SMARTMATRIX_OPTIONS_HUB12_MODE);, HUB12 mode is not an option for the indexed layer

I made a new branch for testing that has two new kMatrixOptions defines:


SMARTMATRIX_OPTIONS_HUB12_MODE has the same effect as (SM_HUB75_OPTIONS_INVERT_DATA | SM_HUB75_OPTIONS_INVERT_OE) and you can enable either one of them to test different combinations

Thanks for the directions. I have something wrong. I don’t know how to determine the order of the layers.

const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);
SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);

SMARTMATRIX_ALLOCATE_INDEXED_LAYER(background, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kIndexedLayerOptions);
SMARTMATRIX_ALLOCATE_INDEXED_LAYER(layer1, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kIndexedLayerOptions);

void setup() {

layer1.drawString(0, -7, 1, “He”); // Tes Vertikal


I don’t see any issues, but I didn’t try it myself. You have the order of the layers correct.

Hi, I have „re-done” all of my tests and will reiterate the information here. I have swapped the matrix for an older but similar one, red LEDs this time, swapped the ESP32 board and set up the wiring again.

Unfortunately the links for buying either of this panels are not up anymore, but I have the specifications of the seller claimed they are saved.

LED Matrix Panel specs
Pixel Configuration 1 Red
Module Size 320mm × 160mm
Drive Mode Constant Current drive 1/4 scan
Drive IC 74HC595

I searched for these parameters on Aliexpress (the original source for my modules) and found this - It is not the listing or seller that I bought from but they seem identical.

This particular matrix is tested as being 3.3v input signal tolerant as it has been properly driven by rpi-rgb-led-matrix with the custom mapping described here - Monochrome 32*16 P10 HUB12 LED matrix control with ESP32

It is also usable with the DMD2 library, at least with the older Arduinos, albeit those output 5V so it doesn’t really help as an arguent -

Picture of the panel’s back side

Chip namings correspond to what the seller listed.

Please note that the sides of the connector as I see them are flipped because I am doing the wiring to the ribbon connector.

GPIO5 A 1 - 2 OE GPIO25
GPIO18 B 3 - 4 GND GND
GPIO19 C 5 - 6 GND NC
GPIO26 SCK 9 - 10 GND NC
GPIO2 R 11 - 12 GND NC
NC E 13 - 14 GND NC
NC D 15 - 16 GND NC

Various test sketches
All of them start like this:

const uint16_t kMatrixWidth = 32;
const uint16_t kMatrixHeight = 16*2;


#include <MatrixHardware_ESP32_V0.h>
#include <SmartMatrix.h>
#define COLOR_DEPTH 24
const uint8_t kRefreshDepth = 36;
const uint8_t kDmaBufferRows = 4;

Also, all of them use the mono layer:

SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);

const uint8_t kGFXMonoLayerOptions = (SM_GFX_MONO_OPTIONS_NONE);
SMARTMATRIX_ALLOCATE_GFX_MONO_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kGFXMonoLayerOptions);

#define BLACK   0x0000
#define RED     0xF800

The following test results are different attempts to understand what’s going on by displaying different things with different kMatrixOptions. kPanelType is always SMARTMATRIX_HUB12_16ROW_32COL_MOD4SCAN.



same with

same with

same with

for(int j=0; j<kMatrixHeight; j++) {
    for(int i=0; i<kMatrixWidth; i++) {




backgroundLayer.drawLine(0,0,kMatrixWidth,kMatrixHeight/2,RED); with either SMARTMATRIX_OPTIONS_HUB12_MODE or SMARTMATRIX_OPTIONS_ESP32_INVERT_CLK:

Changing the clock speed only affects the extent of flickering and ghosting on the panels which tend to vary a bit between panels, but the bottom line is that no matter what I change - matrix options, the matrix itself, the esp32 etc. the stray/incorrect pixels are still there. However, the same ESP32 can correctly drive HUB75 panels using this library and these panels can be controlled with a Raspberry Pi. So I am at a loss, I cannot seem to isolate the issue.
Do you have any other ideas? Would you like to have one of these modules arranged to be shipped to you?

Thank you again for your time and work.

Hi, I have exactly the same panel as you, it’s version 2. Version 3 works great for me. In the evening I will write what I came up with and send it.

Hi, panels version 1 and 3 work well. The video shows a difference in voltage levels of 3.3 v - 5V. It’s good up to 4.5V. Then you need a level converter. The difference in brightness between 4.5 - 5V is minimal. Version 2 of the panel behaves exactly like you. I used the library I have for it (slow digitalWrite) and it works well. So the mapping has the same as version 1 or 2. I don’t know maybe a small time shift of clk and R1. Thank you very much for your help.

version 1:

version 2:

version 2 library DMD3 ESP32 same connection MatrixHardware_ESP32_V0 Arduino forum: