Picture of Arduino and Touchpad Tic Tac Toe
Or, an exercise in input and output multiplexing, and working with bits.  And a submission for the Arduino contest.

This is an implementation of a tic tac toe game using a 3x3 array of bicoloured LEDs for a display, a simple resistive touchpad, and an Arduino to tie everything together.

To see how it works, check out the video:

What this project requires:

Parts and consumables
One perf board (or strip board)
Nine bicoloured LEDs, common cathode
Nine identical resistors, in the 100-220 ohm range
Six identical resistors, in the 10kohm - 500kohm range
One single pole, double throw switch
A bunch of header pins
A bunch of electrical wire
One small square sheet of transparent acrylic, ~ 1 mm thick, 8 cm on the side
Clear sticky tape
Heatshrinks (optional)

All of the above are quite common items, total cost should not exceed USD$20.

One Arduino setup (Arduino Duemilanove, Arduino IDE, computer, USB cable)
Usual electrical tools (multimeter, solder solder gun, wire snips, wire cutter)

Everything Arduino related can be found at http://www.arduino.cc.

On with the build!

Remove these adsRemove these ads by Signing Up

Step 1: Wiring up the LED matrix

Picture of Wiring up the LED matrix
For an LED to light, both its leads must be connected.  If we were to dedicate a pair of pins to each of the 18 LEDs (9 red, 9 green), we'd quickly run out of pins on the Arduino.  However, with multiplexing, we'll be able to address all the LEDs with merely 9 pins!

To do this, the LEDs are wired up in a crossbar fashion, as shown in the first figure.  The LEDs are grouped in columns of threes, and their cathodes are grouped in rows of sixes.

By setting a particular anode line high, and a particular cathode line low, and having a high impedance on all the other anode and cathode lines, we can select which LED we want lit up, as there is only one possible path the current can take.

For instance, in the second figure, setting the green anode 1 line high, and the cathode 1 line low, the bottom left green LED lights up.  The current path in this case is shown in blue.

But what if you want to light up more than one LED on different lines?  We'll use persistence of vision to achieve this.  By selecting pairs of LED lines very very quickly, it gives the illusion that all the selected LEDs are lit at the same time.

Step 2: LED matrix layout

Picture of LED matrix layout
The circuit diagram below shows how the LEDs are physically wired up (G1-G9: green LEDs, R1-R9: red LEDs).  This diagram is for single red and green LEDs, if you are using bicoloured common cathode red/green LEDs, there's only one cathode leg per red/green pair that you have to wire up.

The red and green anode lines go into the PWM pins of the Arduino (pins 3, 5, 6, 9, 10, 11 on the Duemilanove), so that we can have effects like fading later on.  The cathode lines go into pins 4, 7 and 8.

Each of the cathode and anode lines have 100 ohm resistors for protection.

Step 3: Addressing the LED Matrix

For the tic tac toe code, we'll need to be able to store the following information about the LEDs:
- whether an LED is lit or not
- if lit, whether it's red or green

One way of doing this is to store the state in a 9-cell array, using three digits to represent the state (0 = off, 1 = red on, 2 = green on).  Everytime we need to check on the states of the LED, for example, to check if there's a win condition, we'll need to cycle through the array.  This is a workable method, but rather clunky.

A more streamlined method would be to use two groups of nine bits.  The first group of nine bits stores the on-off status of the LEDs, and the second group of nine bits stores the colour.  Then, manipulating the LED states simply becomes a matter of bit arithmetic and shifting.

Here's a worked example.  Let's say we draw our tic tac toe grid graphically, and first use 1s and 0s to represent the on-off status (1 is on, 0 is off):

000  = matrix with bottom left LED lit

010 = matrix with diagonal LEDs lit

If we enumerate the cells from the bottom left, we can write the above representations as a series of bits.  In the first case, that would be 100000000, and in the second case, it would be 001010100.  If we think of these as binary representations, then each series of bits can be condensed into a single number (256 in the first case, 84 in the second case).  So instead of using an array to store the state of the matrix, we can just use a single number!

Similarly, we can represent the colour of the LED in the same way (1 is red, 0 is green).  Let's first assume all the LEDs are lit (so the on-off status is represented by 511).  The matrix below will then represent the colour state of the LEDs:

010   green, red, green
101   red, green, red
010   green, red, green

Now, when displaying the LED matrix, we just have to cycle through each of the bits, first in the on-off state, and then in the colour state.  For example, let's say our on-off state is 100100100, and the colour state is 010101010.  Here's our algorithm for lighting up the LED matrix:

Step 1.  Do a bitwise addition of the on-off state with a binary 1 (ie bit masking).
Step 2.  If it's true, the LED is lit.  Do now a bitwise addition of the colour state with a binary 1.
Step 3.  If it's true, light up the red LED.  If it's false, light up the green LED.
Step 4.  Shift both the on-off state and colour state, one bit to the right (ie bit shifting).
Step 5.  Repeat Steps 1 - 4 until all nine bits have been read.

Note that we're filling the matrix backwards - we start with cell 9, then proceed back down to cell 1. 

Also, the on-off and colour states are stored as an unsigned integer type (word) instead of a signed integer type.  That's because in bit shifting, if we're not careful, we might inadvertenly change the sign of the variable.

Attached is the code for lighting up the LED matrix.

Step 4: Constructing the touch pad

Picture of Constructing the touch pad
The touchpad is constructed from a sheet of thin acrylic, large enough to overlay over the LED matrix.  Then, tape down the row and column wires onto the acrylic sheet, using clear tape.  Clear tape is also used as the insulating spacer between the wires, at the intersections.

Be sure to use clean tools, to prevent finger grease from getting onto the sticky side of the tape.  Fingerprint stains not only look ugly, but make the tape less sticky.

Trim off one end of each of the lines, and solder the other end to a longer wire.  Solder a resistor in-line with the wires, before soldering on connectors.  The resistors used here are 674k, but any value between 10k and 1M should be fine.

The connections to the Arduino are made using the 6 analog pins, with pins 14-16 connected to the wire grid rows, and pins 17-19 connected to the columns.

Step 5: The touch pad - how it works

Picture of The touch pad - how it works
Just as we used a crossbar multiplexer to set up an LED matrix with minimal pins, we can use a similar crossbar multiplexer to set up a touch sensor array, which we can then use to activate the LEDs. 

The concept for this touch pad is simple.  It is essentially a wire grid, with three bare wires running in rows, and three bare wires running in columns above the rows.  At each intersection point is a small square of insulation that prevents the two wires from touching.  A finger touching the intersection will make contact with both wires, resulting in a huge, but finite resistance between the two wires.  A small current, but detectable, current can therefore be made to flow from one wire to the next, via the finger.

To determine which intersection was pressed, the following method was used:
Step 1: Set all the column lines to OUTPUT LOW.
Step 2: Set the row lines to INPUT, with the internal pullups activated.
Step 3: Take an analog read on each row line until the value drops below a given threshold.  This tells you in which row the pressed intersection is.
Step 4:  Repeat Steps 1-3, but now with the columns as inputs and the rows as outputs.  This tells you which column the pressed intersection is.

To minimise the effects of noise, a number of readings are taken and then averaged.  The averaged result is then compared against a threshold.

Since this method just checks against a threshold, it's not suitable for detecting simultaneous presses.  However, since tic tac toe proceeds in turns, reading a single press is sufficient.

Attached is a sketch illustrating how the touchpad works.

As with the LED matrix, bits are used to represent which intersection was pressed.

Step 6: Putting everything together

Picture of Putting everything together
Now that all the individual components are done, it's time to put them all together.

Overlay the wire grid on the LED matrix.  You may need to reorder the pin numberings in the LED matrix code to get it synchronised with the wire grid sensor.  Secure the wire grid in place with fastenings or adhesives of your choice, and stick on a nice playing board.

Add a switch between pin 12 and ground of the Arduino.  This switch is to toggle between 2 player mode, and 1 player mode (vs the microcontroller).

Step 7: Programming Tic Tac Toe

Attached is the code for the game.

Let's first break down the tic tac toe game into its various steps, in the two player mode:

Step 1: Player A picks an unfilled cell by touching an intersection. 
Step 2: The LED for that cell lights up with the colour A.
Step 3: Check to see if Player A has won.
Step 4: Player B picks an unfilled cell.
Step 5: The LED for that cell lights up with colour B.
Step 6: Check to see if Player B has won.
Step 7: Repeat 1-6 until there's a win condition, or if all the cells are filled.

Reading the cells:
The program loops between reading the grid and displaying the LED matrix.  As long as the grid sensor does not register a non-zero value, this loop will continue.  When an intersection is pressed, the Pressed variable stores the position of the pressed cell.

Checking if the cell is unfilled:
When a position reading is obtained (variable Pressed), it is compared against the current cell status (stored in the variable GridOnOff) using a bitwise addition.  If the Pressed cell is unfilled, then proceed to light up the LED, otherwise return to reading the cells.

Toggling the colours:
A boolean variable, Turn, is used to record whose turn it is.  The LED colour chosen when a cell is picked is determined by this variable, which alternates each time a cell is chosen.

Checking for a win condition:
There are only 8 possible win conditions, and these are stored as word variables in an array (winArray).  Two bitwise additions are used to compare a player's filled cell positions to the win conditions.  If there's a match, then the program displays a win routine, after which it starts a new game.

Checking for a draw condition:
When nine turns have been recorded and there is still no win condition, then the game is a draw.  The LEDs are then faded out and a new game is started.

Switching to one player mode:
If the switch is in the on position, the program goes into one player mode, with the human player starting first.  At the end of the human player's turn, the program simply picks a random cell.  Obviously, this isn't the smartest strategy!

Step 8: Remarks and further improvements

Here a video showing the one player mode, with the program playing totally random moves:

The program shown here is only a minimal, bare bones version.  Many other things can be done with this:

1) Lighting up LEDs three at a time
The current code displays only one LED at once.  However, with the wiring shown here, it's possible to light up all the LEDs connected to one cathode line at the same time.  So, instead of cycling through all the nine positions, all you need to do is cycle through the three cathode lines.

2)  Use interrupts to display the LEDs
Depending on the LED display routine and the amount of processing, the LEDs may show some degree of flickering.  By using interrupts, the timing of the LEDs can be controlled precisely and would lead to a smoother display.

3) A smarter computer player
The currrent code takes up only a few kb, leaving quite a bit more for the implementation of a smarter computer tic tac toe player.

Hope you've enjoyed reading this instructable as much as I had fun working on it!

1-40 of 73Next »
rbusch6 days ago

that is one very well written instructable. great detail and explenations :) excelent job and very cool project!

Chi HinL1 month ago

Sorry, i want to ask how to import those library to the board?

AnnabelleS9 months ago

I'm making this for a science project, and I've looked all over, but I can't find where to get that size and thickness for the transparent acrylic sheet. Does anyone know where I can get one?

origamiwolf (author)  AnnabelleS9 months ago

It's not necessary to use the exact size and thickness I used in the instructable. In fact, any clear, flat material will work as long as it's non-conductive, transparent, and large enough to put the 3x3 grid of LEDs below. So a thin sheet of glass will work, as will a thin sheet of other types of plastic. One place to find these would be in picture frames - you could get a cheap one from a dollar store, and use the glass or plastic that comes with it.

thank you so much!
hccSmarties00710 months ago


Can you please reply to our email..We would of really appreciated.

Raphango11 months ago

Man... really one of the best instructables I've ever seen....


jt_hos1 year ago
Me and some friends just did this today... thanks, I have to say that it's been one of the best Instructables I've seen. I liked very much how you explained everything that was at work within this...
origamiwolf (author)  jt_hos1 year ago
Thank you, I hope you enjoyed building it!
origamiwolf (author) 2 years ago
The black dots show the connections to the cathode and anode leads, it's to make things clearer in a perspective diagram otherwise you can't tell where the wires should connect.
nehcyhtac2 years ago
Hi! We're trying to recreate this concept--we're running into serious problems though. We cannot seem to get the colors to show in order and we cannot seem to get some LEDs to light individually. When using the same button pattern over and over again we see unique patterns in the light grid--no consistency. We're using RGB (10mm) common cathode (4 legs, we've curled up the blue legs).

Please see the following video we made as documentation of the problem:

origamiwolf (author)  nehcyhtac2 years ago
I can't quite tell what's wrong, but one suggestion could be to try a 2 x 2 grid first then work your way up to the 3 x 3.
j416972 years ago
does it work with arduino uno?
origamiwolf (author)  j416972 years ago
I haven't tested it on the Uno, but it should work pretty much the same way.
thepoynt3 years ago
Any suggestions on how to test the touchpad by itself? I haven't built any of the rest of the project, and I'd like to make sure this part works before going on.

btw, great project idea - I'm enjoying building it!
origamiwolf (author)  thepoynt3 years ago
Connect multimeter probes to a row wire and a column wire, and set it up the measure resistance. If the ouchpad is workig correctly, you should see a dip in the resistance when you touch the row and column intersection. Repeat this for each pair of row and column wires.
robot13983 years ago
made the keypad and got it to work.........
origamiwolf (author)  robot13983 years ago
Great to hear that!
bmorgan63 years ago
I have a question where can i find the switch you ask for and does it have to be a throw switch?
origamiwolf (author)  bmorgan63 years ago
It has to be a switch that allows two states. You can get these switches online, from places like element14 or Mouser.
Keanan3 years ago
I notice in the code it has i % 3. I assume this is for the double anode/ one cathode for the LEDs you are using. So how would one change the code to accommodate for dipole LEDs instead of tripole?
origamiwolf (author)  Keanan3 years ago
No, the i % 3 comes from the way the matrix is addressed. Instead of storing two coordinates (ie row, column) for each LED, each one is simply labelled with a digit between 1 and 9.  The i % 3 and i / 3 code segments convert this single digit into the row and column coordinates.
So then, what must be changed for 2 lead LEDs to work instead of the 3 lead ones?
origamiwolf (author)  Keanan3 years ago
With a dipole LED, you just need to flip the HIGH and LOW digital states on the anode and cathode lines to access the two colours.

Let's say you have one row line and one column line, with the dipole LED across them. Then, if the row line is set to HIGH and the column line is set to LOW, it will turn on one LED colour. To get the other colour, the row line is set to LOW while the column line is set to HIGH.
aldrome3 years ago
Hi, I really like your idea!! And i was wondering if it is really importat that The red and green anode lines go into the PWM pins of the Arduino, I mean, why do they have to be PWM?, can they be the normal pins like number 2 or 13? It's because I'm trying to mix this with another idea I have.

Thanks for everything.
origamiwolf (author)  aldrome3 years ago
Hi aldrome,

I used PWM here because I wanted the LEDs to fade out. You can use the normal pins as well, but the LEDs will just have two brightness levels - on, or off.

-- Wolf
jwoo20234 years ago
can I use arduino uno?
origamiwolf (author)  jwoo20234 years ago
Sure, this should work on the Uno as well.
thanks for the info
skylen4 years ago
So it sounds like this touchpad matrix uses capacitive sensing, rather than resistive touch operation. When a finger is placed on the intersection of a row wire and a column wire, it increases the capacitance between the wires, causing the LOW level on the column wire to couple more strongly to the row wire, resulting in the touched row dropping in voltage more quickly than if it were not pressed.

Example: ChaN's Simple Touch Sensor
origamiwolf (author)  skylen4 years ago
Thanks, yes, that's a more likely explanation as you can sometimes get each intersection to trigger without a firm touch.
artecx4 years ago
I've problems with downloading the .pde files.
any solution to download them proper?
they all got a .tmp extension
origamiwolf (author)  artecx4 years ago
Just rename the .tmp to .pde.
you have a great idea in that game
maewert4 years ago
I really enjoyed this instructable.

A few comments however.
1.  I see that the random number sequence is always the same.  You need to add a random seed.
2.  The computer is very easy to beat since it does not take a winning move or try to block the user's winning moves.  These changes make the computer more difficult to beat but not impossible, so playing is still fun.

I updated the code to correct these two items and to make it work without your special hardware (i.e. you can play with a standard Arduino and a serial monitor or with your led touchpad).

This could be the start of the old 'tic-tac-toe playing chicken' seen in some county fairs where the person plays against the chicken.  When it is the chickens 'turn' the door to the chicken food is opened and the chicken appears to be thinking then pecks a selection.  This works so long as the person can't see what the chicken is packing at and assumes it is a similar display/keyboard they are presented with.  Very funny seeing kids getting beat by a chicken!

If there is community interest we could always make the 'impossible to beat the computer' version but where is the fun in playing that?  :-)

Best Wishes
origamiwolf (author)  maewert4 years ago
Great job! :)

Yes, the code in my instructable is very minimal, and there's so much that can still be done. For instance, instead of having it rigidly rule based, it would be possible to code up a learning algorithm. So initially, the computer plays randomly, but each win or loss will strengthen (or weaken) particular moves.

Such algorithms exist already, but it would be fun to see it on an Arduino. :)
Adi00054 years ago
This is the first time I am using bicoloured LEDs. So I was wondering if you could include a diagram of led matrix of arrangement of the bicoloured Leds.
origamiwolf (author)  Adi00054 years ago
Not quite sure what you mean, as the diagram in this step (step 1) already shows how the LEDs are connected.

Here, I'm using an LED with 3 terminals - one red anode, one green anode, and a common cathode.
This will be my first project with arduino. It don't looks hard. Can i don't use ''touchpad'' but just buttons in matrix?
origamiwolf (author)  kristiansmic4 years ago
Sure, yes, any kind of button switch would work.
1-40 of 73Next »