A square wave using the tone() function is applied to the input and a pin change interrupt is used to count CHANGE transitions on the output. If the tone is near the cutoff frequency, a small increase in capacitance will move the cutoff frequency lower, causing fewer output transitions.
The code looks like this (not yet made into a library), using the EnableInterrupt library to set up the pin transition interrupts.
// Start sampling
transitionCount = 0;
enableInterrupt(OUTPUT_PIN, countTransitions, CHANGE);
tone(INPUT_PIN, frequency);
delay(SAMPLE_DURATION_MS); // 50ms seems to be plenty
// Stop sampling
noInterrupts();
noTone(INPUT_PIN);
disableInterrupt(OUTPUT_PIN);
interrupts();
There is a global, volatile variable transitionCount which is incremented by the pin change interrupt handler:
void countTransitions() {
++transitionCount;
}
For my purposes, I'm using a threshold of 3% of the expected transitions. That is, I consider it a touch when I get 3% or less of the expected pin change transitions.
Finding the Critical Frequency
So what frequency do we send? I have found that a little under 4KHz works well, but the total capacitance is sensitive to whether the Arduino is connected to a USB cable or not. I've added code to find the right frequency at power-up using this logic:- Set the frequency to 8Khz.
- Send the tone and count transitions. If we have 50% or more of what we expect, stop, and use that frequency for sensing.
- Otherwise, decrement the frequency by 100Hz and go to step 2.
Notes and Further Study
The cutoff frequency for an RC circuit is 1/(2πRC). Since the resistance is 3MΩ, this means that for a cutoff frequency around 4KHz, the total capacitance in the circuit is only about 15pF, some of that coming from the diode. I find it somewhat remarkable that we can measure such a low capacitance with a few lines of Arduino code.According to the Wikipedia page on Body Capacitance, a human being is roughly equivalent to a 100pF capacitor. If so, the filter cutoff frequency will be lowered to well under 1KHz when touching the sense object.
Some things to investigate further:
- Can we drive multiple sensors from a single input line? (That's partly why I left the diode, to reduce ringing from multiple sensors.)
- Can we sense from multiple touch points at the same time? (All outputs would be connected to ground – will they interfere with each other?)
- Can we sense from two overlapping touch points, separated by an insulating layer? (This is one way touch-screens are made: One layer has touch points connected into rows, the other layer has columns. The intersection gives you the (x,y) position.)
- Does this technique work when the Arduino is plugged into a wall wart? (All my testing has been under battery power – that's the configuration I want to use, but I'd like to find out how robust it is with other power sources.)
- How much capacitance does a human add to the circuit? (Just need to find the cutoff frequency while touching the sense object.)
No comments:
Post a Comment