Tuesday, June 24, 2014

CUSTOM DIY MIDI FOOT CONTROLLER for ABLETON LIVE - Arduino

I'm a geek. I know it. I like DIY'ing things. I bought a 3d printer (which is sitting in my office not working right now)... and like building drones. I usually bite off more than I can chew and often have to go to others for help. This time around, it was to build a custom Midi foot controller to use with Ableton Live for our click/loop tracks.


I have a Keith MacMillen Softstep... but its really complicated to program, and the buttons are rubber. I never knew if the thing was ever pressed or not. I wanted the "click" of a regular guitar pedal. And I don't need something that complicated. There are some other pedals you can purchase... but their footprint wasn't correct for my pedal board. And I didn't want to spend another $300-$400.

So for around $70 I built my own.

Physical Construction: 
I used luan ply and just made it in the wood shop.
SKETCHUP MODEL

Switches:
You need momentary SPST switches. I got the "silent" ones so it doesn't sound like a firecracker going off in the middle of the worship service. Something like this:

Microcontroller: 
I used an arduino teensy that I bought from sparkfun. It offers a couple of important things:
• It has USB connectivity
•It's powered via USB
•It supports a native MIDI control without need for some intermediary software.
•It has a ton of digital pins

LCD Display
I bought it HERE from sparkfun. I wanted a serial rather than parallel connection so I didn't have to chew up lots of extra pins. (pins= possible switches or leds, or connectors)

Connections. 
I suppose if I were really thorough I'd have some sort of fancy connection diagram. Basically,
I hooked pin 1 up to the serial LCD pin. And then the switches have all the connections from there. You could in theory have 24 or so physical buttons/switches. Or if you were really good with programming could figure out a way to use multiple banks. But that's too complicated for me.

Code:
This was the hard part. I first got it working with the MIDI buttons sketch. Then got the serial LCD sketch to work. As I'm not a programmer, I had to learn to combine the two together.
Here's the Arduino Code




/* Buttons to USB MIDI Example
   You must select MIDI from the "Tools > USB Type" menu
   To view the raw MIDI data on Linux: aseqdump -p "Teensy MIDI"
   This example code is in the public domain.
 
   You'll have to change the pin assignments below if you use different pins than I did.
*/

#include
#include
#define txPin 1

// the MIDI channel number to send messages
const int channel = 1;
SoftwareSerial LCD = SoftwareSerial(0, txPin);
// since the LCD does not send data back to the Arduino, we should only define the txPin
const int LCDdelay=10;  // conservative, 2 actually works


// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button14 = Bounce(14, 100);
Bounce button15 = Bounce(15, 100);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 10);  // which is appropriate for good
Bounce button3 = Bounce(3, 10);  // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 10);
Bounce button5 = Bounce(5, 10);  // if a button is too "sensitive"
Bounce button6 = Bounce(6, 200);  // to rapid touch, you can
Bounce button7 = Bounce(7, 10);  // increase this time.
Bounce button8 = Bounce(8, 10);
Bounce button9 = Bounce(9, 10);
Bounce button10 = Bounce(10, 10);
Bounce button11 = Bounce(11, 10);
Bounce button12= Bounce(12, 10);



// wbp: goto with row & column
void lcdPosition(int row, int col) {
  LCD.write(0xFE);   //command flag
  LCD.write((col + row*64 + 128));    //position
  delay(LCDdelay);
}
void clearLCD(){
  LCD.write(0xFE);   //command flag
  LCD.write(0x01);   //clear command.
  delay(LCDdelay);
}
void backlightOn() {  //turns on the backlight
  LCD.write(0x7C);   //command flag for backlight stuff
  LCD.write(157);    //light level.
  delay(LCDdelay);
}
void backlightOff(){  //turns off the backlight
  LCD.write(0x7C);   //command flag for backlight stuff
  LCD.write(128);     //light level for off.
   delay(LCDdelay);
}
void serCommand(){   //a general function to call the command flag for issuing all other commands
  LCD.write(0xFE);
}


void setup() {
  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!

  pinMode(txPin, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);  // Teensy++ 2.0 LED, may need 1k resistor pullup
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP); //channel 1
  pinMode(15, INPUT_PULLUP); // channel 2 Teensy 2.0 LED, may need 1k resistor pullup
  LCD.begin(9600);
  clearLCD();
  lcdPosition(0,0);
  LCD.print("  Scott's MIDI      Dominator");
}

void loop() {
  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button14.update();
  button15.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();


  // Check each button for "falling" edge.
  // Send a MIDI Note On message when each button presses
  // Update the Joystick buttons only upon changes.
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
  if (button14.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
    if (digitalRead(14) == LOW) {
    LCD.print ("SONG 1");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 1     ");}
  }
  if (button15.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
        if (digitalRead(15) == LOW) {
    LCD.print ("SONG 2");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 2     ");}
  }
    if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
    if (digitalRead(2) == LOW) {
    LCD.print ("SONG 3");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 3     ");}
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendNoteOn(63, 99, channel);  // 63 = D#4
    if (digitalRead(3) == LOW) {
    LCD.print ("SONG 4");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 4     ");}
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendNoteOn(64, 99, channel);  // 64 = E4
    if (digitalRead(4) == LOW) {
    LCD.print ("SONG 5");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 5     "); }
  }
  if (button5.fallingEdge()) {
    usbMIDI.sendNoteOn(65, 99, channel);  // 65 = F4
    if (digitalRead(5) == LOW) {
    LCD.print ("SONG 6");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("     SONG 6     ");}
  }
  if (button6.fallingEdge()) {
    usbMIDI.sendNoteOn(66, 99, channel);  // 66 = F#4
    if (digitalRead(6) == LOW) {
    LCD.print ("PLAY");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print (">>>>>PLAY<<<<<");}
  }
  if (button7.fallingEdge()) {
    usbMIDI.sendNoteOn(67, 99, channel);  // 67 = G4
    if (digitalRead(7) == LOW) {
    LCD.print ("STOP");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("      STOP      XXXXXXXXXXXXXXXX"); }
  }
  if (button8.fallingEdge()) {
    usbMIDI.sendNoteOn(68, 99, channel);  // 68 = G#4
    if (digitalRead(8) == LOW) {
    LCD.print ("NEXT");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("      NEXT      >>>>>>>>>>>>>>>>");}
  }
  if (button9.fallingEdge()) {
    usbMIDI.sendNoteOn(69, 99, channel);  // 69 = A5
    if (digitalRead(9) == LOW) {
    LCD.print ("PREVIOUS");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("    PREVIOUS    <<<<<<<<<<<<<<<<"); }
  }
  if (button10.fallingEdge()) {
    usbMIDI.sendNoteOn(70, 99, channel);  // 70 = A#5
    if (digitalRead(10) == LOW) {
    LCD.print ("EXTRA BUTTON 11");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("EXTRA BUTTON 11"); }
  }
  if (button11.fallingEdge()) {
    usbMIDI.sendNoteOn(71, 99, channel);  // 71 = B5
    if (digitalRead(11) == LOW) {
    LCD.print ("EXTRA BUTTON 12");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("EXTRA BUTTON 12"); }
  }
    if (button12.fallingEdge()) {
    usbMIDI.sendNoteOn(72, 99, channel);  // 72 = C6
    if (digitalRead(12) == LOW) {
    LCD.print ("EXTRA BUTTON 13");
    LCD.print (0xFE, BYTE);
    LCD.print (0x01, BYTE);
    LCD.print ("EXTRA BUTTON 13");
          }
    delay(50);
  }

  // Check each button for "rising" edge
  // Send a MIDI Note Off message when each button releases
  // For many types of projects, you only care when the button
  // is pressed and the release isn't needed.
  // rising = low (pressed - button connects pin to ground)
  //          to high (not pressed - voltage from pullup resistor)
  if (button14.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button15.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }
  if (button3.risingEdge()) {
    usbMIDI.sendNoteOff(63, 0, channel);  // 63 = D#4
  }
  if (button4.risingEdge()) {
    usbMIDI.sendNoteOff(64, 0, channel);  // 64 = E4
  }
  if (button5.risingEdge()) {
    usbMIDI.sendNoteOff(65, 0, channel);  // 65 = F4
  }
  if (button6.risingEdge()) {
    usbMIDI.sendNoteOff(66, 0, channel);  // 66 = F#4
  }
  if (button7.risingEdge()) {
    usbMIDI.sendNoteOff(67, 0, channel);  // 67 = G4
  }
  if (button8.risingEdge()) {
    usbMIDI.sendNoteOff(68, 0, channel);  // 68 = G#4
  }
  if (button9.risingEdge()) {
    usbMIDI.sendNoteOff(69, 0, channel);  // 69 = A5
  }
  if (button10.risingEdge()) {
    usbMIDI.sendNoteOff(70, 0, channel);  // 70 = A#5
  }
  if (button11.risingEdge()) {
    usbMIDI.sendNoteOff(71, 0, channel);  // 71 = B5
  }
  if (button12.risingEdge()) {
    usbMIDI.sendNoteOff(72, 0, channel);  // 71 = C6
  }
}










Monday, January 20, 2014

I was so proud of the body of Christ today:

Ricky is a man that one of our members at Grace Community Church of Frederick met at the Frederick Rescue Mission. Ricky was homeless and one of our members (Erik) took Ricky in, had him over to their house several times for dinner. They starting picking Ricky up to bring him to church. A couple of months ago Erik baptized Ricky as a disciple of Jesus at our church. Ricky has been attending faithfully and is a valued part of our body.

On Saturday, Ricky was rushed to the ER with significant health issues that placed Ricky in the ICU. Ricky's family is out of the picture. But Erik was right there with him. Erik slept overnight at the ICU to be by Ricky's side. The Dr.'s met with us to communicate Ricky's condition and asked who we were (since we were not family). All we could say is "We are disciples of Jesus and Ricky is a part of our Church." When no one else was there; the church was.

Today I learned something new about making disciples of Jesus- that following Jesus sometimes means sitting at the ICU hospital bed next to a homeless man to share Jesus' love. It means sleepless nights and prayers upon prayers. And I'm telling you this incredible act of kindness was not done by someone who is paid to be a pastor, but was done by a regular church member; someone who realized it was their life's calling to be a sold-out Christ follower.

That. Was. Awesome.

Please pray for Ricky- He has a very serious liver condition. The next steps and future is uncertain.

-Scott Avey