I'm using a Teensy 2.0 to build a button box that will be used with iRacing to control most all of the in-car controls and settings in-game. The project will eventually be expanded to around 120 control wired up in a 12x10 grid and utilizing push-button momentaries, a couple on-off toggles, a few rotary encoders, and a pair of 12-position rotaries.

Right now, I'm just familiarizing myself with the Arduino software, learning how to make sketches, and taking my time making sure everything works right. I'm using a simple breadboard and wires until everything is working smoothly. Currently, I'm trying to get a 3x3 matrix of momentary switches to work in-game. Once I've got that I'll figured out, I'll expand the project.

I have run across a few problems that I've researched to solve, but I have some more that have popped up in the process.

Here is my code so far. I'm utilizing a keypad matrix.

Code:
// Button Box Sketch Initial Prototype
// Rev. 1.0
// Travis Mihm

// Initialize the integers for the Row and Column Matrix

const int numRows = 3;        // Number of Rows is assigned as a constant integer
const int numCols = 3;        // Number of Columns is assigned as a constant integer
const int debounceTime = 250;  // Set the milliseconds for debounce as a constant integer

//Use Keymap to define the character for the buttons when pressed

char keymap[numRows][numCols] = // the keymap assignments remain constant characters

{
  
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'}
  
};

//Set array for pins being used

const int rowPins[numRows] = {11, 12, 13};          //Assign constant integers relating the number of rows to their corresponding pins

const int colPins[numCols] = { 8, 9, 10};  //Assign constant integers relating the number of columns to their corresponding pins

//Begin setup procedure

void setup() 

{
  
  Serial.begin(9600);                                   // Start conversation with the serial port
  
  for (int row = 0; row < numRows; row++)               // For loop; Initial condition is the ingeger "row" set at zero. It then tests to see of the row integer is less than
                                                        // the numRows integer. If true, the statement {} runs, and the integer "row" is incremented. If false, the for loop
                                                        // terminates  
  {
    
    pinMode(rowPins[row], INPUT);                       // Set row pins as input type
    
    digitalWrite(rowPins[row], HIGH);                   // Turn on Pull-Ups
    
  }
  
  for (int column = 0; column < numCols; column++)      // Same loop with the rows, but for the columns now
  
  {
    
    pinMode(colPins[column], OUTPUT);                   // Set column pins as output pins
                                        
    digitalWrite(colPins[column], HIGH);                // Set all columns inactive initially
    
  }
  
}

// The "for" loops were to set the initial ready-conditions for the board. Now the code begins the body of the loop procedures to output which buttons get pressed

void loop()

{
  
  char key = getKey();
  if( key != 0) 
  
  {
    
    Serial.print("You pressed ");
    
    Serial.println(key);
    
  }
  
}

// returns the the key pressed, or 0 if no key is pressed.

char getKey()

{
  
  char key = 0;
  
  for (int column = 0; column < numCols; column++)
  
  {
    
    digitalWrite(colPins[column], LOW);    //Activate (column number)

    for(int row = 0; row < numRows; row++) //Scan rows on this column for a
                                           //key press
    {
  
      if(digitalRead(rowPins[row]) == LOW) //When key is pressed...
  
      {
    
        delay(debounceTime);                       // Set the time for the debounceTime integer
    
        while(digitalRead(rowPins[row]) == LOW);   // While the row for the column being scanned is still active
    
        key = keymap[row][column];                 // The key integer is now whatever was set in the keymap function under the current row and column being scanned
        
      }
      
    }
    
    digitalWrite(colPins[column], HIGH);          // Deactivate the current column
    
  }
  
  return key;                                     // returns the current key intiger to the getKey function. This ends the getKey loop and starts it over again.
  
}
1. - First, I'd like to be able to name the buttons more than just one character. I cannot seem to figure out the process for that. I tried using something like "A1" instead of 'A1' as from what I understood, the "" marks were the solution to my problem.

2. - I currently have the debounceTime at 250ms; any less than that, and I get the stray double-press when the momentary switch is released. However, I'd rather use something like a button state change. That will be useful for my toggle switches, as I really want those to act like momentaries (the toggle is really just for looks, to mimic an ignition switch, starter switch, etc. So one would toggle on or off like a momentary, another would only trigger when toggling from off to on, etc.) and I assume would be useful for the encoders as well. But I'm a little confused on how I'd incorporate a button state change into a matrix. Am I just overthinking it?

3. - I'm still a little confused on how I get the button presses recognized by my computer/iRacing. Is this where USB Type comes into play? Would I be able to name the switches through that?


My apologies if this has all been asked recently or are commonly solved around here. I have a head injury that has affected my working memory, and it gets a little tough to remember how I solved a problem, if I had found a solution somewhere, what I was trying to solve in the first place, etc Lots of sticky notes and lists and diagrams drawn out right now. If I need to include a schematic let me know, but it's fairly easy to deduce how it's wired up.

I have not touched the USB Type, it's still set at serial. Will I be able to communicate through iRacing at all with it on Serial, or will I have to change the device type to something else?

-Travis