Close

Software to drive the matrix

A project log for IoT RGB LED Matrix Controller (ESP32)

This project is about building and programming an ESP32 based controller for a 32x32 RGB LED matrix, controlled from Node-RED over MQTT

solenoidSolenoid 01/01/2018 at 17:550 Comments

I looked if there was anything done on the software side for something less powerful than a Raspberry Pi. Some hardware is unfortunately very finicky and won't even work and lower clock speeds (WS2812 LED's, OV7670 camera...). Fortunately Adafruit had libraries and examples for Arduinos, unfortunately though the only Arduinos I had on hand were Leonardos (ATmega32U4 based), which were explicitly unsupported for various reasons.

Operation theory

The 32x32 RGB LED matrix is updated row-by-row, over 16 rows, upper and lower part at the same time. There are 6 pins for the color, so 3 for the upper half and 3 for the lower. 4 pins select one of the 16 rows (both for upper and lower matrices) and a clock signal that clocks in the pixel values. Then there are some other pins whose function I haven't quite understood...

Pixel glory!

As my ESP32 hadn't arrived yet I started with the Adafruit's library as an example and wrote a program to drive the matrix from an Arduino Leonardo. The reason they did not support this particular model was because they wanted to remain compatible on a certain number of other models, however the way the Leonardo pins are mapped to the Arduino pinout made it awkward to accommodate the library in a way that would remain maintainable. They did some really clever tricks to speed-up draw time to avoid visible flickering, such as using automatic pointer address increase in assembly (this is cycle counting business right there!).

I really liked the way Adafruit "parallel-banged" the GPIO directly from memory, basically the upper and lower pixel RGB values (6 bits) were stored on a single byte which was directly applied on an entire GPIO port array. This meant a simple loop could just sequentially bang the contents of a 32*32/2=512 byte array to a port without any conditionals or checks, considerably speeding up the screen update rate compared to, say, an RGB object that would define 3 bits per pixel to which the compiler would add all sorts of operations and jumps...

Working example

Finally I got some sort of animation going on:

Discussions