Introduction: Wooden LED Gaming Display Powered by Raspberry Pi Zero
This project realizes a 20x10 pixel WS2812 based LED display with a size of 78x35 cm which can be easily installed in the living room to play retro games. The first version of this matrix was built in 2016 and rebuilt by many other people. This experience was used to sum up all improvements to build a new version of the matrix and bring this now to instructables.com. Main new features are the update to a Raspberry Pi Zero instead using and Pi A plus an Arduino and replacing the previous large controller with a Bluetooth gamepad. Also the software was improved including the simulator, which allows you to develop the code on a computer even if you have no access to the matrix hardware.
One special feature of this LED matrix is the special wood veneer, which is used to cover the LED and to hide them, when LEDs are disabled. This highly increase the acceptance factor of non-tech people ;-) Of course, if this special veneer is not available in your country, you can also use some other diffuse material like acrylic to hide the LEDs. It is also planned to provide some key parts in the future to make it easier to rebuild the project.
Supplies
- Raspberry Pi Zero W (with some adaption, all other models will also work)
- 200 LED/s s (WS2812B LED stripes with 30 LED/m)
- 4x SPI LED matrix display with MAX7219
- Cables
- Bluetooth gamepad (e.g. this from Pimoroni)
- Power Supply 5V with at least 5A
- MDF wood for laser cutting
- Wooden veneer or diffusion acrylic plate
- Capacitor, Resistor
- Some screws
Step 1: Laser Cutting
Base structure of the matrix is made of MDF wood with a thickness of 3mm and cut by a laser cutter. If you do not own a laser cutter, you can use an online service like ponoko.com or formulor.de or contact the next fablab/makerspace in your environment. It is also possible to use cardboard or other lighter materials but the attached files are design for 3mm thickness, so thinner or thicker materials need a redesign of the files. Design was done in Fusion 360.
Most of the parts hold together just by sliding them in place, only some of the parts like the outer borders should be glued together using wood glue. Ensure that your matrix is fully working before applying any glue! Also the wood veneer has to be glued on, but this is the last step after ensuring that everything works.
At the right (lower) side of the backplane, there is a cut out segment to secure the electronic components to the matrix and still have access to this components when the veneer is glued on.
Step 2: Install LEDs
The LED stripes are standard 30 LED/m WS2812 stripes, which are available at Amazon, eBay or other online stores all over the world. This is normally also the cheapest addressable LED stripe available. If you want to use other LEDs, you have to ensure the 30 LED/m distance to fit to the matrix pattern. The lasercutted segments have small cut out regions to fit to the LED width of 10 cm. This LED stripes have double-sided tape on their back, so you can just glue them directly to the MDF after precise positioning. Check the correct orientation of every stripe before using the tape (DIN-DOUT direction).
Wiring pattern is a zig-zag so at the end, there is only one input pin to the matrix and cable lengths are as short as possible. To proper distribute the power and reduce the cabeling at the top of the matrix, every LED stripe is connected to 5V and GND at the bottom of the matrix. You can use either single wires or prototyping PCBs to distribute the 5V and GND line.
Step 3: Assembly
The explosion view helps to identify the correct pieces for the assembly. Just follow the step-by-step installation pictures. The backplane has cross structures to hold the long side walls and some of the short walls. If you have problems to install the pieces, use sand paper to fix it.
Step 4: Soldering
There are different ways to solder there power lines for the different stripes together. Either you can use single wires or some kind of common rail out of copper to solder the different wires. In this case, pieces of prototype PCBs were used to guide the power rails to the stripes. WS2812B stripes already have separate power cables which you can use to connect the power rail to the first stripe input (left side on the picture).
Step 5: Install SPI Display
To display game scores and text, a LED matrix display based on the LED driver MAX7219 is used. It is connected via SPI (Serial Peripheral Interface) to the Raspberry Pi. Four 8x8 displays are combined to a 32x8 pixel dot matrix display. You can buy this 8x8 pixel displays for e.g. at eBay, there are also combined 32x8 pixel displays available. Also you have different color options; in this case red displays were used. Because SPI works like a shift register, the displays are connected together in serial by connecting data out of the first matrix to data in of the second one and so on starting from the right side of the display.
This display is only readable from outside, if it is placed directly behind the veneer layer. If not, there is only a red blur visible. So you have to mount it on top of the backplane cut-out segment with a distance of 30mm between the surface of the backplane and the surface of the matrix. I have used some left over wooden pieces and screws to adapt the missing 19 mm between the backplane and the PCBs, but you can also any outer type of spacers.
Wiring of the display is shown in step 7.
Step 6: Install Pi
In this installation, a Raspberry Pi Zero is used. You can also use any other Raspberry Pi model, but newer ones with integrated WiFi and Bluetooth allow you to easily connect to wireless gamepads and simplify the programming.
You can secure the Pi by using at least two screws and small spacers to screw it to the backplane.
For the Raspberry Pi Zero W, the following pins are used:
- PIN 2: 5V
- PIN 6: GND
- GPIO18 -> LED stripes
- GPIO11: SPI CLK -> MAX7219 matrix CLK
- GPIO10: SPI MOSI -> MAX7219 matrix DIN
- GPIO8:SPI CS -> MAX7219 matrix CS
Some people reported issues with using GPIO18 for the LEDs. Please use GPIO21 in this case. If so, you have to change the code in line 21 to pixel_pin = board.D21.
The WS2812B strip is used here outside its spec. Normally it requires a 5V logic level on DIN, but the Pi only provides 3,3V. Even if this works in most of the cases, you should test this with your strip. If it does not work, you can add a level converter like a 74HCT245 or any other 3V3 to 5V converter between the Pi and the strip.
Step 7: Wiring and Power Supply
Wiring is done according to the wiring scheme. The power supply is a 5V DC supply.
For an easy on/off switching of the matrix, a switch is added between the power plug and the matrix circuits. Nevertheless, because the Raspberry Pi does not like hard switch off, there is a shutdown option in the software to safely shutdown the Pi via Gamepad before switching of the matrix.
The LED strip DIN pin is connected via a Resistor to the Pi, also a large capacitor (4700uF) is added to buffer the power supply. Please check out the Adafruit Überguide for Neopixels for more details.
LEDs are consuming a maximum current of 60mA per LED, so a maximum current of 200x60mA = 12A is possible!!! By reducing the brightness and not using all LEDs in full white, this is more a theoretical value, but it depends on the code which maximum current is reached. So selecting a large enough power supply is very important. For most of the applications a power supply with 5V/5A (25W) should be enough.
To fixate the backplane with the Pi and the Matrix display, some small pieces of wood can be used to scrum them in the edges and also use screws to hold the backplane in place.
Step 8: Setup Pi
1. Download latest Raspbian lite image from raspberrypi.org
2. Copy it to and SD card, 8GB is enough. You can use e.g. etcher to do this.
3. Before booting the Pi with the SD card, prepare WIFI and ssh access
4. Insert the SD card to any computer, a boot folder should be accessible
5. Copy the following lines to the file wpa_supplicant.conf (generate it if not exists) and change the parameters depending on your Wifi and region
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev country=US update_config=1 network={ ssid="Home Wifi" psk="mypassword" key_mgmt=WPA-PSK }
6. Add an empty file called ssh (without any extension) to boot to enable ssh access
7. Now insert the SD card to the Raspberry Pi and boot it. Check your wifi router to get the IP address of the Pi
8. start a SSH connection to the Pi using a terminal (Linux, Mac) or e.g. Putty an Windows. Insert the IP of the Pi instead of 192.168.x.y
ssh pi@192.168.x.y
9. Update the Pi (takes some time!)
sudo apt-get update sudo apt-get upgrade
10. Install pip and setup tool
sudo apt-get install python3-pip sudo pip3 install --upgrade setuptools
11. Install Neopixel driver, ws281x lib, pygame and libsdl
sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel sudo pip3 install pygame sudo apt-get install libsdl1.2-dev sudo pip3 install --upgrade luma.led_matrix
12. Enable SPI by calling raps-config, navigate to 5 Interfacing Options / P4 SPI / Enable
sudo raspi-config
13. Add Bluetooth Gamepad
sudo bluetoothctl [bluetooth]# agent on [bluetooth]# pairable on [bluetooth]# scan on [bluetooth]# pair aa:bb:cc:dd:ee:ff [bluetooth]# trust aa:bb:cc:dd:ee:ff [bluetooth]# connect aa:bb:cc:dd:ee:ff [bluetooth]# quit
where aa:bb:cc:dd:ee:ff is the MAC dress of your bluetooth gamepad. This address should be shown after calling the “scan on” command. Ensure that your Bluetooth controller is ready to pair, please check the manual of the controller how to do this.
14. You can now connect to you Pi via, default password is raspberry (Windows users may use Putty):
ssh pi@192.168.x.y
Step 9: Python Code, Test and Simulator
Code is available on Github. games_pi_only.py and all bmp files are needed.
git clone <a href="http://href=">href="https://github.com/makeTVee/ledmatrix/tree/master/python/pi_only</a>
The code has an option to run in simulation mode outside the Pi using pygame to simulate the matrix. This is very helpful to develop new features without having direct access to the matrix hardware. Also debugging is much easier. You have to set the PI constant to activate simulation mode (Line 15):
PI=False
In this simulation mode, alse the Keyboard is used instead of the Bluetooth gamepad. Buttons 1, 2, 3, 4 are mapped to A, B, X, Y of the gamepad, arrow keys for directions, “s” for start and “x” for select. You can use a standard editor plus the console or some integrated IDEs like Micosoft Visual Studio Code or Jetbrain PyCharm to do the development on your PC.
If you use the matrix and the Raspberry Pi, you have to define:
PI=True
To copy the code to the Raspberry Pi, you can use the scp command (Windows WinSCP). Open a console window, switch to the folder contenting the Github files and call
scp games_pi_only pi@192.168.x.y:/home/pi scp *.bmp pi@192.168.x.y:/home/pi
then connect to the Pi via ssh (Windows users may use Putty):
ssh pi@192.168.x.y
after successful logging on, you can start the python code by calling:
sudo python3 games_pi_only.py
If the code runs correctly, you can enable autostart by calling:
sudo nano /etc/rc.local
and add the following line before exit 0:
/usr/bin/nice -n -20 python3 /home/pi/games_pi_only.py &
Save (Ctrl+O) and Exit (Ctrl+X)
Step 10: Final Test and Veneer
Before the veneer is glue on top of the front, the matrix should be tested to ensure, that all LEDs are working. It is much easier to fix something before the veneer is glued on.
The used wood veneer is a special maple veneer paper called Microwood, which is one-side covered with paper and has a thickness of 0,1 mm. The paper side can be glued directly on the mdf using standard water free paper glue.
Step 11: The Result
Have fun and enjoy the game!

Grand Prize in the
Raspberry Pi Contest 2020
199 Comments
Question 2 months ago
Hi! I am currently building this on a 34x34 scale, however our LEDs zigzag horizontally instead of vertically like here. Is there any way to rotate the output image 90 degrees?
Answer 2 months ago
Sure, everything regarding the zigzag happens in drawPixelRgb and drawPixel. You have to change the matrix mapping there.
Question 1 year ago
Answer 1 year ago
please comment out:
drawImage('/home/pi/pi.bmp')
because the image does not fit to your display size
Reply 1 year ago
I commented that out and the script runs the selection screen. But you can't select a game because the select.bmp image causes it to crash when you choose it. Same problem as the pi.bmp image. Is there a way to change the images to fit my size display?
Reply 1 year ago
def drawImage(filename):
for row in range(0,20):
for col in range(0,10):
r,g,b = im.getpixel((col,row))
drawPixelRgb(col,row,r,g,b)
updateScreen()
Reply 1 year ago
I would like to enlarge the clock numbers to fit my display but I cannot figure out what the code is doing with the bitwise mask operation in the drawNumber def. I want the numbers to be 6 led's wide and 13 led's high each. I was able to change the starting positions of the numbers but what is the clock_font used for and do I have to modify it and with what? Can you explain the what the drawNumber def is doing and what the mask bytearray is being used for? Thanks.
Reply 1 year ago
The clock_font masks the bits (LEDs) for every number (5x3 pixels size), so for example the first line ist the zero character: 0x1F, 0x11, 0x1F
0x1F means 11111, 0x11 means 10001, so if you read it out in columns, you are getting:
111
101
101
101
111
which is the zero character. So you have to design your own font in a drawing program or on a squared paper and read it out in a similar way like it is done for the 5x3 characters. Hope that helps.
Reply 1 year ago
Thanks. I was able to make the numbers larger. Ingenious way of mapping them out! I also had some flickering issues. I had to take the 220ohm resistor and swap it out with a 100ohm resistor. Works fine now. One last question...I hope. Now that I have the basic concept down and working on a smaller level, I want to make a very large one. Like the size of a wall. Is there an easy way to program this to have 2 led lights light up in each box?
Reply 1 year ago
Great you solved it! Do you mean 2 LEDs per box or 4 (square)? Should not be to complex, unfortunately my time is very limited these days. When do you plan to build the large one?
Reply 1 year ago
I would like to start with 2 leds up and down per box. I think that would be simpler to keep track of which column leds are turned on and off in the code. If I can make that work then I would try 4 leds per box, 2 across and 2 down per box. I think that would be a little more difficult to keep track of the leds across the led strips. Once I get these to work, I'll start building the wall sized one.
Reply 1 year ago
I ended up changing the .bmp files to match the size of my matrix grid. I made them 16x56 but also had to make them 16bit color mode. The script now runs without errors in the demo mode. I am having other problems when trying to run it in normal mode. I had to change the score display settings because the text was going up and down and facing backwards. Got it working now after lots of reading. But, the LED lights just light up randomly in random spots. Some are constantly changing colors and others just stay lit. They do not display the .bmp images. I have 896 led's and I am using three separate 5 volt power supplies which supply power to about 300 led's each. I tried using the different board pins for the data and that didn't change anything. I read that somebody else had to change the /boot/config.txt file settings. I haven't tried that yet. Any other ideas that might lead me in the right direction?
Reply 1 year ago
I figured it out. I had the three power supplies grounded to different grounding pins on the Raspberry Pi. For some reason, it did not like that. I combined the grounds and plugged them into one grounding pin on the Pi and all LED's light up. I am not using capacitors since I have the three power supplies. Everything seems to light up just fine.
Question 3 years ago
hi~
Now i'm making this project!!
'Waiting for controller' comes out, but the raspberry pie image doesn't come out in display.
What do you think is the problem?
Answer 3 years ago
Please first check the function of the pixels with the examples from the Adafruit library: https://learn.adafruit.com/neopixels-on-raspberry-pi/python-usage Just to ensure that everything is wired correctly.
Reply 3 years ago
We already check LED ON!
If there's a difference, I'm using game pad '8bitdo Zero2 '...
Is different pad causing the error...?
Reply 3 years ago
I never used this controller. So I have uploaded a test_gamepad.py file to my Github: https://github.com/makeTVee/ledmatrix/tree/master/python
Can you please test it with your gamepad to see if the pygame joystick lib works?
Reply 3 years ago
Thank you :-)
I'll try it!
Reply 1 year ago
I know it has been a while since this question was asked. But I had the same problem with the pi.bmp image not loading properly. I added the clearScreen() method before the call to the drawImage('/home/pi/pi.bmp') method and then added the updateScreen()method after the drawImage() call in the "else" section at the top of the Main def. Fixed my issue.
Reply 3 years ago
I'm using new game pad and finally game pad connection is successful.
But pi.bmp image doesn't come out.
Strange and different led image come out,,,,,,,,
What's different is that I'm using 'Neopixel LED STRIP'.
What is the problem??😅😅