Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

reverse engineering the keypad module

Status
Not open for further replies.
pullups are connected to the 4 colums
I thought all of your code says you have 3 columns...

+1 for visitor. Show what's connected to what and which switches/leds are which (ie SW1, LED1, etc)
 
Have always had 4 colums and 3 rows. the colums have pullup resistors
all are connect to portc
one item that I think is a typo in the pullup.bas modules are in the keypad12 the a colum are HIGH and pullup16 it is set LOW.
 
here is a simple schematic. just the portc connections shown.
no need to add clutter with the led connections as they are simply connections to each led in a 4 x 3 matrix
switch matrix2.jpg
 
Have always had 4 colums and 3 rows
You're right. Sorry. I got confused by the keypad12.bas comments...
Code:
Module Keypad12rev
{
Column1 = PORTX.0
Column2 = PORTX.1
Column3 = PORTX.2
PORTX.3 NC
Row1 = PORTX.4
Row2 = PORTX.5
Row3 = PORTX.6
Row4 = PORTX.7
}

Looking at the schematic, you would be better off swapping your S1 and S3 labels so that the switches are numbered "S1-S2-S3" from top to bottom.
That matches up with the order of switches in the other three columns.
 
still hacking at this and wondering if I made it 4 rows x 3 colums
then the rows are tied high. I keep running out of rows.
My issue is sw1 and sw9 are in same colum and act the same way.
 
as per the simple schematic I posted, pressing s1 acts the same as pressing s6, pressing s2 has no effect
same is true with s7 and s9 as well as s10 and s12
disregard post #65 as the switches don't match up with schematic I posted,
 
I think it is time for:

1) Full, accurate schematic.

2) Zip file containing all code, with all include files.

3) Well lit photographs of both sides of your circuit board, so we can see if schematic matches reality.

With this I can try and help. no promises...

EDIT: Ooops... Sorry. Just realised that I do not own a PIC18F43K22, so I cannot help. Ignore all of the above :(
 
Last edited:
Here's a simple scanning routine that should match the connections in post #63

keypad12mrd.bas:
Code:
Module Keypad12
//
// this is for the mrdeb 3x4 keypad
// inputs are COL1-COL4 (PORTC.0-PORTC.3) with ext 10K pullups
// outputs are ROW1-ROW3 (PORTC.4-PORTC.6)
// note: in the schematic S1 and S3 are swapped around, so S3 is on ROW1 and S1 is on ROW3
//
// assumes the following connections:
//  Column1 = PORTX.0
//  Column2 = PORTX.1
//  Column3 = PORTX.2
//  Column4 = PORTX.3
//  Row1 = PORTX.4
//  Row2 = PORTX.5
//  Row3 = PORTX.6
//  PORTX.7 = NC, unused
//

// validate data port...
#option KEYPAD_PORT = PORTC
#if IsOption(KEYPAD_PORT)
   #if Not IsValidPort(KEYPAD_PORT)
      #error KEYPAD_PORT, "Invalid option. Keypad must be connected to a valid port name."
   #endif
   #option _KEYPAD_PORT_TRIS = GetTRIS(KEYPAD_PORT)  
#endif

// normally you wouldn't use this, but...
// have code swap keys S1 and S3 since they aren't in the proper order
#option KEYPAD_SWAP_S1_S3 = true

// bring PORT and TRIS options into the module
Dim
   FKeyPort As KEYPAD_PORT,
   FKeyPortTris As _KEYPAD_PORT_TRIS

// read keypad
// returns 0 = nothing pressed, otherwise key = 1-12
Public Function GetKey() As Byte
    Dim Counter As Byte
    Dim RowData As Byte
    Dim ColData As Byte
   
    For Counter = 0 To 2                    // scan three rows...
        FKeyPortTris = $FF                  // Make all pins inputs
        FKeyPortTris.Bits(Counter+4) = 0    // Make a single row an output
        FKeyPort = 0                        // and set it low (writes to LATx)
        Result = 0                          // default to no key detected                          
       
        If (FKeyPort and $0F) <> $0F Then   // Check if any columns are active (ie low)
            RowData = Counter
            If FKeyPort.bits(0) = 0 Then
                ColData = 1
            ElseIf FKeyPort.bits(1) = 0 Then
                ColData = 4
            ElseIf FKeyPort.bits(2) = 0 Then
                ColData = 7
            ElseIf FKeyPort.bits(3) = 0 Then
                ColData = 10              
            EndIf          
            Result = Coldata + RowData
            // **KLUDGE**
            // swap keys S1 and S3 since they aren't in the proper order
          #if (KEYPAD_SWAP_S1_S3)
            if (Result = 3) then
                Result = 1
            elseif (Result = 1) then
                Result = 3
            endif
          #endif               
            Break                               // exit loop        
        EndIf
    Next
End Function

FKeyPortTris = $FF              // Make all pins inputs

End Module

Here's an example...
Code:
Device = 18F43K22
Clock = 8

Include "intosc.bas"
Include "setdigitalio.bas"

#option KEYPAD_PORT = PORTC
include "keypad12mrd.bas"

// turn off analog functions
SetAllDigital()

// wait for key 1 to be pressed
Repeat
Until (GetKey() = 1)

// wait for key 5 to be pressed
Repeat
Until (GetKey() = 5)

// wait for any key
while (GetKey() = 0)
end while

Remove all of the 'Output' and 'Input' statements in your code for the switch row and column pins.
The keypad module will take care of that for you.

edit: updated to check for col bit = 0 instead of 1
 
Last edited:
I will give it a try, thanks.
will add an LCD write to verify results of a key press but entering a WRITE command ?
tried several different but the END WHILE statement has me flustered.
 
making progress thanks to tumbleweeds code suggestion
needs some work to output correct keys pressed. I edited out the key swap but tried with and neither is correct. hopefully just a little editing
Code:
Device = 18F43K22
Clock = 8

// import LCD library...
#option KEYPAD_PORT = PORTC
#option SWORDFISH_SE = true
// some LCD options...
'#option KEYPAD_PORT = PORTc
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.0
#option LCD_EN = PORTD.1

Include "keypad12mrd.bas"
Include "LCD.bas"
Include "setdigitalio.bas"//Include "SetDigitalIO.bas"
Include "utils.bas"
Include "Convert.bas"
Include "intosc.bas"

// turn off analog functions
Dim keypressed As Byte
SetAllDigital()
keypressed=0
 While True
'led=1
DelayMS(1000)
 keypressed = Keypad12mrd.GetKey()
    If keypressed<>0 Then
    DelayMS(50)
    WriteAt(2,1,"Key: ",DecToStr(keypressed,2))//, " Cnt: "))//,DecToStr(Counter,2))
   End If
    
Wend

with out code swap
1 4 7 10
2 5 8 11
1 4 7 10
with code swap which is really not needed IMO
3 4 7 10
2 5 8 11
3 4 7 10
 
You have a hardware problem. Row 3 must be connected to the row 1 input instead of row 3 input. Period.
 
with code swap which is really not needed IMO
If it's not needed then keys S1 and S3 aren't connected the way your schematic in post #63 shows.

You can leave the code in there and just change
#option KEYPAD_SWAP_S1_S3 = true
to
#option KEYPAD_SWAP_S1_S3 = false
 
found issue w/ board. corrected and results work as they should.
now on to getting the leds to come on and off.
would like to use basically same setup as the new keypad12 routine but??
have too many distractions right now (wife is conveying info etc)
back at it later today?
 
From your posts it sounds like you only want to have 1 led on at a time.
That's pretty simple...

ledmatrix.bas:
Code:
module ledmatrix

{
// from forum post #3... either the comments are wrong or the matrix is "random"
// LED1
LED_COL1=1  LED_COL2=0  LED_COL3=0 LED_COL4=0
LED_ROW1=0  //leds 1-4  led1 is on             
LED_ROW2=1  //leds 5-8     
LED_ROW3=1  //leds 9-12               

// LED5??? shouldn't this be LED6 on?
LED_COL1=0  LED_COL2=1  LED_COL3=0 LED_COL4=0
LED_ROW1=1  //leds 1-4             
LED_ROW2=0  //leds 5-8   led #5 is on 
LED_ROW3=1  //leds 9-12               

// LED9??? shouldn't this be LED12 on?
LED_COL1=0  LED_COL2=0  LED_COL3=0 LED_COL4=1
LED_ROW1=1  //leds 1-4             
LED_ROW2=1  //leds 5-8     
LED_ROW3=0  //leds 9-12  LED #9 is on 

anyway, the code below assumes the leds are in proper order...           
}

//LED MATRIX
Dim LED_COL1 As PORTB.0
Dim LED_COL2 As PORTB.1
Dim LED_COL3 As PORTB.2
Dim LED_COL4 As PORTB.3
Dim LED_ROW1 As PORTB.4
Dim LED_ROW2 As PORTB.5
Dim LED_ROW3 As PORTB.6

// make led pins outputs and turn them all off
public sub AllOff()
    // turn off columns
    low(LED_COL1)
    low(LED_COL2)
    low(LED_COL3)
    low(LED_COL4)
    // turn off rows
    high(LED_ROW1)
    high(LED_ROW2)
    high(LED_ROW3)
end sub

// turn on a single led
//  led_no = 0 -> nothing on (all off)
//         = 1-12 -> turn on specified led
// the routine ignores the comments above and sets the leds "in order"
// so it may not match the (unknown) schematic
// it's long-hand so it can easily be adjusted to match

public sub SetLed(led_no as byte=0)
    AllOff()
    select (led_no)
        // ROW1
        case 1      // row1, col1
            LED_COL1 = 1
            LED_ROW1 = 0
        case 2      // row1, col2
            LED_COL2 = 1
            LED_ROW1 = 0
        case 3      // row1, col3
            LED_COL3 = 1
            LED_ROW1 = 0
        case 4      // row1, col4
            LED_COL4 = 1
            LED_ROW1 = 0
        
        // ROW2
        case 5      // row2, col1
            LED_COL1 = 1
            LED_ROW2 = 0
        case 6      // row2, col2
            LED_COL2 = 1
            LED_ROW2 = 0
        case 7      // row2, col3
            LED_COL3 = 1
            LED_ROW2 = 0
        case 8      // row2, col4
            LED_COL4 = 1
            LED_ROW2 = 0
        
        // ROW3
        case 9      // row3, col1
            LED_COL1 = 1
            LED_ROW3 = 0
        case 10     // row3, col2
            LED_COL2 = 1
            LED_ROW3 = 0
        case 11     // row3, col3
            LED_COL3 = 1
            LED_ROW3 = 0
        case 12     // row3, col4
            LED_COL4 = 1
            LED_ROW3 = 0
    end select
end sub

// init
AllOff()

end module

and an example...
Code:
Device = 18F43K22
Clock = 8

Include "intosc.bas"
Include "setdigitalio.bas"

#option KEYPAD_PORT = PORTC
include "keypad12mrd.bas"

include "ledmatrix.bas"

dim ledno as byte

// turn off analog functions
SetAllDigital()

// turn off all leds (they startup off so this doesn't really do anything)
SetLed(0)

SetLed(1)       // turn on led 1
// wait for key 1 to be pressed
Repeat
Until (GetKey() = 1)

SetLed(5)       // turn on led 5
// wait for key 5 to be pressed
Repeat
Until (GetKey() = 5)

SetLed(0)
// wait for any key
// while waiting cycle leds
ledno = 1
while (GetKey() = 0)
    SetLed(ledno)
    ledno = ledno + 1
    if (ledno > 12) then
        ledno = 1
    endif
    Delayms(100)        
end while

// loop forever showing led X while key X is pressed
while (true)
    SetLed(GetKey())
end while

If you want to have multiple leds on at the same time then you'll need to have a real routine that scans the matrix using a timer and interrupts.
 
back at it this morning.
Thanks for the suggestion tumbleweed. will try it out but need to put on port B since the switches are on port C
I started experimenting using binary but didn't get anywhere.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top