Pseudo capacitive touch interface

Was building a prototype for an electronic instrument (highland bagpipe chanter). I wanted to implement a simple touch interface using a micro controller (Arduino) and minimum of parts:

The simplest interface I could think of was a resistive touch interface where the users touch creates electrical connection between two metallic electrodes. You can implement this by connecting a large value resistor between the supply voltage (HIGH) and an I/O pin. When the I/O pin is not touched the resistor will pull the pin to HIGH. When the user places a finger between GND and the I/O pin it will read as LOW:

Wanting to go even simpler and wanting to be able to adjust the sensitivity (depends on resistor value) I ended up leaving out the resistor altogether. Most micro controllers has internal pull-up resistors that may be turned on by software. Unfortunately these are usually too small to be used for this purpose. Almost all micro controllers does have a small amount of internal capacitance between their I/O pins and GND so I opted to use this for sensing:

When an typical I/O pin is set as OUTPUT and driven HIGH the internal capacitor is charged to the supply voltage. Shortly after switching the pin back to INPUT this charge will remain on the pin which will read as HIGH. If some kind of connection is present between the I/O pin and GND this charge will eventually drain away and the pin will read LOW. By varying the time before the pin is read after the switch the sensitivity to touch can be controlled by software rather than a physical resistor.  Since I was implementing a flute like interface I was only interested to measure which one in a row of electrodes that was not touched The following Arduino code return which on the pins 2 through 9 is NOT touched or if ALL is touched:

Note when a pin is not being scanned it is written LOW thus providing a GND path for the other pins.

Code as text:

unsigned char scan()
 unsigned char r = LOW;
 unsigned char i;
 for (i = 9; i > 1; i--)
 pinMode(i, OUTPUT);
 digitalWrite(i, HIGH);
 pinMode(i, INPUT);
 digitalWrite(i, LOW);
 delayMicroseconds(1000); //Sensitivity
 r = digitalRead(i);
 pinMode(i, OUTPUT);
 digitalWrite(i, LOW);
 if (r == HIGH)
 return i;


Leave a Reply