B4R Question Matrix Keypad 1 wire example + string/byte question

pecket

Member
Hi.

I was hoping to make sense of this and solve the issues before posting, but unfortunately I really can't seem to grasp this "stick to binary" concept. Converting between these types just prints the ascii code, not the bytes themselves.

I'm trying out the "one wire 4x4 matrix keypad" concept due to lack of expendable pins. Everything is working quite alright, despite a few "ghost values" occuring every now and then, but quite rare, giving me the wrong analog value completely. Any tips regarding this issue is also more than welcome. This is the schematic I've been using to connect to the Arduino:
keypad2.png


However, my code doesn't work unless I depend completely on strings, and since that is not recommended, I would prefer this approach instead. For anyone wondering about the triple delay commands in the if-statement, it's simply to avoid these "ghost values" that sometimes manifests. Pardon the code inefficiency. I'm completely new with this and B4R is awesome, except for the compiled size and the strange variable conversion requirements I keep stumbling over:
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Public Keypad_Keys_Numeric() As UInt = Array As UInt(700, 400, 300, 200, 150, 130, 116, 105, 88, 81, 75, 68, 61, 57, 55, 50)
    Public Keypad_Keys_Real() As Byte = "123A456B789C*0#D"
    Private keypadpin As Pin
    Private keypadpinnr As Byte = 0x00
    Private keydown As Byte = 0
    Private Keypad_Lastkey As UInt
    Private KeypadTimer As Timer
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    keypadpin.Initialize(keypadpinnr, keypadpin.MODE_OUTPUT)
    KeypadTimer.Initialize("Keypad_Tick", 10)
    KeypadTimer.Enabled = True
End Sub

Private Sub Keypad_Tick
    Dim newkeypress As String
    newkeypress = Keypad_UpdateKey
    If newkeypress <> "" Then
        Log("Key input: ", newkeypress)
    End If
End Sub

Private Sub Keypad_UpdateKey As String
    Dim rawvoltage As UInt = keypadpin.AnalogRead
    If rawvoltage < 10 And keydown = 1 Then
        Log("Key released: ", Keypad_GetKeyName(Keypad_Lastkey))
        keydown = 0
    Else
        If keydown = 0 And rawvoltage > 10 Then
            Delay(3)
            rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
            Delay(3)
            rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
            Delay(3)
            rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
            Log("Key pressed: ", rawvoltage)
            Keypad_Lastkey = rawvoltage
            keydown = 1
            Return Keypad_GetKeyName(Keypad_Lastkey)
        End If
    End If
    Return ""
End Sub

private Sub Keypad_GetKeyName(value As UInt) As String
    Dim i As Int
    For i = 0 To 15
        If value > Keypad_Keys_Numeric(i) Then
            Return As String(Keypad_Keys_Real(i))
        End If
    Next
    Return ""
End Sub
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Check this library: https://www.b4x.com/android/forum/threads/keypad.72494/

You can return a Byte from Keypad_GetKeyName (untested code):
B4X:
Sub Process_Globals
   Public Serial1 As Serial
   Public Keypad_Keys_Numeric() As UInt = Array As UInt(700, 400, 300, 200, 150, 130, 116, 105, 88, 81, 75, 68, 61, 57, 55, 50)
   Public Keypad_Keys_Real() As Byte = "123A456B789C*0#D"
   Private keypadpin As Pin
   Private keypadpinnr As Byte = 0x00
   Private keydown As Byte = 0
   Private Keypad_Lastkey As UInt
   Private KeypadTimer As Timer
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   Log("AppStart")
   Log(Array As Byte(Keypad_Keys_Real(3)))
   keypadpin.Initialize(keypadpinnr, keypadpin.MODE_OUTPUT)
   KeypadTimer.Initialize("Keypad_Tick", 10)
   KeypadTimer.Enabled = True
End Sub

Private Sub Keypad_Tick
   Dim newkeypress As Byte = Keypad_UpdateKey
   If newkeypress <> 0 Then
     Log("Key input: ", Array As Byte(newkeypress))
   End If
End Sub

Private Sub Keypad_UpdateKey As Byte
   Dim rawvoltage As UInt = keypadpin.AnalogRead
   If rawvoltage < 10 And keydown = 1 Then
     Log("Key released: ", Array As Byte(Keypad_GetKeyName(Keypad_Lastkey)))
     keydown = 0
   Else
     If keydown = 0 And rawvoltage > 10 Then
       Delay(3)
       rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
       Delay(3)
       rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
       Delay(3)
       rawvoltage = Max(rawvoltage, keypadpin.AnalogRead)
       Log("Key pressed: ", rawvoltage)
       Keypad_Lastkey = rawvoltage
       keydown = 1
       Return Keypad_GetKeyName(Keypad_Lastkey)
     End If
   End If
   Return 0
End Sub

private Sub Keypad_GetKeyName(value As UInt) As Byte
   Dim i As Int
   For i = 0 To 15
     If value > Keypad_Keys_Numeric(i) Then
       Return Keypad_Keys_Real(i)
     End If
   Next
   Return 0
End Sub

Note that for the logging, I'm converting the byte value to an array of bytes in order to print the ASCII character.
 
Upvote 0
Top