PDA

View Full Version : Keypad entry?



TONIGALEA
- 7th August 2004, 13:51
Hello Guys
i am using the example from melab keypad entry to enter numbers like 2 digits,3 digits, 4 digits etc
i modifiad the program below for 3 digits but know there has to be a better way of doing this.
this program relies on the user entering a 3 digit number but want to make it flexible so that any number of digits between 1 to 5 can be entered .
Any help would be appreciated

Toni





'************************************************* ***************
'* Name : keypad.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2004 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 9/27/04 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

DEFINE LOADER_USED 1 ' uses a bootloader
Include "Modedefs.Bas"


Define OSC 20
clear

' Setup Hardware for uart
DEFINE HSER_BAUD 115200
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_CLROERR 1


DEFINE LCD_DREG PORTD ' Use Portd for LCD Data
DEFINE LCD_DBIT 4 ' Use Upper(4) 4 bits of Port
' PORTD-4 thru PORTD-7 connects to
' LCD DB4 thru LCD DB-7 respectively
DEFINE LCD_RSREG PORTE ' PORTE for RegisterSelect (RS) bit
DEFINE LCD_RSBIT 0 ' PORTE-0 pin for LCD's RS line
DEFINE LCD_EREG PORTE ' PORTE for Enable (E) bit
DEFINE LCD_EBIT 1 ' PORTE-1 pin for LCD's E line

DEFINE LCD_BITS 4 ' Using 4-bit bus
DEFINE LCD_LINES 2 ' Using 2 line Display
DEFINE LCD_COMMANDUS 2000 ' Command Delay (uS)
DEFINE LCD_DATAUS 50 ' Data Delay (uS)

' ** Define LCD Control Constants **

I CON 254 ' Control Byte
Clr CON 1 ' Clear the display
Line1 CON 128 ' Point to beginning of line 1
Line2 CON 192 ' Point to beginning of line 2

' Define program variables
col var byte ' Keypad column
row var byte ' Keypad row
key var byte ' Key value

bigword var word
NUM VAR BYTE[3]
x VAR BYTE

' Initialise Hardware
' -------------------
ADCON1 = 7 ' Make PORTA and PORTE digital
TRISA=%00000000
TRISB=%00000000
TRISC=%10000000
OPTION_REG.7 = 0 ' Enable PORTB pullupsTRISD=%00000000



pause 1000
Low PORTE.2 ' LCD R/W low (write)

lcdout I,Clr:Pause 30
lcdout I,Line1," KEY PAD TEST "
lcdout I,Line1,"..Power UP.. !!"
pause 500


loop:
lcdout I,Clr:Pause 30
lcdout I,Line1, "Press any key" ' Display sign on message
gosub getword
lcdout I,Clr:Pause 30
lcdout I,Line2,#bigword
pause 1000
Goto loop




' Subroutine to get a key from keypad
getkey:
Pause 50 ' Debounce

getkeyu:
' Wait for all keys up
PORTB = 0 ' All output pins low
TRISB = $f0 ' Bottom 4 pins out, top 4 pins in
If ((PORTB >> 4) != $f) Then getkeyu ' If any keys down, loop

Pause 50 ' Debounce

getkeyp:
' Wait for keypress
For col = 0 to 3 ' 4 columns in keypad
PORTB = 0 ' All output pins low
TRISB = (dcd col) ^ $ff ' Set one column pin to output
row = PORTB >> 4 ' Read row
If row != $f Then gotkey ' If any keydown, exit
Next col

Goto getkeyp ' No keys down, go look again

gotkey: ' Change row and column to key number 1 - 16
key = (col * 4) + (ncd (row ^ $f))
Return ' Subroutine over
getword:
for x = 1 to 3
Gosub getkey ' Get a key from the keypad
lcdout I,Line2+x,#key ' Display ASCII key number
NUM[x]=key
next
bigword= NUM[1]*100 + (NUM[2]*10)+(NUM[3])

return

End

Melanie
- 7th August 2004, 14:52
Well Toni... you have to make some kind of decisions here...

I'm going to ask you to close your eyes and think of the number of digits I'm holding up in my left hand right now. Not easy to guess is it? Same with your PIC. It's trying to guess how many digits you want to enter... so basically we have these choices...

1. Fixed Length

The PIC waits until you've entered a fixed number of Digits... say three or five or whatever, and then goes away to process the result. This is the method used for typically Pass-Key applications for Door-Entry or those cheap worthless safes you see with Digital Locks.

A more advanced (and proper) version of this incorporates a timeout, so that once entry begins, it must be completed within a set time period, otherwise everything is reset back to the beginning. For example if you have a 3-digit door entry code, but somebody only enters two digits and walks away, you don't want those two-digits to remain 'in the system' forever, so the next user gets a fresh start at entering three digits cleanly.

2. Variable Length - Record Delimited Method

Here you enter as many digits as you want, and then you terminate your data-entry with an 'Enter' (Return) Key or similar (eg the way you send AT commands to your modem). this is called the Record Delimiter, and on receipt the host will know that you've finished entering your variable-length data and it now has to go away and process it. If you have a numeric keypad, then the chances are you've got a '*' or '#' key which you can assign to this task. So, now for example if you want to enter the numeric value 671, you would key '671*' or '671#'. This is the kind of method employed by automated telephone Credit-Card or Banking applications... "Please enter your account number followed by the Hash or Square Key"... and by the more technically advanced telephone drug dealers... "If you want to buy Marijuana please press the Hash key".

That last comment will probably go over the heads of our American friends as they know it as the "Pound" key. Why?

3. Variable Length - Timeout Method

Here the method is as I described in section 2 above, however the Record delimiter here is TIME. For example four seconds after you've entered your last digit the host decides that since no more keys have been pressed, this is all that is to be accepted. The drawback here is that you can't hesitate too long between digits as the host will assume (rightly or wrongly) you're not going to enter any more. If you leave the timeout too long, then the user gets bored waiting for his front door to open and he'll climb in thru the window.

That's basically all your choices. Fixed length is easy... everybody uses it. Variable length has to be delimited by some method so the host knows when it can start processing the entered data.

There is actually a fourth method... rarely used and difficult to impliment correctly...

4. Variable Length - Lookup Method

As the user types in the data, the host is performing lookup in real-time... and performs its programmed action if the lookup matches the entered data. The critical factor here is TIME, otherwise (say it's a door-entry application), if the user enters 333741 and the door unlock code is 3337, the host will unlock the door incorrectly after the fourth digit has been entered. Therefore you normally employ the Lookup "in arrears" that is after allowing some finite time to see if another digit is going to be entered. So really this method when implimented correctly, actually becomes a variation of Method 3.

Melanie

TONIGALEA
- 8th August 2004, 11:43
Thanks Mel for making the time to explain it all to me i have looked at all your suggestions and i think i would go down the option 2. Variable Length - Record Delimited Method
i am going to try it out myself today and i would let you know how i got on later

Thanks again for all your help
Toni

TONIGALEA
- 8th August 2004, 16:10
i managed to get what i wanted using the following code and your advise.
with this i can enter a number that is up to a word value.
it would need some improvements but its also simple .
Let me know what you think '************************************************* ***************
'* Name : keypad.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2004 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 9/27/04 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************

DEFINE LOADER_USED 1 ' uses a bootloader
Include "Modedefs.Bas"


Define OSC 20
clear

' Setup Hardware for uart
DEFINE HSER_BAUD 115200
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_CLROERR 1


DEFINE LCD_DREG PORTD ' Use Portd for LCD Data
DEFINE LCD_DBIT 4 ' Use Upper(4) 4 bits of Port
' PORTD-4 thru PORTD-7 connects to
' LCD DB4 thru LCD DB-7 respectively
DEFINE LCD_RSREG PORTE ' PORTE for RegisterSelect (RS) bit
DEFINE LCD_RSBIT 0 ' PORTE-0 pin for LCD's RS line
DEFINE LCD_EREG PORTE ' PORTE for Enable (E) bit
DEFINE LCD_EBIT 1 ' PORTE-1 pin for LCD's E line

DEFINE LCD_BITS 4 ' Using 4-bit bus
DEFINE LCD_LINES 2 ' Using 2 line Display
DEFINE LCD_COMMANDUS 2000 ' Command Delay (uS)
DEFINE LCD_DATAUS 50 ' Data Delay (uS)

' ** Define LCD Control Constants **

I CON 254 ' Control Byte
Clr CON 1 ' Clear the display
Line1 CON 128 ' Point to beginning of line 1
Line2 CON 192 ' Point to beginning of line 2

' Define program variables
col var byte ' Keypad column
row var byte ' Keypad row
key var byte ' Key value

bigword var word ' Calculated keypad entry
NUM VAR word[7] 'Number of digits
x VAR BYTE

' Initialise Hardware
' -------------------
ADCON1 = 7 ' Make PORTA and PORTE digital
TRISA=%00000000
TRISB=%00000000
TRISC=%10000000
OPTION_REG.7 = 0 ' Enable PORTB pullupsTRISD=%00000000



pause 1000
Low PORTE.2 ' LCD R/W low (write)

lcdout I,Clr:Pause 30
lcdout I,Line1," KEY PAD TEST "
lcdout I,Line1,"..Power UP.. !!"
pause 500


loop: bigword=0
NUM[1]=0:NUM[2]=0:NUM[3]=0:NUM[4]=0:NUM[5]=0
lcdout I,Clr:Pause 30
lcdout I,Line1, "Press any key" ' Display sign on message
gosub getword
lcdout I,Clr:Pause 30
lcdout I,Line2,#bigword

pause 1000
Goto loop




' Subroutine to get a key from keypad
getkey:
Pause 50 ' Debounce

getkeyu:
' Wait for all keys up
PORTB = 0 ' All output pins low
TRISB = $f0 ' Bottom 4 pins out, top 4 pins in
If ((PORTB >> 4) != $f) Then getkeyu ' If any keys down, loop

Pause 50 ' Debounce

getkeyp:
' Wait for keypress
For col = 0 to 3 ' 4 columns in keypad
PORTB = 0 ' All output pins low
TRISB = (dcd col) ^ $ff ' Set one column pin to output
row = PORTB >> 4 ' Read row
If row != $f Then gotkey ' If any keydown, exit
Next col

Goto getkeyp ' No keys down, go look again

gotkey: ' Change row and column to key number 1 - 16
key = (col * 4) + (ncd (row ^ $f))
Return ' Subroutine over
getword:
for x = 1 to 7

Gosub getkey ' Get a key from the keypad
if key = 10 then key = 0
if key = 16 then goto breakout
lcdout I,Line2+x,#key ' Display ASCII key number
NUM[x]=key
next
breakout:

if x = 2 then
bigword= NUM[1]
endif
if x = 3 then
bigword= NUM[1]*10 + (NUM[2]*1)
endif
if x = 4 then
bigword= NUM[1]*100 + (NUM[2]*10)+(NUM[3])
endif
if x = 5 then
bigword= NUM[1]*1000 + (NUM[2]*100) +(NUM[3]*10)+(NUM[4]*1)

endif
if x = 6 then
if( NUM[1]>6)or ( NUM[2]>5) then goto large
bigword= NUM[1]*10000 + (NUM[2]*1000) +(NUM[3]*100)+(NUM[4]*10)+(NUM[5])

endif
return

large :
lcdout I,Line2," Value Too Large"
pause 500
goto loop
End

















Best Regards
Toni