Hi Everyone,
Long time no post in the forum, but recently I finished a little project that I think can be interesting for someone, so I've decided to post it here.
It's basically a MIDI switcher for an amp. So, a device that can receive MIDI messages (ie, from your MIDI foot controller) and control your amp channel, reverb or other characteristics that can be changed via the normal footswitch.
It's really something I don't need now, because I only use my amp (Peavey Bandit) as a power amp and I feed it with my POD, but one friend was in need of one and I decided to give it a try.
In addition, I just had in my drawer a recently purchased Aruino nano asking for a project...
The deviceDevice features:
-DC Jack compatible with BOSS PS
-MIDI IN. This is where we will receive the messages. I have a placeholder for MIDI OUT as well, but I didn't implemente it yet (my thought is to do a MIDI through, just relaying what comes in)
-Stereo jack. In my case, the Bandit uses a stereo jack to control 2 things, amp channel and booter. You will need to adapt this to your amp needs.
-Push button. Used to configure presets and save them.
How does it work?:
The Arduino stores in Non Volatile Memory all the presets, one for each MIDI Program.
In each preset, you can configure what relay is on/off of the two. These will control your amp.
When a Program Change MIDI message is received, it activates/deactivates the appropriate relays based on the presets stored.
In order to change a preset, first you need to send the PC MIDI message, then push the button multiple times until you reach your desired setup. Every time you push, the device cycles through all combinations. When you are happy with it, you need to push for a long period (more than 1 second), and it will be stored and ready for next time you send the same PC MIDI message.
Tecnical details:The MIDI switcher has 2 main parts:
-Arduino nano: All the Arduion power in a small package.

I bought it here, really cheap:
http://www.banggood.com/ATmega328P-Nano-V3-Controller-Board-Compatible-Arduino-p-940937.html-Relay module: It has 2 relays. We can connect them as Normally Closed or Normally Open, depending on your needs.

I bought this one from ebay, but you can get similar ones from multiple places:
http://www.ebay.es/itm/MODULO-RELAY-RELE-5V-DE-2-CANALES-PARA-ARDUINO-ARM-PIC-AVR-DSP-RASPBERRY-PI-/261475911035?In order to put the small amount of external components needed for the prouject, I used a perfboard PCB I had laying aroung.
Here you have the design:

As you can see... small part count. Only 3 resistors and one diode, and one optocoupler. BTW, the diode is the one in vertical, with the cathode in pin 2 of the opto.
Connections:
SW1: Momentary Push button, normally open. If you have a differnt type of button, you will need to adapt the software. The pins is configured with and internal pullup, so no extra resistor is required.
SW GND: This one goes to the other pin of the pushbutton.
RELAY1 & RELAY2: these will go to the relay module In1 and In2.
FOOT1 & FOOT&: For future use. Explained later.
MIDI IN 4 & 5: These go to the MIDI IN jack.
MIDI OUT 2,4,5: You can skip these, only for future use.
9v(BAT): Power in from DC jack. It can be up to 12v
GND(BAT): Ground from DC jack.
RELAY PWR: Relay power (5v). It gets connected to Vin
RELAY GND: Relay module ground.
You will need to adapt the way you connect the relay to the amp, as this depends on the amp. Look for the footswitch schematic, and try to replicate it with the relays.
In my case (Peavey Bandit) it goes like this:
Sleeve: Common, it goes to the central pin of each relay.
Ring: To one of the outer pins of Relay 1.
Tip: To one of the outer pins of Relay 2.
Here you have it in a sweet box.... whenever I have time I will move it to a better enclosure. But this one works great


Guts shot:
SoftwareAnd, here you have the code. You will need:
-Mini USB cable
-Arduino IDE. you can get it from
www.arduino.cc-Depending on the arduino you buy, you might need an extyra driver. Check with the vendor.
-Extra libraries you will need to install:
Onebutton : To control events based on button pushes.
http://www.mathertel.de/Arduino/OneButtonLibrary.aspxMIDI Library: To send/receive MIDI messages.
http://playground.arduino.cc/Main/MIDILibrary#include <OneButton.h>
#include <EEPROM.h>
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>
#define LED1 11 //set pin for Relay1
#define LED2 10 //set pin for Relay2
#define SW1 12 //set pin for button
MIDI_CREATE_DEFAULT_INSTANCE();
byte curr_program; //current PC value
// Setup a new OneButton on pin 11.
OneButton button1(SW1, true);
// -----------------------------------------------------------------------------
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters,
// see documentation here:
// http://arduinomidilib.fortyseveneffects.com/a00022.html
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
// Do whatever you want when a note is pressed.
// Try to keep your callbacks short (no delays ect)
// otherwise it would slow down the loop() and have a bad impact
// on real-time performance.
}
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
// Do something when the note is released.
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
}
void handleProgramChange(byte channel, byte number)
{
//do something when receiving PC messages
byte value;
curr_program=number; //stores the PC number for later
//read preset value from EEPROM
value=EEPROM.read(number);
//activate relay 1 if needed
if (getBit(value,1))
{
digitalWrite(LED1,HIGH);
}
else
{
digitalWrite(LED1,LOW);
}
//activate relay 2 if needed
if (getBit(value,2))
{
digitalWrite(LED2,HIGH);
}
else
{
digitalWrite(LED2,LOW);
}
}
// This function will be called when the button1 was pressed 1 time.
void click1() {
//toggle Relay1
byte value;
value=digitalRead(LED1)+digitalRead(LED2)*2;
value++;
if (getBit(value,1))
{
digitalWrite(LED1,HIGH);
}
else
{
digitalWrite(LED1,LOW);
}
//activate relay 2 if needed
if (getBit(value,2))
{
digitalWrite(LED2,HIGH);
}
else
{
digitalWrite(LED2,LOW);
}
} // click1
// This function will be called when the button1 was pressed 2 times in a short timeframe.
void doubleclick1() {
} // doubleclick1
// This function will be called once, when the button1 is pressed for a long time.
void longPressStart1() {
//save preset
byte value=0;
if (digitalRead(LED1))
{
setBit(value,1);
}
if (digitalRead(LED2))
{
setBit(value,2);
}
EEPROM.write(curr_program,value);
} // longPressStart1
// This function will be called often, while the button1 is pressed for a long time.
void longPress1() {
//Serial.println("Button 1 longPress...");
} // longPress1
// This function will be called once, when the button1 is released after beeing pressed for a long time.
void longPressStop1() {
//digitalWrite(LED2,LOW);
} // longPressStop1
// -----------------------------------------------------------------------------
void setup()
{
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(SW1, INPUT_PULLUP);
//write inital presets, only for debugging.
for (int i=0;i<128;i++)
{
//EEPROM.write(i,i);
}
//Define button handling functions
button1.attachClick(click1);
button1.attachDoubleClick(doubleclick1);
button1.attachLongPressStart(longPressStart1);
button1.attachLongPressStop(longPressStop1);
button1.attachDuringLongPress(longPress1);
// Connect the handleNoteOn function to the library,
// so it is called upon reception of a NoteOn.
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
// Do the same for NoteOffs
MIDI.setHandleNoteOff(handleNoteOff);
// And for PC message
MIDI.setHandleProgramChange(handleProgramChange);
// Initiate MIDI communications, listen to all channels
MIDI.begin(MIDI_CHANNEL_OMNI);
//Serial.begin(9600); //Set serial to 9600, only for debugging
}
void loop()
{
// Call MIDI.read the fastest you can for real-time performance.
MIDI.read();
// There is no need to check if there are messages incoming
// if they are bound to a Callback function.
// The attached method will be called automatically
// when the corresponding message has been received.
// Call button tick to check button status
button1.tick();
}
byte setBit(byte &store, byte bitn) { //bit 1 is right-most
store |= (1 << (bitn - 1)); //set bit 5 to '1'.
}
byte clearBit(byte &store, byte bitn) {
store &= !(1 << (bitn - 1));
}
bool getBit(byte store, byte bitn) {
byte b = (1 << (bitn - 1));
return (store & b);
}
Pending topics:There are some improvements pending. When I have the time I will implement them:
1- Take the LEDs outside of the box. When I have the definitive box, I will simply remove the red LED from the module, and plug in 2 new LEDs that will be visible from the outside.
2- MIDI through: The ideas is to conncet the MIDI OUT and modify the software to simply output everything that comes from MIDI IN. This way you can daisy chain it with another MIDI device you need to control
3- Footswitch IN: I have left 2 FOOT1 and FOOT2 connections reserved. The ideas is to connect the current amp footswitch. With this and a routine to detect rising/falling edges, I plan to be able to still use the footwitch at the same time as the MIDI Switch.
4- Find a catchy name for it.

I hope this will be of interest for someone. If you plan to build one and need help, don't hesitate to contact me.
Have a nice DIY day!
Mat