Newbie question on Multiple Switches using single Input

Andrei IRL

Senior Member
Hi guys. Could do with a bit of help on this.
Im in need to control second transistor on my project that is based around 08M2 chip. Unfortunately i have ran out of I/O pins.
Currently i have two push buttons, i read somewhere that it is possible to read them using single pin via readadc.
I need to be able to read when either button is press as well as when both are pressed.
Would any one have time to explain how i go about it please. And how the buttons would be connected to a single pin?
I get the idea but i have sat down twice to draw the diagram and just cant work it out. The code i think should be easy enough to adjust.
Thanks very much in advance.
 

Andrei IRL

Senior Member
You use resistors of varying values to create voltage divders and then use readADC to determine which button was pressed. Here's an example:

http://www.reuk.co.uk/wordpress/wp-content/uploads/2013/05/multiple-switches-on-one-input.jpg

Each button will give a different ADC value. Holding two buttons down will give yet another value.
Thats exactly what i was looking for.
Thanks very much for that Hemi, i appreciate it.
Another question, would any one know if readADC command might play a large part if my code is time sensitive, i mean i need for the code to be running as fast as possible through the routine. Would readADC slow it down any more then any other regular command?
 

AllyCat

Senior Member
Hi,

AFAIK READADC takes about 1 ms, quite similar to many/most PICaxe instructions (with a 4 MHz clock).

Of course the multiple IFs (or SELECT ... CASE, etc.) will take longer than a single "test pin" command. Perhaps use a READADC into b0 and then you might use IF bit7 .... , etc. to be the fastest.

Cheers, Alan.
 

Andrei IRL

Senior Member
Hi,

AFAIK READADC takes about 1 ms, quite similar to many/most PICaxe instructions (with a 4 MHz clock).

Of course the multiple IFs (or SELECT ... CASE, etc.) will take longer than a single "test pin" command. Perhaps use a READADC into b0 and then you might use IF bit7 .... , etc. to be the fastest.

Cheers, Alan.
Hi Alan. Would you care to explain in more detail if you don't mind please how that routine would work? I haven't created many programs yet.
Thanks very much.
 
Last edited:

AllyCat

Senior Member
Hi,

First you need to decide on a suiatble hardware configuration. Let's assume that you have a 1k resitor from the ADC input to ground (0v), one switch connects a resistor of 10k from the supply rail to the ADC pin and the other switch connects 22k between supply and ADC pin. With no switch closed the ADC should read zero (or close to it).

If we operate the "10k" switch then the READADC should "see" about 255 * 1k / (10k + 1k) which equals about 23. Operating only the other switch should read 255 * 1k / (22k + 1k) = 11 and both operated should give about 34. The "thresholds" between these values would be about 0 + 11 / 2 (= 5) , 11 + 23 / 2 (= 17) and 23 + 34 / 2 (= 28). So you could use code such as:

Code:
READADC pin , w0
IF w0 > 17 THEN
     SERTXD("Switch 1 is Closed",cr,lf)
     w0 = w0 MIN 23 - 23           ;  "MIN" prevents wrapping below zero
ENDIF
IF w0 > 5 THEN
     SERTXD("Switch 2 is Closed",cr,lf)
ENDIF
I'm not sure that it would be much faster, but it might be possible to find suitable resistor values to give direct bit flags. However, for the example above we'd typically need to subtract 5 from w0 (again avoiding an underflow). Then, writing the "expected" values in binary gives:

%0000 0000 (0),
%0000 0110 (6),
%0001 0010 (18) and
%0001 1101 (29).
Then we could use IF bit2 = 1 THEN ... [Switch 2 is closed] and IF bit4 = 1 THEN ... [Switch 1 is closed]. But the "safety margins" (tolerances) are much more critical than the simple decimal number comparisons above.

Cheers, Alan.
 

Andrei IRL

Senior Member
Hi,

First you need to decide on a suiatble hardware configuration. Let's assume that you have a 1k resitor from the ADC input to ground (0v), one switch connects a resistor of 10k from the supply rail to the ADC pin and the other switch connects 22k between supply and ADC pin. With no switch closed the ADC should read zero (or close to it).

If we operate the "10k" switch then the READADC should "see" about 255 * 1k / (10k + 1k) which equals about 23. Operating only the other switch should read 255 * 1k / (22k + 1k) = 11 and both operated should give about 34. The "thresholds" between these values would be about 0 + 11 / 2 (= 5) , 11 + 23 / 2 (= 17) and 23 + 34 / 2 (= 28). So you could use code such as:

Code:
READADC pin , w0
IF w0 > 17 THEN
     SERTXD("Switch 1 is Closed",cr,lf)
     w0 = w0 MIN 23 - 23           ;  "MIN" prevents wrapping below zero
ENDIF
IF w0 > 5 THEN
     SERTXD("Switch 2 is Closed",cr,lf)
ENDIF
I'm not sure that it would be much faster, but it might be possible to find suitable resistor values to give direct bit flags. However, for the example above we'd typically need to subtract 5 from w0 (again avoiding an underflow). Then, writing the "expected" values in binary gives:

%0000 0000 (0),
%0000 0110 (6),
%0001 0010 (18) and
%0001 1101 (29).
Then we could use IF bit2 = 1 THEN ... [Switch 2 is closed] and IF bit4 = 1 THEN ... [Switch 1 is closed]. But the "safety margins" (tolerances) are much more critical than the simple decimal number comparisons above.

Cheers, Alan.
Thanks very much for that. I alleviate you taking the time to explain it to me.
I will try imlement this in my code.
Thanks again.
Andrei.
 

hippy

Technical Support
Staff member
The ideal approach with ADC button detectors is to maximise the difference between button combninations. For two buttons, one approach is to use a 1K pull-down on the ADC pin and 1K pull-up for one button, a 1K+1K (2K) pull-up for the other. ADC readings will then roughly be ..

Open / 1K = 0
2K / 1K = 85
1K / 1K = 128
(1K|2K) / 1K = 160

Then find the mid points ...

0 .. 85 = 42
85 .. 128 = 106
128 .. 160 = 144

Then ...

Code:
ReadAdc BTN_ADC, b0
Select Case b0
  Case > 144 : Gosub BothPushed
  Case > 106 : Gosub OnePushed
  Case > 42  : Gosub TheOtherPushed
  Else       : Gosub NonePushed
End Select
 

Andrei IRL

Senior Member
The ideal approach with ADC button detectors is to maximise the difference between button combninations. For two buttons, one approach is to use a 1K pull-down on the ADC pin and 1K pull-up for one button, a 1K+1K (2K) pull-up for the other. ADC readings will then roughly be ..

Open / 1K = 0
2K / 1K = 85
1K / 1K = 128
(1K|2K) / 1K = 160

Then find the mid points ...

0 .. 85 = 42
85 .. 128 = 106
128 .. 160 = 144

Then ...

Code:
ReadAdc BTN_ADC, b0
Select Case b0
  Case > 144 : Gosub BothPushed
  Case > 106 : Gosub OnePushed
  Case > 42  : Gosub TheOtherPushed
  Else       : Gosub NonePushed
End Select
You are an absolute gentleman hippy.
Thanks very much guys.
You have really no idea how much i appreciate your time.
Andrei.
Ireland.
 
Top