Capacitive Touch Sensing Game Controller & Processing Game

I really like my phone because of the way I can seamlessly interact with its touch screen – among many other things. Most touch screens nowadays utilize capacitive touch sensing technology (which I’ll explain later), so this project is my little way of exploring this amazing technology at a very rudimentary level. As you’ll soon find out, my project ended up going much further than I had initially anticipated, and resulted in the creation of a homemade video game which I played with a homemade controller and (you guessed it) the controller uses homemade capacitive touch sensors! Check out a video of it in action:

Capacitve Touch Sensing Game Controller & Processing Game from Treehouse Projects on Vimeo.

In actuality, the project is extremely simple, so I’ll explain it briefly first. The capacitive touch sensors may sound fancy, but all they are doing is reacting to my body’s natural capacitance – that is, the charge I have stored in my body. Perhaps you have heard of a very common electrical component called a capacitor. A capacitor consists of two conductive ‘plates’ with a dielectric insulator in the middle and it’s used in everything from power supplies to radios. I’ll get into more detail later, but in our case, the negatively charged plate is our body (ground), the positively charged one is the connection we have with the Arduino, and the dielectric insulator is our skin! Cool, eh?

That’s where the aluminum contacts come in. They give me a nice and big area to touch with my finger and, consequently charge the ‘capacitor’ (body | skin | aluminum). An Arduino is programmed to detect how long it takes for this makeshift capacitor to reach a higher potential, and if the capacitance is high enough, then the Arduino will be able to pick up the change in potential and let us know when it occurs. I have six of these pins set up to give me Left, Right, Up, Down, A, and B controls. The video game is even simpler, but I will admit that it seemed a little daunting at first and I was quite close to giving up. In retrospect, I’m glad I pulled up my socks and wrote one for myself, line for line. I have a detailed explanation of how the game works later on in the post but in case you are wondering, I made it Spongebob themed as a tribute to a show I used to watch and enjoy a lot.

Click Here to Play the Game!

Be sure to let everyone know what your high score is by leaving a comment below!


Resources Required

This project was not very resource intensive. As long you have the extremely versatile Arduino or an equivalent ATmega microcontroller with the Arduino bootloader, it would be as simple as uploading my code, and hooking up the pins. What I used for this project was:

  1. Microcontroller
    I used one loaded with the Arduino bootloader, imitating an Arduino Duemilanove. Any Arduino will do, as well as any other ATmega microcontroller.
  2. Small piece of conductive material
    I used a tiny strip of aluminum, and cut out the tabs which would act as the buttons to touch. Any conductive material which you connect wires to in some way will suffice.
  3. Foam
    I cut out a piece of foam to use as the housing for my aluminum squares, and give my controller the NES styled shape I was going for.
  4. Wire
    I used wire jumpers to connect everything from the breadboard to the Arduino (see circuit diagram below), and 24 AWG wire to solder the aluminum contacts to.
  5. 1 Mega Ohm Resistors
    Depending on how many buttons you want, you’ll need one resistor each.

That’s all you need. Take one hour, and the above materials which would cost you less than a dollar (except the microcontroller which would cost you anything from $1.50 to $20 but can be used for uncountable projects, definitely a great investment), and you’ve got your very own capacitive touch sensing game controller!

If you want to write the video game to interface your controller with all on your own, you’ll need a few hours to get a good grip on the language (assuming you have a relatively decent programming background). If you don’t have programming experience, don’t worry. This is the easiest language I have ever used, and it’s an absolutely perfect place to start. In fact, the Processing IDE and syntax is exactly the same as the Arduino’s! Download Processing here.

Images

Click to enlarge

capsensegame capsensegame
capsensegame capsensegame

Process

    1. The idea for this project was born after reading Alan Chatham’s awesome Instructable: Turn a pencil drawing into a capacitive sensor for Arduino.
    2. I found a small strip of aluminum (about 0.4″ x 2.0″) and cut it into 6 equal pieces length wise – these would be the contacts which would pick up my body capacitance and trigger certain actions.
    3. I soldered wires to each of the aluminum tabs. This was hard because my soldering iron isn’t good at all. It really helps to clean the surface with flux paste though.
    4. I embedded each of the tabs in a block of foam, precisely where the skin for the controller would allow me access to them.
    5. Then, I connected the wires to a breadboard, and hooked up all the resistors and wire jumpers to the Arduino. Below is a circuit diagram I made to show you how everything goes together. Note that the black wires coming out the bottom are mean to be the ones I just soldered, and would have the aluminum tabs soldered on. They are the capacitive sensors.
      -
      Warning:
      Be extra careful when wiring everything, particularly when you are hooking up the 5V to each pin. Make sure the resistor is there, or else you run the great risk of destroying your microcontroller.

      capsensegame

    6. It was time to upload the code. I adapted Alan’s code to fit my project’s setup, and I was done (see code below). He explains how his code works really well, so be sure to check out his intuitive explanation. His code, however, is written for the AVR GCC compiler. Don’t worry if you don’t know how bit shifting and lower level C coding works though, his embedded comments are nice. If you want to learn how to program standalone AVRs, I would highly recommend visiting Dean Camera’s website (Four Walled Cube), but particularly his page on AVR Articles. They are absolutely excellent, and he’s a really cool guy (he works for Atmel!).
      -

      -
    7. Finally, I picked up Processing, and made the video game to play with the controller I just made. All the code and assets required for the video game are attached in a zipped folder at the bottom of this post, and in the following section I will explain exactly how the code for the game works.

How the Game Works

Hopefully you tried the game out at the top of the post before reading this so that you understand what I am about to explain. In case you didn’t, click here. There are two versions of this game. The first one includes the code to run my controller or mouse, and the second one is the code only for the mouse. Since I’m the only one who has the controller, I’ll quickly go over the code that doesn’t have the parts to process the serial input from the Arduino – with the added benefit of it being simpler to explain and understand. If you are adventurous and do make the controller, I should have both versions attached for you to download below. Let’s get to work! Start by looking over the code for the game below.

If you are new to programming, it may seem overwhelming. Trust me, it isn’t. I’ll explain the code block by block:

  1. At the top of the code, you’ll notice lots of variables. These are simply variables I have created which define the parameters of the game. Things like how long I want the game to last, or how many jellyfish I want in the game. Pretty simple, and very useful to keep your code easy to follow – even for yourself.
    -
  2. In the setup function, we now setup the way the game screen will look, and initialize some things like the Jellyfish objects (more on that later), and load the images/fonts we will be using. Note that these images and fonts will all be in the zip folder you can download below to try everything out for yourself.
    -
  3. The draw function is the heart of all Processing applications, and mine is no exception. This is the function which will loop forever – or at least until you close the window. So it is in this function that you should check what should be displaying on the game screen at a given time, and display it. I tried to make it simple my making three obvious scenarios for the draw function: the player will either be at the start screen, playing the game, or at the end screen. When we start with the gameStart variable equaling false, we know we are at the start screen because the game hasn’t started yet. It is here that we wait for the player to press the ‘a’ key. If the player presses ‘a’, we set gameStart to true, and the next time the draw function loops, we will hop to the next if statement and check if its conditions are met. Follow through the draw function as if it is a story, and run through the loops in your head. You’ll understand how everything fits together nicely.
    -
  4. When the game is active (that is, gameStart is true and endScreenActive is false, so we are actually playing the game), you will notice that we keep calling the function called moveSpongebob. Surprisingly, this function is mean to move Spongebob! Every time we run this function, we update Spongebob’s position based on our mouse’s location (defined internally by Processing as the variables mouseX and mouseY). When we update his position, what we are really doing is drawing him again at a new spot (which could also be the same spot from the last loop if you didn’t move your mouse), because after each loop of the draw function everything on the screen clears. Then we loop through each of the Jellyfish in the current screen, and see if their position matches Spongebob’s. If it does, we know Spongebob caught a Jellyfish, so we destroy the Jellyfish and increment the score by one.
    -
  5. Our last block of code is simple, and outlines an important concept in object oriented programming. To make my programming task easier to handle, I created a Jellyfish object. This is useful, because now each Jellyfish on the screen is actually a specific Jellyfish, with specific personalities and traits. So I can call on a specific Jellyfish whenever I want. Think about it this way: I clone a Jellyfish based on this basic skeleton Jellyfish object I have. Inside each Jellyfish clone lie traits/attributes. More specifically, we have traits like its x and y location, how long it has been alive for at its current position, and whether it is in fact alive or dead (caught by Spongebob).
    -
    In our very first block of code, we defined an array of Jellyfish objects, so I can access whichever Jellyfish I want to by calling it like this: jellyfish[1], jellyfish[2], etc., depending on how many Jellyfish I initially set for the game. So when we create a Jellyfish, we give it a random x and y location, as well as a certain lifeDuration at a single spot. When we move the jellyfish after its lifeDuration hits zero, we give it a new lifeDuration and keep repeating. The lifeDuration is not the total amount of time the jellyfish is alive, it’s the total amount of time it is alive in one spot.
    -
    You’ll notice that each Jellyfish object also has some functions. A real life Jellyfish would have attributes like color and size, and functions like sleep and sting. Our Jellyfish works the same way, except its attributes are what I mentioned above and its functions are getXLoc, getYLoc, setLifeStatus, and drawJellyfish. These are all quite self explanatory, and are used in different parts of the code. Akin to how we have to draw Spongebob again every time the draw function loops, we have to draw each Jellyfish again too based on its attributes. The getXLoc and getYLoc functions are used in the moveSpongebob function, so that we can compare Spongebob’s position with a Jellyfish’s to see if he has caught it. If he did, then we call the final Jellyfish function, setLifeStatus, and pass it a false argument so that it indicates that Jellyfish is dead/caught, and we need to assign new attributes to revive it at a new position on the screen next time we draw it. Of course, if Spongebob doesn’t catch a Jellyfish, once its lifeDuration is up I have programmed it to automatically take a new position.

I hope you have received a basic understanding of how this game works. Mull it over, let me know if you have any questions, and don’t give up. My best advice to you is to read code like a story. That’s essentially what the computer is doing, and if you can’t read the story without getting stuck somewhere and scratching your head, I can assure you the computer definitely won’t enjoy it either.

Conclusion

I had a blast working on this project. The only thing I regret is not having good enough fabrication tools to make my project look better (hence the foam and hand colored drawings). Not to worry though, I am always on the hunt for tools and am working on some of my own as well.

If I could change one thing, it would be replacing the Arduino with a standalone AVR. I just didn’t have the time for that as I am working on a lot of other projects – which is also why I got delayed in posting this one. But look out for lots of wireless technology, flying machines, robots, and mobile apps, all coming your way very soon!

All in all, I couldn’t have asked for a better result, thanks to the people below.

References

As always, this project could never have been possible without lots of support and inspiration. Thank you!

Resources for Download

Posted in Projects, Tutorials
14 comments on “Capacitive Touch Sensing Game Controller & Processing Game
  1. Adam says:

    Simple + Amazing = simply amazing
    Keep doing simple and amazing things mate
    All the best

  2. Adam says:

    got 66 from the first try

  3. Jason Knight says:

    Just a little advice, avoid checking conditions you already know the state of and running if statements when you may have already handled the value… that’s else’s job. Likewise, don’t go banging ports should an invalid value get through.

    if ((pinToMeasure<8) {
    port = &PORTD;
    ddr = &DDRD;
    bitmask = 1 << pinToMeasure;
    pin = &PIND;
    } else if (pinToMeasure<14) {
    port = &PORTB;
    ddr = &DDRB;
    bitmask = 1 << (pinToMeasure - 8);
    pin = &PINB;
    } else if (pinToMeasure<20) {
    port = &PORTC;
    ddr = &DDRC;
    bitmask = 1 << (pinToMeasure - 13);
    pin = &PINC;
    } else return 0;

    Programming 101 – Think about it, if you handle 0..7, you know it's not higher so don't run the IF statements for higher values… so on and so forth. You then don't have to check for greater than — one less compare per if, not doing extra IF's when not needed! If it's not inside any of your valid ranges, bomb out before you go shoving values at the ports.

    I know it's probably a minor improvement at best, but it is less code and would run faster…

    Array lookups, while consuming a bit more RAM, may also be a faster approach.

    Also, if you know you're only testing for 50 or greater, why are you looping to 16000? Not sure I get the point of that.

    for (int cycles=0; cycles<51; cycles++) {
    if (*pin & bitmask) break;
    }

    Makes more sense, doesn't it?!? Once you hit the long charge, you're done and can kill it.

    Also, I'd consider making it return boolean, that way you're not doing an excess compare in the key logic.

    I'm probably gonna try this myself within the coming weeks — Question, what's the latency like on this; just what is the shortest reliable time I'd be able to read say… 12 buttons?

    • Great comment and questions, exactly the kind of thing I was hoping for. I’ll try my best to address each one to the best of my knowledge:

      1. if Statements – You are absolutely right, I can’t believe I let that slip. Although the way I have it should work fine, your suggestion definitely helps make it more bulletproof. I also really like shortening code. Will certainly implement this change.

      2. Number of Cycles – You are right, 16000 is high, and I will change that as well. I think 50 is too low for number of cycles though. The reason a higher number is used than one which I am testing for is for debugging the project. Sure, I found the optimal value of 50 for my purposes, but someone else using this code may be using a 2 Mega Ohm resistor, and the value would need to be higher. In that case, if they want to find out how many cycles it takes for the sensor to get pulled up, and I leave the code at 50, it may become confusing. Once again, yes, 16000 is high, but I think it would be wise to keep it higher than the bare minimum limit that worked for me. I will do some more testing, and check what a better number of cycles should be.

      3. Returning a Boolean – I’m not too keen on returning a boolean value. This is pretty much due to the same reason as the one given above. I like to print the exact values I am getting to the terminal. A true or false value won’t give me enough information. Of course, I could set a flag or something to indicate when I am in ‘debug’ mode so that it prints a value, but it would just complicate the code for anyone taking a fresh look at it since I am putting it on my blog – at the expense of the speed of the code.

      4. Latency – Forgive me for misunderstanding, but are you asking what the latency would be if you were trying to read 12 buttons at once? This can only read one button at a time. But for me, with the 1 Mega Ohm resistor, it takes an absolute minimum of 35 cycles for it to register a ‘button press’. Out of curiosity, how would I find out what that equates to in time? Do you know what the default clock settings would be on my Arduino’s ATmega328? I also noticed that depending on how closely the buttons are placed together, the capacitance of the surrounding buttons does change when you press one (albeit very slightly, but this is certainly not an unexpected phenomenon).

      Thanks Jason, I will have an updated version of the code posted based on your suggestions once you confirm that my rationale is correct/incorrect (or after a few days). Please let me know if you any more suggestions/questions.

  4. Jason Knight says:

    I agree that the limit should be reasonably high — but should an input fail to respond it shouldn’t go off to never-never land every ‘frame’.

    For boolean response, I’d just add a parameter ‘returnBoolean’ that returns 0 if it’s below the threshold (which works like false) or the cycle count.

    if (returnBoolean && (cycles<maxCycles)) return 0;
    return cycles;

    I was thinking on the mapping and calling the pins by their arduino numbers — wouldn't it be easier to simply use the AVR mapping? Then you could use an "& 0xF8" to determine the port and a & 0×07 to get the bitmask shift… the former would then let one use switch instead of IF (faster for multiple values). You want to feed it the arduino pin numbers, that's what define's and/or constants are for …and unlike most other dev's right now, I don't have paranoid delusions about #define being 'evil'. On that note, you have a variable in place for the cutoff, but you don't use it? I'm throwing a lot more things into #define so that you can set 'em and forget 'em.

    I'm working up a rewrite of your code 'my way' — arduino style for now, though when I go to use it it'll be on a teensy++ — I've got no way to test this right now since all my existing AVR's are in other projects, but I've got a new batch on the way.

    My latency question… I think you misunderstood. I know you can't read them simultaneously, but I just need to know how long it takes to read them all end-to-end, or even simpler how many times I can read them over a second. Realistically for what I'd like to do with one of these I'd need to be able to read all 12 of my buttons in under 30ms — aka 33.33~ times a second. I see you are only testing 10 times a second (with a .. questionable method, I'd be worried about that missing due to timer granularity issues) — just need to know how fast it can be pushed. realistically I may need around 60 or more times a second capable, just so I have time left over for everything else. I'll likely just figure that out on my own once I have a version up and running… though since I'll be using a teensy++ with it's AT90USB1286 I'll have to make a different version of the software to deal with the different port mappings… most 328's are the same 16mhz though so performance should be the same. (though the new Arduino Leonardo's use the same AT32 as the regular Teensy)

    I imagine I can also change the time it takes by playing with the pullup resistor values… as you noted, different resistance == different charge times. I may put a POT in for testing so as to figure out what resistance I should be using for all of them.

    Here's where I'm at with a rewrite — I know it at least compiles. Gonna be fun to do that all over again for the teensy++'s extra dozen and a half digital pins once I've got hardware in hand for testing.

    http://www.deathshadow.com/wip/capSensor/touch.c.html

    • Hey Jason!

      Really sorry, I forgot to reply.

      Well, I wasn’t aware of AVR pin mappings back then, but now I am. I also misunderstood latency, but now I get it. I see how all your points make a lot of sense now! Thanks for those excellent suggestions.

      Though I can’t seem to find your cap sense project on your blog. Did you go through with it?

  5. Burner says:

    I am new to arduino, I have opened, and verified the sketch- and all is well. I then uploaded it to my Uno r3 board.

    My first question is: How do I run the game sketch? I get errors when I try to verify it.

    My second question is: How can I use this setup to run other games? i.e; NES roms etc

    Any advice will be appreciated

    • Hi Burner,

      Q1: The game sketch? Do you mean the file for the actual video game? If so, are you sure you are not just copy and pasting the code into the IDE and trying to run it? What you should be doing is downloading the appropriate folder with all the resources you need already inside it (scroll down to the bottom of this post to “Resources for Download”). Try running the game in Processing. It should work fine.

      Q2: Do you mean the hardware setup? Well this is a totally different question. It depends what you are running your NES roms on. I’ll assume it’s a computer. Well, in that case, what you need is a HID (Human Interface Device). You could convert the RS232 signals from the Arduino to HID with some additional hardware, or reflash it with some custom firmware (which is probably easier, check out http://mitchtech.net/arduino-usb-hid-keyboard/ as an example). Then your NES emulator will recognize your arduino as a ‘joystick’, and you are good to go.

      I hope that answers your questions, let me know if you have any others.

      Thanks for visiting!

  6. vikram says:

    hi how to run that game using arduino

    • Treehouse Projects says:

      Do you mean the game controller code, or the actual video game? The controller code can be run by pasting it into the Arduino IDE, and the game code can be run by pasting it into the Processing IDE. If I recall correctly, you can also paste Processing code in the Arduino IDE, and it should work as well. I hope I answered your question, Vikram.

  7. vikram says:

    ya but i pasted the game code in Arduino IDE it is shows error “expected constructor, destructor, or type conversion before ‘jellyfish array’”

  8. vikram says:

    hey i’m running the game in processing it is running well with mouse and in Arduino IDE i’m running the controller program how to integrate with the game?
    thanks for previous idea

    • Treehouse Projects says:

      Oh, you do not need to run the Arduino and Processing IDEs separately to integrate the two. See, the Processing IDE is capable of reading from the serial port (among many other things). You just use the Arduino IDE to flash the controller code to the Arduino, and then launch the game in processing. If you did everything right, it should work right away. I do think that you may need to adjust some parameters in your controller’s code in order to compensate for various differences your hardware may have in terms of levels of capacitance.

      Thanks, sorry about the late reply. Let me know if you need more help.


Leave a Reply

Your email address will not be published. Required fields are marked *

12 Pings/Trackbacks for "Capacitive Touch Sensing Game Controller & Processing Game"
  1. [...] use of the Arduino CapSense library of late, so it was only a matter of time before we posted a capacitive sensing game controller that is able to move sprites around a [...]

  2. [...] you are interested in creating your own capacitive device, Treehouse Projects has detailed the entire procedure, from parts to process, and even outlined the coding of the fantastically silly jellyfish-netting [...]