Intro: LED Pong
I call this "LED Pong". I built it from scratch and I based the design on a 1-meter strip of individually addressable LEDs and an Arduino Uno. Pong was one of the first video arcade games ever made. It was released by Atari in 1972 and if you are unfamiliar with it, this video provides a good overview of the gameplay: http://www.youtube.com/watch?v=pDrRnJOCKZc
Following my design is not for the faint of heart, unless you plan to have printed circuit boards manufactured, you will need to have excellent solder skills. You will also need a lot of time, patience, and some money. This project took me about 6 months to complete (Don't worry, you can probably finish it in a couple weeks if you're motivated) and I spent about $60 on parts. However, you can modify the project to suit you needs (and save money). If you don't want all the bells and whistles, you can just omit them! In fact, this project really only needs an Arduino, two buttons, and the LED strip to work! Everything else is just extra.
I have divided this Instructable into two parts: The first part covers the building aspect and the second is an in-depth look at the software side of the project. I will do most of the in-depth explaining (I.E. How shift registers work) in Part 2. Also, I taught myself how to do most of the programming so my way may not be the best way to do something. If you know of a better way to code a function, please let me know in the comments section!
It is a good idea to test the components (LCD, LED strip, etc.) before and after you install them. To do this you will need to install the necessary libraries and then load the example from the correct library. I provide links to the libraries and tell you how to install them in step 9: "Part 2: Software".
As a last note, if you are having problems, check out step 19: "Troubleshooting, Troubleshooting, and more Troubleshooting" for some ideas on how to fix any problems. Also, be sure to frequent step 20: "Updates" for any updates/upgrades I do in the future.
Here is an index for easy navigation:
2. Part 1: Hardware
3. Base and LED Strip
6. Arduino Shield
7. Mounting Everything to the Board
9. Part 2: Software
11. Main Function
12. Color Wheel Function
13. chaseForward and chaseReverse
14. player1Celebrate and player2Celebrate
15. rainbowCyclePlayer1 and rainbowCyclePlayer2
17. shift1 and shift2
18. Final Notes
19. Troubleshooting, Troubleshooting, and more Troubleshooting
Step 1: Operation
This is a detailed explanation of how the game operates; an instruction manual, if you will. If you don't like details, or reading, or instruction manuals, skip this step.
When you first turn on LED Pong, the LCD will tell player 1 to select the winning score by pressing their button and then player 2 will confirm by pressing their button. Player 1 can then press their button and pick a score, 1 - 9, to play to. Player 2 can then confirm the winning score by pressing their button.
Player 1 starts with the ball by default (the button LEDs indicate whose turn it is) and the game will start when they press their button. Once pressed, the 'ball' will go towards player 2. Each player is only allowed one button press when the ball is coming towards them. You can't 'spam' the button. If you press the button early, tough luck, the game will not register any more button presses until a new ball appears. The receiving player can send the ball back by pressing their button when the ball is 1 - 2 LEDs away from them (first picture).
When a player wins, a rainbow effect appears and the colors move towards the winner. The winner will start with the ball for the next game unless the game is turned off.
The potentiometer (fancy word for knob) by the scoreboard adjusts the speed of the ball. Turning it right slows the ball down and turning it left speeds it up (it is possible to return the ball on the fastest setting).
Step 2: Part 1: Hardware
1. Base/LED Strip
- I originally bought the WS2801 LED Strip but returned it because I was having a lot of trouble getting it to work right.
- (2) 1x4 male pin headers. I bought 100 of them on Ebay for $6
- (2) 16-pin DIP socket. They are five for $1 on Ebay
- (2) 74HC595 Shift Registers. 10 for $3 on Ebay
- (14) 330 ohm resistors. 100 for $2.50 on Ebay
- A 5k or 10k potentiometer
- Arduino IIC/I2C Serial Interface Adapter Board Module For Arduino 1602 LCD. $3 on Ebay
- TIP31C or equivalent transistor. 2 for $1 on Ebay
- 470uf capacitor. 10 for $1 on Ebay
- 0.1uf disc capacitor. 30 for $1 on Ebay
- One small heatsink
- Some sort of female power jack or screw terminal
- At least (5) 1x4 male pin headers
- (16) 330 ohm resistors
- (2) 74HC595 Shift Registers
- (2) 74HC595 Shift Registers.
- (16) red LEDs
- Soldering iron
- Duct Tape
- Hot glue gun
- Various gauges of solid strand wire
- Plenty of perf board (check on Ebay)
- (Optional) Several female jumper wires (120 for $8 on Ebay)
- (Optional) Adhesive rubber feet
Total Cost: ~$50, not including the Arduino
Step 3: Base and LED Strip
Unless you plan to rebuild your pong game every time you want to use it, the first thing you will need is a platform to mount everything on. I dug around in my garage and found a wooden board several feet long and about 2.5" wide. Plexiglass (or better yet Lexan) would work equally well. I originally cut the board down to approximately 48" long but later had to shorten it to 45" because I had to cut out a segment on my LED strip; but more on that later. If you use wood for your platform and you have access to a router, I recommend routing a channel down the center, on the bottom of the board. That way you can hide your wiring underneath, instead of on the side of the board (which is what I did unfortunately).
Once your platform is cut to size, you will need to attach the LED string somehow. My LED string came encased in a rubber shield that would not stay glued to the wood. I could have removed the rubber but decided to attach a strip of duct tape to the bottom of it instead (first image). I then found the center of the strip and the board and glued them together with hot glue.
My LED strip did not come with any wires connected to it so I soldered on some pin headers that I could connect wires too. Take note: one end of the LDP8806 LED strip is the input and the other end is the output. It will not work if you connect your Arduino to the output end so when you wire it up and it doesn't work, try the other end.
If you want to test the LED strip, run the example called "strandtest".
Step 4: Scoreboards
The scoreboards display the score and I attached the ball speed potentiometer to the right scoreboard, although you could place it anywhere. I could not find a datasheet for my 7-segment displays anywhere so I had to make my own (first picture). To do that, I used my volt meter to find the two pins that were 'common anode'. Then I used a 5 volt power supply and a 330 ohm resistor to find which pin lit up which LED. I wrote all that information down on a note sheet.
I proceeded to put together the left scoreboard following the schematic (third picture). The scoreboards are daisy-chained together - the data pin of one shift register feeds into pin 9 of the other shift register. This makes it so both shift registers only use 3 pins, instead of 6 pins, on the Arduino.
Make sure that you put the potentiometer on either the left or right scoreboard. Also, when you are adding the power cable and signal cable, make sure you use more wire than you think you will need, especially if you want to be able to remove your Arduino when you are finished.
If you would like to test your scoreboards, copy and paste this into Arduino.
Step 5: LCD
Soldering the LCD to the Arduino interface board should be pretty straightforward, but it ended up costing me a lot of time and frustration. As you can see in the first picture, I soldered the interface board on backwards! Do not do that! It's deceiving because the backlight works when the board is soldered on backwards, which might initially make you think that it's working properly. It's not. I had to spend several hours desoldering the LCD and then reattaching it (second and third picture). Moral of the story: triple check the orientation before you solder. Also, the variable resistor adjusts the contrast of the screen. If everything is connected correctly but nothing shows up on the LCD, give it a few turns in either direction.
If you wish to test the LCD, connect SDA to A4 and SCL to A5, then run the example called "HelloWorld".
Step 6: Arduino Shield
The wiring is as follows:
- Latch to pin 6
- Clock to pin 7
- Clock to pin 9
- Latch to pin 10
- Clock to pin 12
- Latch to pin 13
- Clock to pin 4
- SCL to pin A5
On my Arduino Uno, the gap between pin 7 and pin 8 was to wide for my perfboard so I had to use two pieces of perfboard and then I soldered them together once the spacing was correct (first picture). Then I soldered on the 1x4 headers. If you can, buy the long pin headers because it's nice to have extra clearance underneath (I used the shorter pin headers) (second picture). Make sure you at least solder on enough headers to cover digital pins 1-13, analog pins 2, 4, and 5, vin, and at least one ground.
Next, I soldered on the female power jack and then soldered on the scoreboards, LED strip, and the wires that will attach to each push-button and LED shift register.
Initially, I was not sure how much power LED Pong would use so I made a 5v voltage converter that could handle a few amps. After testing, I found that the circuit draws about 150mA when it is being played and then it jumps to 500mA when someone wins. The L7805 voltage converter can handle up to an amp of current so you could probably get away with using it like this. Just make sure you put a heat sink on it! If you want to do what I did, follow the schematic (fifth picture). Datasheets: TIP31C, L7805
Also, I should have put the transistor further to the right because it's right on top of the Arduino USB jack (sixth picture).
When I finished the voltage regulator circuit, I plugged in a 9v power supply and tested it with a voltmeter and it provided a cool 5.14 volts.
Finally, I soldered the power wires to their respective places. You will need to connect the gnd header(s) to ground and the vin to the 5v output from the transistor. This will supply your Arduino with power when LED Pong is turned on. Do not do anything with the 5v power pin on the Arduino board.
To test your circuit thus far, copy and paste this code into Arduino.
If everything works when you turn it on, give yourself a pat on the back and go get a beer (if you're old enough). All of the difficult stuff is behind you.
Step 7: Mounting Everything to the Board
Now you are ready to connect everything together! You have a few options when it comes to mounting everything. You can permanently mount everything or you can do what I did and make it so everything can be removed. I already had the midpoint marked on the wood so I just found the middle of the Arduino and lined them up. I wanted to make sure I could easily remove my Arduino from the project so I used two screws to hold it in place (first and second picture).Now, you are going to add a few more wires. If you look at the fifth picture, you are going to add the two brown wires that supply power to the scoreboards. One is connected to ground and the other is connected to the +5 volts from the voltage regulator output. You are also going to add ground and +5v wires that link the two scoreboards together (fifth picture).
Next, I mounted the scoreboards to the wood with a couple really small-diameter nails I found in my garage (third picture); thumb tacks would also work. I decided to space the scoreboards 2 inches away from the Arduino and then I nailed them in place using a small wrench as the hammer (fourth picture). I would advise taping some foam to the scoreboard when you're pounding in the nails so you don't accidently damage/scratch them.
Now for the LCD. You are going to need to connect SDA from the serial interface to A4 and SCL to A5 if you haven't already. Then, connect the ground wire to ground and the 5V to the output from the transistor. You can then mount the LCD however you would like. I just hot glued it to the Arduino shield (sixth and seventh picture).
Originally, I hot glued the wires to the board (ninth picture) but it looked kind of messy and they fell off eventually. So I ended up using staples from a stapler and carefully pounded them in (tenth picture). It worked really well!
As you can see from the eleventh picture, the Arduino can still be easily removed.
Step 8: Buttons
I wanted my push buttons to be unique so I built my own. Store/internet bought buttons would probably work just as well and would take a lot less time to install. If you want to follow my footsteps, the first nine pictures show how to build your own buttons from a keyboard.
Once I had the buttons, I had to figure out how I wanted to arrange the LEDs. I ended up going with an arrow design (tenth picture) and proceeded to build it following the schematic (eleventh picture). If you come up with a better LED arrangement, let me know! You could also daisy-chain two or more shift registers together (such as what we did with the scoreboards) which would allow you to use 16+ LEDs.
Once you are done, each side should look similar to picture twelve and then picture thirteen once you have secured the wires and glued everything down.
This concludes the hardware section of the Instructable and your pong game should now be completely functional! Simply copy and paste the LED Pong code and upload it to your Arduino (make sure you have the libraries installed!). You should only need to upload the code to your Arduino once, from then on, the game should work whenever you turn on the Arduino.
It was at this point where I found out my transistor gets slightly hot, so I put a small heatsink on it (which barely gets warm). You can see the attached heatsink in the Introduction video.
Step 9: Part 2: Software
If you have not installed the libraries, do it now! To install a library follow the instructions here: http://arduino.cc/en/Guide/Libraries
The following steps provide a detailed explanation about how the code works. If you don't care how it works, simply copy and paste the code from the previous step into Arduino and run it. Like I said before, I taught myself how to do more of the advanced coding, so my way may not be the best way to do it. If you know of a better way to code a function, feel free to let me know in the comments section!
Pro tip: You can add each function into a separate tab in Arduino (first picture). This will give you easy access to each function and will help with debugging. To create a new tab, click the downward pointing arrow below the Serial Monitor button and then click on "New Tab", or press ctrl+shift+N.
2. Main function
3. Color wheel function
4. chaseForward and chaseReverse
5. player1Celebrate and player2Celebrate
6. rainbowCyclePlayer1 and rainbowCyclePlayer2
8. shift1 and shift2
Step 10: Initialization/Setup
These two lines are the hexidecimal numbers that display each digit on the scoreboards (0-9).
This code sets both scoreboards to display the digit '0'.
Next, I made it so player 1's and player 2's LEDs were turned off.
shiftOut(data2, clock2, MSBFIRST, 255);
shiftOut(data3, clock3, MSBFIRST, 255);
Then we declare both push buttons as inputs.
Lastly, we call the selecScore function, explained in step 16.
Step 11: Main Function
The first thing we do is update each scoreboard with the score. They will both be set at zero at the beginning of the game because player1Points and player2Points are initialized to zero in the setup.
shiftOut(data1, clock1, MSBFIRST, ~digitOne[player1Points]);
shiftOut(data1, clock1, MSBFIRST, ~digitTwo[player2Points]);
if(player2Points >= score)
This next part maps the values of the potentiometer and stores the position of the potentiometer as a value. That value will then become the amount of time inbetween each LED. For example, if val is 100, then the program will light up an LED in the LED strip and then wait 100 milliseconds before lighting up the next LED.
val = map(val, 0, 1023, 1, 100);
This next part determines whether to send the LEDs towards player 1 or player 2.
chaseForward(strip.Color(127, 0, 0), val);
if(flag == 'R')
chaseReverse(strip.Color(0, 0, 127), val);
i = 0;
//Turns off player 1 LEDs
shiftOut(data2, clock2, MSBFIRST, 255);
chaseForward(strip.Color(0, 127, 0), val); // White
int BbuttonState = digitalRead(player2);
if(BbuttonState == LOW && turn == 'B' && flag != 'F' && flag != 'R')
i = 30;
//Turns off player 2 LEDs
shiftOut(data3, clock3, MSBFIRST, 255);
chaseReverse(strip.Color(127, 0, 127), val); // Red
Main function code here
Step 12: Color Wheel Function
byte r, g, b;
switch(WheelPos / 128)
r = 127 - WheelPos % 128; //Red down
g = WheelPos % 128; // Green up
b = 0; //blue off
g = 127 - WheelPos % 128; //green down
b = WheelPos % 128; //blue up
r = 0; //red off
b = 127 - WheelPos % 128; //blue down
r = WheelPos % 128; //red up
g = 0; //green off
Color wheel function code here
Step 13: ChaseForward and ChaseReverse
First, the program checks to see if the button to return the ball back to player 1 has been pressed. If it is pressed before the code loops 30 times, cheat becomes 'true'. This makes it so that the button can only be pressed once per side.
Each time the function loops, the next LED in the strip is lit up for 'wait' milliseconds. 'wait' is the value set by the potentiometer.
If the button is pressed and the 'ball' is two or less LEDs from the end of the string, and the button has not been pressed yet, then the ball will be sent back towards player 1. If the button is pressed before 'i' is 28 or if it is never pressed than player 2 will lose a point.
if(digitalRead(player2) == LOW)
cheat = 'Y';
strip.setPixelColor(i, c); // Set new pixel 'on'
strip.show(); // Refresh LED states
strip.setPixelColor(i, 0); // Erase pixel, but don't refresh!
if(i > 27 && cheat != 'Y')
int BbuttonState = digitalRead(player2);
if(BbuttonState == LOW)
turn = 'B';
flag = 'R';
If player 2 loses the point, a point is added to player1Points and the updated score is displayed on the scoreboards. The player 1 LEDs are also illuminated.
shiftOut(data1, clock1, MSBFIRST, ~digitOne[player1Points]);
shiftOut(data1, clock1, MSBFIRST, ~digitTwo[player2Points]);
if(player1Points < score)
lcd.print("PLAYER 1 SCORES!");
//Turn on player1 LEDs
shiftOut(data2, clock2, MSBFIRST, 0);
chaseForward function here
Step 14: Player1Celebrate and Player2Celebrate
The functions player1Celebrate and player2Celebrate are the same except that one pertains to player 1 and the other to player 2 (obviously). The function starts out by displaying the winning player on the LCD. Then, a rainbowCycle function is called (explained in the next step), the points are set to zero, and the scoreboards display the points (zero).
player1Celebrate function here
player2Celebrate function here
Step 15: RainbowCyclePlayer1 and RainbowCyclePlayer2
Once again, rainbowCyclePlayer1 and rainbowCyclePlayer2 are very similar. Here I will only explain rainbowCyclePlayer1.
The functions are called when one of the players wins the game. The function starts by turning off player 1's LEDs, Then I actually use the same code from the strandtest example to make the LEDs light up in a rainbow effect. In rainbowCyclePlayer1, the colors move towards player 1 and in rainbowCyclePlayer2, the colors move towards player 2.
Once again, the 'delay(wait)' is the number of milliseconds set by the potentiometer. The function ends by turning on player 1's LEDs, because in this case, player 1 won the game.
rainbowCyclePlayer1 function here
rainbowCyclePlayer2 function here
Step 16: SelectScore
This function is really straightforward and is only called once, when the power is first turned on. The LCD prints out a message that tells you to pick the winning score. Once the LCD is done giving you instructions, the score defaults to 1 and then player 1 and player two can choose the winning score by pressing their respective buttons.
When player 1 presses their button, the program adds one to the buttonPushCounter and the number is printed to the LCD. If the buttonPushCounter reaches 10, it gets set back to 1. If you want to make it so you can select a higher score than 9, you can change that here.
When player 2 presses their button, it confirms the winning score, and whatever number buttonPushCounter is set to, is returned and subsequently becomes the winning score.
selectScore function here
Step 17: Shift1 and Shift2
Well, brownie points to anyone who can figure this out...
Because we're using a shift register to control player 1's and player 2's LEDs, we can turn on and off different pins. Before I soldered the LEDs to the shift register, I connected them on a breadboard and figured out what pins were turned on when I shifted certain numbers. I came up with a list of numbers shown in the first picture. If you followed my schematic, shifting out 127 lit up the LED on the end of the tail, 191 lit up the second LED in the tail, 199 lit up the next three LEDs, 249 lit up the next two LEDs, and 254 lit up the last LED in the arrow.
By shifting these numbers out in succession, it made the arrow look like a runway/launch pad that was pointing in the direction the ball was going to go; which was pretty cool. However, there needs to be some sort of delay in-between shifting out each set of LEDs and as many of you know, a delay function stops the program. This is bad because it makes it so whoevers turn it is to send out the LED, sometimes has to push their button multiple times before the program read the button press.
I spent a little bit of time researching timer interrupts but did not feel like spending hours experimenting with them so I have put this part of the project on hold for the time being. If anyone wants to figure this out or at least provide some ideas in the comments section, that would be pretty cool.
Here is a foundation for the function
Step 18: Final Notes
If you read through this Instructable you should have an understanding of how LED Pong works. if you have any suggestions or further improvements for LED Pong, please don't hesitate to tell me in the comments! This is a project that has lots of room for improvement.
The first and second picture are some self-adhesive rubber feet I stuck to the bottom of the board to prevent it from sliding around. I put four feet on each end and two in the middle of the board.
Step 19: Troubleshooting, Troubleshooting, and More Troubleshooting
My LED strip won't work
Your LED strip might be wired backwards, try connecting the other side of the strip to the Arduino.
My LED strip looks like this: (first picture)
This happened to me for some unknown reason and my LED strip was out of warranty (of course). The LED strip worked just fine one day, and then looked like the first picture the next. The first six LEDs worked just fine but after the 6th LED, either none of the LEDs would show up, or they would show up all white, or once in a while, a few random ones would be lit up and the rest would be off. I spent some time trying to debug it but eventually decided to just cut it out. After you cut out the broken segment, solder the strip back together.
**Before you cut up your strip, verify that it is actually the strip causing the problems and not a faulty piece of code. Run the strandtest example and then cut out the segment if it still acts weird.
I can't see any letters on my LCD or the letters are hard to read
Adjust the contrast by turning the screw either way on the variable resistor.
It worked fine before I soldered it together...
Occasionally, circuits won't work for no explanation at all and you have to rebuild them. This can be really frustrating, especially if you check your wiring and it looks fine. This happened to me when I built the LED arrow for player 1 (third picture). I soldered everything together and then the LEDs wouldn't turn on or they would stay on and wouldn't turn off (I can't remember exactly). I checked and rechecked all my wiring, and then checked the wiring many more times. It was solid, not one wire was missing or soldered to the wrong spot. I tried different shift registers and tried connecting it to player 2's side. No luck. I ended up rebuilding it and checking to make sure the shift register worked after soldering each LED. Both sides ended up working just fine. I like to have an explanation for everything so I justified the non-working circuit by convincing myself a pin in the black socket was broken or bent or something. I mean what else could it be?
Step 20: Updates
This is where I will post all updates I make to this Instructable or the LED Pong game. These will be things such as improvements to the code and any hardware upgrades to the game. I will also post the date of each update.
DATE OF UPDATE UPDATE
6/25/2013 No updates yet!