PDA

View Full Version : Complete Keypad Example



T.Jackson
- 8th May 2007, 17:31
Interfacing PIC's to hardware peripherals like keypads is relatively straight forward. Once you know how. Here I present to you all a complete and ready to build project that should hopefully make it all look like a snack to do. Because it actually really is. This Universal Keypad interface, in its current configuration, is serial by nature. Connected to a Hyper Terminal program it will print to the screen the literal values of the keys as they're pressed. This even includes the hash & star keys.

The keypad is robust. When I say robust I mean that there is absolutely positively no chance of key bouncing - (key bouncing is typically a multiple output of the key whilst being depressed) - but with this keypad, it's impossible for more than one key to be processed at any given time. This effectively eliminates the possibility of errors if the user attempts to press many keys simultaneously.

With little modification the hardware circuit & software that I present, could be easily adapted towards something more specific. Perhaps a simple burglar alarm, or maybe just a combination lock that controls some external device. The circuit uses a PIC16f628a processor and as it stands, only 400 words of code space has been used thus far. So there's plenty of room left for you to create your very own application specific projects. I promote the project as bare bones essential and universal in the fact that the serial output could be quickly exchanged with a relay. It's an adaptive building block!
</td>
</tr>
</table>
http://www.picbasic.co.uk/forum/attachment.php?attachmentid=1605&d=1178636421
The Hardware Schematic

Pin numbers and all. No excuse not to build this. As you can see, there's hardly anything to it. We have the keypad, one discrete active component - NPN transistor, and a handful of passives. Also, it's worth while noting that the 4MHz crystal isn't critical, you could if you wish use an RC oscillator. You'll save a few bucks. Also, arguably, the PIC's internal pull ups could be used instead of the 100K externals.

The 4x3 matrix keypad consists of 4 rows & 3 columns. By using a process known as multiplexing, we can effectively provide direct support for 12 buttons using only 7 wire connections. Here's how it works: We continuously scan the columns incrementally, only one is ever on at a time, then we read the rows to determine what button was pressed. For example; if RB1 is low - (by the way the cols are active low) - pressing the hash key will cause RB0 to be pulled low. Similarly, if the 9 key is pressed RB2 swings low.

Power for the circuit is derived from any regulated 5V DC rail. 100nF & 10uF associated capacitors provide adequate decoupling for the circuit. These may need to be changed if heavier loads are anticipated. For example, adding a relay to switch something, ideally the 10uF capacitor will be upgraded to say 100uF. RA4 on the PIC is an open drain line, meaning it can sink current but it can't source it. In other words, it can't swing high only low. Hence the 2K2 pull up is required for the first column. This rather low value ensures a fast transition from low to high.






<hr/>



Include "modedefs.bas"
Define OSC 4
CMCON = 7

TRISA = %00001000
TRISB = %00001101

'// Declare Variables...
Col_A VAR PORTB.1
Col_B VAR PORTA.2
Col_C VAR PORTA.4

Row_A VAR PORTA.3
Row_B VAR PORTB.3
Row_C VAR PORTB.2
Row_D VAR PORTB.0

Buzzer VAR PORTB.5
RX_To_PC VAR PORTA.0

Scan_Col VAR BYTE ' Counter - current col
Key_Press VAR BYTE ' Value of key (0-9) & * + #
Key_Down VAR BYTE ' Flag set true when key is depressed
Allow_Key VAR BYTE ' Flag - disallow multiple keys being pressed
I VAR byte ' General working var

Scan_Keypad:

@ incf _Scan_Col, 1 ' Inc col pos...

SELECT CASE Scan_Col ' Col (1-3)

CASE 1
Col_A = 0 ' Switch on col (active low)
Col_B = 1 ' Col off
Col_C = 1 ' Col off

'// 3 Key
IF Row_A = 0 THEN ' Key down? ...
IF Allow_Key = 0 THEN ' Any other key down?
Key_Press = 3 ' Load var w/value of key
Allow_Key = 1 ' Disallow other keys
ENDIF
ENDIF
'// 6 Key
IF Row_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 6
Allow_Key = 1
ENDIF
ENDIF
'// 9 Key
IF Row_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 9
Allow_Key = 1
ENDIF
ENDIF
'// # Key
IF Row_D = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 35
Allow_Key = 1
ENDIF
ENDIF

CASE 2
Col_A = 1
Col_B = 0
Col_C = 1

'// 2 Key
IF Row_A = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 2
Allow_Key = 1
ENDIF
ENDIF
'// 5 Key
IF Row_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 5
Allow_Key = 1
ENDIF
ENDIF
'// 8 Key
IF Row_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 8
Allow_Key = 1
ENDIF
ENDIF
'// 0 Key
IF Row_D = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 0
Allow_Key = 1
ENDIF
ENDIF

CASE 3
Col_A = 1
Col_B = 1
Col_C = 0

'// 1 Key
IF Row_A = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 1
Allow_Key = 1
ENDIF
ENDIF
'// 4 Key
IF Row_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 4
Allow_Key = 1
ENDIF
ENDIF
'// 7 Key
IF Row_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 7
Allow_Key = 1
ENDIF
ENDIF
'// * Key
IF Row_D = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 42
Allow_Key = 1
ENDIF
ENDIF

Scan_Col = 0
END SELECT

'// Output key serially, once only
IF Key_Down <> Key_Press THEN ' Key already been sent?
IF Key_Press <> 255 THEN ' 255 denotes no key press
IF Key_Press = 42 OR Key_Press = 35 THEN ' Numerical key?
SEROUT RX_To_PC, N2400, [Key_press] ' No
ELSE '
SEROUT RX_To_PC, N2400, [#Key_press] ' Yes
ENDIF

'// Brief chrip of the piezo & flash of the LED
for i = 0 to 20
toggle buzzer
pause 5
next
ENDIF
Key_Down = Key_Press ' Copy of key just sent
Buzzer = 0 ' Make sure LED is off
ENDIF

'// Check for key release, all cols on (active low) ...
Col_A = 0
Col_B = 0
Col_C = 0

IF Row_A = 1 THEN
IF Row_B = 1 THEN
IF Row_C = 1 THEN
IF Row_D = 1 THEN
Allow_Key = 0
Key_Down = 0
Key_Press = 255
ENDIF
ENDIF
ENDIF
ENDIF

GOTO Scan_Keypad

http://www.picbasic.co.uk/forum/attachment.php?attachmentid=1607&stc=1&d=1178637549

Trent Jackson
<hr/><br/><br/><br/>

Pic_User
- 8th May 2007, 17:49
Hey thanks Trent,
nice piece of work, will certainly use it
will give thread a +++vote too!
-Adam-

T.Jackson
- 8th May 2007, 18:37
No Worries. I actually had a fair bit more to write, 10,000 character limit is cumbersome to work with. I"m currently reading over things, trying to shorten sentences in attempts to fit more in. Would prefer to keep it all as one single post.

precision
- 9th May 2007, 06:19
No Worries. I actually had a fair bit more to write, 10,000 character limit is cumbersome to work with. I"m currently reading over things, trying to shorten sentences in attempts to fit more in. Would prefer to keep it all as one single post.

Its quite simple for me


<font color="#000080">@Config = _XT_OSC &amp; _WDT_OFF &amp; _PWRTE_OFF &amp; _LVP_OFF &amp; _BODEN_OFF
</font><font color="#800000"><b>DEFINE </b></font><b>PIC16F877A
</b><font color="#800000"><b>DEFINE </b></font><b>OSC </b><font color="#0000FF"><b>4

</b></font><font color="#800000"><b>INCLUDE </b></font><font color="#FF0000"><b>&quot;KeyPad.bas&quot; </b></font><font color="#0000FF"><b><i>' ( mister_e 's great keypad include file )
</i></b></font><font color="#800000"><b>INCLUDE </b></font><font color="#FF0000"><b>&quot;MYLCD.BAS&quot;
</b></font><b>CMCON = </b><font color="#0000FF"><b>7
</b></font><b>ADCON1 = </b><font color="#0000FF"><b>7

</b></font><b>myvar </b><font color="#800000"><b>VAR BYTE

</b></font><b>start:
</b>@ <b>READKEYPAD _myvar
</b><font color="#800000"><b>LCDOUT </b></font><font color="#0000FF"><b>$fe</b></font><b>,</b><font color="#0000FF"><b>1
</b></font><font color="#800000"><b>LCDOUT </b></font><font color="#FF0000"><b>&quot; Key Value = &quot;</b></font><b>,</b><font color="#800000"><b>DEC2 </b></font><b>myvar
</b><font color="#800000"><b>GOTO </b></font><b>start
</b>

T.Jackson
- 9th May 2007, 08:55
I haven't seen Mister_e's keypad routine. Anyone have the link handy?

T.Jackson
- 9th May 2007, 09:07
Notes & Eratta:
First paragraph under schematic I state: Also, it's worth while noting that the 4MHz crystal isn't critical, you could if you wish use an RC oscillator. You'll save a few bucks. <hr/>*This assumes that you won't be connecting the keypad to the serial port. A crystal is mandatory if you intend to build the project entirely as presented.

Darrel Taylor
- 9th May 2007, 09:45
I haven't seen Mister_e's keypad routine. Anyone have the link handy?


Matrix Keypad routine
http://www.picbasic.co.uk/forum/showthread.php?t=3250


But that's OK,

new entries (ways) are welcome!
<br>

zaferakbay
- 20th June 2007, 21:47
güzel çalışma teşekkür ederim



TÜRKİYE

mister_e
- 20th June 2007, 23:59
güzel çalışma teşekkür ederim can't be found
Désolé je ne comprends pas :D

Sayzer?

RAYMON
- 29th July 2007, 18:18
I find the T.Jackson program very well, but I need a routine or a help for a program, to make a spy, to see example thank you

Col_1 VAR PORTB.4
Col_2 VAR PORTB.5
Col_3 VAR PORTB.6

Row_1 VAR PORTB.3
Row_2 VAR PORTB.2
Row_3 VAR PORTB.1
Row_4 VAR PORTB.0



Col_1/ Row_1 = 1
Col_1/ Row_2 = 4
Col_1/ Row_3 = 7
Col_1/ Row_4 = *

Col_2/ Row_1 = 2
Col_2/ Row_2 = 5
Col_2/ Row_3 = 8
Col_2/ Row_4 = 0

Col_3/ Row_1 = 3
Col_3/ Row_2 = 6
Col_3/ Row_3 = 9
Col_3/ Row_4 = #

CASE 1
Col_1 = 0
Row_1 = 0
Row_2 = 0
Row_3 = 0
Row_4 = 0


'// 1 Key
IF Row_1 = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 1
Allow_Key = 1
ENDIF
ENDIF
'// 4 Key
IF Row_2 = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 4
Allow_Key = 1
ENDIF
ENDIF
'// 7 Key
IF Row_3 = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 7
Allow_Key = 1
ENDIF
ENDIF
'// * Key
IF Row_4 = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 42
Allow_Key = 1
ENDIF
ENDIF

Scan_Col = 0

http://www.electroniquepratique.com/detail.php?idMg=44&id=523

Mini espion pour clavier de PC

RAYMON
- 30th July 2007, 12:00
Hello I have modidier the program in this manner, I do not know if it is correct mercy
'// Define port pins as inputs and outputs ...
TRISA = %00001000
TRISB = %11111111

'// Declare Variables...
Col_A VAR PORTB.6
Col_B VAR PORTB.5
Col_C VAR PORTB.4

Row_A VAR PORTB.0
Row_B VAR PORTB.1
Row_C VAR PORTB.2
Row_D VAR PORTB.3


RX_To_PC VAR PORTA.0

Scan_Col VAR BYTE ' Counter - denoting current col in scan
Key_Press VAR BYTE ' Contains value of key (0-9) & * + #
Key_Down VAR BYTE ' Flag set true when key is depressed
Allow_Key VAR BYTE ' Flag - disallow multiple keys being pressed
I VAR byte ' General working var
CROW_A VAR byte
CROW_B VAR byte
CROW_C VAR byte
CROW_D VAR byte
COROW_A VAR byte
COROW_B VAR byte
COROW_C VAR byte
COROW_D VAR byte
COLROW_A VAR byte
COLROW_B VAR byte
COLROW_C VAR byte
COLROW_D VAR byte
Scan_Keypad:

'// Scan cols
@ incf _Scan_Col, 1 ' Inc col pos...

SELECT CASE Scan_Col ' Col (1-3)

CROW_A = Col_A & Row_A
CROW_B = Col_A & Row_B
CROW_C = Col_A & Row_C
CROW_D = Col_A & Row_D

'// 1 Key
IF CROW_A = 0 THEN ' Key down? ...
IF Allow_Key = 0 THEN ' Any other key down?
Key_Press = 1 ' Load var w/value of key
Allow_Key = 1 ' Disallow other keys
ENDIF
ENDIF
'// 4 Key
IF CROW_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 4
Allow_Key = 1
ENDIF
ENDIF
'// 7 Key
IF CROW_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 7
Allow_Key = 1
ENDIF
ENDIF
'// * Key
IF CROW_D = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 42
Allow_Key = 1
ENDIF
ENDIF

Acetronics2
- 30th July 2007, 15:06
Hi, Raymon

If It's G.Samblancat's production ... do not be surprised if some "little" ( LOL ) bugs make you waste your time ...

Alain

RAYMON
- 30th July 2007, 21:34
The original program scans the keypadin order to determine the key to support or slacken one function of the ports of the peak. me I wish to write a routine which goes espionner any keyboard, for that of Jackson we have the source code and it is easy to see the management of its keyboard. But on another chart made by another, it is already the unknown thus one needs a program which goes espionner the keypad.
________________________________________________

Le programme original scrute le clavier afin de déterminer la touche appuyer ou relâcher on fonction des ports du pic. moi je souhaite écrire une routine qui va espionner n'importe quel clavier,pour celui de Jackson nous avons le code source et c'est facile de voir la gestion de son clavier. Mais sur une autre carte faite par un autre,c'est deja l'inconnu donc il faut un programme qui va espionner le clavier .
bonjour de Paris Merci AU 76

RAYMON
- 31st July 2007, 12:07
Hello

Here another program which uses another technique for the keypad, can help me has to write a routine or have an idea. my program does not have constrained foncionnement of the program has to supervise.

thank you

start:
pcode=0

clavier:
porta.2=0
trisb=%11110000 '0=out / 1=in
portb=%00000000
pause 10 'Let stabilize state
msb=portb
if msb=240 then 'No key pressed
goto clavier
endif

TRISB=%00001111 '0=out / 1=in
portb=%00000000
pause 10 'Let stabilize state
lsb=portb
if lsb=15 then 'Key is already released
goto clavier
endif
pause 100 'Enable one key press each 500ms

msblsb=msb + lsb 'Combine line & column

Acetronics2
- 31st July 2007, 16:17
Hi, Raymon

There's a little problem in your goal definition ...

you want to know what happens on EVERY keyboard ...

BUT ...

1) you have different key counts
2) you have "matrix" and "common" keyboard architecture ... plus a "diode" architecture that permits 56 keys instead of the classical 16 ones ( using a full port ...), plus the Key to resistance value system ...,plus ...

3) you have "digital" outputs and "serial" outputs ( like a PC keyboard ) ...

Reading what happens won't be the same manner for each keyboard ...

so ... I think you should , at first have a better definition of what you REALLY want to do ...

If you wanna paste Keyboard scanners ( like in Hollywood films ... i.e. ) ... think first it's ONLY movies ... really, really far from the reality !!!

1 Keyboard type = 1 Scanner type ... That's it !!!

Amitiés du 76

Alain

RAYMON
- 31st July 2007, 19:05
Only for the keypads 4X3 or 4X4, not for the keyboards PC or others. those which uses the columns and lines because the figures theirs are already to associate.
thank you

Dennis
- 19th November 2009, 15:40
Hi All
I would like to pronpt the user on my LCD for input ...
capture several key presses followed by a hash # signifying input is complete ...for example 123#
Display it on the LCD
Then transmit the number 123

I'm guessing something like



newkey VAR byte ' this would equal keypress1 , 2,3 etc

Pause 500 ' Wait for LCD to startup

main:

Lcdout $fe, 1 ' Clear LCD screen
Lcdout "Enter key followed by #" ' prompt user for input # denotes end of input
HERE"S where I'm struggling << how do i get the keypresses into one VAR
Lcdout "Input successful"
SEROUT RX_To_PC, N2400, [newkey]
pause 2000
Lcdout "Code sent"

goto main



So would i alter (if I may and can) Steves keypad code to somthing like
Instead of the Serout in the program send the first keypress to something like
Key_Press1 then Key_Press2 then Key_Press3 etc ...
and keep doing it until a # input is observed ?

Is this possible ?

Any help would be appreciated

Kind regards

Dennis

fratello
- 27th July 2011, 12:59
No more posts here...but hope to find help :) !
I try to build this device ; on pushing on different button - having one different result !
But...nothing happens :( ... Something's wrong ! Any advice ? Thanks !

@ DEVICE pic16F628A, INTRC_OSC, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_ON, LVP_OFF, CPD_OFF, PROTECT_OFF


Include "modedefs.bas" ' Serial Protocol
Define OSC 4 ' 4MHz crystal used
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode

'// Define port pins as inputs and outputs ...
TRISA = %00001000
TRISB = %00001100

'// Declare Variables...
Col_A VAR PORTB.1
Col_B VAR PORTA.2
Row_A VAR PORTA.3
Row_B VAR PORTB.3
Row_C VAR PORTB.2

Buzzer VAR PORTB.5

Scan_Col VAR BYTE ' Counter - denoting current col in scan
Key_Press VAR BYTE ' Contains value of key (0-9) & * + #
Key_Down VAR BYTE ' Flag set true when key is depressed
Allow_Key VAR BYTE ' Flag - disallow multiple keys being pressed
I VAR byte ' General working var

Scan_Keypad:

'// Scan cols
@ incf _Scan_Col, 1 ' Inc col pos...

SELECT CASE Scan_Col ' Col (1-2)

CASE 1
Col_A = 0 ' Switch on col (active low)
Col_B = 1 ' Col off

'// 3 Key
IF Row_A = 0 THEN ' Key down? ...
IF Allow_Key = 0 THEN ' Any other key down?
Key_Press = 3 ' Load var w/value of key
Allow_Key = 1 ' Disallow other keys
ENDIF
ENDIF
'// 6 Key
IF Row_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 6
Allow_Key = 1
ENDIF
ENDIF
'// 9 Key
IF Row_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 9
Allow_Key = 1
ENDIF
ENDIF

CASE 2
Col_A = 1
Col_B = 0


'// 2 Key
IF Row_A = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 2
Allow_Key = 1
ENDIF
ENDIF
'// 5 Key
IF Row_B = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 5
Allow_Key = 1
ENDIF
ENDIF
'// 8 Key
IF Row_C = 0 THEN
IF Allow_Key = 0 THEN
Key_Press = 8
Allow_Key = 1
ENDIF
ENDIF

Scan_Col = 0
END SELECT

'// Ouput key
IF Key_Down <> Key_Press THEN ' Key already been sent?
IF Key_Press <> 255 THEN ' 255 denotes no key press
IF Key_Press = 42 OR Key_Press = 35 THEN ' Numerical key?

'// Brief chrip of the piezo & flash of the LED
for i = 0 to 20
toggle buzzer
pause 5
next
gosub result_key
ENDIF
Key_Down = Key_Press ' Copy of key just sent
Buzzer = 0 ' Make sure LED is off
ENDIF
endif
'// Check for key release, all cols on (active low) ...
Col_A = 0
Col_B = 0

'// Reset flags allowing other keys to be processed if no keys are depressed
IF Row_A = 1 THEN
IF Row_B = 1 THEN
IF Row_C = 1 THEN
Allow_Key = 0
Key_Down = 0
Key_Press = 255
ENDIF
ENDIF
ENDIF

GOTO Scan_Keypad ' Loop back

Result_key :
SELECT CASE key_press
case 3
high buzzer
pause 1000
low buzzer
case 6
high buzzer
pause 2000
low buzzer
case 9
high buzzer
pause 3000
low buzzer
end select
return

fratello
- 27th July 2011, 20:09
Solved in another way... Thanks to Mr.Mister_e and Mr.Darrel !!!
The hardware is now : col_0 = portB.0 ; col_1 = portB.1 ; row_1-3 = portA.0-2

@ DEVICE pic16F628A, INTRC_OSC, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_ON, LVP_OFF, CPD_OFF, PROTECT_OFF


Include "modedefs.bas" ' Serial Protocol
Define OSC 4 ' 4MHz crystal used
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode

'// Define port pins as inputs and outputs ...
TRISA = %00000111
TRISB = %00000000

Buzzer VAR PORTB.5

include "c:\pbp\keypad2.pbp" ' see http://www.picbasic.co.uk/forum/showthread.php?t=3250

main:
gosub keypadscan
gosub check
goto main

check:
select case key
case 1
high buzzer
pause 1000
low buzzer

case 2
high buzzer
pause 2000
low buzzer

case 3
high buzzer
pause 3000
low buzzer

case 4
high buzzer
pause 4000
low buzzer

case 5
high buzzer
pause 5000
low buzzer

case 6
high buzzer
pause 6000
low buzzer

end select
Return

end 'of story !


Maybe it's useful for somebody !