Capacitive sensing
Today we were learning about different kinds of sensors. You can take a look at some of them in the Tom Igoe»s Sensor Workshop webpage at ITP.
At the end of the class we were learning how to do a home-made capacitive sensor using some Aluminium foil, and here I put some pictures and code of what we were doing.
Materials:
Aluminium foil
1-10M resistor
Notes:
Use short cable (see code comments).
Play with several number of resistors (see code comments).
PD:
At the beginning we had some problems reading the values from the aluminium foil. Sometimes when we touched the sensor, it didn»t send anything to the Arduino. Then we put more resistors, as you can see in the picture, and everything worked fine.
Code:
AVR port-manipulation code from a forum post by ARP
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1169088394/0#0
/*
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;
int sensorPin = 11;
float accum, fout; // these are variables for a simple low-pass (smoothing) filter
float fval = .2; // fval of 1 = no filter - .0001 = max filter
void setup() {
Serial.begin(9600);
// Arduino pin sensorPin input, sensorPin-1 output, sensorPin+1 output for "guard pin" (optional)
pinMode(sensorPin - 1, OUTPUT); // output pin
pinMode(sensorPin, INPUT); // input pin
pinMode(sensorPin + 1, OUTPUT); // guard pin used to shield high impedance input
digitalWrite(sensorPin + 1, LOW); // guard pin low
}
void loop() {
y = 0; // clear out variables
x = 0;
for (i=0; i < 4 ; i++ ){ // do it four times to build up an average
// not really necessary but takes out some jitter
// LOW-to-HIGH transition
digitalWrite(sensorPin - 1, HIGH);
while (digitalRead(sensorPin) != HIGH) {
x++;
}
delay(1);
// HIGH-to-LOW transition
digitalWrite(sensorPin - 1, LOW);
while(digitalRead(sensorPin) != LOW ) {
y++;
}
delay(1);
}
// Easy smoothing filter "fval" determines amount of new data in fout
fout = (fval * (float)x) + ((1-fval) * accum);
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
}