I'm working on a control system that will have several relays, a bunch of LEDs and a number of switches.  I was rapidly running out of port pins on a TAP-28 board to handle all the desired I/O.  Possible solutions included adding an I2C port expander such as the Microchip 23018, but this was an additional complexity to the already-expanding project.

key_array_3_-_extra_sm

Reading the switches seemed like the easy place to save some port pins.  The control system needs at least 5 switches but maybe more.  These switches are momentary contact to set various options or to initiate actions, and only one will be pressed at a time.  Borrowing from Graham's idea to use a pot (variable resistor) as a multi-position switch and my post on an idea to use an analog input to read switches and a pot, the answer seemed pretty simple.  Use an analog input and a resistor network to read a series of switches.  I made a prototype with 10 switches but the concept could be greatly expanded.

The schematic is shown below.  Ten resistors form a multi-tap voltage divider between +5V and ground.  I used 440Ω resistors for each of these (actually, I used 2  220Ω resistors in series for each because of the format of my prototype board).  Each switch connects a different tap to an analog input, resulting in a different analog voltage for each switch.  I added an additional resistor to pull the analog value up to +5V when no button is pressed.  Its value is about 100x the value of the other resistors.

key_array_schematic

The resistors add almost nothing to the cost of the switches.  If the switches have leads spaced on 0.1" centers, building a prototype on a piece of perf board is simple.

key_array_2_-_sm

 

The Software

The resistors I used are 5% tolerance.  If the resistors were perfectly matched, the expected values would be 0%, 10%, 20% and so on of the full scale reading.  Because the resistors aren't matched, the actual voltage values that will be measured vary around the expected values.  I used a case-select statement to break the readings into 10 zones.  The listing below is in Swordfish Basic - converting to other languages should be straight forward.

Keypad Test (Swordfish PICBasic)
'keypad test
 Device = 18f25k20

Clock = 20
 
Include "USART.bas"
Include "convert.bas"
Include "ADC.bas"
Include "math.bas"
 
Dim ADVal As Word
Dim ADVal1 As Word
 
Dim Button As Integer
Dim ButtonWas As Integer
 
Function ADInAsmVolt() As Word
result = (ADC.Read(1) + 1) * 5000 / 1024
End Function
 
ADCON1 = %10000000
ADCON0.7 = 1
ADCON0.6 = 1
ADC.RightJustify = true
ADC.SetConvTime(FOSC_16)
 
USART.SetBaudrate(br9600)
 
 
While 1=1
 
ADVal = ADInAsmVolt
DelayMS(50)
ADVal1 = ADInAsmVolt
If abs(ADVal-ADVal1) < 25 Then 'repeatable read
  Select ADVal

Case < 250
Button = 1
Case < 750
Button = 2
Case < 1250
Button = 3
Case < 1750
Button = 4
Case < 2250
Button = 5
Case < 2750
Button = 6
Case < 3250
Button = 7
Case < 3750
Button = 8
Case < 4250
Button = 9
Case < 4700
Button = 10
Else
'no button pressed
  Button = 0

End Select
Else
'invalid read
  EndIf

 
If Button <> ButtonWas Then
If Button <>0 Then
USART.Write("Button = ", DecToStr(Button),13,10)
Else
'don't print 0
  EndIf

ButtonWas = Button
EndIf
 
Wend

 

When I tried the initial version of the software, I would get an erroneous reading occassionally - a higher number button than the button actually pressed was indicated.  What was happening was that the ADC read was only catching part of the button press, resulting in a ADC value greater than it should have been.  I added the statement to require two consistent reads in a 50 µs period to be a valid read.  This completely eliminates erroneous readings and doesn't make reading the keys feel sluggish at all.

The approach will be very stable.  The ADC and the voltage divider are both referenced to supply voltage, so the output is ratio-metric and independent of supply voltage.  The resistors, in close proximity, will be subject to the same thermal drift and the measurement increments are large so drift won't be an issue.

The maximum number of buttons used is limited by the ADC resolution and the tolerance of the resistors.  I'll leave it as an exercise for the reader to determine the range of values for a given voltage divider tap, given that each resistor may be ±5% from its rated value.

 

Conclusion

Ten keys. 

One port pin. 

Extra cost almost nothing. 

Win.

Share this article

Forum Activity

Recent Articles

ROKNEWSPAGER ERROR: File not found: images/stories/authors/346/EEVBlog%20242.jpgROKNEWSPAGER ERROR: File not found: images/stories/authors/Jon%20Chandler/bookmark%20screen.jpg

EEVblog #242 – Hakko FX-888 Soldering Iron Hack +

Dave has posted another excellent video blog, this one a hack he did on a Hakko FX-880 soldering iron.  The hack is interesting because he solves a design problem  and explains in detail the...

Geoff's Projects: The Maximite BASIC Computer +

From Geoff's Projects Blog comes the Maximite BASIC computer.  It looks like an interesting bit of kit and the table of contents at the blog has some other interesting topics. The Maximite is a small...

Rangerbob's Reverse Geocache +

Rangerbob's Reverse Geocache
Since I first saw Mikal Harts Reverse Geocache Puzzle I knew I needed to build one. My best mate and his wife are avid GeoCachers (is that a word?) and I decided to make a special gift for his 30th birthday....

Useful Online Tools and References +

There are a lot of useful tools on-line.  I got busy and organized some of the ones I use often.  Perhaps you'll find these useful.  Please share others that you use. I installed these...

Handy RadioShack Test Lead Set +

Handy RadioShack Test Lead Set
RadioShack is starting to get some nice products but sadly, they are not well described on the package or on the web site.  I took a leap of faith and purchased this test lead set and I'm quite pleased...

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

New Resources

Andrew Carters Electrical Engineering Blog
Jumper One - electronic projects, tutorials, hwd hacking

More...     Add Link

Whos Online

We have 29 guests and 2 members online

Member Access


showcase

The module implements a modulo-based PSEUDO Random Number Generator for SF.

More


showcase

Graham shares a C30 library for interfacing with serial EEPROMs such as 25LC256.

More


showcase

This module controls between 1 and 8 hobby servos connected to PortB. Setup & forget type module...

More


showcase

This module is an accurate pressure and temperature sensor which is based on the MS5561.

More