calculator-like code entry with matrix keypad and display


Closed Thread
Results 1 to 36 of 36

Hybrid View

  1. #1

    Default calculator-like code entry with matrix keypad and display

    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,
    Code:
    '*************************************
    '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

  2. #2


    Did you find this post helpful? Yes | No

    Default not wysiwig!

    Ok so I have started sifting through the code, the way I have it made no sense.
    So here's my altered code:
    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
    Code:
    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

  3. #3
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    4,132


    Did you find this post helpful? Yes | No

    Default

    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

  4. #4


    Did you find this post helpful? Yes | No

    Default lost...

    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)
    Code:
     
    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
    Last edited by Dennis; - 15th December 2009 at 02:29.

  5. #5


    Did you find this post helpful? Yes | No

    Default doing the math !

    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
    Code:
    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
    Code:
    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
    Last edited by Dennis; - 15th December 2009 at 04:50. Reason: Now I'm wondering if I should be multiplying and not dividing :-(

  6. #6
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Dennis you can use the DIG command:

    Code:
    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.
    All progress began with an idea

  7. #7
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    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' , Anyway after you
    get your actual number into a variable, use the DIG function to acquire the digits.
    Code:
    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 !
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

Similar Threads

  1. a little help with keypad on 18f4520 please
    By Dennis in forum mel PIC BASIC Pro
    Replies: 17
    Last Post: - 24th November 2009, 20:38
  2. Keypad input test
    By Kalind in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 8th October 2008, 04:00
  3. Need help in matrix keypad coding
    By rano_zen06 in forum mel PIC BASIC Pro
    Replies: 15
    Last Post: - 24th May 2008, 13:16
  4. LCD display not working properly
    By dilpkan in forum mel PIC BASIC Pro
    Replies: 14
    Last Post: - 2nd February 2008, 07:43
  5. Keypad entry?
    By TONIGALEA in forum General
    Replies: 3
    Last Post: - 8th August 2004, 16:10

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts