I'm pulling my hair out over this one. I'm using a nucleo for testing, rather than an AVR, hence it's here in general electronics though it is generisable to any controller (but mods, please feel free to move it if I guessed wrong).
Many microcontrollers contain hardware to perform touch sensing, but the ones that don't are cheaper - and therefore alternate methods as worth investigating.
One way in which this sensing can be done is as follows, assuming a sensor with a guard ring around it to improve isolation from environmental effects. The sensor pad acts as a capacitor with a value of a few picofarads. When a conductive object such as a finger moves close to it, its capacitance increases, maximising when the sensor is touched. A collecting capacitor - 100n or so - can be connected to the sensor pad using a fet, and a similar capacitor for the guard ring.
1) start by emptying all the caps. i/o ports in push-pull and set to '0' do this. Thirty or forty microseconds will do this, depending on the output impedance of the port.
2) short deadband delay, to avoid interractions - all i/o ports set three state and the fet turned off.
3) charge the sensor pad and guard ring: a couple of microseconds on a push-pull output.
4) short deadband delay
5) turn on the fet to transfer charge from the sensor to the collection capacitor
6) measure the voltage on the collection capacitor; if it has not reached a trigger voltage then back to (3) and repeat until it does, or you time out.
The trigger voltage *can* be the i/o logic level, but that's a bit noisy; if you have a comparator against a standard voltage available, that's much better. You're counting the number of cycles required to reach the trigger voltage; decreasing numbers indicate a finger is getting closer and a big decrease indicates it's touching. As an example, using the i/o logic as the trigger, the noise between samples is around fifty counts; using an internal comparator and voltage reference, the noise is one or two counts. With this method, I can see a clear indication of a hand approaching the sensor through the thickness of a desk - a count change of perhaps ten or twelve.
This is where the head-scratching starts. With the system idling, I see a continuous sawtooth on the count signal; the period is about ninety-five seconds and the height is a relatively constant 70-72 counts. This is irrespective of how fast the signal is collected (i.e. pauses between sampling from instant to a couple of seconds) and whether the unit is attached to a computer (and therefore mains ground) or completely galvanically isolated using a batteries and fibre optics for communications... This sawtooth makes it impossible to filter the signal to get a clean reference for low level signals (I see a count of about 1700 normally, so the noise is about 2.5%, and I'm hoping to be able to trigger on changes of around five or ten counts - as the hardware controller can do. Actually touching the sensor gets the count down to six or seven hundred, so that bit's easy - but I want to be able to detect approach as well as actual contact.
My head is starting to hurt where I'm scratching it... any thoughts?