• PicŪ Basic


  • Keypad

    Interfacing a Keypad With a PIC

    Understanding how a keypad works is important if you are going to use it. Once you understand it's working, the code is very easy to write.

    Note there is an INKEY command as well, but it limits you to using a port. This is a method of using any 7 pic pins to read the keypad with.

    Understanding how a keypad works will also enable you to trace the different pins of an unknown keypad using a multimeter. Keep in mind that the wire pads where you connect to is not necessarily in a logical sequence.

    Keypads are usually internally arranged in a matrix. This means that there are horizontal lines and vertical lines overlapping each other. Where a horizontal line and a vertical line cross each other, there is a switch.



    If you look at a 3 x 4 keypad, it has 4 horizontal lines and 3 vertical lines. You can see this as there are 4 sets (rows) of switches from top to bottom, and 3 vertical sets of switches from left to right.

    If key 1 is pressed, then horizontal line A and vertical line 1 will be shorted together.
    If key 2 is pressed, then horizontal line A and vertical line 2 will be shorted together.
    If key 4 is pressed, then horizontal line B and vertical line 1 will be shorted together
    If key 9 is pressed, then horizontal line C and vertical line 3 will be shorted together
    As you can see, each key has a unique position in the 3 x 4 matrix. The pic will use that to identify which key has been pressed.

    In this setup you will need 7 pic pins to read the 12 keys of the keypad. We will use the four horizontal lines as "supply" lines and then read the three vertical lines to see which key was pressed. To make sure the three vertical lines does not give faulty readings due to static or other interferences which can very easily pull a pic pin up or down, there has to be pull-down resistors added to bias the input pins of the pic. Wire them to GND, so the pins will read 0 if read.



    Note if you used the four horizontal lines as inputs and the three vertical lines as outputs, you will have to add an extra resistor. Like we have it here, you save a resistor.

    Here's how the pic will identify which pin is pressed -

    Make horizontal line A a high or 1 while the other lines are low or 0
    Read vertical line 1, if 0, key 1 is not pressed.
    Read vertical line 2, if 0, key 2 is not pressed
    Read vertical line 3, if 0, key 3 is not pressed
    Make horizontal line B a high or 1 while the other lines are low or 0
    Read vertical line 1, if 0, key 4 is not pressed.
    Read vertical line 2, if 0, key 5 is not pressed
    Read vertical line 3, if 0, key 6 is not pressed
    You should get the idea by now

    Now lets say you

    Make horizontal line C a high or 1 while the other lines are low or 0
    Read vertical line 1, if 0, key 7 is not pressed.
    Read vertical line 2, if 1, key 8 is pressed
    You can now exit the key read routine and handle the 8 key pressed.

    Remember the pic runs through this routine extremely fast. A routine to keep the pic from reading the same pin over and over is sometimes required.

    First you have to tell the pic which pins are inputs and which are outputs. A 0 (zero) is an output and a 1 (one) is an input, and is read from right to left in a Byte. Assume we have a pic with 3 ports, A, B and C. % is binary (0's and 1's to make up a byte)

    TrisA = %00000100
    TrisB = %00000000'
    TrisC = %00000011

    ' Zero all port output pins to keep all peripheral components switched off.
    PortA = 0
    PortB = 0
    PortC = 0
    We define a user variable register that will hold the key pressed value in it.

    Dim KeyVal As Byte ' Key pressed value.
    To make it easy on yourself name the pic pins used so you know what you are doing

    Symbol Relay PortC.2''' ' Output to Relay Driver

    Symbol HorA PORTA.5 ' Horizontal line A Output
    Symbol HorB PORTA.1 ' Horizontal line B Output
    Symbol HorC PORTB.2 ' Horizontal line C Output
    Symbol HorD PORTB.0 ' Horizontal line D Output
    Symbol Ver1 PORTC.0 ' Vertical line 1 Input
    Symbol Ver2 PORTC.1 ' Vertical line 2 Input
    Symbol Ver3 PORTA.2 ' Vertical line 3 Input'''
    Any time now we type a pin's name, the pic will automatically associate that name with the relevant pin. We can now write the code with familiar names and not worry which pin is connected to which horizontal or vertical line.

    As you can see the pins are not organized in any sequence. In this case other external components used the pins the INKEY command would have used. Also the PCB layout can be done using the pic pins easiest for routing to the keypad plug.

    Let's for example say we have a relay on portC.2 we want to work if someone wants to open a gate.

    If key 1 is pressed, the relay must open the gate for 20 seconds (20000ms), stop and close it for 20 seconds.

    If key 2 is pressed, the relay must open the gate for 5 seconds (5000ms), stop and close it again for 5 seconds.

    If key 5 is pressed, disable the gate for 60 seconds

    ' Main Program Here
    Main :
    Gosub KeyPad''' ' Jump from here to the KeyPad subroutine and check if a key is pressed.
    'the code will return here -
    If keyval = 12 then Goto Main ' no key pressed, redo
    If Keyval = 1 then Relay = 1 : delayms 20000 : Relay = 0 : Delayms 20000 : Goto Main
    If Keyval = 2 then Relay = 1 : delayms 5000 : Relay = 0 : Delayms 5000 : Goto Main
    if Keyval = 5 then delayms 60000 : Goto Main

    ' Any other keypad value will end up here. Since no function is asigned to them,
    ' go back to the main loop.

    Goto Main
    Note that due to the long delay timers after a key has been pressed, there is almost no chance of the key being read multiple times over and cause a faulty reaction. During opening or closing of the gate, the keypad is ignored.

    ' Subroutines Start Here
    ' Read Keypad

    KeyPad:
    HorA = 1 : HorB = 0 : HorC = 0 : HorD = 0 ' Only Horizontal line A is 1, the rest is 0
    If Ver1 = 1 then KeyVal = 1 : Return
    If Ver2 = 1 then KeyVal = 2 : Return
    If Ver3 = 1 then KeyVal = 3 : Return

    HorA = 0 : HorB = 1 : HorC = 0 : HorD = 0 ' Only Horizontal line A is 1, the rest is 0
    If Ver1 = 1 then KeyVal = 4 : Return
    If Ver2 = 1 then KeyVal = 5 : Return
    If Ver3 = 1 then KeyVal = 6 : Return

    HorA = 0 : HorB = 0 : HorC = 1 : HorD = 0 ' Only Horizontal line A is 1, the rest is 0
    If Ver1 = 1 then KeyVal = 7 : Return
    If Ver2 = 1 then KeyVal = 8 : Return
    If Ver3 = 1 then KeyVal = 9 : Return

    HorA = 0 : HorB = 0 : HorC = 0 : HorD = 1 ' Only Horizontal line A is 1, the rest is 0
    If Ver1 = 1 then KeyVal = 10 : Return ' * key is 10
    If Ver2 = 1 then KeyVal = 0 : Return
    If Ver3 = 1 then KeyVal = 11 : Return ' # key is 11


    'And to identify that no key was pressed

    Keyval = 12 'No key was pressed
    Return

    End
    I like to return with a value in a variable, it makes it easy to use the value in a single register.

    I also provide for a 'No Key Pressed'. Since I keep the snippets for future programs that may use the same routine, it may be required to sense if no key has been pressed within a certain time, used often for ie. coded access.
    In high speed applications and if there are long wires with capacitance to the keypad it may be nessesary to implement a delay to give the pic pins time to rise enough before reading the pin statusses -

    HorA = 1 : HorB = 0 : HorC = 0 : HorD = 0 : Delayus 100 ' Only Horizontal line A is 1, rest is 0
    Keypads can be used for a host of different applications. These include -

    General control (like above)
    Access Control ie security, could precede the general control.
    Instrument / equipment setup procedures
    Calibration of instruments or equipment
    Simple Calculator - yes, pics can do that too

    contributed by Fanie
  • Recent Activity

    joesaliba-353

    Watchdog timer

    Thread Starter: joesaliba

    I have a code that basically looks for four input and four outputs, depends on various timing and input conditions. I use interrupt and some delays...

    joesaliba Today, 18:20 Go to last post