The only analog physical quantity that the Arduino can detect, besides accepting digital signals from its digital port, is voltage. The detected value of any analog sensor is almost always converted to a voltage value through the relevant circuitry and fed into its analog port for analog-to-digital conversion. Capacitive values would require relatively more complex and expensive circuitry to convert to voltage values in order to be detected by the Arduino, whereas the detection of many physical processes can be easily and reliably accomplished by detecting capacitive values, with the most common place being touch sensors. The popular MaKey MaKey is an example. Here is a capacitance detection method that does not require any components except a piece of wire and a port.
The idea of this method is to first set a digital port to a low potential and turn on the arduino's internal pull-up resistor to start calculating the time it takes for this port to reach a high potential. And this time is related to the value of this port's capacitance to ground, the higher the capacitance, the longer the time. In hardware it's just a matter of connecting a wire to a port. Touching the bare end of this wire with your finger will cause a change in capacitance, and the arduino can detect this change by the method described above. To increase the sensitivity, you can connect a piece of tin foil to the wire. To prevent strong static electricity on your hand from piercing the chip, you can cover the tin foil with a thin layer of paper.
The code used is below. You can easily use it in your project. After the program is downloaded and run, touch the wire connected to port 8 with your finger to light up the led in port 9, and leave your finger, the led will go out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
int ledPin = 9;
int capval;
void setup()
{ pinMode(ledPin, OUTPUT); Serial.begin(9600); Serial.println( "Touch senser" );
} void loop ()
{ digitalWrite(ledPin,LOW); capval = readCapacitivePin(8); Serial.println(capval, DEC); if (capval > 2) {
// turn LED on: digitalWrite(ledPin, HIGH); delay(10); } } // readCapacitivePin // Input: Arduino pin number // Output: A number, from 0 to 17 expressing // how much capacitance is on the pin // When you touch the pin, or whatever you have // attached to it, the number will get higher #include "pins_arduino.h" // Arduino pre-1.0 needs this uint8_t readCapacitivePin( int pinToMeasure) {
// Variables used to translate from Arduino to AVR pin naming
volatile uint8_t* port;
volatile uint8_t* ddr;
volatile uint8_t* pin;
// Here we translate the input pin number from
// Arduino pin number to the AVR PORT, PIN, DDR,
// and which bit of those registers we care about.
byte bitmask;
port = portOutputRegister(digitalPinToPort(pinToMeasure));
ddr = portModeRegister(digitalPinToPort(pinToMeasure));
bitmask = digitalPinToBitMask(pinToMeasure);
pin = portInputRegister(digitalPinToPort(pinToMeasure));
// Discharge the pin first by setting it low and output
*port &= ~(bitmask);
*ddr |= bitmask;
delay(1);
uint8_t SREG_old = SREG; //back up the AVR Status Register
// Prevent the timer IRQ from disturbing our measurement
noInterrupts();
// Make the pin an input with the internal pull-up on
*ddr &= ~(bitmask);
*port |= bitmask;
// Now see how long the pin to get pulled up. This manual unrolling of the loop
// decreases the number of hardware cycles between each read of the pin,
// thus increasing sensitivity.
uint8_t cycles = 17;
if (*pin & bitmask) { cycles = 0;}
else if (*pin & bitmask) { cycles = 1;}
else if (*pin & bitmask) { cycles = 2;}
else if (*pin & bitmask) { cycles = 3;}
else if (*pin & bitmask) { cycles = 4;}
else if (*pin & bitmask) { cycles = 5;}
else if (*pin & bitmask) { cycles = 6;}
else if (*pin & bitmask) { cycles = 7;}
else if (*pin & bitmask) { cycles = 8;}
else if (*pin & bitmask) { cycles = 9;}
else if (*pin & bitmask) { cycles = 10;}
else if (*pin & bitmask) { cycles = 11;}
else if (*pin & bitmask) { cycles = 12;}
else if (*pin & bitmask) { cycles = 13;}
else if (*pin & bitmask) { cycles = 14;}
else if (*pin & bitmask) { cycles = 15;}
else if (*pin & bitmask) { cycles = 16;}
// End of timing-critical section; turn interrupts back on if they were on before, or leave them off if they were off before
SREG = SREG_old;
// Discharge the pin again by setting it low and output
// It's important to leave the pins low if you want to
// be able to touch more than 1 sensor at a time - if
// the sensor is left pulled high, when you touch
// two sensors, your body will transfer the charge between
// sensors.
*port &= ~(bitmask);
*ddr |= bitmask;
return cycles;
} |
This idea is not original to me, the readCapacitivePin function comes from the following address:
http://playground.arduino.cc/Code/CapacitiveSensor
http://tieba.baidu.com/p/2060482431