Close
0%
0%

MatTris — Tetris on an LED Matrix

Classic Tetris running on a custom WS2812 2020 LED-based matrix powered by RP2040!

Similar projects worth following
Meet MatTris, a DIY Tetris console built completely from scratch. I was born in 1998, and my first introduction to Tetris was through those monochrome LCD handhelds that came loaded with 10 to 100 built-in games. That’s what inspired me to build my own version using modern hardware. Years later, while working with addressable LEDs and microcontrollers, I wanted to recreate that same experience, but using hardware I designed myself. This project began with the idea of using a WS2812B mini LED matrix as the display, paired with a microcontroller (Waveshare RP2040 Tiny) to control the matrix and handle all game logic.

To bring everything together, we designed a custom PCB that integrates a 14×20 LED matrix, input buttons, and a dedicated power management circuit. The entire system is powered by a LiPo cell, with an onboard power management IC responsible for charging and discharging the cell.

This article covers the complete build process of this project; let's get started.

MATERIALS REQUIRED

The following materials were used in this project:

  • Custom PCB (Provided by HQ NextPCB)
  • RP2040 Tiny Waveshare board
  • WS2812B 2020 Package LEDs
  • 100 nF Capacitors 0603 Package
  • 10 uF Capacitor 1206 Package
  • IP5306
  • 10 uH Inductor
  • Indicator LED 0805 Package
  • USB Type-C port
  • Push Buttons 6x6 SMD
  • 2 Ohms 1206 Package
  • RP2040 Tiny Programmer
  • 3D Printed Enclosure

3D MODEL

This project started in Fusion 360. We first imported the 3D models of the WS2812B 2020 package LEDs into Fusion, along with the CAD models of the SMD switches, USB Type-C port, RP2040 Tiny, and the battery.

We then designed a 91 × 47 mm PCB. The upper section of the board was dedicated to the RGB LEDs, where we used the pattern feature to create a 14-row by 20-column LED matrix. In the lower section, we placed the SMD switches following a Game Boy–style layout, with a D-pad consisting of UP, DOWN, LEFT, and RIGHT buttons, followed by the A and B buttons.

The RP2040 Tiny was placed on the backside of the PCB. Alongside this, we also modeled an enclosure to hold the PCB securely in place, cover the backside containing the battery, and make the device comfortable to hold. We even added a ring at the top of the enclosure, which serves as a design element and allows an ID card strap to be attached so the device can be worn as a badge or hung somewhere.

After finalizing the model, we exported the enclosure mesh and 3D printed it on my new Anycubic Kobra S1 using Hyper PLA, and the print turned out really clean. I had been using an Ender 3 for a long time, and this upgrade turned out to be exactly what I needed for projects like this.

We also exported key dimensions for component placement, board outline, and general layout reference. These dimensions were later used during the PCB design process.

PCB DESIGN

The PCB design process begins with preparing the schematic for the project. In our case, we had previously worked with WS2812B 2020 package LEDs. These LEDs are not the easiest to work with because of their small size, but that same compact form factor is exactly what makes them ideal for matrix-based projects.

We reused the schematic from our earlier 8×8 Tiny Matrix project as a starting point. Instead of an 8×8 layout, we expanded the design to a 14×20 matrix by adding more LEDs.

We then added another section to the schematic for the RP2040 Tiny board, which was connected to six push buttons. All buttons are connected to GND and individual GPIO pins. When a button is pressed, it pulls the corresponding GPIO pin low, and the microcontroller registers this as a button press.

We used the Waveshare's RP2040 Tiny, which is an RP2040-based SMD development board designed to be mounted directly onto a PCB as a module, similar to ESP-12F or ESP32 modules. The RP2040 Tiny features castellated pads, which allow it to be soldered onto the backside of the PCB and integrated cleanly into the overall design.

Check out its wiki for more info—https://www.waveshare.com/wiki/RP2040-Tiny

For power, we’ve included our trusted IP5306—a power management IC we’ve used in many previous projects. It provides a stable 5V output from a 3.7V lithium cell and includes features like charging indication, low battery warning, and high/low voltage cutoffs, all essential for safe lithium cell operation.

NextPCB PCB SERVICE

After completing the PCB design, Gerber data was sent to HQ NextPCB, and an order was placed for a green solder mask with white silkscreen; we even ordered a stencil this time.

After placing the order, the PCBs and stencil were both...

Read more »

TETRIS v8.step

step - 28.94 MB - 12/22/2025 at 06:33

Download

tetris sch.pdf

Adobe Portable Document Format - 312.56 kB - 12/22/2025 at 06:31

Preview

  • 1
    STENCIL PROCESS

    We started the circuit assembly process by applying solder paste to the PCB, but there was a slight problem. The number of components used in this project is quite large, which also means a very high number of pads. Because of this, using a solder paste dispensing syringe would be impractical. Instead, we used a custom stencil made specifically for this circuit.

    A stencil is essentially a thin metal sheet with laser-cut slots and holes that match the component pads on the PCB. Using a stencil allows solder paste to be applied evenly across all pads. In industrial settings, where circuits are mass-produced, stencils are commonly used for this purpose.

    • We first set up a makeshift PCB and stencil holder using extra PCBs. This setup helped keep the main PCB stationary and ensured it did not move during the process.
    • After aligning the stencil openings with the PCB component pads, we applied solder paste over the stencil and used a scraper to spread it evenly across the slots. This process deposited a thin, uniform layer of solder paste onto each component pad, preparing the board for component placement.
  • 2
    SMD COMPONENTS PLACEMENT PROCESS

    Now comes another tedious process: SMD component placement. It is tedious because of the sheer number of LEDs used in this project. In total, we used 280 LEDs along with several other SMD components, bringing the overall component count to over 300. All of these components had to be placed manually.

    • We started by placing the 100 nF decoupling capacitors in their designated locations. For the pick-and-place process, we used ESD-safe tweezers.
    • Next, we placed all 280 SMD RGB LEDs onto their pads, making sure each LED was oriented correctly, as incorrect orientation would prevent the LEDs from working.
    • After the LED placement, we added the remaining SMD components, which included the SMD push buttons and all the parts related to the power management circuit.
    • Once all components were placed, the entire board was carefully lifted and placed onto an SMD reflow hotplate. The hotplate heats the PCB from below up to the solder paste melting temperature, which is around 200°C. As a result, all the components are soldered securely to their pads.
  • 3
    TESTING SMD LEDs

    Before we move ahead with the placement of the RP2040 board on the backside of the PCB, we tested whether the LEDs were working or not. If the LEDs were not working and the RP2040 was already mounted on the back side of the PCB, we would not be able to use a hot plate to correct the LEDs.

    We added jumper wires to the 5V, GND, and GPIO0 terminals of the RP2040. These jumper wires were then connected to a XIAO SAMD21 M0 development board.

    We uploaded the sketch below to the XIAO, which turns on each LED in the chain one after another in green. This sketch was taken from the example sketches of the Adafruit NeoPixel library.

    #include <Adafruit_NeoPixel.h>
    #ifdef __AVR__
    #endif
    #define PIN        0
    #define NUMPIXELS 280
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    #define DELAYVAL 50
    void setup() {
    #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
    clock_prescale_set(clock_div_1);
    #endif
    pixels.begin();
    }
    void loop() {
    pixels.clear();
    for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
    pixels.setPixelColor(i, pixels.Color(0, 150, 0));
    pixels.show();
    delay(DELAYVAL);
    }
    }

View all 9 instructions

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates