Guitar Rig 5 DIY Foot Pedal Controller

My father recently acquired an electric guitar, which he has been happily using in combination with Guitar Rig 5 (a guitar pedal/amp simulation software), a Behringer UCG102 guitar link, and a Lenovo miix tab 2.  Using win8.1 x64 bit with updated ASIO drivers, the little system packs quite a punch; even the most complex effects only give a latency of about 13ms!  The software is great, it allows you to simulate/add as many effects/pedals as you want without needing to buy dozens of expensive pedals.  Unfortunately, this also comes with a downside. 























                    
                    (Guitar Rig 5 Interface)                                                                                 (Lenovo Miix 2 8")                                                          (Berhinger USB Interface)


Due to the very nature of the setup, changing presets/pedals in real time while playing is not something that is easy to do with a tablet.  While it is possible to assign keyboard shortcuts to various presets, trying to hit a key on a keyboard and play at the same time is not so easy.  Commercial Foot pedals that control Guitar Rig are available, but are difficult to find and very expensive ($300)!


                        
 














                            (Rig Kontrol 3)


After thinking for awhile about the subject, I got an idea!  I remember reading that some of the newer Arduinos offered usb HID simulation, including keypresses!  I could simply make my own box with some momentary switches and I would have the same product at a fraction of the cost.  As you will see later on, a simple controller like mine can be built for well under $20, including the enclosure!

 Now no offense to Arduino; they make some great stuff, but I think even the most loyal customers must agree that they charge a pretty hefty premium for their products.  But as long as you are willing to wait a while to get the parts, some Arduino Pro Micros with usb hid support can be found for as little as 7$ on Ebay.

 Make SURE to order the ones with the newer ATMEGA32U4 chip, not the ATMEGA328 like the pro mini which is cheaper, otherwise usb emulation will not work without extra parts and more headaches.
       
 I wanted to make a controller with four buttons, which could then be expanded up to 12 presets by hitting more than one button at once.  A nice led indicator would also be necessary to indicate what preset you are currently on.  A resistor ladder was used to connect the buttons and free up pins.  If you do create a resistor ladder, make sure to wire the buttons with different resistor values if you want to be able to distinguish multiple button presses at once.  I used 220, 390, 680, and 2.2k ohm resistors to ensure adequate separation between the buttons and used a 1K resistor to tie the analog pin to ground.

 As with everything in programming, there are always 100 different ways to do the same thing, but I wanted something a little more elegant than just using digital writes to turn leds on and off.  Seeing as I had nice clear colored leds, I figured a pwm cycled sine wave would provide a pleasing fading effect to the leds.  To do this, I had the buttons switch boolean values on and off which then triggered the keypresses and leds, otherwise the fading effect would stop as soon as you let go of the momentary switch.  That's enough talking, lets see how it works shall we?
                     



The LEDs In ACTION!



The Inside of the Box (Please Excuse the Point to Point Wiring!)




THE FULL SETUP!


The box was purchased at radio shack, and the leds/resistors/grommets were bought at Tayda Electronics.  I recommend you use 1% resistors instead of 5%, or you may need to change the values in the matrix of my code slightly.

Here is a Video of it In action:

YouTube Video



CODE TIME!

You will notice in the script that I have the box play a short introduction flash when you first plug it into usb, that is completely optional.  I have not included keystrokes for multiple buttons as of yet because I simply don't need that many presets, but it should be just a matter of copy and pasting some existing code and changing a value here or there if you want the extra buttons:

(Sorry! Lots of Scrolling Ahead!)

CODE

int j = 1; // integer used in scanning the array designating column number
//2-dimensional array for assigning the buttons and there high and low values
int Button[21][3] = {{1, 837, 845},// button 1
                     {2, 730, 738}, // button 2
                     {3, 603, 612}, // button 3
                     {4, 318, 323}, // button 4
                     {7, 896, 900}, // button 1 + button 2
                     {8, 877, 882}, // button 1 + button 3
                     {9, 851, 857}, // button 1 + button 4
                     {10, 816, 822}, // button 2 + button 3
                     {11, 760, 770}}; // button 2 + button 4
   

int analogpin = 0; // analog pin to read the buttons
int label = 0;  // for reporting the button label
int counter = 0; // how many times we have seen new value
long time = 0;  // the last time the output pin was sampled
int debounce_count = 50; // number of millis/samples to consider before declaring a debounced input
int current_state = 0;  // the debounced input value
int ButtonVal;

const int bled = 9;
const int yled = 6;
const int gled = 5;
const int rled = 3;

boolean b1 = false;
boolean b2 = false;
boolean b3 = false;
boolean b4 = false;

long randNumber;

void setup()
{
  Keyboard.begin();
 
  pinMode(bled, OUTPUT);
  pinMode(yled, OUTPUT);
  pinMode(gled, OUTPUT);
  pinMode(rled, OUTPUT);
 
  randomSeed(analogRead(1));
  randNumber = random(0,2);
 
  switch(randNumber){
    case 0:
    digitalWrite(rled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    digitalWrite(yled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(bled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(bled,LOW);
    digitalWrite(yled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    digitalWrite(yled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(bled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(bled,LOW);
    digitalWrite(yled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    digitalWrite(yled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(bled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(bled,LOW);
    digitalWrite(yled,HIGH);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,LOW);
    delay(50);
    digitalWrite(gled,HIGH);
    digitalWrite(rled,LOW);
    delay(50);
    break;
    case 3:
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    digitalWrite(rled,HIGH);
    digitalWrite(gled,HIGH);
    digitalWrite(yled,HIGH);
    digitalWrite(bled,HIGH);
    delay(50);
    digitalWrite(rled,LOW);
    digitalWrite(gled,LOW);
    digitalWrite(yled,LOW);
    digitalWrite(bled,LOW);
    delay(50);
    break;

    }

}

void loop()
{
  static float in = 4.712;
  float out;
   // If we have gone on to the next millisecond
  if (millis() != time)
  {
    // check analog pin for the button value and save it to ButtonVal
    ButtonVal = analogRead(analogpin);
    if(ButtonVal == current_state && counter >0)
    {
      counter--;
    }
    if(ButtonVal != current_state)
    {
      counter++;
    }
    // If ButtonVal has shown the same value for long enough let's switch it
    if (counter >= debounce_count)
    {
      counter = 0;
      current_state = ButtonVal;
      //Checks which button or button combo has been pressed
      if (ButtonVal > 0)
      {
        ButtonCheck();
      }
    }
    time = millis();
  }
 
  if (b1==true)
  {
  in = in + 0.0005;
  if (in > 10.995)
    in = 4.712;
  out = sin(in) * 64 + 64;
  analogWrite(rled,out);
  }
  if (b1==false)
  {
    out = 0;
    analogWrite(rled,out);
  }
  if (b2==true)
  {
    in = in + 0.0005;
  if (in > 10.995)
    in = 4.712;
  out = sin(in) * 64 + 64;
  analogWrite(gled,out);
  }
  if (b2==false)
  {
    out = 0;
    analogWrite(gled,out);
  }
  if (b3==true)
  {
    in = in + 0.0005;
  if (in > 10.995)
    in = 4.712;
  out = sin(in) * 64 + 64;
  analogWrite(yled,out);
  }
  if (b3==false)
  {
    out = 0;
    analogWrite(yled,out);
  }
  if (b4==true)
  {
    in = in + 0.0005;
  if (in > 10.995)
    in = 4.712;
  out = sin(in) * 64 + 64;
  analogWrite(bled,out);
  }
  if (b4==false)
  {
    out = 0;
    analogWrite(bled,out);
  }
 
}

void ButtonCheck()
{
  // loop for scanning the button array.
  for(int i = 0; i <= 21; i++)
  {
    // checks the ButtonVal against the high and low vales in the array
    if(ButtonVal >= Button[i][j] && ButtonVal <= Button[i][j+1])
    {
      // stores the button number to a variable
      label = Button[i][0];
      Action();    
    }
  }
}

void Action()
{
  if(label == 1)
  {
   b1=true;
   b2=false;
   b3=false;
   b4=false;
   Keyboard.print('1');
   }
  if(label == 2)
  {
   b1=false;
   b2=true;
   b3=false;
   b4=false;
   Keyboard.print('2');
  }
  if(label == 3)
  {
   b1=false;
   b2=false;
   b3=true;
   b4=false;
   Keyboard.print('3');
  }
  if(label == 4)
  {
   b1=false;
   b2=false;
   b3=false;
   b4=true;
   Keyboard.print('4');
  }
}