Picture of DIY 3D Controller
Make a 3D interface using an six resistors, aluminum foil, and an Arduino. Take that, Wii.

Update: a much more thorough explanation of this project is available from Make Magazine. It might be easier to follow their instructions, and I think their code is more up to date.

The basic goal here was to make a 3D hand-position sensing system that most people can build, while still preserving some semblance of functionality. To get an idea of possible applications, check out the demo video. If you think you can build one that is simpler and equally accurate, or slightly more complex and more accurate, share in the comments!

DIY 3D Interface: Tic Tac Toe from Kyle McDonald on Vimeo.
Remove these adsRemove these ads by Signing Up

Step 1: Materials

Picture of Materials



  • (3) 270k resistors
  • (3) 10k resistors
  • Solder
  • Wire
  • Aluminum foil
  • Cardboard


  • Tape (e.g.: scotch)
  • Shielded wire (e.g.: coaxial cable, ~3')
  • (3) alligator clips
  • 3-pin header
  • Zip-tie
  • Shrink wrap tubing or hot glue

Step 2: Make the Plates

Picture of Make the Plates
This sensor will work using simple RC circuits, with each circuit sensing distance in one dimension. I found that the easiest way to arrange three capacitive plates for this purpose is in the corner of a cube. I cut the corner of a cardboard box into an 8.5" cube, and then cut some aluminum foil to fit as slightly smaller squares. Tape on the corners keeps them in place.

Don't tape down the entire perimeter, we'll need it later for attaching the alligator clips.

Step 3: Make the Connectors

Picture of Make the Connectors
To connect the Arduino to the plates we need some shielded wire. If the wire isn't shielded, the wires themselves act more obviously as part of the capacitor. Also, I've found that alligator clips make it really easy to connect things to aluminum -- but there are probably plenty of other ways, too.

  • Cut three equal lengths of shielded cable. I chose about 12". The shorter the better. Coaxial cable works, but the lighter/more flexible the better.
  • Strip the last half inch or so to reveal the shielding, and the last quarter inch to reveal the wire.
  • Twist the alligator clips to the wires onto the wires and solder them together.
  • Add some heat shrink tubing or hot glue to keep things together.

Step 4: Make the Circuit

The "circuit" is just two resistors per piece of aluminum. To understand why they're there, it helps to know what we're doing with the Arduino. What we'll do with each pin, sequentially, is:

  • Set the pin to output mode.
  • Write a digital "low" to the pin. This means both sides of the capacitor are grounded and it will discharge.
  • Set the pin to input mode.
  • Count how much time it takes for the capacitor to charge by waiting for the pin to go "high". This depends on the values for the capacitor and the two resistors. Since the resistors are fixed, a change in capacitance will be measurable. The distance from ground (your hand) will be the primary variable contributing to the capacitance.

The 270k resistors provide the voltage to charge the capacitors. The smaller the value, the faster they'll charge. The 10k resistors affect the timing as well, but I don't completely understand their role.

We'll make this circuit at the base of each wire.

  • Solder the 10k resistor to the end of the wire opposite the alligator clip
  • Solder the 270k resistor between the shield and the wire (plate). We'll shield the wire with the same 5 V we use to charge the capacitors

Step 5: Finish and Attach the Connector

Once the 3 connectors are finished, you might want to add heat shrink tubing or hot glue to insulate them from each other, because you'll be soldering the shielding/5 V points together.

For me, it was easiest to solder the two outermost connectors together and then add the third.

Once you've soldered the three connectors, add a fourth wire for supplying the shield/5 V.

Step 6: Connect and Upload Code

Picture of Connect and Upload Code
  • Plug the connector into the Arduino (pins 8, 9 and 10)
  • Snap the alligator clips onto the plates (8:x:left, 9:y:bottom, 10:z:right)
  • Provide power by plugging the fourth wire (my red wire) into the Arduino's 5 V
  • Plug in the Arduino, start up the Arduino environment
  • Upload the code to the board (note: if you are outside North America, you will probably need to change #define mains to 50 instead of 60).
The Arduino code is attached as Interface3D.ino and the Processing code is attached as

Step 7: Do Something Cool!

If you look at the serial window in the Arduino environment, you'll notice it's spitting out raw 3D coordinates at 115200 baud, at approximately 10 Hz = 60Hz / (2 full cycles * 3 sensors). The code takes measurements as many times as possible on each sensor over the period of two cycles of the mains power frequency (which is suprisingly stable) in order to cancel out any coupling.

The first thing I did with this was make a simple 3D Tic Tac Toe Interface. If you want to start with a working demo, the code is available here, just drop the folder "TicTacToe3D" in your Processing sketches folder.

Three helpful things that the Tic Tac Toe code demonstrates:

  • Linearizes the raw data. The charge time actually follows a power law relative to distance, so you have to take the square root of one over the time (i.e., distance ~= sqrt(1/time))
  • Normalizes the data. When you start up the sketch, hold the left mouse button down while moving your hand around to define the boundaries of the space you want to work with.
  • Adding "momentum" to the data to smooth out any jitters.

In practice, using this setup with aluminum foil I can get a range of the largest dimension of foil (the biggest piece I've tested is 1.5 square feet).

Step 8: Variations and Notes


  • Build massive sensors
  • Optimize the resistors and code for things that vibrate quickly, and use it as a pickup/microphone
  • There are probably other tricks for decoupling the system from AC hum (a huge capacitor beteween the plates and the ground?)
  • I've experimented with shielding the plates on the bottom, but it only seems to cause problems
  • Make an RGB or HSB color picker
  • Control video or music parameters; sequence a beat or melody
  • Large, slightly bent surface with multiple plates + a projector = "Minority Report" interface


The Arduino playground has two articles on capacitive touch sensing (CapSense and CapacitiveSensor). In the end, I went with an inversion of a design I stumbled across in a friend's copy of "Physical Computing" (Sullivan/Igoe) describing how to use RCtime (the circuit had the capacitor and one resistor fixed, and measured the valueof a potentiometer).

The microsecond timing was accomplished using some slightly optimized code from the Arduino forums.

Again: just from starting at tons of theremin schematics I don't completely understand, I'm well aware there are better ways to do capacitive distance sensing, but I wanted to make something as simple as possible that's still functional. If you have an equally simple and functional design, post it in the comments!

Thanks to Dane Kouttron for tolerating all my basic electronics questions and helping me understand how a simple heterodyne theremin circuit works (originally, I was going to use these -- and, if tuned correctly, it would probably be more accurate).
kovacp112 days ago

The 'code is available here' link above is broken,

Is the code available anywhere and tare there instructions for compiling it?

Thank you

kovacp112 days ago

What is the application code written in?

I use visual studio - has anyone made an app for that.

Thank you

akumama1 month ago

Hey Kyle, this is amazing, I first saw it on MAKE but have been meddling with it myself for some time now. I have got it working to an extent, but when I run it in processing, once I've clicked to get it to follow my hand, the ball just floats around one area. Do you know why this might be?

fanak11 months ago
An interesting application would be to make this as a controller for a mechanical arm
vvieira2 fanak2 months ago

In progress...
But the sensors still not working with me :/

Ramzeez1002 months ago

Hi, I realize this comment may be a bit late, but I'm a bit new to Arduino and I was trying to get this to work. I'm using an Arduino Uno, which Make Magazine used, and I fixed the processing code and got everything uploaded and running. When I run the TicTacToe3D program from processing I am able to see the grey cubes and the red ball, but when I place my hand in while left click holding the window, nothing happens except for the program saying "defining boundaries". Any help?

theamateur3 months ago

probably the coolest instructable i have seen to this day.

rami20133 months ago
Hi all,
I’m testing this with just one panel and using the test program (_3DInterface)
if I’m shorting pin 8+9+10 it’s working but reports three outputs,I would like just one output and that pins 9 and 10 (on the arduino) will be disconnected.
tried changing line for(inti=8;i<11;i++) pinmode(i,input), to for(inti=8;i<9;i++) pinmode(i,input)
but it didn't work, each time i remove the short line between pins 8+9+10 the output stops.

Please advise
bugmeidareyou3 months ago
Hi all,
I’m testing this with just one panel and using the test program (_3DInterface)
if I’m shorting pin 8+9+10 it’s working but reports three outputs,I would like just one output and that pins 9 and 10 (on the arduino) will be disconnected.
tried changing line for(inti=8;i<11;i++) pinmode(i,input), to for(inti=8;i<9;i++) pinmode(i,input)
but it didn't work, each time i remove the short line between pins 8+9+10 the output stops.

Please advise
AVNERD1994 months ago
Is there any way i could make a bunch of small ones and put them in a pattern to make a touchless keyboard?
fmmehr5 months ago
hey thanks for your great project the only thing is i can't make the tictactoe3d working on processing app it gives me errors and it can't export the application can you please help me or can u send me the ready made tt3d app to instal or right code thank you
my email is
mindlelle1 year ago
Hi, I have done everything and I see TicTacToe3D screen with boxes and orange ball. but the problem is that the ball doesn't move at all. It doesn't react. Any advice? What could be a problem? Help me~
jkctech mindlelle5 months ago
allready tried to calibrate it? and did you use shielded wire, or else your body may act as a capacator.

Hope it helps!
johnnnny jkctech5 months ago
how do you calibrate it? i have the same not-moving ball
MaC Malik10 months ago
Completed with :
Arduino : UNO [haven't tested this with Leonardo yet]

Processing version : 1.5.1 [as a must ,
because there is a part of the code is not compatible with the newer versions , maybe if you can replace it something is ok with for newers , then newers is ok ;) ]
I done it without shielded wires , but because the wires are not shielded , a capacitance between the wires and my body is created (same as between my hand and the plates) which is already mentioned earlier by Kyle, and that will disturb the readings and make controlling the ball a little harder ( I have to keep my body away from the wires) and from there the importance of shielding is shown up (beside stopping the antenna effect as well) ;).
MaC Malik10 months ago

I have some how solved the problem and I a sure with the solution with only 38% (since I don't really know what EXACTLY was wrong with it).

What I did is
[/\]Opening the serial port and check the values coming out of Arduino
[/\]and as mentioned in the previous comment, I had only one number coming out then stops sending numbers.

[/\]then I Removed all the connections from the Arduino pins while watching the serial monitor.

[/\]Nothing changed yet , but when I tried putting a wire (one of the wires that should be connect to the Arduino I/O pins in this instructable :8,9 and 10) on one of the three pins (8,9 and 10) and then take it off fast and doing the same with same wire with the other pins , in and out , in and out .

[/\]Then I FINALLY Saw the Numbers coming out of Arduino to the Serial (maaaan , how I was happy back then) after that,when I ran processing, the ball started responding and moving(finally).

I know it might seem as if I am telling a story , but here is what I did so you can get clue to fix your situation with (My opinion is that maybe the three pins were some sort of "stuck" at the beginning).

Best of Luck :) .
MaC Malik10 months ago
I did not solve the problem yet,However,

To all of you who has the "Not Moving Ball" problem , I know the starting point of the debugging :
I checked the Arduino's "Serial Monitor" and I found that Arduino does send NOTHING in the serial line ( except for a number that shows up one time at the beginning)

And thats WHY (I Assume with 99%) the ball in processing Does Not Move.

So all of you (including me =3 ) start debugging from there.
GoodLuck ;).
schmitta11 months ago
The shielded cable/ center conductor is the capacitor. The foil just takes away current from the shield capacitor. The hand forms a capacitor with the body being ground and current flows from the foil to the hand electrostatically robbing current from the shield capacitor's center conductor. The center conductor is first grounded through the 10k resistor when the logic zero is written to that port. Then when the port is made an input it is at a high impedance (cmos) and little current flows through the 10k to the port. The shield is at 5 volts. The center conductor of the shielded cable is at ground and charges through the 270k resistor until it reaches 2/3 of Vcc. Then a logic 1 is triggered. The foil is passing current to the hand and robbing current from the center conductor causing a longer time until the 2/3 Vcc is reached. The closer the hand is to the foil the higher the capacitance value of the hand/foil capacitor and the more current is robbed from the charging center conductor extending the charge time of the center conductor. Alvin....
NehadTabl11 months ago
Hi Kylem!!

I did everything, but the box is not moving. what’s the problem??
Can you help me please??
I made 220K ohm by two 100k series with two 10k ( behind each other) … do you think this is the problem?
hornedCapybara12 months ago
I'm trying to make this work, and it isn't working.
I loaded the code to arduino, and i load the processing code and run it, and all i get is a blank white screen. Please tell me what im doing wrong!
Newermore1 year ago
Hi kylemcdonald. Firstly I want to say how much this project interests me, so I want to make it by myself and use it as a school project to show possibilities of Arduino. But I'm not so good at programming and do not understand whole program, that you have made for the Arduino. Can you please e-mail me to what program does step by step? I will be very grateful.

#define resolution 8
#define mains 50 // 60: north america, japan; 50: most other places

#define refresh 2 * 1000000 / mains

void setup() {

// unused pins are fairly insignificant,
// but pulled low to reduce unknown variables
for(int i = 2; i < 14; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, LOW);

for(int i = 8; i < 11; i++)
pinMode(i, INPUT);


void loop() {
Serial.print(time(8, B00000001), DEC);
Serial.print(" ");
Serial.print(time(9, B00000010), DEC);
Serial.print(" ");
Serial.println(time(10, B00000100), DEC);


long time(int pin, byte mask) {
unsigned long count = 0, total = 0;
while(checkTimer() < refresh) {
// pinMode is about 6 times slower than assigning
// DDRB directly, but that pause is important
pinMode(pin, OUTPUT);
PORTB = 0;
pinMode(pin, INPUT);
while((PINB & mask) == 0)
return (count << resolution) / total;

extern volatile unsigned long timer0_overflow_count;

void startTimer() {
timer0_overflow_count = 0;
TCNT0 = 0;

unsigned long checkTimer() {
return ((timer0_overflow_count << 8) + TCNT0) << 2;

cantona1 year ago
Any ideas on how to make this emulate a mouse using the Arduino leonardo ?
Hey I believe I've done everything in the instructions right. I built it all correct, there's no shorts. I've uploaded the _3DInterface into the Arduino. When i try to use the TicTacToe it only comes up with a whit screen and an error (ArrayIndexOutOfBoundsException: 1). It highlights a part of the script
serial = new Serial(this, Serial.list()[serialPort], 115200);
Please help =) thank you!!
Hahaha yes i got it to work, i had to change there serial number at the top to zero. since my arduino is in com 5
Exception in thread "Animation Thread" java.lang.ArrayIndexOutOfBoundsException: 1
at TicTacToe3D.setup(
at processing.core.PApplet.handleDraw(Unknown Source)
at Source)
this is what it said at the bottom of the processing
TomB221 year ago
I installed processing and arduino software. I upload sketch to arduino and copied Tic Tac Toe 3D to sketch folder in processing. I'm running processing and I can see window with dimensions of 7x7cm, however I don't see any any points inside the square and I'm not sure how to initialize it. Could you pls help me out? Am I missing something? Thanks a lot for any help!
i only get a white screen nothing shows up, i get stuff through the serial port though
i am using processing 2.0b3
throw up a gist of what you entered for the code.

its exactly the same
how could i use an arduino leonardo to make this into a mouse?
royshearer1 year ago
Does the serial port numbering array work in the same way in mac OSX?
I have

[0] "/dev/tty.usbmodemfa131"
[1] "/dev/cu.usbmodemfa131"
[2] "/dev/tty.Bluetooth-PDA-Sync"
[3] "/dev/cu.Bluetooth-PDA-Sync"
[4] "/dev/tty.Bluetooth-Modem"
[5] "/dev/cu.Bluetooth-Modem"

from Processing.
I upload to /dev/tty.usbmodemfa131 in Arduino successfully and get good numbers out of the serial monitor there.
When I use a [0] variable for the serial port in Processing however, I get a lot of interference on the serial monitor - not gobbledygook, just weird strings of numbers if varying lengths. I just see the grey cube and nothing else happens.
When I use a [1] variable i get the following error:
RXTX Warning: Removing stale lock file. /var/lock/LK.012.018.043 Unknown Application
and lots more.

Am I doing anything wrong?
I switched to the earlier v1.5 of Processing and that seemed to fix my problem. Greta fun now!
I can use either [0] or [1] as serial port variables
TheGreatS1 year ago
All I'm getting the the serial window is gibberish symbols like ÿ, ñ, and ö. It looks like all the electronics are checking out, no short circuits and everything is where it should be. What can I do?
oops, made the same mistake as arovira bosh, its working now! SO AWESOME!
Ops sorry I changed my serial monitor to 115200 and I think that now it's working because appears 3 columns with numbers arround 6000 changing when i put my hand in the cube. But i'm still with the other software problem. Thank you!

Nice work!

I have some problems with the step 5:

I have a _3Dinterface.ino loaded in my arduino
Here if I open my serial monitor I only can see letters running

Then I open Processing program and then I open the TicTacToe3D.pde and the other 2 opens automatically. then I export my application and this creates an application with the name TicTacToe3D, when I open the app I can only see a grey screen with anything.

I'm using a Macbook pro with Mountain Lion

Can you help me please?

Thank you very much!
tespi1 year ago

that's a really great example, thanks a lot!

I am trying to control 2 such controllers from one arduino, I changed interface3D.ino by adding to void loop() 3 additional lines (without really understanding, what they mean). Serial monitor now shows 5 parameteres, but the sixth one not. What does that binary number means and how could I make it work with 6 plates?

Here is the code:

void setup() {


for(int i = 2; i < 14; i++) {

pinMode(i, OUTPUT);

digitalWrite(i, LOW);


for(int i = 8; i < 14; i++)

pinMode(i, INPUT);



void loop() {

Serial.print(time(8, B00000001), DEC);

Serial.print(" ");

Serial.print(time(9, B00000010), DEC);

Serial.print(" ");

Serial.print(time(10, B00000100), DEC);

Serial.print(" ");

Serial.print(time(11, B00001000), DEC);

Serial.print(" ");

Serial.print(time(12, B00010000), DEC);

Serial.print(" ");

Serial.println(time(13, B00100000), DEC);


Thanks for your answer!

Get More Out of Instructables

Already have an Account?


PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!