Pong Game with Arduino UNO and OLED Display – Project Explanation

 

Pong Game using Arduino UNO and OLED Display

The Pong Game using Arduino UNO and OLED Display is a classic embedded systems project where a retro arcade-style game is implemented using the Arduino Uno and a 0.96” I2C OLED display based on the SSD1306 controller.

The circuit design and simulation were created using Cirkit Designer, making it easy to visualize and test before hardware implementation.

This project demonstrates how Arduino can handle:

  • Real-time graphics rendering

  • Button input handling

  • Game logic implementation

  • Sound effects using buzzer

  • I2C communication


 Objective

  • Develop a basic arcade-style game using Arduino

  • Interface an OLED display using I2C protocol

  • Understand graphics rendering in embedded systems

  • Learn collision detection and game logic

  • Implement input-output handling


 Components Used

  • Arduino Uno

  • 0.96” I2C OLED Display (SSD1306)

  • Push Buttons (Up / Down) or Potentiometer

  • Breadboard

  • Jumper Wires

  • USB Cable

  • Buzzer (connected to pin 11 for sound effects)


 Working Principle

1️⃣ Display Initialization

The OLED uses I2C communication:

OLED PinArduino UNO Pin
VCC5V
GNDGND
SDAA4
SCLA5

The display is initialized using:

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

0x3C is the default I2C address of the OLED.


2️⃣ Game Logic Execution

The game consists of:

  • A moving ball (X & Y coordinates)

  • Player paddle (right side)

  • MCU paddle (left side)

  • Score tracking system

Ball Movement

The ball moves continuously using timed updates:

  • BALL_RATE controls ball speed

  • PADDLE_RATE controls paddle refresh rate

The ball direction changes when:

  • It hits vertical walls

  • It hits top or bottom walls

  • It collides with paddles


3️⃣ Collision Detection

The program checks:

✔ Ball hitting vertical boundary → Score update
✔ Ball hitting top/bottom → Reverse Y direction
✔ Ball hitting player paddle → Reverse X direction
✔ Ball hitting MCU paddle → Reverse X direction

This creates a simple ball physics simulation.


4️⃣ Input Handling

Push Buttons

pinMode(UP_BUTTON, INPUT_PULLUP);
pinMode(DOWN_BUTTON, INPUT_PULLUP);

When pressed:

  • UP button → Paddle moves up

  • DOWN button → Paddle moves down

Because of INPUT_PULLUP, buttons read LOW when pressed.


Potentiometer (Optional Alternative)

Instead of buttons:

  • Connect potentiometer middle pin to A0

  • Use analogRead()

  • Map value to screen height (0–53)

This gives smooth paddle control.


5️⃣ Sound Effects

The buzzer connected to pin 11 generates tones:

  • Paddle hit sound

  • Wall bounce sound

  • Score sound

Example:

tone(11, 250, 25);

This enhances user interaction.


6️⃣ Screen Refresh

The Arduino continuously updates:

  • Ball position

  • Paddle position

  • Score display

At game over:

  • Displays “YOU WIN!!” or “YOU LOSE!”

  • Waits 5 seconds

  • Resets the game


 Graphics Rendering

The project uses:

  • drawPixel() → Ball

  • drawFastVLine() → Paddles

  • drawRect() → Court boundary

  • setCursor() & print() → Score

Graphics are handled using:

  • Adafruit_GFX library

  • Adafruit_SSD1306 library

These libraries simplify drawing shapes and text on OLED.


 Features

  • Real-time paddle control

  • Ball physics simulation

  • Collision detection

  • Automatic MCU opponent

  • Score counter (0–9 limit)

  • Sound feedback

  • Game reset after win/lose


 Learning Outcomes

Students learn:

  • I2C communication protocol

  • OLED interfacing

  • Embedded graphics basics

  • Real-time programming using millis()

  • Game logic design

  • Interrupt-free timed control

  • Digital input handling


 Applications

  • Embedded game development

  • Learning graphics programming

  • Understanding display communication

  • Educational STEM project

  • Arduino display practice


 Why Use Cirkit Designer?

Using Cirkit Designer helps:

✔ Visualize wiring before hardware setup
✔ Prevent short circuits
✔ Simulate safely
✔ Speed up prototyping

Working Principle

Code:
/*
  A simple Pong game.
  https://notabug.org/Maverick/WokwiPong
 
  Based on Arduino Pong by eholk
  https://github.com/eholk/Arduino-Pong
*/

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

#define UP_BUTTON 2
#define DOWN_BUTTON 3

const unsigned long PADDLE_RATE = 64;
const unsigned long BALL_RATE = 16;
const uint8_t PADDLE_HEIGHT = 12;
const uint8_t SCORE_LIMIT = 9;

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

bool game_over, win;

uint8_t player_score, mcu_score;
uint8_t ball_x = 53, ball_y = 26;
uint8_t ball_dir_x = 1, ball_dir_y = 1;

unsigned long ball_update;
unsigned long paddle_update;

const uint8_t MCU_X = 12;
uint8_t mcu_y = 16;

const uint8_t PLAYER_X = 115;
uint8_t player_y = 16;

void setup()
{
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

    // Display the splash screen (we're legally required to do so)
    display.display();
    unsigned long start = millis();

    pinMode(UP_BUTTON, INPUT_PULLUP);
    pinMode(DOWN_BUTTON, INPUT_PULLUP);

    pinMode(7, OUTPUT);
    digitalWrite(7, LOW);

    display.clearDisplay();
    drawCourt();

    while(millis() - start < 2000);

    display.display();

    ball_update = millis();
    paddle_update = ball_update;
}

void loop()
{
    bool update_needed = false;
    unsigned long time = millis();

    static bool up_state = false;
    static bool down_state = false;
   
    up_state |= (digitalRead(UP_BUTTON) == LOW);
    down_state |= (digitalRead(DOWN_BUTTON) == LOW);

    if(time > ball_update)
    {
        uint8_t new_x = ball_x + ball_dir_x;
        uint8_t new_y = ball_y + ball_dir_y;

        // Check if we hit the vertical walls
        if(new_x == 0 || new_x == 127)
        {
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;

            if (new_x < 64)
            {
                player_scoreTone();
                player_score++;
            }
            else
            {
                mcu_scoreTone();
                mcu_score++;
            }

            if (player_score == SCORE_LIMIT || mcu_score == SCORE_LIMIT)
            {
                win = player_score > mcu_score;
                game_over = true;
            }
        }

        // Check if we hit the horizontal walls.
        if(new_y == 0 || new_y == 53)
        {
            wallTone();
            ball_dir_y = -ball_dir_y;
            new_y += ball_dir_y + ball_dir_y;
        }

        // Check if we hit the CPU paddle
        if(new_x == MCU_X && new_y >= mcu_y && new_y <= mcu_y + PADDLE_HEIGHT)
        {
            mcuPaddleTone();
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        // Check if we hit the player paddle
        if(new_x == PLAYER_X && new_y >= player_y && new_y <= player_y + PADDLE_HEIGHT)
        {
            playerPaddleTone();
            ball_dir_x = -ball_dir_x;
            new_x += ball_dir_x + ball_dir_x;
        }

        display.drawPixel(ball_x, ball_y, BLACK);
        display.drawPixel(new_x, new_y, WHITE);
        ball_x = new_x;
        ball_y = new_y;

        ball_update += BALL_RATE;

        update_needed = true;
    }

    if(time > paddle_update)
    {
        paddle_update += PADDLE_RATE;

        // CPU paddle
        display.drawFastVLine(MCU_X, mcu_y, PADDLE_HEIGHT, BLACK);
        const uint8_t half_paddle = PADDLE_HEIGHT >> 1;

        if(mcu_y + half_paddle > ball_y)
        {
            int8_t dir = ball_x > MCU_X ? -1 : 1;
            mcu_y += dir;
        }

        if(mcu_y + half_paddle < ball_y)
        {
            int8_t dir = ball_x > MCU_X ? 1 : -1;
            mcu_y += dir;
        }

        if(mcu_y < 1)
        {
            mcu_y = 1;
        }

        if(mcu_y + PADDLE_HEIGHT > 53)
        {
            mcu_y = 53 - PADDLE_HEIGHT;
        }

        // Player paddle
        display.drawFastVLine(MCU_X, mcu_y, PADDLE_HEIGHT, WHITE);
        display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, BLACK);

        if(up_state)
        {
            player_y -= 1;
        }

        if(down_state)
        {
            player_y += 1;
        }

        up_state = down_state = false;

        if(player_y < 1)
        {
            player_y = 1;
        }

        if(player_y + PADDLE_HEIGHT > 53)
        {
            player_y = 53 - PADDLE_HEIGHT;
        }

        display.drawFastVLine(PLAYER_X, player_y, PADDLE_HEIGHT, WHITE);

        update_needed = true;
    }

    if(update_needed)
    {
        if (game_over)
        {
            const char* text = win ? "YOU WIN!!" : "YOU LOSE!";
            display.clearDisplay();
            display.setCursor(40, 28);
            display.print(text);
            display.display();

            delay(5000);

            display.clearDisplay();
            ball_x = 53;
            ball_y = 26;
            ball_dir_x = 1;
            ball_dir_y = 1;
            mcu_y = 16;
            player_y = 16;
            mcu_score = 0;
            player_score = 0;
            game_over = false;
            drawCourt();
        }

        display.setTextColor(WHITE, BLACK);
        display.setCursor(0, 56);
        display.print(mcu_score);
        display.setCursor(122, 56);
        display.print(player_score);
        display.display();
    }
}

void playerPaddleTone()
{
    tone(11, 250, 25);
    delay(25);
    noTone(11);
}

void mcuPaddleTone()
{
    tone(11, 225, 25);
    delay(25);
    noTone(11);
}

void wallTone()
{
    tone(11, 200, 25);
    delay(25);
    noTone(11);
}

void player_scoreTone()
{
    tone(11, 200, 25);
    delay(50);
    noTone(11);
    delay(25);
    tone(11, 250, 25);
    delay(25);
    noTone(11);
}

void mcu_scoreTone()
{
    tone(11, 250, 25);
    delay(25);
    noTone(11);
    delay(25);
    tone(11, 200, 25);
    delay(25);
    noTone(11);
}

void drawCourt()
{
    display.drawRect(0, 0, 128, 54, WHITE);
}


 Conclusion

The Pong Game using Arduino UNO and OLED Display proves that the Arduino Uno is not limited to automation tasks — it can also create interactive graphical systems.

This project strengthens understanding of:

  • Embedded programming

  • Display interfacing

  • Real-time logic handling

  • Input-output control

  • Game physics simulation

It is an excellent beginner-to-intermediate level project that combines hardware and software concepts into a fun and engaging learning experience.


 

IOT & SMART SYSTEM PROJECTS

  1. IoT Weather Monitoring System (NodeMCU ESP8266 + DHT11 + Rain Sensor)
  2. ESP8266 NodeMCU Smart Health & Environment Monitoring System with Pulse, Temperature and Motion Sensors
  3. ESP32 Wi-Fi Weight Sensor with HX711
  4. Smart RFID Access Control System Using ESP32 Dev Board and UHF RFID Reader Module
  5. Smart IoT Motor Control System Using ESP32 Dev Board and L298N Motor Driver Module
  6. Smart Waste Management System Using Arduino Nano, Ultrasonic Sensor & GSM Module – Solar Powered IoT Solution
  7. Raspberry Pi Zero W and GSM SIM900 Based Ultrasonic Distance Measurement System
  8. Arduino UNO Smart Surveillance System with ESP8266 WiFi, PIR Motion Sensor & Camera Module
  9. Arduino UNO Environmental Monitoring System with OLED & 16x2 I2C LCD Display
  10. Arduino UNO-Based Smart Home Automation System with Flame and IR Sensors 
  11. Arduino Nano-Based Landslide Detection System with GSM Alerts – Smart Disaster Monitoring Project
  12. Arduino Nano Rain-Sensing Stepper Motor System
  13. Arduino Based Automatic Tire Inflator Using Pressure Sensor, Relay Module and LCD Display
  14. Arduino-Based Automatic Cooker Using Servo Motors, DC Stirrer Motor, Temperature Sensor and Relay-Controlled Heater
  15. Arduino Sketch for Plastic Bottle and Can Reverse Vending Machine

 TRAFFIC & SMART CITY PROJECTS
  1. RFID-Based Smart Traffic Control System (Arduino Mega)
  2. Arduino UNO Traffic Light Control System – Smart LED Signal Project
  3.  Arduino UNO Controlled Traffic Light System with Joystick Interface

ROBOTICS PROJECTS
  1. Arduino UNO Smart Obstacle Avoiding Robot (Ultrasonic + IR + GSM)
  2. Arduino-Powered Autonomous Obstacle Avoidance Robot with Servo Control
  3. Arduino Nano Bluetooth Controlled Line Follower Robot Using L298N Motor Driver
  4. Arduino UNO Bluetooth Controlled 4WD Robot Car Using L298N Motor Driver
  5. Arduino UNO Multi-Sensor Obstacle Avoidance & Bluetooth Controlled Robot Car Using L298N
  6. Raspberry Pi Motor Control Robot (L298N + Li-ion)
  7. RC Car Simulation with L298N Motor Driver and Joystick Control using Arduino (CirkitDesign Simulation)
  8. Raspberry Pi Robotic Arm Control System with Camera Module and Motor Driver – Smart Automation & Vision-Based Robotics Project
  9. ESP32-Based 4WD Robot Car Using Dual L298N Motor Drivers – Circuit Diagram and IoT Control Project

LORA & WIRELESS COMMUNICATION PROJECTS
  1. Arduino LoRa Communication Project Using Adafruit RFM95W LoRa RadioArduino Nano with RFM95 SX1276 LoRa
  2. Arduino Nano with RFM95 LoRa SX1276 Module – Long Range Wireless Communication Project
  3. Arduino Nano Digital Clock Using DS3231 RTC and TM1637 4-Digit Display – Circuit Diagram and Project Guide

 LED, LIGHTING & DISPLAY PROJECTS
  1. Arduino UNO Controlled NeoPixel Ring Light Show
  2. Wi-Fi Controlled NeoPixel Ring (ESP8266)
  3. Chained NeoPixel Rings with Arduino – Addressable RGB LED Control Project
  4. Arduino Nano-Controlled Lighting System with Gesture and Sound Interaction
  5. Raspberry Pi GPIO Multi-LED Control System – Beginner-Friendly Embedded Electronics Project
  6. 4 Channel Relay Module with Arduino UNO

 SENSOR & DETECTION PROJECTS
  1. Arduino UNO Color Sensor + Proximity System (TCS3200 + Inductive)
  2. Arduino Color Detection Project Using Adafruit TCS34725 RGB Color Sensor
  3. Arduino Gas Leakage Detection and Safety Alert System Using MQ-2 Gas Sensor
  4. MQ-135 Air Quality Detector Using Arduino | Cirkit Designer Simulation Project
  5. Pulse Sensor Using Arduino – Complete Guide with Simulation 
  6. HX711 Load Sensor Demo Using Arduino | Digital Weight Measurement Project
  7. Track Time with DS1307 RTC and Display on Arduino Uno with 16x2 LCD | Cirkit Designer Project
  8. Parking Sensor Simulator using Arduino Uno and HC-SR04 Ultrasonic Sensor

 FUN & INTERACTIVE PROJECTS
  1. Pong Game with Arduino UNO and OLED Display – Project Explanation
  2.   Arduino UNO Bluetooth-Controlled Servo Motor System
  3. Arduino UNO-Based Interactive Touch and Distance Sensing System with LED Indicators and Servo Control

 INDUSTRIAL / AUTOMATION PROJECTS
  1. Arduino UNO Smart Waste Sorting System Using Ultrasonic Sensor, Moisture Sensor, Servo, Stepper Motor and LCD
  2. Arduino-Based Smart Waste Segregation System Using Metal, Plastic and Moisture Sensors with Stepper and Servo Control
  3. ESP32-Based Digital Weighing Scale Using 50kg Load Cell, HX711 Module and 16x2 LCD Display
  4. Arduino-Based Smart Toll Gate Automation System with RFID, GSM, Ultrasonic Sensor and LCD Display

  5. Arduino-Based Automatic Pill Dispenser Machine with LCD Display, Servo Motor and Buzzer Reminder

  6. Arduino UNO Smart Water Quality Monitoring System with pH Sensor, Turbidity Sensor and LCD Display

  7. Arduino-Based Ocean Cleaning Boat Robot with Dual IBT-2 Motor Drivers and Conveyor Belt System

  8. IoT-Based Accident Detection and Health Monitoring System Using Raspberry Pi with GSM, GPS and Camera Integration

  9. Raspberry Pi RFID and Keypad Based Smart Door Lock System with LCD Display and L298N Motor Driver

  10. Smart Shopping Trolley Using Arduino UNO & RFID | Automatic Billing System

  11. Arduino UNO Based Automatic Liquid Hand Sanitizer & Soap Dispenser System

  12. Arduino Based Robotic Weeding Machine with Ultrasonic Obstacle Detection and L298N Motor Driver

  13. Arduino UNO Based Biometric Electronic Voting System with LCD Display and Fingerprint Authentication

  14. Arduino UNO Based Electronic Voting System with ILI9341 TFT Display





Comments

try for free