Fork this with Git

RGB LED Matrix visualizer

For HUB75 modules, running on Raspberry Pi and Pico W
Project started on September 05, 2023.

Recent activity on GitHub:

I initially bought a 32x32 RGB LED matrix in 2018. Back then the idea was to fit it onto a bag, as some kind of wearable device, for 35C3. But it never really worked out. So in preparation for CCCamp23 I noticed the LED panel again and decided to order some more of them.

These are the 32x32 4mm pitch RGB LED Matrix Panels from Pimoroni, with either the Interstate 75 W or the Adafruit RGB Matrix Bonnet to run them with a RP2040 or a Raspberry Pi, respectively.

Tetris (paused)
Someone tries to beat Breakout
3D design for panel mounts

Everything runs from a single Python codebase, either simulated in a GUI window on a development PC, on the Raspbian Python interpreter or directly on the Pico MicroPython environment.

Screenshot of weather widget
Portable matrix showing a QR code
Portable matrix showing battery state

For portability I'm simply using a voltage regulator to connect a 4S LiPo battery. I made one of them from recycled single-use vape batteries, but I also used some of my RC-model batteries.

Recycled vape batteries
Back side of portable matrix
Pico without voltage regulator

On the software side I wrote some code to show static images, GIF animations, scroll text across the matrix, etc. I also implemented Snake, Tetris and Breakout, as well as some other utilities, like OTA updating for the Pico, a Telegram bot integration, a weather widget and a service checking if a device is reachable on the network.

Game of Life
Aphex Twin logo

Right now the 64x64 panel is placed next to the TV in my livingroom, randomly cycling through some animations and games.

Animated globe
Animated Sephiroth
Animated Cloud

I wasn't really able to get breakout into a playable state before CCCamp23. But luckily I also got a patch set (1, 2, 3, 4) from Jannis that fixed the collision behaviour of the ball in breakout! We met on the camp and had a very nice time together. And soon afterwards the patches appeared in my inbox and actually made the game playable! This was really awesome 😊💪 Thanks again!

Another player already scored 80 points
64x64 panel in my livingroom
Backside of 64x64 panel

Here are my notes for installing everything on a Raspbian OS.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pip git vim htop
git clone
cd Raspberry-Pi-Installer-Scripts
sudo ./
# Answer y, Bonnet, Quality (and solder the mentioned link on the board)
cd ..

git clone
sudo pip3 install Pillow bdfparser "qrcode[pil]" evdev

cd Raspberry-Pi-Installer-Scripts/rpi-rgb-led-matrix/bindings/python
pip3 wheel --no-deps -w dist .
sudo pip3 install dist/rgbmatrix-0.0.1-cp39-cp39-linux_armv7l.whl

sudo apt-get install libopenjp2-7

# append isolcpus=3 to /boot/cmdline.txt
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
blacklist snd_bcm2835

sudo update-initramfs -u
sudo reboot

# test python bindings work
cd rgb-matrix-visualizer
sudo ./

sudo sh -c 'echo enable_uart=1 >> /boot/config.txt'

Although I'm currently still having some problems getting the wetterdienst dependency running on the Raspberry Pi.

Two small panels and materials for the large matrix
Game of Life on four matrices
96x32 frame design

I also want to give a shout-out to Pimoroni. I managed to rip-off the power connector on one of the panels. They sent a replacement without any additional cost, but I took the chance and ordered some more spare panels.

Power connector ripped-off from PCB

The modules bought this year have pretty consistent color reproduction. But compared to the one module I bought five years earlier, there is a very noticable difference. On these pictures both modules show the same RGB values.

Color reproduction issue (1)
Color reproduction issue (2)

I added some simple compensation to mostly adjust for this issue.

# For some reason the red and green LEDs on older Pimoroni panels
# are far brighter than on newer panels.
# Adjust this by multiplying rg channels with 0.75 and b channel
# with 0.85, depending on hard-corded coordinate ranges.
class MapperColorAdjust(MapperNull):
    def set_pixel(self, x, y, color):
        # second panel from the left, with 32 <= x,
        # is "old" type with brighter LEDs.
        # rest of panels to the left are less bright.
        # so adjust brightness of other panel channels down.
        if x >= self.gui.panelW:
            color = (int(color[0] * 0.75), int(color[1] * 0.75), color[2] * 0.85)

        self.gui.set_pixel(x, y, color)

I also planned to build a large LED matrix based on WS2812 LED strips. They can be driven easily with a Raspberry Pi.

Level shifter for WS2812 strips
Large matrix frame and strips

I was even able to get a basic frame finished before CCCamp23. But that's where time ran out.

Frame for large matrix, back side
Frame for large matrix, front side
Corner piece for large 32x32 matrix

I haven't yet given up that plan completely, but I have to think of a solution for diffusing the light first. The LEDs are too small and spaced too far apart to look good in this configuration.

More Pictures

Some more photographs I didn't use above.
Animated Nintendo 64 logo
Empty matrix
LED strips for large matrix
Color reproduction issue (3)