How to Store a multi-digit (up to 7)number from keypad entry?

Started by basiclover, Feb 22, 2022, 08:03 AM

Previous topic - Next topic

basiclover

As the InKey function does store only a single digit at a time I imagined to do the following:
-convert the single inkey digit to string
-concatenate  the successive converted digit into a single tring
-Convert that string to decimal value, but don't find anything in the manual to do that.
Help greatly appreciated

RGV250

Hi,
I suppose a lot has to do with how you are going to use the returned values, my first thought is to just create an array of bytes and store press 1 in pos 0 and so on.

Regards,
Bob

basiclover

I want to control a DDS Ad9850 entering the required frequency from a keypad

Stephen Moss

Might not be the best method as it is just of the top of my head and I am assuming that you are inputting the required decimal value via the keyboard but...
1) Create an array to hold the Inkey data big enough to hold the required number of digits and load the populate it with the Inkey data
2) Once all Inkey data is collected use a For-Next loop that checks all the elements in the array and adds the data to a string using the Str$ command, i.e.

For A = 0 to 5 'For 6 element Array
StringName = StringName + Str$(ArrayName(A))
Next

However you do it I think you will need to use the Str$ command in the manual so read up on that.

david

Maybe something like this-

kpad:   While InKey=16: Wend           'wait for key press
       num=LookUp InKey,[42,0,35,255,7,8,9,255,4,5,6,255,1,2,3] 'translate value
      If num<10 Then freq=freq*10+num
      If freq<10 Then Cls
      Print At 1,1, Dec freq,"Hz"   
      If freq >9999999  Then GoTo option1    'exit with correct entry
      While InKey<>16:Wend   'wait for key up
      DelayMS 50             'debounce
      GoTo kpad

option1: Print At 2,1, "*=New  ",At 2,10,"#=Run" 
         While InKey<>16:Wend            'wait for key release
         DelayMS 50               
         While InKey=16: Wend           'wait for key press
         num=LookUp InKey,[42,0,35] 'translate value *  0  #
       If num=42 Then GoTo new     '*
       If num=35 Then GoTo dds     '#


The third line does it all but you need an exit prompt so that you can do number, number, number, , , and then a hash symbol to say entry is finished.  The example given was used for 10MHz and upwards, hence the exit at >9,999,999.

Cheers,
David

david

This may be more concise-

kpad:   While InKey=16: Wend           'wait for key press
      num=LookUp InKey,[42,0,35,255,7,8,9,255,4,5,6,255,1,2,3] 'translate value
      If num<10 Then number=number*10+num
      Print At 1,1, Dec number," Hz  " 
      If num=35 Then GoTo freq 'exit on # key back to loop.
      While InKey<>16:Wend   'wait for key up
      DelayMS 50             'debounce
      GoTo kpad

Cheers,
David

basiclover

@ RGV250 & stephen Moss
I already thought about arrays, but all the functions about arrays are for string arrays, and I nees a number

basiclover

@ DAVID
your suggestion seems very interesting
I'm going to work it out to my requirements
thanks a lot

RGV250

Hi,
QuoteI already thought about arrays, but all the functions about arrays are for string arrays, and I nees a number
I am not sure where you have been looking but you can definitely store numbers in arrays.

Page 48 of the manual.
Dim MyByteArray[10] as Byte ' Create a 10 element unsigned byte array

In your code something like  MyByteArray
  • = ValueReturned  will store the value returned from the keypress.

Bob

RGV250

Hmm,
It did not like the square brackets without being in a code box, it should look like
MyByteArray[x] = ValueReturned
Bob

basiclover

@ RGV250
you are right, it's not always straightforward to find what you need in this big manual.I will experiment simple code with arrays to familiarise with as soon as I receive my keypad within the next days and come back if I need more help
Thanks

top204

As has been shown above, there are many ways to convert the key presses from a keypad into a value, so here are a couple of my ideas that I've just thrown together. It also shows the flexability, and ease of understanding, of the Positron compilers, when a fully working and usable program can be created in approx 30 minutes:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Read a 4x3 keypad and convert the digits into an integer or floating point value, depending on which procedure is called
' Written for the Positron8 compiler by Les Johnson
'
    Device = 18F25K20                                       ' Use an 18F device
    Declare Xtal = 16                                       ' Tell the compiler what frequency the device is running at
    Declare Float_Display_Type = Fast                       ' Use the faster, more accurate, floating point display library routine
'
' Setup USART1
'   
    Declare Hserial_Baud = 9600
    Declare HRSOut1_Pin = PORTC.6
'
' Setup the keypad's Port
'   
    Declare Keypad_Port PORTB
   
    Include "Strings.inc"                                   ' Load the Strings library into the code for the StringToFloat procedure
'
' Create some variabes for the demo
'   
    Dim dValue As Dword                                     ' Holds the result of the integer keypad routine
    Dim fValue As dValue.Float                              ' Aliased to hold the result of the floating point keypad routine
   
'--------------------------------------------------------------------
' The main program starts here
' Get value entries from the keypad and transmit the ASCII result to a serial terminal
'
Main:
    Do                                                      ' Create a loop
        HRSOutLn "\rType a Floating Point value on the keypad\r",
                 "* key is the decimal point, # is the exit key"       
        fValue = fKeyPad()                                  ' Convert a floating point value from the keypad     
        HRSOutLn "Value typed is ", Dec2 fValue             ' Transmit the ASCII value to a serial terminal
       
       
        HRSOutLn "\rType an Integer value on the keypad\r",
                 "# is the exit key"
        dValue = iKeyPad()                                  ' Convert an integer value from the keypad
        HRSOutLn "Value typed is ", Dec dValue              ' Transmit the ASCII value to a serial terminal
    Loop                                                    ' Do it forever

'--------------------------------------------------------------------
' Read a 4x3 keypad and return the integer value typed on it when the # key is pressed
' Input     : None
' Output    : Returns the integer value typed into the keypad
' Notes     : Exits the procedure when the # key is pressed
'
Proc iKeyPad(), Dword
    Dim bPrevKey As Byte = 16                               ' Create a variable to hold the previous key pressed
    Dim bIndex As Byte = 0                                  ' Create a variable to hold the index of ValString
    Dim ValString As String * 10 Heap                       ' Create a string variable to hold the ASCII keypress values
    Dim bKey As Byte                                        ' Holds the value from the keypad

    Clear ValString                                         ' Clear the string before entering the loop   
    Do                                                      ' Create a loop
        bKey = InKey                                        ' Read the keypad
        DelayMS 50                                          ' A small debounce delay
        bKey = LookUp bKey, [49, 50, 51, 16,                ' \
                             52, 53, 54, 16,                ' |
                             55, 56, 57, 16,                ' | Convert the keypad layout to relative ASCII values
                             16, 48, 13, 16]                ' /
        If bKey <> bPrevKey Then                            ' Is the current key press the same as the last key press?
            If bKey <> 16 Then                              ' No. So is the keypad value 16 (no key pressed)?
                If bKey = 13 Then                           ' No. So is the # key pressed?
                    Result = Val(ValString, Dec)            ' Yes. So convert the ASCII value held in ValString into an integer
                    Repeat : Until InKey = 16               ' Wait for the keypad to be free of presses
                    ExitProc                                ' Exit the procedure
                EndIf
                ValString[bIndex] = bKey                    ' Add the ASCII digit to the String
                Inc bIndex                                  ' Increment up the String
            EndIf
        EndIf
        bPrevKey = bKey                                     ' Keep a record of the key pressed       
    Loop                                                    ' Loop until the # key is pressed
EndProc

'--------------------------------------------------------------------
' Read a 4x3 keypad and return the floating point value typed on it when the # key is pressed
' Input     : None
' Output    : Returns the float value typed into the keypad
' Notes     : The * key is the decimal point
'           : Exits the procedure when the # key is pressed
'
Proc fKeyPad(), Float
    Dim bPrevKey As Byte = 16                               ' Create a variable to hold the previous key pressed
    Dim bIndex As Byte = 0                                  ' Create a variable to hold the index of ValString
    Dim ValString As String * 10 Heap                       ' Create a string variable to hold the ASCII keypress values
    Dim bKey As Byte                                        ' Holds the value from the keypad

    Clear ValString                                         ' Clear the string before entering the loop   
    Do                                                      ' Create a loop
        bKey = InKey                                        ' Read the keypad
        DelayMS 50                                          ' A small debounce delay
        bKey = LookUp bKey, [49, 50, 51, 16,                ' \
                             52, 53, 54, 16,                ' |
                             55, 56, 57, 16,                ' | Convert the keypad layout to relative ASCII values, including the decimal point
                             46, 48, 13, 16]                ' /
        If bKey <> bPrevKey Then                            ' Is the current key press the same as the last key press?                 
            If bKey <> 16 Then                              ' No. So is the keypad value 16 (no key pressed)?
                If bKey = 13 Then                           ' No. So is the # key pressed?
                    Result = StringToFloat(ValString)       ' Yes. So convert the ASCII value held in ValString into a floating point value
                    Repeat : Until InKey = 16               ' Wait for the keypad to be free of presses
                    ExitProc                                ' Exit the procedure
                EndIf
                ValString[bIndex] = bKey                    ' Add the ASCII value to the String
                Inc bIndex                                  ' Increment up the String
            EndIf
        EndIf
        bPrevKey = bKey                                     ' Keep a record of the key pressed       
    Loop                                                    ' Loop until the # key is pressed
EndProc   

With the keypad used in the circuit, the "*" pad is the decimal point, and the "#" pad is the enter key to finish the conversion. With some changes to the mechanisms used in the above program, the keypad entry system can also be made to work within the flow of a program, instead of its own loop.

I've been looking for a reason to create a keypad entry procedure for a while, so the above routines will now go into my Si4732 radio chip project, to enter the frequency it will operate at. :-) This will work alongside the rotary encoder mechanism for changing values of some of the device's settings.

Below is the above program running in a simulator:

Keypad Entry.jpg

John Drew

Hi Les,
Would you consider putting those procedures in the Wiki?
Unless you plan to put them in the manual that is.
Cheers
John

top204

I forgot about the Wiki John. Thanks for reminding me.

I've added the above thread to the Wiki's Keypad section. I may also add something similar to the compiler's manual because it is a useful addition. However, the manual is getting larger and larger and, sometimes, too large is a bad thing. :-)

I will also be adding it, and a more refined version of it I created last night, to my web site, if I ever get the time to get into it. :-)

John Drew

All good Les,
I always find the manual incredibly helpful. A good PDF index finds things easily.
Positron manual has plenty of room to grow and it's a darn sight easier to read than my Delphi manuals  :)
John

basiclover

Thanks a lot LES for your code

It will take me several days to fully understand your code and simultaneously reading the manual for things I'm not yet familiar with. That keeps my old brain alive...