Touch switch

Hey guys,

I've got a resistive touch switch working in my project, but I've got a question....

Why doesn't it work as well with a pull up resistor, as with a pull down?

I've been told that the usual method of connecting switches to the Arduino is to use a pull up resistor, and that using a pull down wastes electricity, is less immune to noise, and has more potential for damage if mistakes in the wiring are made:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1276283661/10#10

Because of this, I decided to try reversing the wiring on my resisitve touch switch. But doing so doesn't work!

Here's how I've got it wired up now:

Pin -> Touch Wire 1 -> 12M Resistor -> Gnd
Touch Wire 2 > 5v

Placing my finger across touch wires 1 and 2 completes the connection to +5v, and the led on pin 13 lights up.

If I try the reverse however:

Pin -> Touch Wire 1 -> 12M Resistor -> +5v
Touch Wire 2 > Gnd

The led stays lit, as it should because the pin is being pulled high, but placing my finger across the touch wires does nothing, unless I press really hard, then the led dims very slightly.

It should be noted that for testing here, I am using the button example. I believe that the 10K pullup on pin 2 is therefore not enabled. The code doesn't explicity enable or disable it anyway, and I think pins are low by default, so it should be off when the pin is set to input mode.

I believe that the 10K pullup on pin 2 is therefore not enabled.

What 10K pull up is this? If it is the internal pull ups those are closer to 50K.

There are lots of things that could be happening:-
However my guess is the different thresholds in going from a zero to a one to a zero. This chip wasn't designed with this application in mind and the hysteresis on an input pin is not defined. It looks like the distance between +Vcc and the zero threshold is smaller than the distance between 0V and the logic one threshold.

This chip? Do you mean the chip in that other thread? I'm not using that here. I was just referencing what you said about how switches should be used.

Does that chip have 50K pullups then? I haven't looked into that.

My switch here is connected to pin 2 on the Arduino Pro Mini.

And according to this page the pull ups on that are 20K:

So I was wrong about them being 10K, but that's neither here nor there, because as far as I know, they're not enabled.

Does that help make it any clearer what might be going on?

Okay I just did some more tests.

When switching to ground, and pulling pin 2 high via the 12M resistor:

  1. With pin 2's internal pullup turned off, a lot of pressure must be applied to the touch switches to make the led turn off.

  2. With pin 2's internal pullup turned on, no amount of pressure will make the led turn off.

This seems to imply that there is too much resistance across the touch pads, or that there is too little resistance on the pullup. (I assume that turning on the internal pullup reduces the pullup resistance from around 12M ohms to around 20K.)

When switching to Vcc, and pulling pin 2 low via the 12M resistor:

  1. With pin 2's internal pullup off, the barest touch of the touch pad lights the LED fairly bright, but it lights even more brightly if I press hard.

This implies that the resistance across the touch switches is still too great relative to the resistance to ground. So perhaps I should use a a resistor even greater than 12M, though every example of a touch switch I've found reccomends a resistor around that value. I've read human skin can have resistances up to 50M though, so perhaps that would be a better value to use. I am not sure how high I can go though before effectively I cut off the ground signal and the pin floats and does weird things, like act as a capacitance switch.

  1. Enabling pin 2's internal pullup causes the led to light, and once again the touch switch stops working. This makes sense because I've got 12M between the pin and ground, and 20K between the pin and Vcc. So it should go on and stay on. And touching the switch would of course do nothing since that would only serve to pull it even higher.

So... based on all that:

It would seem that if I want the switch to pull down, 12M will work, but it's probably turning on and off rapidly, and 50M would likely be better.

As for pulling up... I don't know why, but it seems that even 50M would not be nearly enough to make it work well, given it barely works as 12M.

[edit]

Another test reveals that with the pull down setup that works the best, a damp finger works even better, which was expected. The LED lights very brightly with a light touch of a damp finger.

And according to this page the pull ups on that are 20K:

Yes well it is wrong, or at least a gross over simplification. The data sheet says the pull up resistor has a maximum value of 50K and a minimum value of 20K.

I was just referencing what you said about how switches should be used.

What I said applies to switches doing a standard job. What you are doing here is using digital inputs in a manor that they are not meant to be used. This is a digital input it is not designed for measuring high resistance values

I've read human skin can have resistances up to 50M

There is no limit, it depends on how dry the skin is.

so perhaps that would be a better value to use

Well no not really. A 12M resistor is a stupidly high value to use, the resistance from a fingerprint would be about the same value. If you use the internal pull up resistors then 30K (about) is going to dominate anything you can do with fingers and skin resistance.

he LED lights very brightly with a light touch of a damp finger.

That implies you are getting pickup and injecting noise into the system normally and the LED is flashing rapidly thus making it dim.
For this sort of application you want to be using something like a 4584 Hex schmitt trigger rather than going directly onto the input pins.

This is a digital input it is not designed for measuring high resistance values.

Would I have better luck using an analog input?

Well no not really. A 12M resistor is a stupidly high value to use

Every page I've found on the web which deals with resistive touch switch circuits uses values in the millions of ohms. Admittedly, I don't think they deal with reading the state using a microcontroller.

the resistance from a fingerprint would be about the same value. If you use the internal pull up resistors then 30K (about) is going to dominate anything you can do with fingers and skin resistance.

So are you saying I should turn on the internal pullups, and swap my resistor out for a 30K one? I guess I can try that.

That implies you are getting pickup and injecting noise into the system normally and the LED is flashing rapidly thus making it dim.
For this sort of application you want to be using something like a 4584 Hex schmitt trigger rather than going directly onto the input pins.

I have no idea what a schmitt trigger is, but I'll look into that. Are you sure there's no way to do this reliably with, say the analog pins instead though? Or is the reason this won't work the same reason using pots over 20K isn't recoomended?

I just tried turning on the internal pullup and switching to ground both directly, and via a 51K resistor. Didn't have any 30Ks on hand.

LED remained solidly lit with both setups, presumably because finger resistance was greater than pullup resistance.

[edit]

Is there anything I can use besides a schmitt trigger? They don't seem to be widely available... there's only one 4854 in a DIP-14 package on both Mouser and Digikey. And I don't really have space on this board for yet another IC.

(Searching now to see if there's any other schmitt triggers in other packages.)

I can't find a schmitt trigger in a smaller package, but I wonder... if the real issue here is just that the signal is noisy, can I just read the noisy signal an analog input and denoise it in software, either with a simple threshold, or some kind of averaging algorithm?

Hm... I was hoping if I couldn't get the resistive touch sensing working that I could go with capacitive, but I just found a thread about that where someone was asking how to implement it on a musical instrument, and apparently you can't place those sensors too close together. And these ones need to be right next to eachother.

I'm fairly confident I can get these resistive switches working reliably with the analog inputs though. I mean it's clear the input is noisy from the way the led was behaving, but when there was no finger on there it wasn't lit at all. So there's a pretty big margin there.

As for whether this might introduce noise elsewhere in my circuit, I don't know. But I'll be prototyping the whole thing on a breadboard and putting capacitors on there for reducing noise because I'm gonna have noisy servos in the circuit, so... I think I should be okay.

I guess the next step is figuring out how to output debug data over the serial connection so I can see exactly what values I'm getting off the analog port.

Yes measuring skin resistance would probably be better with the analogue port.

Is there anything I can use besides a schmitt trigger? They don't seem to be widely available

A shimitt trigger input is a standard way of reading a slow edge.

Schmitt trigger - Wikipedia

There are many ways to implement a schimitt trigger rather than relying on an IC input having them.
As skin resistance will be in the order of 100K to 1M then that is the sort of value you should use, question anything you see with values above 4M7. The internal pullups should not be used as they are too small for the very small currents involved.

I could go with capacitive, but I just found..... you can't place those sensors too close together.

That is true they interfere with each other. Also as you don't actually have to touch a capacitive switch to trigger it it can be a difficulty. I am looking now at the touch panel from a set top box and the sensors are 1cm square of PCP spaced 4mm apart. This uses a AD7147 sensor chip.
You can try small capacitors 1nF or so to cut the noise, most of which will be 50 or 60Hz (depending on what country you are in).

figuring out how to output debug data over the serial connection

Just use print statements.

I just got done running some new tests using the serial monitor and the analog pins.

This time, I tried two touch switches, next to eachother, with one side attached to Vcc, and the other to analog pins 0 and 1, with the pins grounded via 10M ohm resistors.

While this setup seemed to work okay with one touch switch, giving me values of less than 47 when the switch wasn't being tocuhed, and with two switches it does the same, as soon as I touch either of the switches, their values jump up to several hundred, and if I hold my finger on a switch, the two switches will seem to oscillate back and forth, with one dropping in value while the other increases, and vice versa.

I tried using delays of up to 20ms between taking the two analog readings, and 500 between readings of both switches, but this didn't seem to help.

I will now try using smaller resistors as you mentioned, and see if that helps, though based on the behavior the led in yesterday's tests, I suspect the smaller resistors may make things worse.

If this doesn't work, it looks like I'm going to have to figure out how to make a schmitt trigger or make room on the board for another DIP-16 IC.

Okay, I had some 100K resistors on hand, so I tested those out. They seem to work better. The values I'm getting are around 50 with dry skin, and 500 with wet skin, so I may be looking at using resistors which are 200K-1M.

When not touching a contact, even if the other is being touched, the value pretty much stays pegged at zero. I think it rose to 7 once when I was presisng down hard.

I'm not sure if the problems will return with the higher values, but I guess I'll find out once I test it.

[edit]

Tested 200K. Touching left switch had more effect on right switch reading tham before, and tocuhing it with a wet finger didn't cause the reading to jump to 1000 like I expected I would get by doubling the resistance.

Guess I'll have to grab some 1M resistors and see how those fare.

as soon as I touch either of the switches, their values jump up to several hundred,

This will happen if the input impedance is too high, essentially inside the arduino there is only one A/D converter and the inputs are simply switched. With a high input impedance the input capacitor on the A/D can't discharge quickly enough to the new value.

You could try:-
read sensor 1
delay
read sensor 1 again, that is throw away the first reading
read sensor 2
delay
read sensor 2 // throw away the first reading

This switches to the new channel and then the delay allows it to charge. Simply putting delays in between the readings is not going to work because the input multiplexer only switches when you ask for a reading.

I'll give it a try!

Adding a delay seems to work! May need to tweak the values.

I used a delay of 20ms.

With 100K resistance:
When not touching the leads the value stays pegged at 0 most of the itme, rising only as high as 1 when the other leads are touched.

A light touch with a dry finger gives between 4-20.
A hard press gives between 15-35.

With 3M resistance:
When not touching the leads, the value hovers around 0, oscillating a bit, up to as high as 6.

I get 40-200 when barely touching it with a dry finger,
100-300 when applying a normal amount of pressure,
500 when pressing hard,
and over 900 with a light touch and a wet finger.

Increasing the delay to 40ms had no effect on the 100K, but on the 3M:
I get less oscillation, but it still goes as high as 5 or 6 when just sitting there. When touching the other switch the off state can go as hgh as 6.

With a light touch, I got a reading as low as 37, but 99% of the readings are over 100 and as high as 300.

Double checking against the delay of 20, I don't really see a difference between the two.
Dropping the delay to 10, I see a marked increase in noise when the switches aren't being touched. Though the values still don't rise above 6. They just are above 0 a lot more often.
Double checking the noise I get with 20ms, I see I'm getting an oscillation back and forth between the two pins. One stays at 0 while the other rises to 6 and drops again.
Double chekcing 40ms, The oscillations go away, but are replaced by more random noise.
Lastly, with 200K and 40ms, there's almost no noise when not touching the pads, and when touching the pads with dry fingers, there's a little noise on the one not being touched and I get values from like 30 to 50 on the pad being touched.

Don't have 500K or 1M resistors to test with, but I think the sweet spot will be around there.

So... this might just work. I think I'll set up the code to behave like the schmitt trigger, turning on when I get a reading greater than a certain value, and off when I get a reading less than a certain value, so there's that buffer zone which will serve to debounce my input.

Either that, or I'll average the input over time. Or collect X number of inputs and take the median. Averaging will probalby be sufficient and easier though.

I gotta take a closer look at the input, I was only reading it once every half a second in these tests, so the ouytlying values might not happen often.

Thanks for the help! :slight_smile:

scswift

In your initial post, you suggest that you have one input being held down with a 12M resistor, and the other is supplying 5v.
The system seemed to work, but when you swopped it around you had problems.

I suspect rather than have current flowing from the 5v through your skin, into the other pin, you were getting stray voltages picked up by the body, and being transferred into the pin.

You could confirm this by removing the 5v, and seeing if it still works.

I'm curious of the outcome, because I have a project coming up, where I was going to use the capacitive sensing to replace some toggle switches that keep failing.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1248200489 This one seems to work with multiple switches.

Mark

I'd like to test that out for ya Mark, but I took the circuit apart a few days ago and right now my breadboards are a massive jumble of wires as I build the complete circuit.

Once I get that all put together though, I'll see about trying the capacitance thing.

In regards to the touch switches, I can report that the 1M resistors I'm now using are working great! There is next to no noise. I might get values up to 2 on the switch that isn't being touched and the one which is being touched no matter how lightly reads at least 20, but more often in the range of 100-200, and 300 if I press hard.

The above is with a dry finger. With a wet finger it jumps to 900, though you can see it drop as the finger dries off.

Thanks for the update.

Great that you have a working solution.

The other thought I had for this project was the IR sensors, that work at a few millimetres...I know they work for reflective surfaces, but haven't tried them by using a finger.

Please keep me posted of PM me, I'm very keen. :slight_smile:

Mark