Arduino Tutorial: Creating Pong

An Arduino tutorial about making a pong game with an LCD and some push buttons. By Felipe Laso-Marsetti.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

Connections for user input

This Is Tinkering

Yay! Yet another milestone on what will eventually become your own little gaming console :]

So now that you have the LCD working, you need to detect user input in order to be able to control the pong paddles. To do this you will use 4 push buttons (one pair for each player) and correctly detect collisions against the top or bottom of the screen.

Time to make some more connections. But first, take a look at the push buttons you’ll use:
Push Button

There are many different types of push buttons. In this case the image above shows a push button with 4 pins, and there are orange circles around two pairs of pins. Each pair of legs are connected, so it doesn’t matter which one you connect your cables to. The important thing is making sure you are connecting a wire to one of the legs of each pair.

Above the button notice an image showing the state of the push button when it’s not pressed. When the button is pushed down you allow electrical flow from one end to the other. This is how you can detect whether a button is pushed down or not, and this is how you will know when to move a player’s paddle.

Take out another breadboard, preferably another 30-row board, and connect your push buttons along with some jumper wires as shown below:
027

Their purpose are as follows:

  • Red – Simply pass the ground voltage from one side of the breadboard to the other in order to avoid tons of cables that would make it uncomfortable to play.
  • Orange and Yellow – Connect the ground voltage to one set of legs on each of the push buttons.
  • Gray – Will be connected to the input pins on the Arduino. The reason why this jump is made is so that players can comfortably push the buttons without any cables getting in their way.

Now, you may be wondering why you connect the push buttons to an input pin in the Arduino and then to ground, when the image above shows you that you need to pass electricity to the button in order to detect when it’s pressed.

If you are up for another challenge, try to find out why you do this on your own. Here’s a hint: It has to do with the digital and analog input pins in the Arduino. If you don’t want to wait then go ahead and click on the solution below.

[spoiler title=”Solution”]The Arduino’s analog and digital input pins have a pull-up resistor.[/spoiler]

If you have already read the solution but want to know more about pull-up resistors, here’s a little explanation. The Arduino’s input pins typically work by receiving voltage to indicate input, this is by default using a technique called pull-down resistor. What you usually do is connect a resistor between your circuit and the input pin in order to lower the received voltage and avoid damaging the board’s input pins.

In order to avoid having to connect resistors to your circuit you can use the Arduino’s built in resistors on each pin and, thus, use a pull-up resistor. Here is information regarding the digital pins, and here is information regarding the analog pins.

What this technique does is send out +5V of output on the pin you use as a pull-up, and connect the push button to ground. When the input pin detects a value of 0V (ground) then you determine that the button has been pushed down, if the pin reads a value of +5V then the button is not being pressed.
Pullup Resistor

To learn more about pull-up resistors you can visit this link.

For this tutorial you will not use analog pins as true analog inputs, meaning you will not read analog values (the Arduino has 10 bits for each analog pin, allowing you to get integer values from 0 to 1023).

For player one connect a set of push buttons, each from the gray jumper, to pin A5 for the up button and pin 2 for the down button. For player two, connect the remaining pair of push buttons to pin 12 for the up button and pin 3 for the down button.

Connect one of the ground rails of your controller to the ground rail of your other bread board as shown in the second picture below.

This is the final circuit with all of the connections ready:
Final Pong Circuit

Drawing Player 1’s paddle

It’s finally time to write some code of your own and to get your pong game ready and working.

Note: if you like Sublime Text 2, you should try out Stino, a plugin that lets you code and run Arduino sketches form Sublime Text 2. I personally found the code highlighting and auto-completion much better, but due to the problems with Arduino on OS X Mavericks I always had to upload sketches via the main IDE.

Start by opening the Arduino IDE (or Sublime Text if you prefer to use that) and go to Sketch\Import Library…\GLCD.
Import GLCD

The following lines of code should be added at the top of your sketch:

#include <glcd.h>
#include <glcd_Buildinfo.h>
#include <glcd_Config.h>

Next declare constants for the pins corresponding to the buttons for player 1, the screen size, and paddle size, position and movement speed.

// Screen Size
const byte width           = 127;
const byte height          = 63;

// Variables to store the pin number for each player's up/down buttons
const byte oneUpButton     = 19; // Pin A5
const byte oneDownButton   = 2;

// Size of the ball and paddle
const byte paddleHeight    = 8;

// X position of each paddle
const byte onePaddleX      = 10;

// Y position of each paddle
short onePaddleY           = 28;

// Speed of the ball for the X and Y directions, and speed of the paddle movement vertically
short paddleSpeed          = 2;

Finally, create constants for the refresh interval (in milliseconds) and the last refresh interval, to setup a steady frame rate.

// Refresh interval at which to set our game loop 
// To avoid having the game run at different speeds depending on hardware
const int refreshInterval  = 60;

// Used to calculate the delta between loops for a steady frame-rate
unsigned long lastRefreshTime;

Now come the default and required Arduino functions for each sketch, setup() and loop():

/*
 * Default Arduino setup function
 */
void setup()
{
  // Player 1 buttons setup
  pinMode(oneUpButton, INPUT);
  digitalWrite(oneUpButton, HIGH); // Use built in pull-up resistor
  pinMode(oneDownButton, INPUT);
  digitalWrite(oneDownButton, HIGH); // Use built in pull-up resistor

  // Initialize the library to draw dark pixels on a light background
  GLCD.Init();
}

/*
 * Default Arduino loop function
 */
void loop()
{  
  unsigned long now = millis();

  if ((now - lastRefreshTime) > refreshInterval)
  {    
    checkInput();
    draw();
    
    lastRefreshTime = now;
  }
}

setup sets the pins for the paddles for player 1 to input. You also call digitalWrite with a value of HIGH for each pin to activate the pull-up resistors that you read about earlier causing each of the pins corresponding to player 1 to output +5V instead of the default 0V.

In addition, setup calls GLCD.Init() to initialize the display in its default draw mode; dark pixels on a light background. You can read more about the functions of GLCD in the documentation found here.

loop gets the milliseconds since the Arduino board began running and stores the value in a variable called now. Then, a check is performed to see if the refresh interval (acquired by subtracting the current time against the last refresh time) is greater than the refresh interval you defined earlier. If so then you call a pair of functions to check for input, and draw to the screen.

You also set the value of lastRefreshTime to now, in order to correctly check the refresh interval the next time loop gets called.

Time to write each of the functions called inside the loop’s if statement:

/*
 * Checks for user input
 */
void checkInput()
{
  // Get the state of each push button corresponding to player 1
  bool oneUpState = !digitalRead(oneUpButton);
  bool oneDownState = !digitalRead(oneDownButton);

  // Small delay to cleanup and improve the readings
  delay(1);
  
  if (oneDownState)
  {
    // Move player 1’s paddle down
    onePaddleY += paddleSpeed;
    
    // If the paddle is outside of the screen, move it back in
    if (onePaddleY >= height - paddleHeight)
    {
      onePaddleY = height - paddleHeight;
    }
  }
  else if (oneUpState)
  {
    // Move player 1’s paddle up
    onePaddleY -= paddleSpeed;
    
    // If the paddle is outside of the screen, move it back in
    if (onePaddleY <= 0)
    {
      onePaddleY = 0;
    }
  }
}

void draw()
{
  GLCD.ClearScreen();
    
  GLCD.DrawVLine(onePaddleX, onePaddleY, paddleHeight);
}

checkInput gets a boolean value with the state of each button. You negate the value read because you are using a pull-up resistor, so when digitalRead returns 0 then the button is being pushed down.

Afterwards there's a small, 1 millisecond delay to cleanup the readings and then a check is made to see if the down button is being pushed. If so then you update the Y position of the paddle and check for collisions against the screen. The logic used here is pretty straightforward so you shouldn't have any trouble understanding it. The same is done for when the up button is pushed.

draw first clears the screen so there are no remaining pixels or artifacts from your previous frame and then calls DrawVLine with the X and Y positions, and the height of the vertical line to draw. Notice inside both methods how you make good use of the constants previously declared at the top of the header file.

Go ahead and upload the sketch to your Arduino and push the up and down buttons.
Left Paddle

Hurray! the paddle should be moving and correctly colliding against the top and bottom edges of the screen. Awesome job :]