Handheld PONG Console

by Arnov Sharma in Circuits > Microcontrollers

342 Views, 2 Favorites, 0 Comments

Handheld PONG Console

09.gif
10.gif
08.gif
IMG_3521.JPG

Greetings everyone and welcome back! This is Pong PRO, a homemade mini-game device that runs PONG.

Here, we're running PONG on an ESP32 Dev board with an SSD1306 OLED screen and controlling the bar with two directional buttons. Everything is then fixed in unique 3D-printed grips, allowing the user to properly operate the controller.

This project is based on our previous PastePal project's PCBs, which is essentially an ESP32 breakout with two buttons attached to the microcontroller and a 124x32 OLED display. Modeled two handles and transformed the project into a fully functional PONG gaming console.

For this project, we even designed our own PONG game from scratch, and this article will go over the entire build process, so let get started with the build.

Supplies

These were the materials used in this project:

  1. Custom PCB (provided by HQ Next PCB)
  2. ESP32 board
  3. Push Button SMD
  4. SSD1306 OLED 128x32
  5. PCB Standoffs
  6. M3 Bolts
  7. 3D printed Parts

3D Model

untitled.148.png
untitled.150.png
01.PNG
06.PNG
07.PNG
02.PNG
03.PNG
Screenshot 2025-03-11 211330.png
untitled.149.png

The 3D model of this project consists of the original Macropad Assembly, which is made up of three layers: the top layer, the middle layer, and the bottom layer, all of which are joined together by M2.5 PCB standoffs. For this design, we deleted the bottom layer and just kept the top and middle layers.

The middle layer holds all of the electronics components, which include the ESP32 microcontroller board, an SSD1306 OLED screen, and two SMD push buttons. The top layer serves as an asethic cover for the midlayer, which has three openings: one rectangular aperture for the OLED display and two switch actuators.

The switch actuators are modeled and positioned between the top layer's switch opening slots and the SMD switch knob.

Because the switch actuator and switch knob are positioned perfectly on top of each other, squeezing the switch actuator also presses the knob, resulting in a switch click.

To hold this console ergonomically, we took inspiration from the Sega Genesis Controller and designed two handgrip parts secured using M2.5 PCB standoffs used to connect the two PCB layers.

After finishing the model, the switch actuators and handgrip were exported as mesh files and 3D printed with orange PLA and a 0.4mm nozzle.

PCB Design

SCH_page-0001.jpg
04.PNG
05.PNG

The PCB design for this project was straightforward; we utilized an XIAO ESP32 board with D0 and D1 I/O pins to connect it to two SMD switches. We also combined an OLED display with the microcontroller, which is connected to the XIAO's I2C ports.

We created two boards based on the model's dimensions: the top layer board and the middle layer board. Because the midlayer board and the bottom layer share the same form and mounting holes, we will use it for the bottom layer.

HQ NextPCB Service

01.gif
02.gif
IMG_20240921_234542.jpg

After completing the PCB design, we export the Gerber data and send it to HQ NextPCB for samples.

For the mid and top layer boards, two orders were placed. We ordered a black Solder mask with white screen for the mid- and top-layer boards.

After placing the order, the PCBs were received within a week, and the PCB quality was pretty great.

In addition, I have to bring in HQDFM to you, which helped me a lot through many projects. Huaqiu’s in-house engineers developed the free Design for Manufacturing software, HQDFM, revolutionizing how PCB designers visualize and verify their designs.

Take advantage of NextPCB's Accelerator campaign and get 2 free assembled RP2040-based PCBs for your innovative projects.

https://www.nextpcb.com/blog/rp2040-free-pcba-prototypes-nextpcb-accelerator

This offer covers all costs, including logistics, making it easier and more affordable to bring your ideas to life. SMT services can be expensive, but NextPCB is here to help you overcome that hurdle. Simply share your relevant project, and they'll take care of the rest. Don't miss out on this amazing opportunity to advance your tech creations!

HQDFM: Free Online Gerber Viewer and DFM Analysis Tool

08.PNG
09.PNG

Also, NextPCB has its own Gerber Viewer and DFM analysis software.

Your designs are improved by their HQDFM software (DFM) services. Since I find it annoying to have to wait around for DFM reports from manufacturers, HQDFM is the most efficient method for performing a pre-event self-check.

Here is what online Gerber Viewer shows me. Would not be more clear. However, for full function, like DFM analysis for PCBA, you need to download the software. The online version only provides a simple PCB DFM report.

With comprehensive Design for Manufacture (DFM) analysis features, HQDFM is a free, sophisticated online PCB Gerber file viewer.

It provides insights into advanced manufacturing by utilizing over 15 years of industry expertise. You guys can check out HQ NextPCB if you want great PCB service at an affordable rate.

PCB Assembly

04.gif
05.gif
06.gif
07.gif
08.gif
09.gif
11.gif
  1. Using a solder paste dispenser needle, we begin the PCB assembly process by putting solder paste on each component pad.
  2. Next, we pick and place the SMD Switch in its location using an ESD Tweezer.
  3. Subsequently, we remove the board and set it on our Reflow Hotplate, which raises the PCB's temperature from below to the point at which the solder paste melts and the SMD components are all connected to their pads.
  4. We attached the pads of the two CON7 Female Header Pin connectors that we inserted from the back side of the PCB to the location of the XIAO Microcontroller.
  5. We soldered the OLED into place after adding it from the top side.

Board assembly is now complete.

Console Assembly

01.gif
02.gif
03.gif
04.gif
05.gif
  1. Connecting the 9mm PCB standoffs to the top layer of the board via its four mounting holes is how we begin the layer assembly procedure.
  2. The top layer board was flipped, and the two 3D-printed switches were inserted into their designated slots.
  3. Next, the midlayer was positioned from the bottom of the top layer.
  4. We then placed 3D-printed left and right handgrips over the midlayer and secured them with two M2.5 screws to the PCB standoffs.
  5. After attaching both handhrips to the standoffs that connect the top and middle layers of the PCB, we installed the XIAO ESP32 and completed our console assembly.

CODE

Let's have a look at the code we built, and its a simple one.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int buttonUpPin = 1; // Pin for the up button
const int buttonDownPin = 0; // Pin for the down button

const int paddleHeight = 12;
const int paddleWidth = 3;
int playerPaddleY = (SCREEN_HEIGHT - paddleHeight) / 2;
int compPaddleY = (SCREEN_HEIGHT - paddleHeight) / 2;

int ballX = SCREEN_WIDTH / 2;
int ballY = SCREEN_HEIGHT / 2;
int ballVelocityX = 2;
int ballVelocityY = 2;

bool isGameOver = false;
bool playerWin = false;

void setup() {
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
// Clear the Adafruit splash screen
display.clearDisplay();
display.display();
delay(2000);

// Display the welcome screen
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.print("PONG PRO");
display.display();
delay(2000);

pinMode(buttonUpPin, INPUT_PULLUP);
pinMode(buttonDownPin, INPUT_PULLUP);
}

void loop() {
if (isGameOver) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor((SCREEN_WIDTH - 72) / 2, (SCREEN_HEIGHT - 16) / 2);
if (playerWin) {
display.print("You Win!");
} else {
display.print("You Lose!");
}
display.display();
delay(3000);
isGameOver = false;
ballX = SCREEN_WIDTH / 2;
ballY = SCREEN_HEIGHT / 2;
playerPaddleY = (SCREEN_HEIGHT - paddleHeight) / 2;
compPaddleY = (SCREEN_HEIGHT - paddleHeight) / 2;
return;
}

// Update player paddle position
if (digitalRead(buttonUpPin) == LOW) {
playerPaddleY = max(playerPaddleY - 1, 0);
}
if (digitalRead(buttonDownPin) == LOW) {
playerPaddleY = min(playerPaddleY + 1, SCREEN_HEIGHT - paddleHeight);
}

// Update computer paddle position
if (ballY < compPaddleY + paddleHeight / 2) {
compPaddleY = max(compPaddleY - 1, 0);
}
if (ballY > compPaddleY + paddleHeight / 2) {
compPaddleY = min(compPaddleY + 1, SCREEN_HEIGHT - paddleHeight);
}

// Update ball position
ballX += ballVelocityX;
ballY += ballVelocityY;

// Check ball collisions with top and bottom
if (ballY <= 0 || ballY >= SCREEN_HEIGHT - 1) {
ballVelocityY = -ballVelocityY;
}

// Check ball collision with player paddle
if (ballX <= paddleWidth && ballY >= playerPaddleY && ballY <= playerPaddleY + paddleHeight) {
ballVelocityX = -ballVelocityX;
}

// Check ball collision with computer paddle
if (ballX >= SCREEN_WIDTH - paddleWidth - 1 && ballY >= compPaddleY && ballY <= compPaddleY + paddleHeight) {
ballVelocityX = -ballVelocityX;
}

// Check ball out of bounds
if (ballX <= 0) {
isGameOver = true;
playerWin = false;
}
if (ballX >= SCREEN_WIDTH - 1) {
isGameOver = true;
playerWin = true;
}

// Clear display
display.clearDisplay();

// Draw player paddle
display.fillRect(0, playerPaddleY, paddleWidth, paddleHeight, SSD1306_WHITE);

// Draw computer paddle
display.fillRect(SCREEN_WIDTH - paddleWidth, compPaddleY, paddleWidth, paddleHeight, SSD1306_WHITE);

// Draw ball
display.fillRect(ballX, ballY, 1, 1, SSD1306_WHITE);

// Update display
display.display();

delay(30);
}

we are using two buttons to control the paddle. It includes initialization for the display and buttons, variables to track the paddle and ball positions, and game logic to handle ball movement, paddle control, and collision detection.

The game starts with a "PONG PRO" welcome screen and shows "You Win!" or "You Lose!" messages when the game ends, depending on whether the player or the computer missed the ball. The game then resets for another round, continuing in a loop until the device is turned off.

RESULT

10.gif
11.gif
09.gif
IMG_3520.JPG

Here's the end result of this simple yet fun build: a super small handheld game device that runs PONG. In this game, our opponent is the computer, and we are playing against it. When the computer misses the ball, a splash screen appears, indicating that we have won; if we miss the ball, a splash screen appears, indicating that we have lost.

Overall, this is a fun little project that is almost finished; however, because this device is powered via USB port, we haven't included a battery, which we will address in the next iteration of this project.

Special thanks to HQ NextPCB for providing components that I've used in this project; check them out for getting all sorts of PCB or PCBA-related services for less cost.

Thanks for reaching this far, and I will be back with a new project soon.