Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

reading a 4x4 switch matrix

Status
Not open for further replies.

MrDEB

Well-Known Member
I am starting out with swordfish code to read a 4 x 4 switch matrix but something is wrong with my case select
It shows an incompatible type error? I tried inserting comas etc but?? Maybe just go with a bunch of IF THEN statements??

DEVICE = 18F24k20 ' Tell the compiler what chip we are using
CLOCK = 8 ' Tell the compiler what we will be setting the clock to (Mhz)
CONFIG MCLRE = OFF
CONFIG fOSC = INTIO67 ' Internal oscillator, IO on pins 6 and 7
#option LCD_DATA = PORTC.4
#option LCD_RS = PORTC.0
#option LCD_EN = PORTC.1
INCLUDE "SetDigitalIO.bas" // Include this file when we compile so that we can use keywords like 'setalldigital'
INCLUDE "utils.bas"
INCLUDE "convert.bas" //xxxxx
INCLUDE "LCD.bas"
INCLUDE "Keypad16pullup.bas"
INCLUDE "utils.bas"
// import LCD library...
DIM Button_Press AS WORD
/////////////////
//SWITCHES ON PORTB
//ZZZZZZZZZZZZZZZZZ
DIM COLUM1 AS PORTB.0
DIM COLUM2 AS PORTB.1
DIM COLUM3 AS PORTB.2
DIM COLUM4 AS PORTB.3
////////////////////
//INPUTS FROM SWITCH MATRIX
////////////////////////
DIM ROW1 AS PORTB.4
DIM ROW2 AS PORTB.5
DIM ROW3 AS PORTB.6
DIM ROW4 AS PORTB.7
DIM Round_total AS WORD
DIM Total_Score AS WORD
DIM Sum AS WORD
// program start...
SetAllDigital
Cls
colum1= 1
colum2= 1
colum3= 1
colum4= 1
row1= 1
row2= 1
row3= 1
row4= 1
'WriteAt(1,1,"Hello World") //CHANGE AS NEEDED
WHILE TRUE
SELECT Button_Press
CASE 1 COLUM1 = 0 AND ROW1 =0 Sum = 1
CASE 2 COLUM2 = 0 AND ROW1 =0 Sum = 2
CASE 3 COLUM3 = 0 AND ROW1 =0 Sum = 3
CASE 4 COLUM4 = 0 AND ROW1 =0 Sum = 4
CASE 5 COLUM1 = 0 AND ROW2 =0 Sum = 5
CASE 6 COLUM2 = 0 AND ROW2 =0 Sum = 6
CASE 7 COLUM3 = 0 AND ROW2 =0 Sum = 7
CASE 8 COLUM4 = 0 AND ROW2 =0 Sum = 8
CASE 9 COLUM1 = 0 AND ROW3 =0 Sum = 9
CASE 10 COLUM2 = 0 AND ROW3 =0 Sum = 10
CASE 11 COLUM3 = 0 AND ROW3 =0 Sum = 11
CASE 12 COLUM4 = 0 AND ROW3 =0 Sum = 12
CASE 13 COLUM1 = 0 AND ROW4 =0 Sum = 0
CASE 14 COLUM2 = 0 AND ROW4 =0 Sum = 50
CASE 15 COLUM3 = 0 AND ROW4 =0 Sum = Round_total
CASE 16 COLUM4 = 0 AND ROW4 =0 Sum = Total_Score
END SELECT
WEND
 
I don't have a clue what you are trying to do, but your format for the CASE statements is all wrong. You can't just string together everything on one line.

Code:
CASE 1 COLUM1 = 0 AND ROW1 =0
     Sum = 1

CASE 2 COLUM2 = 0 AND ROW1 =0 
     Sum = 2

CASE 3 COLUM3 = 0 AND ROW1 =0
     Sum = 3
     ●
     ●
     ●

Your logic of how the matrix should work makes no sense to me. You've set all the rows and columns high. How is pressing a switch connecting 2 high pins together going to make one of them low? I think you've missed (quite) a few steps
 
The INPUTS on portB.4 to B7 are supposed to be LOW. my bad.
I redid the CASE SELECT to IF THEN END IF
if COLUM1 = 0 AND ROW1 =0 then Sum = 1 end if
if COLUM2 = 0 AND ROW1 =0 then Sum = 2 end if
if COLUM3 = 0 AND ROW1 =0 then Sum = 3 end if
if COLUM4 = 0 AND ROW1 =0 then Sum = 4 end if

if COLUM1 = 0 AND ROW2 =0 then Sum = 5 end if
if COLUM2 = 0 AND ROW2 =0 then Sum = 6 end if
if COLUM3 = 0 AND ROW2 =0 then Sum = 7 end if
if COLUM4 = 0 AND ROW2 =0 then Sum = 8 end if

if COLUM1 = 0 AND ROW3 =0 then Sum = 9 end if
if COLUM2 = 0 AND ROW3 =0 then Sum = 10 end if
if COLUM3 = 0 AND ROW3 =0 then Sum = 11 end if
if COLUM4 = 0 AND ROW3 =0 then Sum = 12 end if

if COLUM1 = 0 AND ROW4 =0 then Sum = 0 end if



if COLUM2 = 0 AND ROW4 =0 then Sum = 50 end if
if COLUM3 = 0 AND ROW4 =0 then Sum = Round_total end if
if COLUM4 = 0 AND ROW4 =0 then Sum = Total_Score end if

I just started this this morning. LOTS wrong but CASE SELECT seemed easier but??
This is a calculator that adds up a players dominions while playing Mexican Train. We play two times a month (55+ community) and sometimes players get stuck with lots of dominions. Want to design a 4 x 4 keypad with the dominions silk screened on the board. Basically an adding machine but no need to press any ADD button. Just press two buttons for each dominio and LCD display displays the sum of each round of play (13 rounds) and a running total of all 13 rounds.
 
Every word I said above, repeat here.

You can't just string together crap on a line.

Code:
if COLUM1 = 0 AND ROW1 =0 then 
    Sum = 1 
end if

if COLUM2 = 0 AND ROW1 =0 then
    Sum = 2 
end if

if COLUM3 = 0 AND ROW1 =0 then
    Sum = 3 
end if

if COLUM4 = 0 AND ROW1 =0 then 
     Sum = 4 
end if

This addresses only your select/case and if/then problems. Same problem with each. You have to follow rhe right format.
 
Does it matter if all on same line??
It will compile and easy to read the IF THEN END IF. Seems as easy as the SELECT CASE??
I am probably wrong? as usual
 
I guess you can join lines together like that. My mistake. That format will be confusing when you have multiple statements within the if/then or case/select.

I always use indenting to tell where an if/then statement ends, even when it contains nested if then loops.

At any rate, nothing you have posted so far makes sense. From your first listing, either rows are inputs and columns are outputs or vice vesa. You have specified neither as outputs yet you've assigned values to all of them. Continuing, having a row and a column in your conditional statement makes zero sense. You are setting one or the other to zero as an output. It's not going to change unless you change it.

If the rows are outputs set low and if the columns are inputs with pullup resistors (internal or external), pressing a button will pull a column low...but notice, pressing any button in the column will pull it low. At that point, you have to make exactly one row low at a time to determine which button in the column has been pressed. The tests in your conditionals will not accomplish this.

You need to do some research on reading matrix switches. What you have posted so far is far from working.
 
Questioning my sanity......

You have included keypad16Pullup.bas in your code but have done nothing with it. You do understand that merely including a file accomplishes nothing? Nevermind - I've tried to explain this before.

If you actually read the include file (see 2nd code block below), you'll see that there is a function called Value() that returns a value of 1 to 16 depending on which key is pressed, and a value of 0 if no key has been pressed.

If you replace almost all of your "code" with something like

Code:
If keypad16pullup.value <> 0 then   //a key has been pressed
     select result
          case = 1
                 keyvalue = x
          case = 2
                 keyvalue = x
          case = 3
                 keyvalue = x
     . . .
          case = 16
                 keyvalue = x
     end select
end if

The value of each key depends on how it's connected of course. Connect as explained in the keypad module.

This is as much help as I can/will give you on this.



Code:
Public Function Value() As Byte
    Dim Counter As Byte
    Dim RowData As Byte
    Dim ColData As Byte
   
    Result = 0                           
   
    For Counter = 0 To 3                //
        FKeyPortTris = $FF              // Make all pins inputs
        FKeyPortTris.Bits(Counter) = 0  // Make a single Column an output
        FKeyPort.Bits(Counter) = 0      //  and set it low
       
        If (FKeyPort >> 4) <> %00001111 Then    // Check if any Rows are "Low"
            Coldata = Counter
            If FKeyPort.4 = 0 Then
                RowData = 1
            ElseIf FKeyPort.5 = 0 Then
                RowData = 5
            ElseIf FKeyPort.6 = 0 Then
                RowData = 9
            ElseIf FKeyPort.7 = 0 Then
                RowData = 13               
            EndIf           
            Result = Coldata + RowData
            Break         
        EndIf 
    Next
End Function

keypad 1.jpg
 
Thanks Mike. I believe that's substantially what the include does.

For my own edification, I maygive this a try tomorrow. I think I have a couple 4x4 arrays from ebay.
 
Once you can read the keypad into a 16 bit variable then you can further process it.
1. Keep a copy of the previous reading and XOR with the current reading will give you keys that have changed.
2. If active high keys then ANDing the result from 1 with the current reading will give you new key presses. Very useful.
3. If active low keys then ANDing the result from 1 with the previous reading will give you new key presses. Very useful.

Debounce is simply done by only reading 20 to 50 times per second.

I posted an example of reading a 3x4 matrix here a few years ago with auto repeat and key rollover. You may find it interesting. Link

Have fun.

Mike.
Edit, Apologies, this was my days of assembly.
 
Thanks Guys.
As I stated, the code I posted was my beginning disaster and before I get to far along I want to correct my mistakes before I sink the ship.
Mistake one--failed to make portB.4-B.7 LOW and am scanning the columns. Using an Adriono code as example but Mikes code makes more sense.
Am wiring up a 2 x 4 matrix to test code then can expand later. but running out of wire.
Will hopefully advance further on this project before the boards for the game hub get here.
Have lots of research to do and never delt with bit masking.
 
Mike's suggestion is a good one, but not for you. You've included the keyboard module. It does exactly what you need. But you need to understand just including it does nothing unless you use the commands it contains.
 
I just got done reading the keypad16 module and yes it basically does all the work.
I see it uses weak pullups on ALL the portB pins thus I don't need to include 10K pullup resistors on pcboard.
need to read the module and grasp what it is actually doing. It has a counter I think is used one time?
Just need to comprehend the code flow and determine how it outputs all 16 key values.
 
As I outlined above, you call the function. You get a zero if no key is pressed. You get 1 - 16 for the 16 keys. You have to translate those values to what you want the switches to read. It's all included in what I wrote above. Please read that. I'm wearing out my damned keyboard explainung things again and again for you.
 
before I get to far off the beaten path, herView attachment 111357 e is my preliminary schematic.


Too late for that. Do you see anything in the keypad module about diodes? Any conment about anything besides pullup resistors? Has the word diode, rectifier or anything like that been mentioned here?
 
Wow, MrDEB actually got something right. Diodes do indeed stop ghosting (I call it cross talk).

Mike.
 
How fast are these old folks going to be pounding on tbese keys adding up their domino scores?

MrDEB is great at grabbing bits and pieces from here and there...without understanding how things work or why. Instead of following through on one method he combines 5 or 10 methods without any understanding.
 
I only said he got something right - not that he understood it. If you pound on a keyboard lots, eventually you will manage to be right. 1000 monkeys etc.

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top