## Critique my touch sensor code please!

10 posts / 0 new
Author
Message

Hi - I'm trying to develop a touch sensor algorithm. I've tried two techniques and, unfortunately, am getting very similar results. I'm getting a couple ADC count change, typically.

I'm trying two separate algorithms:

1. Charge up touch capacitor (ie your finger), then connect that to discharged capacitor. Voltage in discharged capacitor tells me how large the finger capacitance was (the larger the voltage, the larger the touch capacitance).

2. Discharge touch capacitor. Allow it to charge through a pull up for a set amount of time, then read voltage across touch capacitor. The lower the voltage, the larger the touch capacitance.

I have a preprocessor statement switching between the two methods (1 = "CapacitorDivider", 2 = "TimeConstant"). I have a timer running this code 100x per second. I average the resulting values and report them once per second.

Dev platform is an ATMEGA88 on an STK500. I have copper foil with wires soldered to it that are on a piece of plexiglass 0.6mm thick. The area of the foil is maybe 20mm^2. The wire between the foil and the STK500 is maybe 15cm long. So yes, in a better environment I'd have less extra capacitance and get better performance - but still - I had hoped for much better results.

Both methods work... but I'm getting very little resolution. Any suggestions as to how to improve these?

Thanks!

```ISR(TIMER1_COMPA_vect)
{
unsigned int CapValue;
#ifdef CapacitorDivider
//External capacitor connected to PC0. Sense capacitor connected between PB0 and PC0.

//Set both PB0 and PC0 as low outputs to discharge both sense and external capacitor
//sendchar('1');
DDRB |=  1<<PB0; //DDRB.PB0 = 1
DDRC |= 1<<PC0; //DDRC.PC0 = 1
PORTB &= ~(1<<PB0); //PORTB.PB0 = 0
PORTC &= ~(1<<PC0); //PORTC.PC0 = 0

//Make PB0 input to float bottom of capacitor
DDRB &= ~(1<<PB0); //DDRB.PB0 = 0

//Make PC0 high output to charge external capacitor
PORTC |= 1<<PC0; //PORTC.PC0 = 1

//Set PC0 to be input with pull-up (no charge should flow)
DDRC &= ~(1<<PC0); //DDRC.PC0 = 0

//Set PC0 to be input without pull-up, ADC can now be used
PORTC &= ~(1<<PC0); //PORTC.PC0 = 0

//Set PB0 to be low output, causing voltage across capacitors to equalize, with the greater the capacitance on the touch electrode causing a larger voltage at the ADC
DDRB |= 1<<PB0; //DDRB.PB0 = 1

#endif

#ifdef TimeConstant
//External capacitor connected to PC1, external pull up resistor connected to PC1.

//Set PC1 to be low output to discharge external capacitor
DDRC |= 1<<PC1;
PORTB &= ~(1<<PC1);

//Float PC1 to allow external capacitor to charge through pullup resistor
DDRC &= ~(1<<PC1);

//wait for some amount of time - this should be played with to get good results
//unsigned int BeginningTimerValue = TCNT1;
//while (TCNT1 < BeginningTimerValue + 1) ;

#endif

TouchValue += CapValue;
TouchCount++;
if (TouchCount >= 100)
{
printf("i\r", TouchValue/100); //should be percentsymbol i, but apparently that makes AVRFreaks barf
TouchCount = 0;
TouchValue = 0;
}
}

```

Nobody?

Are you trying to track movement on the touch sensor or is it a simple on/off device? EDIT: ok 20 mm2, I assume it's not for tracking movement :)

When you say low resolution, do you mean low signal?

/Jakob Selbing

any reason not to use Atmels touch library?

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Low sensitivity is not a code flaw.
You should give a try changing sensor design the way sensor electrode shall be used as discharge terminal for reference capacitor.
"Touch sensitive switch" at PROJECTS contains a nice explanation.

jaksel wrote:
Are you trying to track movement on the touch sensor or is it a simple on/off device? EDIT: ok 20 mm2, I assume it's not for tracking movement :)

When you say low resolution, do you mean low signal?

I don't want to track movement - but I do want more than an on/off signal. I'd like as much resolution from the signal as possible - so that it can be used not just for touch, but proximity sensing.

glitch wrote:
any reason not to use Atmels touch library?

I tend to shy away from libraries - I always feel like I spend more time getting them to compile than they save me.

Is their method different from mine?

Kas wrote:
Low sensitivity is not a code flaw.
You should give a try changing sensor design the way sensor electrode shall be used as discharge terminal for reference capacitor.
"Touch sensitive switch" at PROJECTS contains a nice explanation.

Looks like you're referring to this project: https://www.avrfreaks.net/index.p...

He's going about it the same as my second method, I think. He also reports sketchy results. So I'm glad I'm not alone!

I had tried touch sensor implementation in regular TTL that worked quite well.
The idea is to feed two XOR inputs with square pulses. One input is fed directly, the other via resistor and diode in parallel. The later gate input serves as touch sensor. Without leakage capacitance (i.e no touch) both inputs are synchronous, and output is steady level.
When the sensor is touched signal front on the sensing input exhibits lower slew rate. Due to threshold nature of sensing logic levels, output exhibits short spikes. These are easily processed later.
IIRC this worked on CMOS as well. Diode is needed for reliable discharge in advance of a new period.
Sorry for misleading with that reference to the project. Found yet another:
http://www.artem.ru/cgi-bin/news?c=v&id=738
Hope diagram and code would do; eventually could translate into a short summary if needed. This set up just measures charge time of RC(sensor) chain.
BTW Ledsee Electronics have el cheapo double touch sensor IC for this. Maybe an option, though.

respek!