4x4 keypad matrix questions.

Grogster

Senior Member
Yes, again with the matrix keypads...
;)

I searched the forums and found several threads, and some very useful code posted by hippy, I think it was, using the 20X2 and a lookup table.

Here is the code to save you looking for it:

Code:
#Picaxe 20X2
#Terminal 38400
#No_Data

'        20X2
'     .---__---.               
'     |+V    0V|   
'     |SI    SO|----------------------> TXD        
'     |C7    B0|<-----------.
'     |C6    B1|<---------. |
'     |C5    B2|----> * * * *     1x1 through 4x4
'     |C4    B3|----> * * * *      Matrix Keypad
'     |C3    B4|----> * * * *        No Diodes
'     |C2    B5|----> * * * *      No Resistors   
'     |C1    B6|<-----' |
'     |C0    B7|<-------'
'     `--------'

Symbol DIR_X        = %00111100
Symbol MSK_X        = %11000011
Symbol XOR_X        = MSK_X 

Symbol DIR_1        = %00100000
Symbol MSK_1        = MSK_X
Symbol XOR_1        = MSK_X | DIR_1

Symbol DIR_2        = %00010000
Symbol MSK_2        = MSK_X
Symbol XOR_2        = MSK_X | DIR_2

Symbol DIR_3        = %00001000
Symbol MSK_3        = MSK_X
Symbol XOR_3        = MSK_X | DIR_3

Symbol DIR_4        = %00000100
Symbol MSK_4        = MSK_X
Symbol XOR_4        = MSK_X | DIR_4

Symbol keyPress     = b2
Symbol lastKeyPress = b3

; ===================================================

SetFreq M32

PullUp %11011000

lastKeyPress = $FF

Do
  Gosub ReadKeyPress
  ReadTable keyPress, keyPress
  If keyPress <> lastKeyPress Then
    lastKeyPress = keyPress
    SerTxd ( "Key = ", #keyPress, CR, LF )
    Pause 40
  End If
Loop

ReadKeyPress:

  dirsB    = DIR_X
  keyPress = MSK_X & pinsB ^ XOR_X
  If keyPress <> 0 Then

    dirsB        = DIR_1 
    keyPress     = MSK_1 & pinsB ^ XOR_1
    If keyPress <> DIR_1 Then : Return : End If

    dirsB        = DIR_2 
    keyPress     = MSK_2 & pinsB ^ XOR_2
    If keyPress <> DIR_2 Then : Return : End If

    dirsB        = DIR_3 
    keyPress     = MSK_3 & pinsB ^ XOR_3
    If keyPress <> DIR_3 Then : Return : End If

    dirsB        = DIR_4 
    keyPress     = MSK_4 & pinsB ^ XOR_4
    If keyPress <> DIR_4 Then : Return : End If

  End If
  keyPress = 0
  Return

  Table %00000000, ( 0  )

  Table %00000101, ( 1  )
  Table %00000110, ( 2  )
  Table %00000111, ( 17 )
  Table %01000100, ( 3  )
  Table %01000101, ( 18 )
  Table %01000110, ( 19 )
  Table %01000111, ( 20 )
  Table %10000100, ( 4  )
  Table %10000101, ( 21 )
  Table %10000110, ( 22 )
  Table %10000111, ( 23 )
  Table %11000100, ( 24 )
  Table %11000101, ( 25 )
  Table %11000110, ( 26 )
  Table %11000111, ( 27 )

  Table %00001001, ( 5  )
  Table %00001010, ( 6  )
  Table %00001011, ( 28 )
  Table %01001000, ( 7  )
  Table %01001001, ( 29 )
  Table %01001010, ( 30 )
  Table %01001011, ( 31 )
  Table %10001000, ( 8  )
  Table %10001001, ( 32 )
  Table %10001010, ( 33 )
  Table %10001011, ( 34 )
  Table %11001000, ( 35 )
  Table %11001001, ( 36 )
  Table %11001010, ( 37 )
  Table %11001011, ( 38 )

  Table %00010001, ( 9  )
  Table %00010010, ( 10 )
  Table %00010011, ( 39 )
  Table %01010000, ( 11 )
  Table %01010001, ( 40 )
  Table %01010010, ( 41 )
  Table %01010011, ( 42 )
  Table %10010000, ( 12 )
  Table %10010001, ( 43 )
  Table %10010010, ( 44 )
  Table %10010011, ( 45 )
  Table %11010000, ( 46 )
  Table %11010001, ( 47 )
  Table %11010010, ( 48 )
  Table %11010011, ( 49 )

  Table %00100001, ( 13 )
  Table %00100010, ( 14 )
  Table %00100011, ( 50 )
  Table %01100000, ( 15 )
  Table %01100001, ( 51 )
  Table %01100010, ( 52 )
  Table %01100011, ( 53 )
  Table %10100000, ( 16 )
  Table %10100001, ( 54 )
  Table %10100010, ( 55 )
  Table %10100011, ( 56 )
  Table %11100000, ( 57 )
  Table %11100001, ( 58 )
  Table %11100010, ( 59 )
  Table %11100011, ( 60 )
I'm planning on basically using this code, but with an 18M2+ and it's B port.
Do you see anything inherently wrong with that concept?

I don't suppose I could use a 14M2?

It does not have enough pins on any ONE port, but I don't suppose you can split the operation across both ports on the 14M2?

Along the lines of rows on portB, columns on portC kind of thing?

I suspect NOT, as the codes I have seen for matrix decoding, seem to rely heavily on being able to read the state of the whole port in one command as an important step in the code.

...but then, I often misunderstand things...
;)
 

premelec

Senior Member
That works yet also you can use READADC and a few resistors on the keypad IF its contacts are still pretty good... this only requires one pin to read the keypad... As the READADC is ratiometric all you need to do is determine the values read and use those to give which key is pressed. There was a spreadsheet published on this forum some years ago comparing various values and methods... I think it was from brightspark...
 

Grogster

Senior Member
Good idea - I will considder it. I had forgotten about that. Probably better to use the scanning method though...
 

hippy

Technical Support
Staff member
I'm planning on basically using this code, but with an 18M2+ and it's B port. Do you see anything inherently wrong with that concept?

I don't suppose I could use a 14M2?
Matrix scanning will work on any PICAXE which has enough I/O pins so 14M2 and 18M2 should be fine.

The code above is rather specialised and tuned for the 20X2 ( I/O on one port, internal pull-ups used ). It should be usable when modified with any PICAXE using a single I/O port for the matrix though external pull-ups may be needed.

Some of the other code on the forum and the CHI008 sample ( File -> Open Samples ) may be more easier to follow and to modify for use.
 

westaust55

Moderator
The Analog input using a single ADC input is certainly viable.
I used it for a 4x3 matrix keypad in my 28X2 based Digital IC logic tester project (see post 5 for schematic):
http://www.picaxeforum.co.uk/showthread.php?18678-PICAXE-based-Logic-IC-Tester
Expanding to a 4x4 would be easy.

As I recall BCJKiwi was one of the first to use/publish on this forum about the 1-wire analog keypad method.
If you search for his post I recall he has a spreadsheet there as well.
 

Grogster

Senior Member
Thank you all - I will do more research on BOTH options.

premelec said on post #2 about the keypad contacts needing to be good - has anyone had issues with ADC values being that dramatically different with long-term use of the keypad keys?

On to the research...
 

Grogster

Senior Member
Yes, that was the thing I saw once before and DID actually play with that on a breadboard and it seemed to work OK. Thanks for the link. :) I have decided to use multipule pins on a 14M2 to scan the keypad, mainly as I have not done this before, so it is a chance for me to learn something new by studying how it works. :) I have also downloaded the CHI008 PDF and am studying that too.
 

giokal

New Member
hi all, testing of code mentioned in the thread # 1, I have encountered several problems, the code to adapt it to 40x2 but I can not understand why once ON the circuit and when striking a key addition to sending effectively this key sends "0", this does every time I press any key.
keypad 4x4.JPG
these are the lines that have changed:
Code:
#Picaxe 40X2
#Terminal 19200	
#No_Data

SetFreq m16 

PULLUP %11000011 ;pullup b7b6....b1b0   manual 2 p159 v7.7 

lastKeyPress = $FF

Do
Gosub ReadKeyPress
ReadTable keyPress, keyPress
If keyPress <> lastKeyPress Then
lastKeyPress = keyPress
LOOKUP keyPress,("0A321B654C987D#0*"),KEYPRESS ;
SerTxd ( "Key = ", keyPress, CR, LF ) 
Pause 40
End If
 Loop
I am using a 4x4 matrix keyboard connected as indicated by the original code, I'm intrigued and energized because when I send this circuit "0" and also by pressing any key
 

rossko57

Senior Member
Yes, the code generates 0 when a key is released. If you don't want that to be sent to the terminal, you must test for the key release case and skip sending.
 

giokal

New Member
Hi rossko57, the first problem is when I turn on the computer and I have not pressed any key the routine sends a "0" either terminal or using the debug, but it confuses me how to detect this second value when you press any key, I can not see inside routine, I understand that DIR_X is responsible for detecting the column of the pressed key but then can not see as does the maching of this column with the respective pulse row for which indeed can explain how it does.

I made a comparison chart to see the behavior bit by bit in port B:
DIR´s.JPG

technical sheet keyboard:
http://www.electronicoscaldas.com/datasheet/Teclado-membrana-matricial-4x4.pdf
 
Top