Intro: Capacitive Switch for Arduino
This is a simple way to make and use capacitive switches with an Arduino or similar device such as a Raspberry Pi. These switches are touch sensitive, can be any shape or size, and can be mounted on any non-metallic base. This makes them perfect for the project I am working on which is a door handle that can detect a human hand. The Arduino code also has built-in debouncing which works pretty well, although I haven't tested this on any interrupt pins.
The code needed to detect a touch is very simple and could easily be ported to a small 8 pin PIC chip if your Arduino resources are getting scarce. This will reduce the number of digital input pins needed from 3 to 1.
There is, of course, a capacitive sensing page on the Arduino Playground, which uses a slightly different circuit. It can be found here for comparison.
P.S. This is my first instructable so any feedback is welcome.
Step 1: Capacitive Switch Principles
The principle of measuring a capacitor with an Arduino is very well explained here, so I won't go into too much detail (and possibly expose my ignorance). Basically, we turn an output pin on, then measure the amount of time it takes for an input pin to reach a certain voltage. The circuit has a resistor and a capacitor both of which will affect this time - the higher the resistance and capacitance are, the longer it will take for the input to reach the pre-set value.
In my circuit, however, the capacitor is you (or whoever is touching the switch). If you have a multimeter that can measure capacitance try putting two plain wires into the capacitor sockets. You will see that, when you touch both wires the meter will register a decent amount of capacitance. In my case about 60 nano Farads.
I have simplified things a bit as we do not need to know an exact value of the capacitance, we just need to be able to recognise the difference in charge time between a switch that is being touched and a switch that is not. So, I have used a digital input pin to measure the voltage and just counted the number of times a simple loop is executed instead of measuring the time.
Step 2: The Switch
The switch is just something metallic. It could even be a bit of bare wire on the breadboard. For my application I need a switch that will detect a persons hand without them having to press any buttons, so I have used a thin strip of steel shim about 0.05mm thick. The thin gauge of the material makes it very easy to cut with either scissors or a craft knife. To test the switch I glued it onto a thin sheet of plastic (a cut down credit card), then soldered a single-core wire to it for insertion into the breadboard.
I tried, at first, to use some self-adhesive aluminium foil, which would have been even easier to fashion into a useful shape, but I couldn't solder it to a lead. More experimentation needed.
You really can use anything (within reason) as a switch and I will be looking out for interesting ways to make this more versatile.
Step 3: The Circuit and Breadboard
You will need the following:
- 1 1MΩ resistor.
- 1 220Ω resistor.
- A transistor of some sort. I used a BC547 NPN.
- A breadboard and wires.
- An Arduino of some sort.
I have also added an LED and a 220Ω resistor to test the switch. The LED is wired to a digital output pin on the Arduino, so it does not affect the circuit diagram.
Step 4: Arduino Code and Testing
Attached is the code for an Arduino (in .ino and .txt format). I have tested this with an Uno and it works pretty well. I have also written a library which uses direct port manipulation for speed.
The basic principle of the code is this:
- Turn the charge pin on - this will start to charge the input pin.
- Count how many empty loops the Arduino does until the input pin is high.
- Turn the charge pin off.
- Turn the discharge pin on - this will discharge the circuit through the 220Ω resistor.
- Turn the discharge pin off.
I have added some logic to debounce the switch. Basically it waits until the switch has been off for 100ms until it registers a switch. This seems to work pretty well.
You may need to tweak the value of the LOOP_LIMIT in this code. A faster processor or more efficient code (using direct port manipulation perhaps) will probably need a higher value.