All source files for this project are available here: https://github.com/Jianan-Li/Tiny-Tetris
Before talking about the Tiny Tetris itself, I need to say that there are a couple firsts with this project:
First time using the laser cutter to make enclosures.
First time using a stencil for applying solder paste.
First time using a toaster oven to reflow PCBs.
First time using an IC in QFN package with 0.5mm pitch (ATmega32u4).
There are two things I don’t like about my previous Tetris Gaming Device. First, it’s too bulky. It doesn’t fit in my pocket, so I can’t bring it anywhere with me. Second, it’s not rechargeable through usb. The battery used in the Tetris Gaming Device is a 7.4V 2S LiPo battery, so you’ll have to use the special LiPo charger to charge it instead of usb.
That’s why I decided to make the second generation of the Tetris Gaming Device. Introducing the Tiny Tetris!
The size of the Tiny Tetris is 94.0 mm (3.70 inches) x 49.5 mm (1.95 inches) x 17.1 mm (0.67 inch). It is powered by a 3.7V LiPo battery and is rechargeable through its micro usb port.
On the left side, there are two general purposes buttons, which I configured to adjust the brightness of the LED display in my demo program, and two indicator LEDs for power and charging respectively.
On the right side, we have a reset button that is connected to the reset pin on the MCU.
On the top, there is a pushbutton power switch. The circuitry used is essentially the same as the breakout board that Adafruit sells.
On the bottom, there is the micro usb port for both charging and programming the MCU (ATmega32u4), and also a 6-pin ICSP/ISP header for flashing the bootloader and setting the fuses with USBTiny or other AVR programmers.
There are a couple things I want to talk about in this post, including the enclosure design, the pcb design and component selection, and then the software.
First, let’s talk about the enclosure design. On the old Tetris, the enclosure is 3D printed on a Stratasys 3D printer. Since I wanted to experiment with different tools and machines in my projects, I decided to laser cut the enclosure for the Tiny Tetris in our student machines shop.
It’s not easy to get the power and speed settings right on a laser cutter, and you’ll have to design the kerf into each piece to get the correct dimensions. The picture above shows about a third of all the tests that I did using scrap acrylic pieces to get everything right.
The design I used consists of six pieces of acrylic: top, bottom, and the four sides. The side pieces have tabs both on the ends and sides, so all the sides pieces can be connected together, and then plug into the top and bottom pieces. The eight holes and the top and bottom pieces are for the flat head M2 screws. If you look carefully at the screw holes, you’ll see that they are countersink holes. I did this with the 3D engraving feature that is available on the Universal Laser Systems. It turns grayscale images into three-dimensional engravings, so all I have to do to countersink the holes is to draw a circular grayscale gradient around the holes.
I used the same technique to 3D engrave the area around the joystick/navigation switch to allow the movement of the switch without exposing too much circuit board from the top, and also the area around the micro usb port to be able to use any micro usb cable with this device.
The design of the buttons on this acrylic enclosure is inspired by this clock kit from Evilmadscientist. When pressed the acrylic would bend just enough to trigger the pushbutton mounted on the pcb inside.
Here is a picture showing the thickness breakdown and how everything is fastened together.
Next, let’s talk about the pcb design and component selection.
I went through a total of four iterations of the pcb design, and they are named Tetris v1.0 ~ Tetris v1.3 as indicated on the pcb. There is a huge difference between v1.1 and v1.2 since I made the decision to replace the ATtiny85 with the ATmega32u4, whereas the difference between v1.0 and v1.1, and v1.2 and v1.3 is not so significant.
Moving from v1.0 to v1.1, I changed the way that the 8-pin headers are connected to the pcb by increasing the hole size. Here are pictures showing the difference between the two.
Moving from v1.1 to v1.2, I decided to replace the ATtiny85 with the ATmega32u4. The main reason is that I realized I wanted to be able to measure the battery voltage and have the device automatically turn off when the voltage is below a certain threshold. This feature requires two more pins – one with ADC to measure the voltage and the other to kill the power – and this means that if I stick with the ATtiny85, some of the pins will have dual functionalities, and it would be even more troublesome to run SoftwareSerial at the same time. So in order to make the device more reliable and function more predictably, I decided to use the ATmega32u4 instead. But this is not a decision that can be made at any time of the day. I was lucky enough to find a small quantity of the ATmega32u4RC available on Digikey. Now if you don’t check Digikey regularly, you probably don’t know that all variants of the 32u4 have been out of stock for months, not only on Digikey but also other major distributors, due to the popularity of the chip. I couldn’t believe it when I accidentally found 71 of the RC version available on Digikey and immediately bought 10 of them.
Also, another change I made to the pcb design is that I added a tiny piece of pcb under the joystick so that it would be able to stick out above the top surface of the enclosure. In v1.1, the joystick is almost impossible to use when the pcb is mounted in the enclosure because it’s not as tall as the LED matrix. So i decided to add a small piece of pcb just for the joystick for better user experience. The two pcbs are aligned using two short pieces of resistor legs before and during the reflow process.
From v1.2 to v1.3, the only thing I changed is the location of the reset button, as I’ve found that it is easier to accidentally press the reset button when it’s located near the top on the right side of the device.
So in the final version, we have a total of five ICs on the board: MCP73831 for charging the battery, NC7WZ14 for latching the pushbutton power switch, TPS61240 for boosting the voltage from 3.7V to 5V, HT16K33 for driving the LED matrix and monitoring button presses, and ATmega32u4.
The joystick/navigation switch used here is the exact same part that was used on the Nokia 3230 cell phone. I remember asking my parents multiple times to buy that phone for me when I was in elementary school. The LED matrices are bought from Adafruit, and I bought two of every single color of the square dot matrix they carry. Finally the battery used in the Tiny Tetris is a 3mm thick 700mAh LiPo battery bought on ebay.
Here are some pictures I took when I was reflowing the boards.
Finally, let’s talk about the software. You might not believe it, but this is actually the first time I’ve ever written any C++ code. I wrote a total of four C++ classes, including a simplified version of the HT16K33 driver, the Tetris game, the Snake game, and a Draw/Paint program. I used the i2c.h instead of Wire.h for the I2C interface because I want to refresh the display at a fixed rate (50Hz) using a timer interrupt, and Wire.h made it impossible because it uses the timer interrupt to drive the I2C interface, and you can’t have one running inside the other.
Here are some pictures of the game play. I also did a demonstration in my short youtube video.
I mentioned above that I wanted to implement the self kill feature when the battery is below a preset value, so here is a GIF showing you what happens when the battery is low.
Before it turns itself off, a low battery symbol is displayed on the screen. After it flashes for 3 seconds, the kill pin on the 32u4 goes high, changing the state of the latching power switch circuit, and turning the device off.