Keypad .kstate question

OK I have some code that I have written which works well for 2 locations in the matrix. It is running on a Teensy LC

void encoderEvent(KeypadEvent enccheck){
  A = enccheck;
  B = enccheck;

  // Determine Active Encoder A or B  
  if (enccheck != 0){
    if (enccheck != NO_KEY){
      if ( enccheck % 2 == 0){
        A = enccheck - 1;
        Astate = encodermatrix.key[A].kstate;
        Bstate = encodermatrix.key[B].kstate;
                        Serial.print("Astate ");
                        Serial.print(Astate);
            Serial.print(", Bstate ");
            Serial.println(Bstate);
        EncoderState(); 
      }else{
        B = enccheck + 1;
        Astate = encodermatrix.key[B].kstate;
        Bstate = encodermatrix.key[A].kstate;  
                        Serial.print("Astate ");
                        Serial.print(Astate);
            Serial.print(", Bstate ");
            Serial.println(Bstate);      
        EncoderState();
        }
      }
    } 

}

This event code runs when a button has been pressed on the Matrix (Keypad) , when the button is pressed it passes the byte enccheck to the event which is the number of the button being pressed.

The if statements determine whether the button being pressed is odd or even and then creates a second button number to be used as its pair putting an odd button number into A and an even button Number into B and then finding the .kstate of each of those buttons A and B and defining them as Astate, and Bstate.

After that the Astate and Bstate are run through a dual stage switch statement which checks the Estate and Bstate and then outputs a grey code based on the Pressed or released state of each button.

The issue I am having is that everything works perfectly for Keys 1 and 2 on the keypad but when 3 and 4 or 5 and 6 or anything beyond 1 and two are paired up the encodermatrix.key[A].kstate and encodermatrix.key**.kstate ALWAYS returns an IDLE (0) state.. A and B are 3 and 4, or 5 and 6 so I am thinking it should get the kstate of 3 and 4 or 5 and 6 and then be fine going through the switch to output the Gray code for those pairs but it doesn't seem to be working that way as previously said it always returns IDLE even when pressed.**
So I am confused and I think I am missing something, maybe it is a variable type issue everything is a byte.. I just don't know.. seems like it should work..
BTW the IDLE states pass through the switch as IDLE and IDLE and I have verified the Key Number is running into and through the switch so it is something in the calling of .kstate with numbers higher than 2

Some questions

Why not post all code so we can try? http://snippets-r-us.com/

Or to at least see where A and B are defined. And why they are (single letter) globals instead of locals.

I'm not 100% sure if it applies to this as well but most of the time the keyboard lib is setup to return '1' rather then 1 when button 1 is pressed. Not a problem to get '1' from '2' - 1 but looking up '1' in an array of 10 is trouble.

Actually that is the main code so I thought that would be the needed part as all that happens before is a keypad matrix definition and then a call to that code through the Keypad.listener event..

I took out all of my serial test outputs to find out how things are being passed.

Anyway here is the full code.. with my verification serial outputs in there...

#include <Keypad.h>

// Variable Declaration
byte A;
byte B;
byte Astate;
byte Bstate;
byte Apin;
byte Bpin;
byte greyCode;
byte greyCodeState;
byte enccheck;
#define ENCODERROWS 4 //four rows
#define ENCODERCOLS 4 //three columns

//Define Encoder Numbers and Pin Map
byte encoders[ENCODERROWS][ENCODERCOLS] = {
  {1, 2, 3, 4},
  {5, 6, 7, 8},
  {9, 10, 11, 12},
  {13, 14, 15, 16}
};
byte encoderrowPins[ENCODERROWS] = {1, 2, 3, 4}; //connect to the row pinouts of the keypad
byte encodercolPins[ENCODERCOLS] = {5, 6, 7, 8}; //connect to the column pinouts of the keypad

//initialize Keypad Physical Matrix
Keypad encodermatrix = Keypad( makeKeymap(encoders), encoderrowPins, encodercolPins, ENCODERROWS, ENCODERCOLS );


// Program
void setup(){
  Serial.begin(1000000);
  encodermatrix.setDebounceTime(1);           // Default is 50mS (1ms min)
  encodermatrix.addEventListener(encoderEvent); // Add an event listener for this keypad
}


//Main loop
void loop(){
CheckEncodersOrder();
}


// Sub Programs
void CheckEncodersOrder(void){
  byte enccheck = encodermatrix.getKey();
}


void EncoderState(void){
  switch (Astate){
    case PRESSED:
      Serial.print("A Pressed, ");
        switch (Bstate){
          case PRESSED:
            Apin = 1;
            Bpin = 1;
            Serial.println("B Pressed");
          break;
          case HOLD:
            Apin = 1;
            Bpin = 1;
            Serial.println("B Hold");
          break;
          case RELEASED:
            Apin = 1;
            Bpin = 0;
            Serial.println("B Released");
          break;
          case IDLE:
            Apin = 1;
            Bpin = 0;
            Serial.println("B Idle");
          break;
        }
      break;
    case HOLD:
      Serial.print("A Hold, ");
        switch (Bstate){
          case PRESSED:
            Apin = 1;
            Bpin = 1;
            Serial.println("B Pressed");
          break;
          case HOLD:
            Apin = 1;
            Bpin = 1;
            Serial.println("B Hold");
          break;
          case RELEASED:
            Apin = 1;
            Bpin = 0;
            Serial.println("B Released");
          break;
          case IDLE:
            Apin = 1;
            Bpin = 0;
            Serial.println("B Idle");
          break;
        }
      break;
    case RELEASED:
      Serial.print("A Released, ");
        switch (Bstate){
          case PRESSED:
            Apin = 0;
            Bpin = 1;
            Serial.println("B Pressed");
          break;
          case HOLD:
            Apin = 0;
            Bpin = 1;
            Serial.println("B Hold");
          break;
          case RELEASED:
            Apin = 0;
            Bpin = 0;
            Serial.println("B Released");
          break;
          case IDLE:
            Apin = 0;
            Bpin = 0;
            Serial.println("B Idle");
          break;
        }
      break;
    case IDLE:
      Serial.print("A Idle, ");
        switch (Bstate){
          case PRESSED:
            Apin = 0;
            Bpin = 1;
            Serial.println("B Pressed");
          break;
          case HOLD:
            Apin = 0;
            Bpin = 1;
            Serial.println("B Hold");
          break;
          case RELEASED:
            Apin = 0;
            Bpin = 0;
            Serial.println("B Released");
          break;
          case IDLE:
            Apin = 0;
            Bpin = 0;
            Serial.println("B Idle");
            Serial.print(A);
            Serial.print(", ");
            Serial.println(B);
          break;
        }
    } 
}


//Encoder Event
void encoderEvent(KeypadEvent enccheck){
  A = enccheck;
  B = enccheck;

  // Determine Active Encoder A or B  
  if (enccheck != 0){
    if (enccheck != NO_KEY){
      if ( enccheck % 2 == 0){
        A = enccheck - 1;
        Astate = encodermatrix.key[A].kstate;
        Bstate = encodermatrix.key[B].kstate;
                        Serial.print("Astate ");
                        Serial.print(Astate);
            Serial.print(", Bstate ");
            Serial.println(Bstate);
        EncoderState(); 
      }else{
        B = enccheck + 1;
        Astate = encodermatrix.key[B].kstate;
        Bstate = encodermatrix.key[A].kstate;  
                        Serial.print("Astate ");
                        Serial.print(Astate);
            Serial.print(", Bstate ");
            Serial.println(Bstate);      
        EncoderState();
        }
      }
    }  
    greyCode = (Apin*10) + Bpin;
    Serial.println(greyCode);
    Serial.println(greyCodeState);
    Serial.println();
    greyCodeState = greyCode;


}

The greyCode output will be 0, 1, 10, or 11.. But as i mentioned I ONLY get 0 (IDLE) out of the .kstate calls in the " // Determine Active Encoder A or B " section when the A and B are anything other than 1 and 2.

byte encoderrowPins[ENCODERROWS] = {1, 2, 3, 4};

Isn't pin 1 a hardware serial pin?

void CheckEncodersOrder(void){
  byte enccheck = encodermatrix.getKey();
}

That function might as well be called DoNothing() because that's what it accomplishes.

  if (enccheck != 0){
    if (enccheck != NO_KEY){

What is the value of NO_KEY?

Oh and reading your second part which I forgot to reply to, From My Understanding the and from what I have seen output by the code through my serial markers is...

The "byte enccheck = encodermatrix.getKey();" is returning the actual number of the key that is determined to be pressed from the matrix table which I am setting to "enccheck". Then in the event because it is called on ANY Key state change through the listener I am changing variables "A" and "B" to "enccheck" which is the button number being pressed

Then it goes through an even or odd determination based on the button pressed to determine the order so if an even button comes up as the pressed button it remains in the even (or "B") position during the switch statement which determines the greycode otherwise the desired output would be reversed. This in turn makes it so if an Odd numbered button is pressed it remains in the odd location (or "A") this also allows me to set the corresponding A or B location to the button number that corresponds in pair with the number of the button that is pressed.. i.e Button 1 is pressed "A" becomes 1 and "B" becomes 2 or if button 2 is pressed then "A" becomes 1 and "B" becomes 2 Still.. This happens correctly with other pairs as well such as if I press button 4 then "A" becomes 3 and "B" becomes 4..

I then send each determined button "A" and "B" to find their corresponding .kstate which I have found returns 0 = IDLE, 1= PRESSED, 2, = HOLD, and 3 = RELEASED. This is where it appears things are messing up as if "A" and "B" are 1 and 2 then it will give me the correct states on the buttons i.e. if button 1 is pressed it will give a 1 (1)PRESSED and if button 2 is the pressed button it will give a (1)PRESSED result and if both are pressed it will give both.. BUT if the Button Numbers change to 3 and 4 (or any other pairs combination) I only get (0)IDLE retuned from the .kstate on both buttons which of course always exits the switch function as Astate=0 and Bstate=0 instead of Astate=1 and Bstate=0 if button 3 is pressed or Astate=0 and Bstate=1 if button 4 is pressed.. as it does properly with buttons 1 and 2.

So that is really where I am at in that I am not sure why it is not determining the .kstate of buttons higher in number than 2

PaulS:

byte encoderrowPins[ENCODERROWS] = {1, 2, 3, 4};

Isn't pin 1 a hardware serial pin?

void CheckEncodersOrder(void){

byte enccheck = encodermatrix.getKey();
}



That function might as well be called DoNothing() because that's what it accomplishes.



if (enccheck != 0){
    if (enccheck != NO_KEY){



What is the value of NO_KEY?

1 can be used as a Serial TX1 or digital pin

.geyKey is in the keypad library and will return what is in the Array at the pressed key location. So based on my program if I pressed a button attached to physical digital pin ROW 1, Column 3 it would return 3.

And as well with the .kstate from what I understand it is supposed to Read the state of the Pins determined by the array when you ask for it. So when I ask for Button "4" I thought it was supposed to return what it finds on Pin 1 and Pin 8 which would correspond to Row 1, Column 4

NO_KEY is part of the Keypad library determining that NO_KEY press has taken place

The "byte enccheck = encodermatrix.getKey();" is returning the actual number of the key that is determined to be pressed from the matrix table which I am setting to "enccheck".

I know what it does. But he enccheck variable immediately goes out of scope. so it was a waste of time and effort calling the getKey() method.

NO_KEY is part of the Keypad library

i know that. And, I know that it has a value associated with the name. You should, too. And, you should know what the value is.

PaulS:
I know what it does. But he enccheck variable immediately goes out of scope. so it was a waste of time and effort calling the getKey() method.
i know that. And, I know that it has a value associated with the name. You should, too. And, you should know what the value is.

Im only using the .getKey to determine which key has been pressed at that moment and to know what that key was as well as to start the Event.

After that I really am not using that information other than to create the correct values in A and B to determine the order of the buttons that I want to check on.

I didn't do a .getKey for each Variable "A" and "B" as that can change so fast I don't want variable "A and B" to be different. I guess I could have just removed enccheck and made it A and then A=B as well but I did it the way I did it because A and B may switch positions Number wise in the Odd/Even section of the code. So it was clarity for me.

As for No_Key I am assuming from what I Read it is 0 when a key(button) is not pressed and as I have not redefined it from the normal Key.. Actually looking at the code I could probably remove that and be fine it was in some code I found for determining whether the Variable was even or odd.

EDIT:

I removed the

"if (enccheck != NO_KEY)"

check and everything behaves exactly the same so not an issue and unneeded

OP: Why do you keep insisting you're doing that which you are not? In this function:

void CheckEncodersOrder(void){
  byte enccheck = encodermatrix.getKey();
}

'enccheck' is a local variable. It goes out of scope and the result from 'getKey()' is thrown away literally microseconds after it's read.

gfvalvo:
OP: Why do you keep insisting you're doing that which you are not? In this function:

void CheckEncodersOrder(void){

byte enccheck = encodermatrix.getKey();
}



'enccheck' is a local variable. It goes out of scope and the result from 'getKey()' is thrown away literally microseconds after it's read.

However enccheck is getting passed to the event (as the event is downstream and a result of that getKey) with the:

encodermatrix.addEventListener(encoderEvent);

and function of void encoderEvent(KeypadEvent enccheck) {

in setup and is resetting A and B to the button number pressed since the Serial Check that I am running for IDLE, IDLE in the switch is returning A as 3 and B as 4 when it does the wrong thing.. and without enccheck passing to the event correctly based on that button press those numbers would not be correct. It also passes other combinations such as 5 and 6, 7 and 8 correctly as well from row 2 but still comes up with 0, 0 for the key state

One more try before I give up. You have two variables named 'enccheck', one global and one local. Which one do you think is getting the value from 'getKey()' and which one do you think is being used in function 'encoderEvent'?

Better read up on scope and variable shadowing. Google can tell you quite a lot about both.

gfvalvo:
One more try before I give up. You have two variables named 'enccheck', one global and one local. Which one do you think is getting the value from 'getKey()' and which one do you think is being used in function 'encoderEvent'?

Better read up on scope and variable shadowing. Google can tell you quite a lot about both.

The uncheck from the getKey is the one getting the variable AS:

If I remove the Global enccheck definition things run as before. (which now I know I don't need)
If I comment out the getKey statement, Nothing Runs at all..
If I remove enccheck from the encoderEvent(KeypadEvent enccheck).. and return the Global Variable all I get is "0"

So right now the Variable enccheck is being passed into the Event as the button number pressed.

So I am still at my initial issue in that for some reason when I state a specific button press above 2, ie 3, 4, 5, ect.. into encodermatrix.key["the specific number here"].kstate why it is just returning an IDLE state.

i.e

encodermatrix.key[1].kstate - returns PRESSED or IDLE
encodermatrix.key[2].kstate - returns PRESSED or IDLE
encodermatrix.key[3].kstate - returns IDLE only
encodermatrix.key[4].kstate - returns IDLE only
encodermatrix.key[5].kstate - returns IDLE only
encodermatrix.key[6].kstate - returns IDLE only

In other words I am not having an issue getting the correct A and B variables.

You said:

encodermatrix.key["the specific number here"].kstate why it is just returning an IDLE state

There are two ways to use the keypad (matrix decoder).

One method is to call getKeys() which will populate the default list of keys, key[10], with the information and status of up to 10 keys that are being pressed simultaneously.

The second method is to call getKey() which is what you are doing. Inside the keypad library getKey() calls getKeys() but will restrict the keypad event function to only report changes when the first key you press or pressed is updated.

Basically the key[LIST_MAX] array is used for multiple simultaneous key presses. If you are pressing only one key at a time then you are calling getKey() and you won't be able to use the key list like this:

encodermatrix.key[1].kstate - returns PRESSED or IDLE
encodermatrix.key[2].kstate - returns PRESSED or IDLE
encodermatrix.key[3].kstate - returns IDLE only
encodermatrix.key[4].kstate - returns IDLE only
encodermatrix.key[5].kstate - returns IDLE only
encodermatrix.key[6].kstate - returns IDLE only

You'll need to use the functions associated with single key use such as keyStateChanged() which returns the value found at key[0].stateChanged, getState() which returns key[0].kstate, and primarily the char which gets returned from getKey().

mstanley:
You said:
There are two ways to use the keypad (matrix decoder).

One method is to call getKeys() which will populate the default list of keys, key[10], with the information and status of up to 10 keys that are being pressed simultaneously.

The second method is to call getKey() which is what you are doing. Inside the keypad library getKey() calls getKeys() but will restrict the keypad event function to only report changes when the first key you press or pressed is updated.

Basically the key[LIST_MAX] array is used for multiple simultaneous key presses. If you are pressing only one key at a time then you are calling getKey() and you won't be able to use the key list like this:

encodermatrix.key[1].kstate - returns PRESSED or IDLE

encodermatrix.key[2].kstate - returns PRESSED or IDLE
encodermatrix.key[3].kstate - returns IDLE only
encodermatrix.key[4].kstate - returns IDLE only
encodermatrix.key[5].kstate - returns IDLE only
encodermatrix.key[6].kstate - returns IDLE only



You'll need to use the functions associated with single key use such as keyStateChanged() which returns the value found at key[0].stateChanged, getState() which returns key[0].kstate, and primarily the char which gets returned from getKey().

so if you can clarify how the .kstate works because as I thought I was reading it is would give me the state of a specific key generally called in a loop but it could also be called individually.

If you haven''t guessed this is to build a greycode value from an encoder. On each turn the encoder presses two buttons in a sequential order twice within a step.

What I am reading is that FIRST button press (sending the button number and starting the event) with the getKey and then determining its Counterpart button through the odd/even check and assigning the variables A and B to relative counterparts with A being the Odd or counterclockwise direction and the B being the clockwise.

Once this is done I am trying to check the state of the buttons A and B to determine which is pressed and which is not so I can determine if the encoder is to press the CW or CCW button..

Right now everything works perfectly when using buttons 1 and 2 in the matrix in that the code coming for the getKey and the with puts out all three states in this order if I turn CW..

CW
B(Button 2) - Idle,
A(Button 1) - Idle,
B(Button 2) - Pressed,
A(Button 1) - Idle,
B(Button 2) - Pressed,
A(Button 1) - Idle,

and CCW
B(Button 2) - Idle,
A(Button 1) - Idle,
B(Button 2) - Idle,
A(Button 1) - Pressed,
B(Button 2) - Idle
A(Button 1) - Pressed,

But when I getKey and the A and B change to Button 3 and 4 or 5 and 6 then I get this on each turn.

CW
B(Button 4) - Idle,
A(Button 3) - Idle,
B(Button 4) - Idle,
A(Button 3) - Idle,
B(Button 4) - Idle,
A(Button 3) - Idle,

and CCW
B(Button 4) - Idle,
A(Button 3) - Idle,
B(Button 4) - Idle,
A(Button 3) - Idle,
B(Button 4) - Idle
A(Button 3) - Idle,

I would have thought that it would put out a similar sequence because the calls to the buttons for the state are the same (other than the button number) and if it did do it as I thought it should react the same way..

I thought about just reading the button as is but as a failsafe for the encoder stepping and so steps aren't missed and or the secondary button read isn't used I sent it through the Switch to verify 0, 1, 10, and 11, though because of the getKey limitation 11 will probably never be seen but if 1 and 10 were seen back to back then it would send a CW and then CCW button press back to back in the same index, or as what happens above in that it send TWO CCW or CW button presses in sequence (which also is wrong but I figured out a fix for that based on the initial AB Idle state.

I am not actually making any sort of table or even calling multiple presses at the same time but I need to find out the state of multiple keys at approx the same time just to verify direction and that the right buttons are pressed at the right time.

I apologize for how blunt I am about to be but I need to figure out your level of programming knowledge before I start explaining really basic things like scope, array indexing, and objects.

The reason I say this is because you are using

encodermatrix.key[6].kstate

completely incorrectly.
encodermatrix.key[indexNumber].kstate is only used when you are expecting several 'encoders' to be pressing their associated buttons "at the same time".
So if I understand you correctly your encoder is something like a wheel with a bump on it that first presses and releases one key and then some short time later the bump presses and releases a second key? Are you doing this so you know which direction the encoder is turning?
I also need to point out that in order to generate any kind of code (grey code in your case) requires multiple bits to be high or low at the same time which directly implies that you should be using getKeys().

Right now everything works perfectly when using buttons 1 and 2 in the matrix in that the code coming for the getKey and the with puts out all three states in this order if I turn CW..

This is just pure luck. What's happening in reality is that you are only registering one button pressing at a time when you see this output.

CW
B(Button 2) - Idle,
A(Button 1) - Idle,
B(Button 2) - Pressed,
A(Button 1) - Idle,
B(Button 2) - Pressed,
A(Button 1) - Idle,

and CCW
B(Button 2) - Idle,
A(Button 1) - Idle,
B(Button 2) - Idle,
A(Button 1) - Pressed,
B(Button 2) - Idle
A(Button 1) - Pressed,

The key list always starts storing active keys at index zero. So when your encoder is going CW button 2 is actually being recorded in the key list at index 0 and when it reverses in the CCW direction button 1 is being recorded in the key list index 0 position. It looks good for this example of your output but it's not working the way you think it is. That is why you can't get keys 3 and higher to work.

I'm off to bed for the evening so to get an idea of what I am talking about take a look at two example sketches.

File --> Examples --> Keypad --> EventKeypad : for when you are reading single keys at a time and,
File --> Examples --> Keypad --> Multikey : for when you need to read multiple keys at a time.

mstanley:
I apologize for how blunt I am about to be but I need to figure out your level of programming knowledge before I start explaining really basic things like scope, array indexing, and objects.

The reason I say this is because you are using

encodermatrix.key[6].kstate

completely incorrectly.
encodermatrix.key[indexNumber].kstate is only used when you are expecting several 'encoders' to be pressing their associated buttons "at the same time".
So if I understand you correctly your encoder is something like a wheel with a bump on it that first presses and releases one key and then some short time later the bump presses and releases a second key? Are you doing this so you know which direction the encoder is turning?
I also need to point out that in order to generate any kind of code (grey code in your case) requires multiple bits to be high or low at the same time which directly implies that you should be using getKeys().

This is just pure luck. What's happening in reality is that you are only registering one button pressing at a time when you see this output.
The key list always starts storing active keys at index zero. So when your encoder is going CW button 2 is actually being recorded in the key list at index 0 and when it reverses in the CCW direction button 1 is being recorded in the key list index 0 position. It looks good for this example of your output but it's not working the way you think it is. That is why you can't get keys 3 and higher to work.

I'm off to bed for the evening so to get an idea of what I am talking about take a look at two example sketches.

File --> Examples --> Keypad --> EventKeypad : for when you are reading single keys at a time and,
File --> Examples --> Keypad --> Multikey : for when you need to read multiple keys at a time.

OK I am pretty novice at programming, but once I find out exactly the way something works I can usually logically figure it out and then find examples of such to get things to work and figure it out fairly quickly.. Your explanation of how kstate actually works indicates that my thought process on how kstate worked is flawed as I thought by what I was reading was flawed and after such I was trying to figure out what was wrong.

In reality I am basically trying to replicate the Grey Code that is output by the Encoder which can be replicated on button presses when the encoder is turning rather than by actual pinstates. This is so that I can have Multiple encoders in a Matrix rather than using up a ton of inputs on the processor for those encoders.. ie 6 encoders would use 12 wires + a ground normally. Where in a 4x3 matrix it would only need 7.

So with what you are saying about kstate and the dumb luck on finding something that worked.. is it possible to limit the list of the multi key to ONLY look at say keys 3 and 4 or 7 and 8 at any given time based on the initial key that was received through geyKey that determined that the encoder had started turning. What I am afraid of with just reading the Keys from the multi key code is the possible loss of synchronization between the Key pairs that would create the Virtual Grey code based on the button states to determine direction.

I could probably jerry rig this code to work with any pairs as I do know the initial turn and button used by turning all the encoders to be at the 0, 1 positions since more than likely encoders will only be turned at one time. But I know that won't be "proper code" and it could cause oddities later.

The encoders that I have are full step encoders that put out the following signals on each index (output A, output B) of (0,0) (0,1) (1,1) and (1,0).. and the virtual grey code I would hopefully be able to track these presses and then be able to process the pairs to figure out the direction of turn and then have a single output command for the direction that the encoder is being turned.

OK after sleeping on it and doing some more reading and trying to decipher the .cpp with my limited knowledge can you let me know if I have the way getKeys works correct..

say I am turning 1 encoder which puts out 4 pulses in the rotating A and B Key press. and say A is the first press

In program

loop 1 the getKeys scan would place button A into the Keys Array in position 0 because it activated.
loop 2 the getKeys scan would add button B to the array in position 1 because it activated while A is still active.
loop 3 button A turns off so he getKeys scan would remove button A from position 0 but leave button B in the array because it is still activated.
loop 4 Both buttons are off so the Active Keys array would be clear

and now say I turn two encoders at the same exact time in the same direction which would be virtually impossible to time them the same am I correct that this would happen: Iwill use A, B, C, and D. AB being one, CD being the other.

Loop 1 - Active A, C into positions 0, 1
Loop 2 - Active A, C remain in positions 0, 1, B, D into positions 2, 3
Loop 3 - Active B, D remain in positions 2, 3
Loop 4 - Everything would clear if nothing was active

When a button is placed in the active array is it possible to call on the state of that button directly by the .char? or is the state call based on the array position?

Since if my understanding is correct on the getKeys and I can call directly then I should be able to still do a comparison of two specific buttons and their current state to cause an action ONLY when both buttons meet a certain requirement i.e. button A on Button B off, or Button A on and Button B on.. which is what I need to be able to do to get the virtual button press greycode so I can determine direction and output.

I had another though but dismissed it, of possible overlapping keypads one for Even and one for Odd but I think that could cause hardware issues depending on what buttons were pressed due to the overlapping columns and the switching pin states. This Idea was so that I could track the odd and even completely independently.

Anyway if you can let me know if my understanding of how it works is on track and if there is a way to look directly at specific buttons as to their activity and state using this I think I will be able to figure out something that works correctly and isn't pure luck.

and now say I turn two encoders at the same exact time in the same direction which would be virtually impossible to time them the same am I correct that this would happen: Iwill use A, B, C, and D. AB being one, CD being the other.

Loop 1 - Active A, C into positions 0, 1
Loop 2 - Active A, C remain in positions 0, 1, B, D into positions 2, 3
Loop 3 - Active B, D remain in positions 2, 3
Loop 4 - Everything would clear if nothing was active

You sir have just made my day! Yes, that is exactly how it is operating. Good job on your sleeping skills. :wink:

When a button is placed in the active array is it possible to call on the state of that button directly by the .char? or is the state call based on the array position?

OK, to continue with your example above, with 4 keys being pressed at different times you could actually have a new keypress fill position 0. Ex. if A goes to position 0 and B goes to position 1, and after a few moments A clears so that all you have on the list is B in position 1, then the next keypress (let's say D) will go to position 0. That means you need to search the list to find the location of any given key. They are only guaranteed to stay in the same position until they have gone through the complete set of states. PRESSED --> [maybe HOLD] --> RELEASED --> IDLE and then that key is removed from the list making that position available for use by another key.

Now that I've talked about the problem let's see if there is a solution. The key list is actually a list of C++ key objects. (See Key.h in the keypad/utility folder.) Each key object has 4 attributes: key.kchar, key.kcode, key.kstate, and key.stateChanged. Any time any key.kstate changes key.stateChanged is made true and keypadEventListener is called in the user's sketch.

So each key on the list has 4 attributes and you can read them any time that a key is on the list. You could use one of the two findInList() functions provided by the keypad library to locate the key within the list. Note: kcode is an automatically assigned number for each key listed in the keymap in the user's sketch.

// Search by character for a key in the list of active keys.
// Returns -1 if the key is NOT found or returns the index into the list of active keys.
int Keypad::findInList (char keyChar) {
  for (byte i=0; i<LIST_MAX; i++) {
    if (key[i].kchar == keyChar) {
      return i;
    }
  }
  return -1;
}

// Search by code for a key in the list of active keys.
// Returns -1 if the key is NOT found or returns the index into the list of active keys.
int Keypad::findInList (int keyCode) {
  for (byte i=0; i<LIST_MAX; i++) {
    if (key[i].kcode == keyCode) {
      return i;
    }
  }
  return -1;
}

Or you could process the list (read the 4 attributes) in your own code. The thing to understand is that each time getKeys() is called (polled by the loop() function) it updates the list if any changes were found. If anything changed then keypadEventListener() is called. This means you could record and compare millis() between two events. Ex. if you see that the state of A changed, stateChanged==true, then you could record the time A_pressed=millis() and A_released=millis(), etc. That would let you compare which events occured at a given time(s).

To answer your other question about multiple keypads, yes you can. Over time I was able to make sure that each keypad runs completely separate from one another. You would just create separete kpd1 and kpd2 and then run both kpd1.getKeys() and kpd2.getKeys() in the loop().

mstanley:
You sir have just made my day! Yes, that is exactly how it is operating. Good job on your sleeping skills. :wink:

OK, to continue with your example above, with 4 keys being pressed at different times you could actually have a new keypress fill position 0. Ex. if A goes to position 0 and B goes to position 1, and after a few moments A clears so that all you have on the list is B in position 1, then the next keypress (let's say D) will go to position 0. That means you need to search the list to find the location of any given key. They are only guaranteed to stay in the same position until they have gone through the complete set of states. PRESSED --> [maybe HOLD] --> RELEASED --> IDLE and then that key is removed from the list making that position available for use by another key.

Now that I've talked about the problem let's see if there is a solution. The key list is actually a list of C++ key objects. (See Key.h in the keypad/utility folder.) Each key object has 4 attributes: key.kchar, key.kcode, key.kstate, and key.stateChanged. Any time any key.kstate changes key.stateChanged is made true and keypadEventListener is called in the user's sketch.

So each key on the list has 4 attributes and you can read them any time that a key is on the list. You could use one of the two findInList() functions provided by the keypad library to locate the key within the list. Note: kcode is an automatically assigned number for each key listed in the keymap in the user's sketch.

// Search by character for a key in the list of active keys.

// Returns -1 if the key is NOT found or returns the index into the list of active keys.
int Keypad::findInList (char keyChar) {
  for (byte i=0; i<LIST_MAX; i++) {
    if (key[i].kchar == keyChar) {
      return i;
    }
  }
  return -1;
}

// Search by code for a key in the list of active keys.
// Returns -1 if the key is NOT found or returns the index into the list of active keys.
int Keypad::findInList (int keyCode) {
  for (byte i=0; i<LIST_MAX; i++) {
    if (key[i].kcode == keyCode) {
      return i;
    }
  }
  return -1;
}



Or you could process the list (read the 4 attributes) in your own code. The thing to understand is that each time getKeys() is called (polled by the loop() function) it updates the list if any changes were found. If anything changed then keypadEventListener() is called. This means you could record and compare millis() between two events. Ex. if you see that the state of A changed, stateChanged==true, then you could record the time A_pressed=millis() and A_released=millis(), etc. That would let you compare which events occured at a given time(s).

To answer your other question about multiple keypads, yes you can. Over time I was able to make sure that each keypad runs completely separate from one another. You would just create separete kpd1 and kpd2 and then run both kpd1.getKeys() and kpd2.getKeys() in the loop().

OK yes I figured out the issue of the key actually taking the earlier place in the list but I was too lazy to write that much.. lol..

So just to clarify in the line "int Keypad::findInList (char keyChar)" if I was to search by the character then "char keyChar" could be the stated variable of the key I want to find the state of such as Key "1" or Key "A" or pretty much anything as long as it was the Character that was defined in the matrix.. Am I correct here.. If so I am sure I can make something work how I want now knowing how things work correctly..

As far as the Dual Keypads with arrays I knew that was possible and actually be using that in the overall program but what I was mentioning was I wasn't sure about overlapping keypads.. ie on keypad Matrix running off of rows dedicated to pins 1, 3 and columns on 5 and 6 and then another with rows 2, 4, and columns on 5, 6.. Basically creating a 4x2 matrix but is read as two separate 2x2 matrix's but I am thinking that depending on the pin state for the columns things may or may not interfere at some point so for safety I am thinking the previous list lookup would be the WAY better route to go..

I actually have a full working program that I made with the KeyPad and the Buxtronix encoder reading but the encoders in single method take up SO many digital pins that it would limit future ideas so that is what I am working on trying to get a Matrix based encoder set-up working.

I thank you very much for clarification on these things as I now think i have the correct direction to get things working the way I expect them to work.

OK So now here is where my definite novice ness comes out. I cannot for the life of me figure out how to use.

// Search by character for a key in the list of active keys.
// Returns -1 if the key is NOT found or returns the index into the list of active keys.
int Keypad::findInList (char keyChar) {
  for (byte i=0; i<LIST_MAX; i++) {
    if (key[i].kchar == keyChar) {
      return i;
    }
  }
  return -1;
}

from the .cpp

So just so I get an understanding of how to use this how would I use this to simply make a query to the list for say button "2".

From what I understand with this I should be able to just see if button "2" is in the list and it would return "2" if it is there and "-1" if it is not..

Please correct me if I am wrong as well as how use it.

Thank you