B4R Question 4 x 4 Keypad: Conversion of string to integer.

Discussion in 'B4R Questions' started by mark35at, Jul 17, 2018.

  1. mark35at

    mark35at Well-Known Member Licensed User

    I am using a 4x4 Keypad to enter data on an Arduino Uno. The letters A to D represent commands and the numbers will be values. For example: Pressing "A" followed by up to six further numbers and then "#" should give me a string "123456" which I then need to convert to an integer and store.

    Something is not correct as you can see from the log output but I cannot see my mistake. In this case the value 36 should be stored in "SpeedDown" but the log shows "##" ?????

    Code:
    A
    Speed down active ....
    3
    6
    #
    Speed down finished ...
    Value: ##
    Code:
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region


    ' planned screen
    '
    ' (A) Speed Down: 20 mm/s
    ' (B) Hold Time:  10 mins
    ' (C) Speed Up:   40 mm/s
    ' (D) Run          (*) Reset

    Sub Process_Globals
        
    Public Serial1 As Serial
        
    Private pad As Keypad
        
    Private KeyBuffer(6As String
        
    Dim vKey As Int=0
        
    Private SpeedDown As Double=0
        
    Private Holdtime As Long=0
        
    Private Speedup As Double=0
        
    Private timer1 As Timer
        
    Private CommandActive As Int=0
        
    Dim bc As ByteConverter
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        pad.Initialize(
    "123A456B789C*0#D"Array As Byte(9876),  Array As Byte(5432), _
         
    "pad_KeyPressed")
        timer1.Initialize(
    "timer1_Tick",1000)
    End Sub


    Sub timer1_Tick
     
    End Sub

    Sub Pad_KeyPressed (Key As String)
     
        
    Log(Key)
     
        
    If Key = "*" Then
            SpeedDown=
    0
            Holdtime=
    0
            Speedup=
    0
            
    'ResetDisplay
        Else if Key = "A" Then
            
    'Speed down
            If CommandActive>0 Then Return        ' a different command key is active
            CommandActive=1
            
    Log("Speed down active ....")
          
            vKey=
    0
        
    Else if Key = "B" Then
            
    'Hold time
            If CommandActive>0 Then Return
            CommandActive=
    2
            
    Log("Hold time active ....")
          
            vKey=
    0
        
    Else if Key = "C" Then
            
    'Speed up
            If CommandActive>0 Then Return
            CommandActive=
    3
            
    Log("Speed up active ....")
          
            vKey=
    0
        
    Else if Key = "D" Then
            
    'Run
            Log("Speed down: ", SpeedDown)
            
    Log("Hold time: ", Holdtime)
            
    Log("Speed up: ", Speedup)
          
        
    else if Key = "#" Then
            
    'Enter pressed
            Select Case CommandActive
                
    Case 1
                    
    Log("Speed down finished ...")
                    SpeedDown=TransferBuffer
                    CommandActive=
    0
                
    Case 2
                    Holdtime=TransferBuffer
                    
    Log("Hold time not finished ...")
                    CommandActive=
    0
                
    Case 3
                    Speedup=TransferBuffer
                    
    Log("Speed up not finished ...")
                    CommandActive=
    0
                  
            
    End Select
          
        
    else if vKey<6 Then 
            
    'put the key in the buffer.
            KeyBuffer(vKey)=Key
            vKey=vKey+
    1
        
    End If

    End Sub

    Sub TransferBuffer As Int
        
    Dim vv As String=JoinStrings(KeyBuffer)
     
        
    Dim v As Int=vv
        
    Log("Value: ",vv)
        
    Return v
    End Sub
     
  2. derez

    derez Expert Licensed User

    In the if-then there is no place for key = a number, so it does not do anything when a number key is pressed.
    Probably this
    "else if vKey<6 Then "
    should be
    "else if Key<6 Then " but even with this it will not read the "6"
     
  3. mark35at

    mark35at Well-Known Member Licensed User

    "vKey" is used to store the number of digits. Up to 6 can be entered with index 0 to 5 and then stored in KeyBuffer(index).

    At present I have no check for entering "000234" for example.
     
  4. mark35at

    mark35at Well-Known Member Licensed User

    This seems to work:

    Code:
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region


    ' planned screen
    '
    ' (A) Speed Down: 20 mm/s
    ' (B) Hold Time:  10 mins
    ' (C) Speed Up:   40 mm/s
    ' (D) Run          (*) Reset

    Sub Process_Globals
        
    Dim Serial1 As Serial
        
    Dim pad As Keypad
        
    Dim KeyBuffer(6As Byte
        
    Dim vKey As Int=0
        
    Dim SpeedDown As UInt=0
        
    Dim Holdtime As UInt=0
        
    Dim Speedup As UInt=0
        
    Dim timer1 As Timer
        
    Dim CommandActive As UInt=0
        
    Dim bc As ByteConverter
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        pad.Initialize(
    "123A456B789C*0#D"Array As Byte(9876),  Array As Byte(5432), _
         
    "pad_KeyPressed")
        timer1.Initialize(
    "timer1_Tick",1000)
    End Sub


    Sub timer1_Tick
       
    End Sub

    Sub Pad_KeyPressed (Key As String)
        
    If Key = "*" Then
            SpeedDown=
    0
            Holdtime=
    0
            Speedup=
    0
            
    'ResetDisplay
        Else if Key = "A" Then
            
    'Speed down
            If CommandActive>0 Then Return        ' a different command key is active
            CommandActive=1
            
    Log("Speed down active ....")
           
            vKey=
    0
        
    Else if Key = "B" Then
            
    'Hold time
            If CommandActive>0 Then Return
            CommandActive=
    2
            
    Log("Hold time active ....")
           
            vKey=
    0
        
    Else if Key = "C" Then
            
    'Speed up
            If CommandActive>0 Then Return
            CommandActive=
    3
            
    Log("Speed up active ....")
           
            vKey=
    0
        
    Else if Key = "D" Then
            
    'Run
            Log("Speed down: ", SpeedDown, " mm/s")
            
    Log("Hold time: ", Holdtime)
            
    Log("Speed up: ", Speedup, " mm/s")
       
        
    else if Key = "#" Then
            
    'Enter pressed
            Select Case CommandActive
                
    Case 1
                    
    'Log("Speed down finished ...")
                    'Log("KeyBuffer: ", KeyBuffer)
                    SpeedDown=bc.StringFromBytes(KeyBuffer)
                    
    Log("Speed down: ", SpeedDown)
                    CommandActive=
    0
                
    Case 2
                    Holdtime=bc.StringFromBytes(KeyBuffer)
                    
    Log("Hold time not finished ...")
                    CommandActive=
    0
                
    Case 3
                    Speedup=bc.StringFromBytes(KeyBuffer)
                    
    Log("Speed up not finished ...")
                    CommandActive=
    0
                   
            
    End Select
           
        
    else if vKey<6 Then  
            
    'put the key in the buffer.
            KeyBuffer(vKey)= Asc(Key)
            
    Log("Key: ", vKey, " Value: ", KeyBuffer(vKey))
            vKey=vKey+
    1
        
    End If

    End Sub
    and the log after pressing A 3 6 5 9 9 # D:

    Code:
    Speed down active ....
    Key: 
    0 Value: 51
    Key: 
    1 Value: 54
    Key: 
    2 Value: 53
    Key: 
    3 Value: 57
    Key: 
    4 Value: 57
    Speed down: 
    36599 mm/s
    Hold time: 
    0
    Speed up: 
    0 mm/s
     
  5. mark35at

    mark35at Well-Known Member Licensed User

    With the above code, it works as required but if the next command is used eg "B" then the array KeyBuffer is not cleared and only the first values are swaped - logical. Need to clear the buffer somehow.
     
  6. mark35at

    mark35at Well-Known Member Licensed User

    This is my final effort and works as required:

    Code:
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region


    ' planned screen
    '
    ' (A) Speed Down: 20 mm/s
    ' (B) Hold Time:  10 mins
    ' (C) Speed Up:   40 mm/s
    ' (D) Run          (*) Reset

    Sub Process_Globals
        
    Dim Serial1 As Serial
        
    Dim pad As Keypad
        
    Dim KeyBuffer(6As Byte
        
    Dim vKey As Int=0
        
    Dim SpeedDown As Long=0
        
    Dim Holdtime As Long=0
        
    Dim Speedup As Long=0
        
    Dim timer1 As Timer
        
    Dim CommandActive As UInt=0
        
    Dim bc As ByteConverter
    End Sub

    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        pad.Initialize(
    "123A456B789C*0#D"Array As Byte(9876),  Array As Byte(5432), _
         
    "pad_KeyPressed")
        timer1.Initialize(
    "timer1_Tick",1000)
    End Sub


    Sub timer1_Tick
        
    End Sub

    Sub Pad_KeyPressed (Key As String)
        
    If Key = "*" Then
            SpeedDown=
    0
            Holdtime=
    0
            Speedup=
    0
            
    'ResetDisplay
        Else if Key = "A" Then
            
    'Speed down
            If CommandActive>0 Then Return        ' a different command key is active
            CommandActive=1
            
    Log("Speed down active ....")
            
            vKey=
    0
        
    Else if Key = "B" Then
            
    'Hold time
            If CommandActive>0 Then Return
            CommandActive=
    2
            
    Log("Hold time active ....")
            
            vKey=
    0
        
    Else if Key = "C" Then
            
    'Speed up
            If CommandActive>0 Then Return
            CommandActive=
    3
            
    Log("Speed up active ....")
            
            vKey=
    0
        
    Else if Key = "D" Then
            
    'Run
            Log(CRLF"Show all values")
            
    Log("Speed down: ", SpeedDown, " mm/s")
            
    Log("Hold time: ", Holdtime)
            
    Log("Speed up: ", Speedup, " mm/s"CRLF)
        
        
    else if Key = "#" Then
            
    'Enter pressed
            Select Case CommandActive
                
    Case 1
                    
    Log("Speed down changed")
                    SpeedDown=bc.StringFromBytes(KeyBuffer)
                    
    Log("Speed down is now: ", SpeedDown, " mm/s")
                    CommandActive=
    0
                    ClearKeyBuffer
                
    Case 2
                    Holdtime=bc.StringFromBytes(KeyBuffer)
                    
    Log("Hold time changed")
                    CommandActive=
    0
                    ClearKeyBuffer
                
    Case 3
                    Speedup=bc.StringFromBytes(KeyBuffer)
                    
    Log("Speed up changed")
                    CommandActive=
    0
                    ClearKeyBuffer
            
    End Select
            
        
    else if vKey<6 Then   
            
    'put the key in the buffer.
            KeyBuffer(vKey)= Asc(Key)
            
    Log("Key: ", vKey, " Value: ", Key)
            vKey=vKey+
    1
        
    End If

    End Sub

    Sub ClearKeyBuffer
        
    Log("KeyBuffer before clear: ", KeyBuffer)
        
    For i=0 To KeyBuffer.Length-1
            KeyBuffer(i)=
    Asc(" ")       
        
    Next
        
    Log("KeyBuffer after clear: ", KeyBuffer)
    End Sub
     
  7. tigrot

    tigrot Well-Known Member Licensed User

    Why not clear the array if another letter is pressed? If letter is pressed start another sequence, this allows to correct previous mistakes without executing the wrong command.
     
  8. mark35at

    mark35at Well-Known Member Licensed User

    @tigrot: thanks for your input but I have programmed the system so that if a "command" is being executed, pressing a new command does nothing. The current command must be terminated but can be repeated if required. If the wrong data is entered, the data can be stopped with "#" and the command repeated. If I was to do it your way, I think the code would be more complicated.

    This is just a small building block in a much larger process. I have never worked with the keypad before. In the actual process, all values are 0 before starting. That is required by the client to ensure that run cannot be selected with old values.

    I have also changed the thread title accordingly.
     
    tigrot likes this.
  9. tigrot

    tigrot Well-Known Member Licensed User

    Most of my pjts have a keypad. The oldest one is a food metal detector running since 1997. It implements lots of functions in a 8 bit PIC. In 20 years I had many feed back from users. So I wanted to give my 5 cents of hint. Good work.
     
    mark35at likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice