How To Detect 22 Switches for MIDI Foot Controller

Hi, I have made a foot controller to control Ableton Live. It has 20 switches and there aren't enough digital inputs on the arduino to wire them normally. How can I detect 20 switches from 14 inputs? A 4x5 matrix? If so how would this work?

Once a keypress is detected I want to send serial data via USB to the computer to be interpreted in C or Processing to emulate a MIDI event as well as an ASCII key press. How would I do this also?

Thanks,

Matthew Hubble

If you need to read more inputs than the arduino has pins for, the answer my friend is multiplexing. This can be done in software or you can use a multiplexing IC such as here
http://www.arduino.cc/playground/Learning/4051

thanks very much trialex that is a really good resource I haven't seen before and its solved my problem. I am going to use 3 of the CD4021BE IC's daisy chained together to get 24 switches using only 3 pins. 20 of these switches are used. 2 other switches are used to change the MIDI channel of the messages to give my foot controller 4 different functions. This is the code I intend to use:

//**************************************************************//
//  Name    : MIDI Foot Controller                              //
//  Author  : Matthew Hubble                                    //
//  Date    : 11 May, 2008                                      //
//  Version : 0.1                                               //
//  Notes   : Code for using a CD4021B Shift Register and           //
//          : sending MIDI                                      //
//**************************************************************//

//define pins
#define MIDIPin 1
#define ledPin 2
#define clockPin 3
#define dataPin 4
#define latchPin 5
#define modePin1 6
#define modePin2 7

//define bits
#define BIT1 1
#define BIT2 2
#define BIT3 3
#define BIT4 4
#define BIT5 5
#define BIT6 6
#define BIT7 7
#define BIT8 8

//define MIDI stuff
#define MIDICHANNEL1 1
#define MIDICHANNEL2 2
#define MIDICHANNEL3 3
#define MIDICHANNEL4 4
#define VELOCITY 127
#define ROOTNOTE1 1
#define ROOTNOTE2 9
#define ROOTNOTE3 17

//declare 3 bytes to hold the binary from 3 CD4021BE IC's 
byte switchVar1 = 0;
byte switchVar2 = 0;
byte switchVar3 = 0;

int modePin1State;
int modePin2State;
int if_flag = 0;

void setup() 
{
  //set MIDI baud rate
  Serial.begin(31250);
  
  //define pin modes
  pinMode(ledPin,OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT); 
  pinMode(dataPin, INPUT);
  pinMode(modePin1,INPUT);
  pinMode(modePin2,INPUT);
  
  //turn on internal pullup
  digitalWrite(modePin1, HIGH);
  digitalWrite(modePin2, HIGH);
}

void loop()
{
  //Pulse the latch pin:
  //set it to 1 to collect parallel data
  digitalWrite(latchPin,1);
  //set it to 1 to collect parallel data, wait
  delayMicroseconds(20);
  //set it to 0 to transmit data serially  
  digitalWrite(latchPin,0);

  //while the shift register is in serial mode
  //collect each shift register into a byte
  //the register attached to the chip comes in first 
  switchVar1 = shiftIn(dataPin, clockPin);
  switchVar2 = shiftIn(dataPin, clockPin);
  switchVar3 = shiftIn(dataPin, clockPin);
  
  //get the state of the mode switches
  modePin1State = digitalRead(modePin1);
  modePin2State = digitalRead(modePin2);
  
  //send appropriate MIDI messages based on input
  switchtoMIDI(switchVar1, ROOTNOTE1);
  switchtoMIDI(switchVar2, ROOTNOTE2);
  switchtoMIDI(switchVar3, ROOTNOTE3);
}

//shiftIn function gets 8 bit binary string
byte shiftIn(int myDataPin, int myClockPin) { 
  int i;
  int temp = 0;
  int pinState;
  byte myDataIn = 0;

  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, INPUT);

  for (i=7; i>=0; i--)
  {
    //Set clockPin to LOW to recieve serial bit
    digitalWrite(myClockPin, 0);
    //wait to recieve bit
    delayMicroseconds(2);
    //read  1 or 0
    temp = digitalRead(myDataPin);
    if (temp) 
    {
      pinState = 1;
      myDataIn = myDataIn | (1 << i);
    }
    else 
    {
      pinState = 0;
    }
    
    //set clockPin to HIGH ready for the next bit
    digitalWrite(myClockPin, 1);

  }
  return myDataIn;
}

// send a MIDI note-on message
void noteOn(byte channel, byte note, byte velocity)
{
  midiMsg( (0x90 | (channel << 4)), note, velocity);
}

// send a MIDI note-off message
void noteOff(byte channel, byte note, byte velocity) 
{
  midiMsg( (0x80 | (channel<<4)), note, velocity);
}

// send a general MIDI message
void midiMsg(byte cmd, byte data1, byte data2)
{
  digitalWrite(ledPin,HIGH);  // indicate we're sending MIDI data
  Serial.print(cmd, BYTE);
  Serial.print(data1, BYTE);
  Serial.print(data2, BYTE);
  digitalWrite(ledPin,LOW);
}

//send MIDI messages based on the mode switches and the MIDI switches
void switchtoMIDI(byte switchVar, int rootnote)
{
  if(modePin1State == HIGH && modePin2State == HIGH && if_flag == 0)
  {
    if(switchVar & BIT1 == 1)
    {
      noteOn(MIDICHANNEL1,rootnote,VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,rootnote,VELOCITY);
    }
    
    if(switchVar & BIT2 == 2)
    {
      noteOn(MIDICHANNEL1,(rootnote + 1),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 1),VELOCITY);
    }
    
    if(switchVar & BIT3 == 3)
    {
      noteOn(MIDICHANNEL1,(rootnote + 2),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 2),VELOCITY);
    }
    
    if(switchVar & BIT4 == 4)
    {
      noteOn(MIDICHANNEL1,(rootnote + 3),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 3),VELOCITY);
    }
    
    if(switchVar & BIT5 == 5)
    {
      noteOn(MIDICHANNEL1,(rootnote + 4),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 4),VELOCITY);
    }
    
    if(switchVar & BIT6 == 6)
    {
      noteOn(MIDICHANNEL1,(rootnote + 5),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 5),VELOCITY);
    }
    
    if(switchVar & BIT7 == 7)
    {
      noteOn(MIDICHANNEL1,(rootnote + 6),VELOCITY);
      delayMicroseconds(1); 
      noteOff(MIDICHANNEL1,(rootnote + 6),VELOCITY);
    }
    
    if(switchVar & 8 == 8)
    {
      noteOn(MIDICHANNEL1,(rootnote + 7),VE