PDA

View Full Version : calculator-like code entry with matrix keypad and display



Dennis
- 14th December 2009, 02:24
Hi all

In a part of the project I am busy building I would like to type in a few numbers using a 4x4 matrix keypad ..for example the number 123

The keypad portion works well so far (I am using the example from mister_e in the code examples area of the forums)

What I am battling with is how to get the digits that are typed in to display on the LCD and then send them only after a # or * is keyed in.
This operation is very similar to the way a calculator or code entry system acts.

So let's say for example I type in the number 123#
If a mistake is made the * key could backspace or clear the display with a prompt to try again (I haven't yet worked out whether to use and array or a select case statement or a bunch of if then statements)
I would like all digits typed in to be displayed on the LCD (just like a calculator/phone/code entry system)
I store the 3 digits in an array datatx[3]
Then I add the three digits datatx[0]+datatx[1]+datatx[2]
(This should give me a single binary number right ?)
once I have that number I would like to send it to the PC using HSEROUT
Here's the code I have so far,


'*************************************
'Keypress display on LCD and TX to wherever
'*************************************

'Ocsillator selections here
OSCCON = $70 'Int CLK 8MHz
OSCTUNE.6 = 1 'PLL 4x
ADCON1= %00001111 '$0F = disable A/D converter
cmcon = 7
INTCON2.7 = 0 'switch pull-ups ON
'END of oscillator selections
'timer/oscillator defines
DEFINE OSC 32 '4x 8MHz
'END of timer/oscillator defines

'Port IO directions and presets for port pins begin here
'TRISX = %76543210 << tris bit order numbering
'TRISA = %11111111 'All pins are outputs
'// Define port pins as inputs and outputs ...
TRISA = %00000000 'example only - TRISB = %00001111 ;Make B4-B7 outputs, B0-B3 inputs,
TRISB = %11111111 'for 4x4 keypad all input
TRISC = %10010000
TRISD = %00000000
TRISE.0 = 0
TRISE.1 = 0
TRISE.2 = 0
'End of Port IO directions and presets for port pins begin here


'variables begin here
A0 var byte
myvar var byte
datatx var byte [3]
datarx var byte
counter var byte
'net var byte
'end of variables

'LCD defines begin here
DEFINE LCD_BITS 4 'defines the number of data interface lines (4 or 8)
DEFINE LCD_DREG PORTD 'defines the port where data lines are connected to
DEFINE LCD_DBIT 4 'defines the position of data lines for 4-bit interface (0 or 4)
DEFINE LCD_RSREG PORTD 'defines the port where RS line is connected to
DEFINE LCD_RSBIT 2 'defines the pin where RS line is connected to
DEFINE LCD_EREG PORTD 'defines the port where E line is connected to
DEFINE LCD_EBIT 3 'defines the pin where E line is connected
'DEFINE LCD_RWREG 0 'defines the port where R/W line is connected to (set to 0 if not used)
'DEFINE LCD_RWBIT 0 'defines the pin where R/W line is connected to (set to 0 if not used)
DEFINE LCD_COMMANDUS 2000 'defines the delay after LCDOUT statement
DEFINE LCD_DATAUS 200 'delay in micro seconds
'END of LCD DEFINES

'includes begin here
INCLUDE "modedefs.bas"
include "c:\pbp\samples\keypad.bas"
'end of includes

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 207 ' 2400 Baud @ 32MHz, 0.17%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

'Keypad code begins here
DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 0 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 4 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
'end keypad code



'keypad capture code begins here


Pause 2000 ' Wait for LCD to startup
start: 'mister_e's keypad code
lcdout "1=send 2=program 3=
for counter = 0 to 3
@ READKEYPAD _myvar 'read keypress variable
LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
datatx = myvar 'pass the variable to solve strange character problem
lcdout "begin is ", dec datatx(0),dec datatx(1),dec datatx(2),dec datatx(3) 'display the variable on the LCD
if datatx = "#" then goto TX
'if datatx = "*" then goto clearkeys
pause 1000
Lcdout $fe,1
next counter
if counter = 3 then goto clearkeys

goto start

TX:
hserout ["i got this string of numbers",$0d,$0a]
HSEROUT ["1st digit ", dec datatx(0),$0d,$0a]
HSEROUT ["2nd digit ", dec datatx(1), $0d,$0a]
HSEROUT ["3rd digit ", dec datatx(2), $0d,$0a]

goto start

clearkeys:
datatx = 0
goto start
end


At this stage:
The LCD shows the 3 digits but only the first one ever changes
Hserout sends the data to the PC but the values are always the same.

I would really appreciate it if someone could help point out where I am going wrong

Kind regards
Dennis

Dennis
- 14th December 2009, 04:52
Ok so I have started sifting through the code, the way I have it made no sense.
So here's my altered code:


'keypad capture code begins here
myvar var byte [3]

Pause 2000 ' Wait for LCD to startup
start: 'mister_e's keypad code

for counter = 0 to 3
if counter = 3 then lcdout "press # to send"
@ READKEYPAD _myvar 'read keypress variable
LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
'datatx = myvar 'pass the variable to solve strange character problem
lcdout myvar
'lcdout datatx
'lcdout "begin is ", dec myvar(0),dec myvar(1),dec myvar(2),dec myvar(3) 'display the variable on the LCD
if myvar = "#" then goto TX
if datatx = "*" then goto clearkeys
pause 1000
' Lcdout $fe,1
next counter


goto start

TX:
hserout ["i got this string of numbers",$0d,$0a]
hSEROUT ["Received:",STR myvar\3,$0d,$0a]
'HSEROUT ["1st digit ", dec myvar(0),$0d,$0a]
'HSEROUT ["2nd digit ", dec myvar(1), $0d,$0a]
'HSEROUT ["3rd digit ", dec myvar(2), $0d,$0a]
'HSEROUT ["B4 ", datatrx(3), $0d,$0a]
'HSEROUT ["B5 ", datatrx(4), $0d,$0a]
goto clearkeys


clearkeys:
myvar = 0
goto start
lcdout $fe,1
end


Now what happens is :

1.LCD shows the keypresses one after the next - spot on!
The main issue I have here is that each keypress from the keypad is not the actual numeric number , in other words 1 is ascii 1 and I want the actual number one decimal aka binary 00000001 and hex 01.
As a solution I thought of doing a table lookup and then conversion for example if i receive the ascii for the 1 button then I do a convert to actual numeric 1 decimal, is there a smipler method ?
Any tips, tricks,workarounds or solutions for this would be welcome.

2.The array myvar is set to [3] in the code. This is fine but the issue is that the * or # character are also included into the array and I only want numbers and possibly letter.
Is there some sort of filter or I could do and exclude them from the array?
Do I need a second array variable ?

3. Hserout is not sending the array values through. Maybe I have messed something up because in the MCS serial port tool all I see is


i got this string of numbers
Received:#mi


Any help, tips,tricks,code mods and snippets or suggestions would be greatly appreciated.

Kind regards
Dennis

Ioannis
- 14th December 2009, 08:01
Hi Dennis.

Well, you think simple and in most cases this is good. But not this one!

OK. Lets take the number in your array, for example 1,2,3.

If at the end, if you add these 3 array elements together you will get 6, or binary 6 if you want.

What about 3,2,1? You will get the same, although is a completely different number. So you have to make calculations and multiply x100, x10 x1 and then sum up the result. Like we did at the second year of elementary school!

I think I did gave you a sample code for this.

Then you need some kind of LCD indexing (I covered this too, please look at your PMs).

The 1st position of the 1st row on LCDs is $80. So if you want to display at this place use:

LCDout $FE,$80+index,1st_character

Then index=index+1 and your next character goes to $80:

LCDout $FE,$80+index,2nd_character.

Of course all the above are pure an educational example. In your code you would put some traps for the index. Also you can avoid the addition in-line the LCDout command and make the index start from $80, etc all in a loop.

Sorry do not have the time to give you a complete working code.

Ioannis

Dennis
- 15th December 2009, 02:26
Hi Ioannis

Thanks a million for the reply,tips and guidance.

Yes Indeed it is your sample code as well as Aratti's that prompted this thread.

See the code snippet you sent me here (all original and intact with no changes)


array var byte[5]
index var byte
i var byte
word_v var word

'Get keypress
index=0

loop:
gosub key_read
if mykey=32 then loop 'No key press returns 32
array[index]=myvar
index=index+1
if index=5 then calculate_result
goto loop
...

caculate_result:
word_var=0:mult=10000
for i=index-1 to 0 step -1
word_var=word_var*mult+array[i]
mult=mult/10
next i
index=0
goto display_result


Ok so there were (and still are) quite a few things that didn't and don't make sense to me. And please understand I am battling to catch on to a lot of the coding tricks and reading the manual and forums and anything else that will give me some form of understanding to get functional.

I took the code snippet and dissected it, tried my best to comment it and then add it to what I had so far.
Then I compiled it solving each compile error as best I could (bearing in mind being a newbie it's difficult to spot common syntax errors and coding mistakes or areas that could be tweaked) and here is what I came up with:
[code]
'using mister_e's keypad code

array var byte[5] 'the array set at 5
index var byte
i var byte
word_var var word ' word for capturing data
mult var byte a byte for multiplication << sould this be a word

index=0 'sets index to 0

loopy: 'main loop for keypress capture


@ READKEYPAD _myvar 'read keypress variable
LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to dsiplay proper keypress
''if mykey=32 then loop 'No key press returns 32 '<<no idea what mykey yshould be ?? a var or a word ?and why 32?
array[index]=myvar 'build the array as the index number increases
index=index+1 'when the code runs past here add 1 to index var
if index=5 then calculate_result 'if the counter/index is 5 calculate result
goto loopy 'start the loop again


calculate_result: 'calculate results label
word_var=0 'set word variable to 0
mult=10000 'multiply result by 10000 to format number
for i=index-1 to 0 step -1 'for loop begins
word_var=word_var*mult+array[i] '
mult=mult/10
next i 'end of for statement
index=0 'set index to 0
goto display_result


goto start


display_result:
lcdout word_var
goto TX
TX:
hserout ["i got this string of numbers",$0d,$0a]
hSEROUT ["Received:",STR myvar\5,$0d,$0a]
'HSEROUT ["1st digit ", dec array(0),$0d,$0a]
'HSEROUT ["2nd digit ", dec array(1), $0d,$0a]
'HSEROUT ["3rd digit ", dec array(2), $0d,$0a]
'HSEROUT ["4th digit ", dec array(3), $0d,$0a]
'HSEROUT ["5th digit ", dec array(4), $0d,$0a]
'HSEROUT ["5th digit ", word_var, $0d,$0a]
goto clearkeys


clearkeys:
myvar = 0
goto loopy

end
[code]

So a few observations so far ...
The code allows for a # or * or A,B,C,D to be typed in, this messes everything up of course.
I have no idea what the array is holding when entering the keys.How can I display the whole array on the LCD ?
After typing in the first few characters like 00123 ended with a hash the code just does its own thing -- well at least that's how it seems.
HSEROUT works at least because everytime I press the # key I get things in MCS serial tool window, they're just wingdings and odd characters, but at least something is happening

Is there a way to capture each keystroke and then add convert them to binary and then add them together and then display the result as decimal ?

I used to have an 8-way dip switch connected to the PIC and then just set the binary number up on that and it was done ! Say for example the number 123 would be as easy as flipping the switches to 1111011 and that was that.
With a keypad I can type in the number by pressing keys 1 (wich is not 1 unless we do a look-up) same for 2 and 3 and then each number is independent and 8 bits in size.
So in order to get the number 123 into some sort of variable I have to

1.accept all keypresses into an array and filter out the keys *,#,A,B,C,D,and if any of these are encountered remove them from the array
(is there a table look-up I could implement for that ?

2.check the size of the array and if it's 3 digits then I should multiply each digit independently so 1 by 100 then 2 by 10 and 3 by 1 (or do nothing to 1)

3.once that's done I should then be able to add them together and finally derive a total ... this total can then be checked to see if it is VALID or not. For example if it is a 3 bit number and I only want a byte then it must be less than 255 otherwise generate an overflow error on lcd.

4.Finally I have the number , then it must either be converted to binary or decimal depending on where it should go.

And then to top it all off the modifiers for LCDOUT and HSERIN/OUT,HSERIN2/OUT SERIN/SEROUT SERIN2/OUT and their behaviour are all slightly different.

That said though, at least I have some code to start working with and I certainly am trying and battling along and I would really appreciate any help,tips,tricks on any of the stupid mistakes I am making or have made in the along the way to finally getting a working code/keypress/data entry system using a 4x4 or 3x3 keypad and LCD.
I was also wondering if this hasn't come up many a time before and it seems the forums are a little sparse for something that does exaclty this unless I am searching for the wrong info ?
Kind regards
Dennis

Dennis
- 15th December 2009, 04:37
Hi all

I am working on the digits now, and I think I have almost got it sorted (or not!)
I just can't see where I am going wrong and I'm sure it's the way I'm working with the array.

To somplify things I have given the variable a set number, the number 123 as in my examples above.
here's the code so far


Start:
Codex VAR BYTE
Temp VAR BYTE [3]
TempTot var byte
Codex = 123
Tempx var byte
'Find character for decimal 100 column
Tempx = Codex/100 'divide Codex by 100 'cos its the digit in 100's column
Temp(0) = Tempx + 48 'add 48 to get ascii value
lcdout "first " ,temp(0)
HSEROUT ["1st digit ", Temp(0),$0d,$0a]
pause 1000

'Find character for decimal 10 column
Tempx = Codex/10 'since Codex = 123 after dividing Temp = 12
Temp(1) = Tempx//10 'Remainder is required so with Codex = 123 the number in Temp = 2
Temp(1) = Tempx + 48 'add 48 to get ascii value
lcdout "second ",temp(1)
HSEROUT ["2nd digit ", Temp(1),$0d,$0a]
pause 1000
'Find character for decimal 1 column
Tempx = Codex//10 'Get Remainder so…with Codex = 123 then Temp = 3
Temp(2) = Tempx + 48 'add 48 to get ascii value
lcdout "third ",temp(2)
HSEROUT ["3rd digit ", Temp(2),$0d,$0a]
pause 1000
TempTot = Temp(0)+temp(1)+Temp(2)
hserout ["here's the binary total ",dec temptot,$0d,$0a]
hserout ["here's the binary total ",bin temp,$0d,$0a]
goto start


Observations:
The first and third digits are correct , the second is a problem (and I think it's the wrong number since it shows up as a ">" character ) so this obviously messes up the total after addition which ends up as 160 as opposed to 123 :-(
Here is what I see in the MCS serial tool window


1st digit 1
2nd digit <
3rd digit 3
here's the binary total 160
here's the binary total 110001


Any help would be appreciated

Dennis

aratti
- 15th December 2009, 08:23
Dennis you can use the DIG command:



Codex var Byte
Temp0 var Byte
Temp1 var Byte
Temp2 var Byte

Codex = 123

Temp0 = Codex DIG 0 ' set Temp0 = to digit 0 of Codex
Temp1 = Codex DIG 1 ' set Temp1 = to digit 1 of Codex
Temp2 = Codex DIG 2 ' set Temp2 = to digit 2 of Codex



That all you need.

Al.

Archangel
- 15th December 2009, 08:33
Hi Dennis,
Your code looks much more difficult to me than it needs to be, you are doing a lot of "yuck" MATH, Math not my forte' :D , Anyway after you
get your actual number into a variable, use the DIG function to acquire the digits.


Digit1 var byte
Digit2 var byte
Digit3 var byte
TempX var byte

Digit1 = TempX DIG 0
Digit2 = TempX DIG 1
Digit3 = TempX DIG 2

HSEROUT ["1st digit ", DEC Digit0,$0d,$0a] 'copied from your code
HSEROUT ["2nd digit ", DEC Digit1,$0d,$0a] 'copied from your code
HSEROUT ["3rd digit ", DEC Digit2,$0d,$0a] 'copied from your code

I haven't looked at your code close enough to understand what the Hex 0D and Hex 0A are for, nor have I tested this code snippet, but it should give you some ideas.
Dadgummit Al posted while I was typing! Same idea too! HiYa Al !

Dennis
- 15th December 2009, 20:14
Joe S and Al thanks so much for the reply !!

And both your codes snippets work like a charm !

I love the DIG command ...very cool !

They certainly did simplify mine somewhat :-)

OK so here's the deal so far.
The HSEROUT line is working well !
Each decimal digit is displayed correctly and in the correct order!
So a number like 123 gets sent and displayed correctly :-)

Now what remains is what I have been on about since the beginning of this thread and that is the following.

I need to get each keypress stored in an array and then 'JOIN' (either by adding them or some other method ) them up into one number..that's why I went off on a tangent in the last post.
All I would like to do is be able to send one bye or word containing the actual number keyed in.
I would like to be able to key in the number 123 (and see it on screen) and then send it as the actual number 123 decimal or binary or hex ...just not as 3 separate bytes. Consider the same thing being done with a bank of 8 dip switches ... I set the dip switches to reflect the number 123 (bin=11110111 and hex =A3) and that's what I would read in and send.
But this seems to be rather difficult to do using a keypad not so ?

Again any suggestions etc would be greatly appreciated

Kind regards
Dennis

Byte_Butcher
- 15th December 2009, 20:52
How about something like this:



keypressed var byte ' latest keypad entry
mynumber var word 'your number, built up from multiple key presses

' each time a key is pressed, do this:

mynumber = (mynumber * 10) + keypressed

Maybe?


steve

Dennis
- 15th December 2009, 21:49
Tried that ... it yeilds undesirable results .. and with each keypress a different value appears in MCS serial tool window :-(


the numbers are 34113
the numbers are 13500
the numbers are 3978
the numbers are 39830
the numbers are 5134

This is probably because the number is continuously multiplied each time the program loops at each keypress ... and the word value aslo can only store two bytes (16 bits)
This is how I tried your suggestion


'end of variables

Pause 2000 ' Wait for LCD to startup
Start:

@ READKEYPAD _myvar 'read keypress variable and place in myvar

LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to display proper keypress




lcdout myvar
lcdout $fe,1
pause 1000
mynumber = (mynumber * 10) + myvar
lcdout "my number ", dec mynumber
hserout ["the numbers are " ,dec mynumber,$0d,$0a]


The plan is along the right lines though!

1.Check keypress to see if it's valid (0-9,A,B,C,D)
2.Store each vaild keypress eg. 1,2,3 (number is 123) <<<<<<<<<<<THIS IS WHERE I HAVE A PROBLEM :( DON'T KNOW HOW TO WORK WITH THE ARRAY!
3.Check for # character which denotes a valid input
4.Take first character and (LSB) and multiply it by 1(byte 1)
5.Take next character and multiply by 10 (byte 2)
6.Take next character and multiply by 100 (byte 3)
7. Now add them up (in this example 100+20+3 = 123)
8.Check that number is valid ... <255 since it must be max one byte (8 bits)
123 is valid since it's less than 255
9.Display and send the number

Those are the steps I need to go through :-)

Hope that helps

Kind regards
Dennis

aratti
- 15th December 2009, 22:12
Dennis tray this snippet:



Array var Byte [3]
A0 var byte
B0 var Byte
KeyPress Var Byte ' will contain the ascii character of the key pressed

A0=0

Ini:
If KeyPress = "#" then
B0= (Array[0]*100)+(Array[1]*10)+Array[2]
HSEROUT [B0]
A0=0
ENDIF

If A0>2 then Ini

Array[A0]=KeyPress -48
A0=A0+1
goto Ini


Al.

Dennis
- 16th December 2009, 01:52
Al .... it's sort of working :-) YAY at least some light at last :-)

I tried your code snippet :-) and it sort of works :-)

You can now enter digits, each keypress shows up on the LCD , a # value denotes a send and a * denotes a clear and retry.

Ok so when I enter 123# , the correct number is sent to the PC com port and arrives perfectly at MCS serial tool window! YAY
In fact any 3 digit number within the range of 100 to 255 works well.
Anything larger is obviously too large for the var byte value so shows up as the number less 256 which means it is behaving correctly since I only want a max of one byte (0 to 255).
For example I enter 455# ,MCS serial tool shows the number as 199 (455-256) .

So the problem now is how to get numbers which are less than 3 digits to work.
For example if I enter the number 99 I get 227 in MCS serial tool
Another example is the number 1 (single digit) shows up as 195

I am trying to figure out why but can't see it as yet.

Another thing is if you do send a number larger that 255 or something less than 3 digits , the next few times , any valid 3 digit number entered is incorrectly displayed ...still looking to slove that one!
I added a retry: label .. which runs when you enter the * key. It clears the vars send pointer to beginning of the main loop :-)


If you have any updates or suggestions I would gladly try them

Please find the current (semi-working) code attached below

Kind regards

Dennis


myvar var byte 'var output from keypress
Array var Byte [3] 'array variable to hold 3 keypresses
A0 var byte 'counter/index
B0 var Byte 'sum of digits
KeyPress Var Byte 'holds each keypress as it happens
Pause 2000 ' Wait for LCD to startup


A0=0 'index = 0

Ini:

lcdout $fe,1
lcdout "enter number"
@ READKEYPAD _myvar 'read keypress variable and place in myvar

LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
keypress = myvar 'pass the variable to solve strange character problem
' will contain the ascii character of the key pressed

lcdout keypress
pause 1000
lcdout $fe,1
'If keypress = "a" or "b" or "c" or "d" then goto numbers
if keypress = "*" then goto retry
If KeyPress = "#" then 'check input keypress for a # value
B0= (Array[0]*100)+(Array[1]*10)+Array[2]'multiply each bit in the array by the correct column value
'if B0 > 255 then goto overflow 'test for overflow B0>255
HSEROUT ["here is the total ",dec B0,$0d,$0a] 'send result to pc com port

A0=0

ENDIF

If A0>2 then retry 'Ini

Array[A0]=KeyPress -48
A0=A0+1

goto ini

numbers: 'tell person to enter only numbers
lcdout "numbers only"
pause 1000
A0=0
myvar=0
goto ini

retry: 'is the * key is pressed then prompt for a retry and clear A0 and myvar
lcdout "retry"
pause 1000
lcdout $fe,1
A0=0
myvar=0
goto ini

overflow: 'tell person to enter 0 to 255 only
lcdout $fe,1
lcdout "0 to 255 ONLY!"
pause 1000
A0=0
myvar=0

goto ini

Jerson
- 16th December 2009, 04:34
Just some minor modifications to your code



myvar var byte 'var output from keypress
Array var Byte [3] 'array variable to hold 3 keypresses
A0 var byte 'counter/index
B0 var Byte 'sum of digits
KeyPress Var Byte 'holds each keypress as it happens
Pause 2000 ' Wait for LCD to startup


A0=0 'index = 0

Ini:

lcdout $fe,1
lcdout "enter number"
B0 = 0 ' start with 0 in the sum of digits
@ READKEYPAD _myvar 'read keypress variable and place in myvar
b0 = b0*10+_myvar ' add in the new number


LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
keypress = myvar 'pass the variable to solve strange character problem
' will contain the ascii character of the key pressed

lcdout keypress
pause 1000
lcdout $fe,1
'If keypress = "a" or "b" or "c" or "d" then goto numbers
if keypress = "*" then goto retry
If KeyPress = "#" then 'check input keypress for a # value
'if B0 > 255 then goto overflow 'test for overflow B0>255
HSEROUT ["here is the total ",dec B0,$0d,$0a] 'send result to pc com port

A0=0

ENDIF

If A0>2 then retry 'Ini

Array[A0]=KeyPress -48
A0=A0+1

goto ini

numbers: 'tell person to enter only numbers
lcdout "numbers only"
pause 1000
A0=0
myvar=0
goto ini

retry: 'is the * key is pressed then prompt for a retry and clear A0 and myvar
lcdout "retry"
pause 1000
lcdout $fe,1
A0=0
myvar=0
goto ini

overflow: 'tell person to enter 0 to 255 only
lcdout $fe,1
lcdout "0 to 255 ONLY!"
pause 1000
A0=0
myvar=0

goto ini

Archangel
- 16th December 2009, 06:29
Hi Dennis,
You might find this thread useful, check the zip files LLoyd posted.

Dennis
- 16th December 2009, 09:36
Hi Joe

Just curious as to what thread? Did you maybe forget to post the URL ?
Will search for all posts by LLoyd :)

Jerson ...Thanks a million will try iut and feedbask asap

Kind regards

Dennis

Dennis
- 16th December 2009, 09:56
Thanks for the modification suggestion

Have tried the code as you have it posted

First issue was a compile error on this line


b0 = b0*10+_myvar ' add in the new number

So I changed it to read


b0 = b0*10+myvar ' add in the new number

and it compiled.

The resultant output in MCS serial tool each time on any keypress is 15 ??

At the moment I'm scanning through to see what else you modified and where the issue lies, will feedback if and when I find the problem :-)

Kind regards
Dennis

Dennis
- 16th December 2009, 10:13
Joe ..

Did you mean this URL ?
http://www.picbasic.co.uk/forum/showthread.php?t=5695
Yes I have been checking it out too that one out too.
There's also this one
http://www.picbasic.co.uk/forum/showthread.php?t=3487&highlight=door+lock
and this one
http://www.picbasic.co.uk/forum/showthread.php?t=12110&highlight=calculator

Kind regards
Dennis

Ioannis
- 16th December 2009, 10:16
I recall now once used the keyboard subroutine and I think it returns 32 when no key is pressed. Have you checked for this? Except if you have a DEFINE SCAN_ONCE 1 on top of your code.

This way it waits in the @ READKEYPAD for as long as no key is pressed.

Ioannis

Dennis
- 16th December 2009, 10:21
Thanks for the reply :-)


Except if you have a DEFINE SCAN_ONCE 1 on top of your code.
I have that enabled :-)

Will try the code ;-)

Dennis

Jerson
- 16th December 2009, 10:50
Thanks for the modification suggestion

Have tried the code as you have it posted

First issue was a compile error on this line


b0 = b0*10+_myvar ' add in the new number

So I changed it to read


b0 = b0*10+myvar ' add in the new number

and it compiled.

The resultant output in MCS serial tool each time on any keypress is 15 ??

At the moment I'm scanning through to see what else you modified and where the issue lies, will feedback if and when I find the problem :-)

Kind regards
Dennis

You may also need to check for the * and # conditions before you modify the B0 variable like this



@ READKEYPAD _myvar 'read keypress variable and place in myvar

if myvar < 10 then
b0 = b0*10+myvar ' add in the new number
else
if myvar = 12 then retry ' check for * condition
if myvar =13 then ' check for # condition
HSEROUT ["here is the total ",dec B0,$0d,$0a] 'send result to pc com port
A0=0
endif
endif



As you can see, I have used the raw values from readkeypad and you may need to change the 12 and 13 to whatever it is you get for * and #

Archangel
- 16th December 2009, 16:39
Joe ..

Did you mean this URL ?
http://www.picbasic.co.uk/forum/showthread.php?t=5695
Yes I have been checking it out too that one out too.
There's also this one
http://www.picbasic.co.uk/forum/showthread.php?t=3487&highlight=door+lock
and this one
http://www.picbasic.co.uk/forum/showthread.php?t=12110&highlight=calculator

Kind regards
Dennis
Hi Dennis,
Yep, the first one, second page, where Lloyd posted the finished code he paid Mr_E to write. Since I do not know your exact plan here I thought you might discover how to handle the arrays and use the numbers. Also dunno why you use byte var hassel instead of using a word simply use something like

if tempx >999 then tempx = 999 or instead of 999 you could cause the routine to jump to a subroutine that handles errors or make 999 into a zero so it works to simply overflow.

Dennis
- 16th December 2009, 17:25
Hi guys

Just a few updates
Jerson ...still trying to see what's wrong with the code snippet you send .. did you try it at all ?
You mentioned raw characters .. did you mean I shouldn't do a lookup ?

Joe... I'm busy going through the gate entry code.

Will feedback as soon as I get more info :-)

Kind regards
Dennis

aratti
- 16th December 2009, 18:24
......So the problem now is how to get numbers which are less than 3 digits to work.
For example if I enter the number 99 I get 227 in MCS serial tool
Another example is the number 1 (single digit) shows up as 195

I am trying to figure out why but can't see it as yet.


Dennis the reason is that the array are no cleared. Add the three lines in red to the previous snippet and you are in business

Al.



Array var Byte [3]
A0 var byte
B0 var Byte
KeyPress Var Byte ' will contain the ascii character of the key pressed

A0=0

Ini:
If KeyPress = "#" then

if A0=2 then
B0= (Array[0]*100)+(Array[1]*10)+Array[2]
HSEROUT [B0]
endif

if A0=1 then
B0= (Array[0]*10)+Array[1]
HSEROUT [B0]
endif

if A0=0 then
B0= Array[0]
HSEROUT [B0]
endif

A0=0
Array[0]=0
Array[1]=0
Array[2]=0
ENDIF

If A0>2 then Ini

Array[A0]=KeyPress -48
A0=A0+1
goto Ini


PS. Dennis the matter was just more complicated so I added the complete correction. I sure you will understand where the problem was.
Al.

Dennis
- 16th December 2009, 18:34
Joe

Thanks for pointing me to the gate access example, unfortunately it does not cover what I am after.
The gate combo program compares each digit as it is typed in to a pre-stored value in eeprom and based on a successful match eventually enable a pin to go high.
Yes granted it does utilize mister_e's keypad code (thanks mister_e...brilliant job - it work's like a charm, no hassle no fuss!)

It does do a lookup as does my example and this is to get the raw scan codes into a 'familiar' character.

It does not capture each keypress into an array.
It does not sum the individual keystrokes and present them as a single byte or word.

I think the gate access code is awesome and I would just like to say thanks to Lloyd for offering the code after he had paid mister_e to write it.

And after having said that, it may be a good time to point out that as much as it is easy and simple to cut and paste pre-built code into the compiler window, this method does nothing for one's education and learning experience. I would like to battle along with code snippets and tips and tricks to eventually get to a working solution , however rough and un-polished it may be.

Yes , agreed , I'm sure it is less frustrating but where's the fun without battling along (especially for me a 'reborn' PIC newbie hobbyist) until 2 or 4am sometimes until I eventually get something working.
I find the forum a fantastic place to get other ideas and share experiences with others who have the same interest , be it hobby or vocation or otherwise.

As you know you can read the manual and google and read sources for hours and then eventually get to a point of giving up or coming right.
I think most of the people on the forum post a message at the point where they have reached the stage where they want to bash their head against a wall and decide to eventually give in and post a message.
Posting a message on the forums can be a rather daunting thought or task because quite often people flame someone for saying the wrong thing or being out of line, not only that, the person posting often feels quite shy since they may be laughed at or 'looked down upon' by some highly skilled few who don't suffer fools easily.
After having battled for nearly 3 months now to get where I am at, I completely understand a newbie's plight to getting functional.
And in the time I have been lurking around on these forums and seeing how to create new threads and add code snippets and URL's and also get into some sort of functional coding style.
I am more than happy to help someone get functional with their project and hope that someday I will have as much knowledge as most of the people who frequent this forum.

I would just like to say THANK YOU to all those who I have interacted with and who have offered assistance to my (sometimes) absurd and 'silly' questions :-)

And a big THANK to all of the people on this forum for keeping it going !

On a final note ....

I am still battling to capture 3 keystrokes into a var/byte/array ,index them , and then add them all up so that they are represented by one byte.
I just can't see where I am going wrong :-(

Kind regards

Dennis

Dennis
- 16th December 2009, 18:48
Hi Al


Welcome back :-) and how are you tonight ?

Was it Siesta time in Milano ?
:-)

Wondered if you had disappeared or given up on me :-)

Will try it right now and feedback asap !

By the way is that the reason for the anything but 3 bits correct value issue ?

Dennis

aratti
- 16th December 2009, 18:56
Wondered if you had disappeared or given up on me :-)


No Dennis, I had a long hard day at work!

Did you read also my added code?

Al.

Dennis
- 16th December 2009, 19:57
Hi Al ...

Sorry to hear about the long hard work day :-( it was a public holiday in my country .. so it felt like a weekend :-)

I tried the code and checked the lines in red.

I excitedly (stupidly I gues) just copied and pasted it in .... :-)
Well it didn't I now only ever see a 0 in hyperterminal for any number keyed in following the #

Time to debug :-) , if you see anything obvious just let me know and I will test.. will keep you posted

Kind regards

Dennis

Dennis
- 16th December 2009, 20:39
Al..
There is some odd behaviour now ... :-(
Here's updated code with added display options and cosmetics for testing.
So far # must be pressed twice and 126 is displayed for any number (1,2 or 3 digits) ??
Check clearing of var's and counter , will continue with tests, I'm willing to bet it's something really small causing the problem
Kind regards
Dennis



'keypad capture code begins here

'variables begin here

Array var Byte [3] 'byte array holds keypresses
A0 var byte 'counter/index
B0 var Byte 'working sum of bytes
KeyPress Var Byte ' will contain the ascii character of the key pressed passed from myvar
myvar var byte 'holds keypress byte
digit var byte 'check the number of bytes entered

start:
A0=0 'set index to 0

Ini: 'main loop

lcdout $fe,1
lcdout "enter number"
@ READKEYPAD _myvar 'read keypress variable and place in myvar

LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
keypress = myvar 'pass the variable to solve strange character problem
' will contain the ascii character of the key pressed

lcdout keypress
pause 1000
lcdout $fe,1

If KeyPress = "*" then goto retry

If KeyPress = "#" then 'if # conditions begin here

if A0=2 then 'if counter is 2 then sum all bytes
B0= (Array[0]*100)+(Array[1]*10)+Array[2] 'byte sum
lcdout "3 digits ",dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a] 'send result to pc com port
endif

if A0=1 then
B0= (Array[0]*10)+Array[1]
lcdout "2 digits " ,dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a]
endif

if A0=0 then
B0= Array[0]
lcdout "1 digit " ,dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a]
endif

A0=0
Array[0]=0
Array[1]=0
Array[2]=0
ENDIF

If A0>2 then Ini

Array[A0]=KeyPress -48
A0=A0+1
goto Ini

retry:
lcdout "retry"
pause 1000
lcdout $fe,1
A0=0
myvar=0
goto ini
goto start
end

aratti
- 16th December 2009, 20:57
Dennis, I think the bug was a missing goto. (see code added in red)

Al.



'keypad capture code begins here

'variables begin here

Array var Byte [3] 'byte array holds keypresses
A0 var byte 'counter/index
B0 var Byte 'working sum of bytes
KeyPress Var Byte ' will contain the ascii character of the key pressed passed from myvar
myvar var byte 'holds keypress byte
digit var byte 'check the number of bytes entered

start:
A0=0 'set index to 0

Ini: 'main loop

lcdout $fe,1
lcdout "enter number"
@ READKEYPAD _myvar 'read keypress variable and place in myvar

LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress
keypress = myvar 'pass the variable to solve strange character problem
' will contain the ascii character of the key pressed

lcdout keypress
pause 1000
lcdout $fe,1

If KeyPress = "*" then goto retry

If KeyPress = "#" then 'if # conditions begin here

if A0=2 then 'if counter is 2 then sum all bytes
B0= (Array[0]*100)+(Array[1]*10)+Array[2] 'byte sum
lcdout "3 digits ",dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a] 'send result to pc com port
endif

if A0=1 then
B0= (Array[0]*10)+Array[1]
lcdout "2 digits " ,dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a]
endif

if A0=0 then
B0= Array[0]
lcdout "1 digit " ,dec B0,$0d,$0a
pause 1000
lcdout $fe,1
HSEROUT ["here is the total ",dec B0,$0d,$0a]
endif

A0=0

GOTO Ini

ENDIF

If A0>2 then Ini

Array[A0]=KeyPress -48
A0=A0+1
goto Ini

retry:
lcdout "retry"
pause 1000
lcdout $fe,1
A0=0
myvar=0
goto ini
goto start
end


Al.

Dennis
- 16th December 2009, 21:11
Al...

First issue is solved :-)
A0=A0-1 was needed :-) this was causing the # to be included in the array :-)
So to solve that problem just step the counter back by 1 :-)
I placed it here in the code :-)


If KeyPress = "#" then 'if # conditions begin here
A0=A0-1


That fixed incorrect numbers issue.
So first time I power up the PIC , I enter a number (1,2 or 3 digits in size) and end with a # and whammo the correct number appears on screen :-) YAY
The problem comes in when as you enter number two .. and three etc ...
each displayed number is out !
It's because the variable does not get cleared ( not sure which one yet)
I noticed that last night (early hours of this morning :-)) and created a retry label which clears the var's and array..particularly myvar << which i think is the culprit !

Haven't tested your goto change yet ....stand by for feedback, will do it asap :-)
Al .. I just noticed you also removed the array clearance , why ? Is it because of the goto ?
Kind regards

Dennis

Dennis
- 16th December 2009, 21:22
Al...

Goto does not fix the problem
With goto in place and your code fro your last post in place unchanged...
after PIC is powered up, first number I enter is 1 and it displays as 10 (10X keypress)the number 20 is 140 ..weird !!
Ok will implement my changes and sort through it now and feedback asap :-)
Dennis

Dennis
- 16th December 2009, 21:29
Al ......

You rock !! Woooohoooo :-)

Ok GOTO was the bug !
for clearing the var's
A0=A0-1 is solution for strange numbers appearing after first keypress.
this problem is caused by the # value ( and the A,B,C,D keys would cause the same issue)

I no longer need to run the code through the retry label anymore ..yay less code! :-)

Any further thoughts mods etc ?

Dennis

aratti
- 16th December 2009, 21:49
this problem is caused by the # value ( and the A,B,C,D keys would cause the same issue

Dennis # character is intercepted by the IF/Then condition and the added " goto ini " command should have solved the issue. As far as A,B,C,D and F just place a trap with an additional IF/then condition. See the example:



If KeyPress >57 then Ini
If KeyPress = "*" then goto retry


Since only "*" ; "#" and numbers from "0" to "9" can pass the if/then condition, this should solve the problem.

Take care.

Al.

Dennis
- 16th December 2009, 21:55
Hi again

I'm wondering if this could become more dynamic in terms of the number of keypresses.
At the moment the keypresses are limited to 3, after that number the program goes a little wonky because of the B0 var which holds the sum of the 3 keypresses (hats off to Al !)
As soon as the desired/required number of keypresses has to increase, the so the need for multiplying increases .

I'm sure the program could be easily sized for a much higher number of keypresses by having more if statements and multiplies. To neaten things up perhaps a single case statement could be used and a check is kept on the index A0 in a byte.
With this in mind, the number of keypresses (number entered) could grow to the size of the number of characters on the LCD ( well almost :-))
This of course now opens the door for a PIC calculator :-)

Al,Ioannis,Joe S, Steve and Jerson ...THANK YOU for all the tips help and suggestions so far :-)
Al thank you for your patience and persisitence and of course the final piece of the puzzle.

This has taught me lot and has been a whole lot of fun!

Again thanks all of you for all the help thus far.

I will post the final code once things are neatened up and commented correctly :-) in the hopes someone finds this useful sometime !

Kind regards
Dennis

Dennis
- 16th December 2009, 22:02
Dennis # character is intercepted by the IF/Then condition and the added " goto ini " command should have solved the issue. As far as A,B,C,D and F just place a trap with an additional IF/then condition. See the example:

I get that ! :-)

But whats the > 59 doing here?




If KeyPress >59 then Ini
If KeyPress = "*" then goto retry


Since only "*" ; "#" and numbers from "0" to "9" can pass the if/then condition, this should solve the problem.

Take care.

Al.

Al.. the goto ini didn't solve the problem .. I had to add the A0=A)-1 ..one extra line no problem.
I think with * it's not a problem because as soon as * is detected the program jumps to retry ...which clears the variables ..
# is different and unfortunately does get included in the array , well at least that's what I'm guessing. Will definitely bug track to see what really happens :-) and feedback to you !

Kind regards
Dennis

aratti
- 16th December 2009, 22:58
But whats the > 59 doing here?

Sorry Dennis, I have mistaken It should be 57 (If KeyPress >57 then Ini)

57 is the ascii value for "9" so if a number is larger then 57 is not loaded into the array.

Download the zipped application I have attached, and run it on your PC. It will help you in converting ascii into decimal hex or binary and vice versa.
Just type into the box the corresponding value and press enter, you will have that value converted into the other three numerical sytem.

enjoy.

Al.