Capsense with Arduino
From Code Lab Wiki
Based on the work done by Paul Badger. Customized Spring of 2008 for use with an arduino with copper wire connected to the sensor port. Sensitivity was adjusted to work through clear heat shrink along an EL wire.
Software shaping and sensing has had calibration and sensitivity issues, dedicated capacitive sensors may be a better alternative moving forward.
/*
CapSense.pde
Paul Badger 2007
Fun with capacitive sensing and some AVR port manipulation code
for the Arduino (or Wiring Boards).
Note that the AVR code is based on Arduino
and will probably require some changes for Wiring Board
How It Works
The physical setup includes a high value (1-10M) resistor
between an output pin and an input pin. When the output pin changes
state, it will eventually change the state of the input pin
in a time constant determined by R * C, where R is the resistor
and C is the capacitance of the pin, plus any other capacitance
(e.g. human body interaction) present at the sensor (input) pin.
It is possible when using this setup to see some variation in
capacitance when one's hand is 3 to 4 inches from the sensors
Experiment with larger resistor values and large sensor plates for
more sensitivity. Lower values of R will probably yield higher reliability.
Use 1 M resistor (or less maybe) for absolute touch to activate.
With a 10 M resistor the sensor will start to respond 1-2 inches away
Setup
Connect a 10M resistor between pins 8 and 9 on the Arduino Board
Connect a small piece of aluminum or copper foil to a short wire as a
sensor and also connect it to pin 9 (the sensor pin). There is nothing
special about pins 8 & 9 and they can be any Arduino digital pins.
When using this technique in an installation or device it's going to be
important to use shielded cable if the wire between the sensor is
more than a few inches long, or it runs by anything that is not supposed
to be sensed.
Calibration may be an issue, and may vary somewhat with humidity or other factors.
Instead of "hard wiring" threshold values - store the "non touched" values
in a variable on startup - and then compare to a "difference" value.
If your sensed object is many feet from the Arduino Board
you're probably going to be better off using the Quantum cap sensors.
AVR port-manipulation code from a forum post by ARP
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1169088394/0#0
*/
int i;
unsigned int x, y;
float accum, fout; // these are variables for a simple low-pass (smoothing) filter
float fval = .07; // fval of 1 = no filter - .0001 = max filter
float lastCount;
int hit = 0;
void setup() {
Serial.begin(9600);
DDRB=B101; // DDR is the pin direction register - governs inputs and outputs- 1's are outputs
// Arduino pin 8 output, pin 9 input, pin 10 output for "guard pin" (this is optional)
// preceding line is equivalent to three lines below
// pinMode(8, OUTPUT); // output pin
// pinMode(9, INPUT); // input pin
// pinMode(10, OUTPUT); // guard pin used to shield high impedance input
digitalWrite(10, LOW); // guard pin low
}
void loop() {
y = 0; // clear out variables
x = 0;
for (i=0; i < 5 ; i++ ){
// LOW-to-HIGH transition
PORTB = PORTB | 1; // Same as line below - but slightly faster
// digitalWrite(8, HIGH);
// output pin is PortB0 (Arduino 8), sensor pin is PortB1 (Arduino 9)
while ((PINB & B10) != B10 ) { // while the sense pin is not high
// while (digitalRead(9) != 1) // same as above port manipulation above - only 20 times slower!
x++;
}
delay(1);
// HIGH-to-LOW transition
PORTB = PORTB & 0xFE; // Same as line below - but slightly faster
//digitalWrite(8, LOW);
while((PINB & B10) != 0 ){ // while pin is not low -- same as below only 20 times faster
// while(digitalRead(9) != 0 ) // same as above port manipulation - only 20 times slower!
y++;
}
delay(1);
}
fout = (fval * (float)x) + ((1-fval) * accum); // Easy smoothing filter "fval" determines amount of new data in fout
accum = fout;
Serial.print((long)x, DEC); // raw data - Low to High
Serial.print( " ");
Serial.print((long)y, DEC); // raw data - High to Low
Serial.print( " ");
Serial.println( (long)fout, DEC); // Smoothed Low to High
if((long)fout > 3){
analogWrite(4,255);
} else {
if((long)fout < 2){
hit++;
if(hit >= 3){
analogWrite(4,0);
hit = 0;
}
}
}
if((millis() - lastCount >= 75) && hit >= 1){
hit = hit - 1;
lastCount = millis();
}
Serial.println("___________________________________");
Serial.print(hit, DEC);
Serial.println("");
}
