Introduction: DIY 3D Controller

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.

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

Picture of 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

Picture of 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).


PrasadM11 made it! (author)2017-01-05

I completed this project. I also made some additional programs with this same setup like a musical instrument, hand controlled 3D camera, drawboard (which recognizes touch input).
Most importantly I was able to register touch using this same setup.So, it acted like a motion and touch tracking interface. One advice to people attempting to make this please add an extra ground plate as shown in the image and use this place during calibration only it helps improve accuracy.
Check out the code and explanation at:

GagandheepR (author)PrasadM112017-10-22

can you please tell me the use of momentumaverage.pde and normalize.pde.

MdZaheerHasan (author)PrasadM112017-09-26

Could you please explain a little more about the ground plate? The calibration technique isn't clear.

SrinivasP25 (author)PrasadM112017-02-20

to which pin have you connected the ground plate to..

samblam (author)2012-05-02

Hi there,
I just made the 3d controller and im now trying to make it work. Im new to processing so when I tried to 'just drop the folder TicTacToe3D' in the folder I found under sketch->show sketch folder it wasnt opening. so i just dragged the 3 .pde files on the screen and pressed Run.

This gave an error
in line 54: if(parts.length == sensors) {

'Cannot find anythin named "sensors"'

Does anyone know what is the problem and what is the solution?


kylemcdonald (author)samblam2012-05-20

yes, it looks like that's a bug with the code. i'm not sure how it got there, sorry!

change "sensors" to "sen" and it should run.

samblam (author)kylemcdonald2012-06-01

Thanks a lot, it's working now. Awesome!

AjayV34 (author)samblam2017-08-06

bro when i run the code , one window will open but dosent show anthing

mashcon5 (author)2012-10-13

When i try to run the program, I keep getting an error message that says my font cannot be found. Any suggestions?

kylemcdonald (author)mashcon52012-10-14

it just means the font is missing or can't be parsed. try using createFont instead of loadFont. read the processing documentation for more info and try asking on the processing forums if you have more questions

AjayV34 (author)kylemcdonald2017-08-06

bro when i run the code , one window will open but dosent show anthing

royshearer (author)2012-12-21

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?

AjayV34 (author)royshearer2017-08-06

bro when i run the code , one window will open but dosent show anthing

royshearer (author)royshearer2012-12-21

I switched to the earlier v1.5 of Processing and that seemed to fix my problem. Greta fun now!

royshearer (author)royshearer2012-12-21

I can use either [0] or [1] as serial port variables

slickman84 (author)2014-05-05

Then I open Processing program and then I open the TicTacToe3D its saying "cannot find anything named sensors.

XYZAidan (author)slickman842014-05-31

Change "sensors" to "sen".

AjayV34 (author)XYZAidan2017-08-06

thx bro but when i click to run output window is white did not show anthing

AjayV34 made it! (author)2017-08-06



ultra2301 (author)2017-02-14

In arduino serial port I am always getting only 0 0 0 values even after moving my hands, Does it mean that connections are faulty or some other problem.

ВсеволодК (author)2017-01-14

I used your code and little bit of schematics for my project of theremin on arduino

凱文鄭 made it! (author)2015-02-04

Hey guys,

I used this awesome system making something fun which is a abduction game of sucking people by UFO. You can move your hand to control the UFO position.

Here is project's github. Enjoy it!:

PrasadM11 (author)凱文鄭2017-01-05

I used your code of UFO game in my project. Thanks and keep up the good work.

adjectives (author)凱文鄭2016-10-15

That's sweet.

Hesgoy (author)2016-07-30

Sir, I have an error " sensors cannot be resolved to a variable" wat to do to clear this error

venkatesh111 (author)2016-05-12

sir the link you have provided for the code is not opening. can you plz provide me the code to the mail

The .ino file? If you're not opening with the arduino software have you tried opening with a text editor like Notepad or Wordpad? That should also show you the code.

MdZaheerHasan (author)2016-06-30

The link for make magazine wasn't working. I think this is what you meant to link:

SrivishnuT made it! (author)2016-03-26

I made it but the pressing sct\etch does not move the ball, i see the cubes but not the ball

MohamadN5 made it! (author)2015-10-01

i did it

but the machine didn't show me my hand position

what's wrong ?

show the picture i added,,,

SrivishnuT (author)MohamadN52016-03-26

I have the same problem too

smartmiltoys (author)2015-02-25

Nothing will EVER be better than the keyboard and mouse. Nobody wants to
hold their arms out for minutes at a time. Nobody who actually does
anything productive on their computer, that is.

GraemeR7 (author)smartmiltoys2016-03-02

Sorry, were you looking for a better-engineered mouse, or were you looking for a neat, feasible, applicable project and demonstration of physics and electrical engineering at work?
Don't knock cool projects just because they are not good for daily use.

rami2013 (author)2013-12-30

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

PetraC6 (author)rami20132016-02-02

You have 3 Serial.print instructions, which print data from all 3 pins.

You should replace this code from the loop function:

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

With this code:

Serial.println(time(8, B00000001), DEC);
soeren (author)2015-10-21

Hi, I'm trying to downscale this to a 2D module (X and Y), but simply removing the third pin from the code everywhere - doesn't seem to work. It just sends out 0 0 from the arduino. Do you have any advice on how to do this? That would be much appreciated. Thank you. Regards, Søren

VirajT (author)2015-09-03

I am getting error in the processing software keeps showing me this.

Error :-- "type string[] of the last argument to method println(object....) doesn't exactly match the vararg parameter type. cast to object[] to confirm the non-varargs invocation, or pass individual arguments of type object for a varargs invocation.'

do i need to connect arduino while runing processing software??

This is my 1st time working on processing software.

thut6 (author)2015-09-03

hey this is cool !
but can this DIY 3D Controller work with android phone?

DangerousTim (author)2014-08-15

why don't you use the capsense library? It's quite good, and you'll need only one resistor per foil...

SIM-Tech (author)DangerousTim2015-08-26

the extra R is for just incase shock go back to Receive pin it will bring voltage down, cap library ur talking about uses one becasuse is a smmall foil

firobug (author)2014-12-26

could you improve this size by additional pannels... you said something about the largest you being able to do was only a foot or so and i think that may be just because of the limits of the capacsitance of the aluminum if we add say another set of say 9 panels could we make this a 2 foot cube and better yet could it be extended by using strips i could glue to my walls and ceiling to give me a full 3d cube to interact in...maybe add streamers to get me a 3d display with projectors.....

SIM-Tech (author)firobug2015-08-26


SIM-Tech (author)2015-08-26

can someone tell me what roll does the shield wires plays in this? seem unnecessary as it is not being connected from one end

skern1 (author)2015-06-18

the processing software keeps showing errors ArrayIndexOutOfBoundsException:

AniketS3 (author)2015-06-13

Can you please explain the math in the code? I want to use this a bit differently, it will be a great help! Thanks! And thumbs up for the project!

iltabhai (author)2015-05-21

This project only works on the processing 1.5.1.

WaleedR (author)2015-05-11

ArrayIndexOutOfBoundsException: 2 is the error and the TicTacToe 3d is not responding.

WaleedR (author)2015-05-10

hey when i upload the code in processing it says can not find anything named "sensors"

ajcracker08. (author)2015-04-21

Has anyone been able to figure out the problem where the grid shows with the ball in the top back cube? It says its calibrating but nothing .

Csaub001 (author)2015-01-19

When I run TicTacToe on processing I get a white screen... Processing highlights this line

serial = new Serial(this, Serial.list()[serialPort], 115200);

any ideas?

About This Instructable




More by kylemcdonald:Structured Light 3D ScanningNandhopper 1-Bit Noise SynthLo-fi Arduino Guitar Pedal
Add instructable to: