News:

SMF for DIYStompboxes.com!

Main Menu

Arduino MIDI Switcher

Started by potul, November 04, 2015, 01:21:57 PM

Previous topic - Next topic

EeroN

#40
potul,

Thank you for sharing your instructions here. I just recently completed a three channel tube preamp with a graphic EQ assignable to each channel (Mesa style). I built a temporary footswitch for it, but eventually wanted to have MIDI control. I took your basic circuit and code, and after some tweaking I got it working.

Eventually, I will control five features of my preamp with the controller: CH1 CH2 or CH3, EQ on/off, reverb on/off (CH1 only). I have alredy implemented these in the code, I just have some wiring to do.

I'm running the controller with 12 V from my preamp, as that's the voltage my relays work at. Relay switching in the preamp is controlled by a CMOS Quad fliflop. The Arduino is controlling transistors, which again pull the corresponding logic pins of the fliflop high for channel changes.

Here's a quick video:

https://www.youtube.com/watch?v=-dw1Pc2Kgns

I'll put it in a Hammond enclosure on my pedalboard, where I'll send program changes from a Boss MS-3.

If anyone wants to see the code or has any other questions, I'll happily answer them.

Thanks again potul and all who have contribted to this thread.

potul

Great!

Happy to see my work is an inspiration for others.

Mat

bogdancat

Quote from: EeroN on July 27, 2018, 05:24:45 AM
potul,

Thank you for sharing your instructions here. I just recently completed a three channel tube preamp with a graphic EQ assignable to each channel (Mesa style). I built a temporary footswitch for it, but eventually wanted to have MIDI control. I took your basic circuit and code, and after some tweaking I got it working.

Eventually, I will control five features of my preamp with the controller: CH1 CH2 or CH3, EQ on/off, reverb on/off (CH1 only). I have alredy implemented these in the code, I just have some wiring to do.

I'm running the controller with 12 V from my preamp, as that's the voltage my relays work at. Relay switching in the preamp is controlled by a CMOS Quad fliflop. The Arduino is controlling transistors, which again pull the corresponding logic pins of the fliflop high for channel changes.

Here's a quick video:

https://www.youtube.com/watch?v=-dw1Pc2Kgns

I'll put it in a Hammond enclosure on my pedalboard, where I'll send program changes from a Boss MS-3.

If anyone wants to see the code or has any other questions, I'll happily answer them.

Thanks again potul and all who have contribted to this thread.

Please post the code for your switch. I'm looking to make a similar one for an Ibanez amp.

EeroN

Sorry, I just now checked back on this thread. Here's my code:


#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 RLY1 11 //set pin for Relay1
#define RLY2 10 //set pin for Relay2
#define RLY3 9  //set pin for Relay3
#define RLY4 8  //set pin for Relay4
#define REVC 7  //set pin for Reverb control (jfet)
#define SW1 12  //set pin for button
MIDI_CREATE_DEFAULT_INSTANCE();

byte curr_program;  //current PC value
byte state;     //current state

byte n = 1;     //these are for cycling states
byte neq = 0;

unsigned long startMillis; //for getting relays to activate simultaneously
unsigned long currentMillis;
const unsigned long period = 50; //set delay for RLY4

bool eq;
bool ch1;
bool ch2;
bool ch3;
bool rev;

// 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);

  if (getBit(value, 1))
  {
    digitalWrite(RLY4, HIGH);
  }
  if (getBit(value, 2))
  {
    digitalWrite(RLY1, HIGH);
    delay(period);
    digitalWrite(RLY1, LOW);
  }
  if (getBit(value, 3))
  {
    digitalWrite(RLY2, HIGH);
    delay(period);
    digitalWrite(RLY2, LOW);
  }
  if (getBit(value, 4))
  {
    digitalWrite(RLY3, HIGH);
    delay(period);
    digitalWrite(RLY3, LOW);
  }
  if (getBit(value, 5) && getBit(value, 2))
  {
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else
  {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

// This function will be called when the button1 was pressed 1 time.
void click1() {

  eq = false;
  ch1 = false;
  ch2 = false;
  ch3 = false;

  byte temp = 1 << n;
  state = temp + neq;

  if (getBit(state, 1))
  {
    digitalWrite(RLY4, HIGH);
    eq = true;
    neq = 0;
    n++;
  }
  else
  {
    neq = 1;
  }

  if (getBit(state, 4))
  {
    digitalWrite(RLY3, HIGH);
    delay(period);
    digitalWrite(RLY3, LOW);
    ch3 = true;
    digitalWrite(LED_BUILTIN, LOW);
  }

  if (getBit(state, 3))
  {
    digitalWrite(RLY2, HIGH);
    delay(period);
    digitalWrite(RLY2, LOW);
    ch2 = true;
    digitalWrite(LED_BUILTIN, LOW);
  }

  if (getBit(state, 2))
  {
    digitalWrite(RLY1, HIGH);
    delay(period);
    digitalWrite(RLY1, LOW);
    ch1 = true;
  }
  if (state == 9) //restart cycling all states
  {
    n = 1;
    neq = 0;
  }
} // click1


// This function will be called when the button1 was pressed 2 times in a short timeframe.
void doubleclick1() { //toggle reverb
  if (rev == false && ch1)
  {
    digitalWrite(LED_BUILTIN, HIGH);
    rev = true;
  }
  else
  {
    digitalWrite(LED_BUILTIN, LOW);
    rev = false;
  }

} // doubleclick1


// This function will be called once, when the button1 is pressed for a long time.
void longPressStart1() {
  //save preset
  byte value;
  if (eq)
  {
    setBit(value, 1);
    //Serial.print("eq ");
  }
  if (ch1)
  {
    setBit(value, 2);
    //Serial.print("ch1 ");
  }
  if (ch2)
  {
    setBit(value, 3);
    //Serial.print("ch2 ");
  }
  if (ch3)
  {
    setBit(value, 4);
    //Serial.print("ch3 ");
  }
  if (digitalRead(LED_BUILTIN) && ch1)
  {
    setBit(value, 5);
    //Serial.print(" rev");
  }

  EEPROM.write(curr_program, value);
  //Serial.println(value, BIN);

} // 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(RLY2,LOW);
} // longPressStop1


// -----------------------------------------------------------------------------
void setup()
{
  pinMode(RLY1, OUTPUT);
  pinMode(RLY2, OUTPUT);
  pinMode(RLY3, OUTPUT);
  pinMode(RLY4, OUTPUT);
  pinMode(REVC, OUTPUT);
  pinMode(SW1, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);

  //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
  //Serial.println("Start");

}
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();
  // See if RLY4 is on, turn it off after preset period
  currentMillis = millis();
  if (digitalRead(RLY4));
  {
    startMillis = millis(); //start counting milliseconds if RLY4 on
    if (currentMillis - startMillis >= period)
    {
      digitalWrite(RLY4, LOW);
    }
  }
}

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));
}

byte getBit(byte store, byte bitn) {
  byte b = (1 << (bitn - 1));
  return (store & b);
}



It's been a while since I wrote this, but I'll try to explain. I'm not really a programmer at all, so the code is probably a bit of a hack job and it's still a work in progress, but it works for now.

The sound preset (channel, eq and reverb on or off) is stored as byte 'value' which has 5 bits. The least significant bit indicates EQ state, the next three are the preamp channels 1 to 3, bit 5 is the CH1 reverb (although I haven't implemented this in my preamp yet, so it just lights the inbuilt led).

So CH1 with no EQ is 00010, CH1 with EQ is 00011, CH2 without EQ is 00100, CH2 with EQ is 00101, CH3 without EQ is 01000, CH3 with EQ is 01001. The reverb for CH1 is activated by a double click, and the current program is saved by a long press.

Also note that all of these different states are non-latching, so they only give a pulse of 50 ms (controlled by "const unsigned long period"), you might need to change it to operate as latching.

Hope this helps!


sixtheory

Ok folks, here's what i got:

I'm needing to adapt this to control a Mesa Roadking Series I head... i Know its a big undertaking.

This amp has 8 remotely-controllable functions via "Latching type, Tip-to-Ground" Logic on  1/4" mono jacks mounted on the rear panel of the amp head. I have a Decibel 11 Midi controller for my guitar rig to control functions via midi.

It might be too much to tackle for me, as i am pretty new to this. I have brief knowledge of programming Arduino for a college project..but thats about it?

Any Help would be greatly appreciated!

EeroN

Quote from: sixtheory on January 01, 2019, 09:37:12 AM
Ok folks, here's what i got:

I'm needing to adapt this to control a Mesa Roadking Series I head... i Know its a big undertaking.

This amp has 8 remotely-controllable functions via "Latching type, Tip-to-Ground" Logic on  1/4" mono jacks mounted on the rear panel of the amp head. I have a Decibel 11 Midi controller for my guitar rig to control functions via midi.

It might be too much to tackle for me, as i am pretty new to this. I have brief knowledge of programming Arduino for a college project..but thats about it?

Any Help would be greatly appreciated!

After a quick google search it seems to be possible to have multiple OneButtons within a single arduino sketch. I'd suggest setting up three of them as follows:

Button1: Channel 1, 2, 3 or 4, long press for program save
Button2: Loop 1, 2 or loop off
Button3: Combinations of Reverb and Solo on/off (4 in total)

It would of course be possible to use a single OneButton, but a total of 255 states is a lot to cycle through :) so from a usability standpoint it's probably worth the trouble to use multiple buttons.

The Nano has a total of 12 digital pins (D2-D13), so you could use the first 8 (D2-D9) for your control outputs and three (D10-D12) for the OneButtons and still have D13 (the inbuilt LED) for an indicator.

The hardware bit also needs some consideration. I've been experimenting with the ULN2003 IC, which I originally got for controlling stepper motors for another unrelated project, but it can be used as a logic buffer too. I'm not sure, but it might be possible to use that instead of having to wire up 8 relays to the arduino. The problem for your project is that the ULN2003 only has 7 inputs but your application needs 8. One solution would just be to use 2 of those, still a lot less PCB real estate than 8 relays.

What you should do is find out the control voltage sent out by the RK.

I can also do a bit of breadboarding for you later today with the Nano and the ULN2003 and report back with my results.

EeroN

I breadboarded the Nano with the ULN2003, and it seems to work as I thought. The ULN2003 doesn't pull the pins all the way to ground, but to about 0.7 V, which is probably close enough to trigger switching on the amp.

I also took a look at the RK schematic (version 2, but I believe the switching circuit on version 1 is similar), and the voltage used by the switching circuitry is 12V and that's what I used to test my circuit, so I'd say it's worth a try. The problem is you'd need a separate powersupply to power the Nano. You can't use the voltage from the RK switching circuit.

Of course, the simple solution to the above concerns would be to just use 8 relays, but this will require a much bigger PCB and will cost more. You'd also need to take into consideration the current drawn by the relays, and you'd need to use a separate power source for the circuit regardless.

ElectricDruid

If you're just triggering switching in the amp, a simple transistor is probably enough. A relay would be overkill. Use the Arduino to switch a transistor, and then use the transistor to short the tip to ground as if it was a foot switch.

T.

EeroN

Quote from: ElectricDruid on January 05, 2019, 05:28:45 AM
If you're just triggering switching in the amp, a simple transistor is probably enough. A relay would be overkill. Use the Arduino to switch a transistor, and then use the transistor to short the tip to ground as if it was a foot switch.

T.

Agreed, and that's how I did mine (see image).



That's also why I suggested the ULN2003, it basically has seven transistor switches in one package, resistors and all. Much less soldering than seven individual transistors. The Road King needs eight, but the remaining one can be easily implemented with a separate NPN transistor.


philos

Nice project! Exactly what i need (the version with two loops)!  I want to use two pedals controlled by MIDI.

Just one change:

Two footswitches, one to each loop. Long press the two at the same time to save rpeset.

Could some good soul post the code to that for me? I don't know pretty much nothing about this stuff.

Thank you in advance!

potul

I can try to help, but I will need to understand what your needs are.

TouringBubble

#51
Sorry to revive this thread, but I wanted to thank you for the inspiration to take on my own project. I've been working on implementing MIDI control on my board for loop switching and control of my Plethora X5, but ran into issues with Boss ES series controllers not being compatible with the Plethora. So, I started to look for alternates, and what I found had limited function or excessive cost to handle everything I need, which includes amp channel switching.

So, I found your project here and it was so straight forward, I decided to just build the amp switching module and it it really going to tie my setup together exactly how I want to.

I took a crack at my own version of the code to make some changes ... and ended up basically rewriting it all to be simpler for what I wanted to implement. I set it up for 4 relays instead of 2. I removed the OneButton code and storing of presets, and changed the triggers from PC to CC messages. I also added hardware DIP switches to code the MIDI channel if needed. There are two additional switches I was going to use for momentary or latched function, but I realized quickly that MIDI doesn't really need this, so I'm leaving it for future expansion.

Here is the code I ended up with, in case anyone wants to use it themselves. I still need to test the MIDI functionality with the channel select function, but my parts won't arrive for a few days. I'll update here if there are changes.


/*
* MIDI 4-Relay Control Switch
* Matt Williams
* Chelsea Guitar Repair
* Adapted from original code by:
* Mateu (Potul) via DIYstompboxes.com
*
* Switches 4 channels to amp ground via
* MIDI CC message.
*
* 2 additional DIP switches can be
* implemented for additional features.
*
* Uses CC channels:
* 85: OUT 1, Tip
* 86: OUT 1, Ring
* 87: OUT 2, Tip
* 88: OUT 2, Ring
*
* Value of 64 or less triggers relay.
*
*/

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>

// PIN ASSIGNMENTS

// 0 RX0    (MIDI IN)
// 1 TX1    (MIDI OUT)
// 2
// 3 ~      (DIP 4)
// 4        (DIP 3)
// 5 ~      (DIP 2)
// 6 ~      (DIP 1)
// 7       
// 8        (Relay 4)
// 9 ~      (Relay 3)
// 10 ~     (Relay 2)
// 11 ~     (Relay 1)
// 12
// 13       
// A0 14
// A1 15
// A2 16
// A3 17
// A4 18   
// A5 19   
// A6
// A7

// DEFINITIONS

#define Relay1 11     //set pin for Relay 1, J1T
#define Relay2 10     //set pin for Relay 2, J1R
#define Relay3 9      //set pin for Relay 3, J2T
#define Relay4 8      //set pin for Relay 4, J2R
#define DIP1 6        //set pin for DIP 1, MIDI Channel
#define DIP2 5        //set pin for DIP 2, MIDI channel
#define DIP3 4        //set pin for DIP 3, OUT 1
#define DIP4 3        //set pin for DIP 4, OUT 2

MIDI_CREATE_DEFAULT_INSTANCE();

// DEFINE INPUTS FOR MIDI CHANNEL
byte Chan1;           // Channel DIP 01
byte Chan2;           // Channel DIP 02
byte Sw1;             // Switch DIP 03
byte Sw2;             // Switch DIP 04

byte inChannel;       // Set MIDI receive channel

// Currently Unused ------
byte SwMode01;        // Var for addnl switch 1
byte SwMode02;        // Var for addnl switch 2
// -----------------------

// PROGRAM CALLS WHEN MIDI MESSAGE IS RECEIVED
// see documentation here:
// http://arduinomidilib.fortyseveneffects.com/a00022.html

void handleProgramChange(byte channel, byte number)
{
    // Can set functions for PC messages here
}

void handleControlChange(byte channel, byte number, byte value){

    // SWITCHING IS HANDLED VIA CC MESSAGE
   
    if (number == 85 && value <=64) {       // OUT 1, Tip
      digitalWrite(Relay1, HIGH);
    }
    else {
      digitalWrite(Relay1, LOW);
    }
   
    if (number == 86 && value <=64) {       // OUT 1, Ring
      digitalWrite(Relay2, HIGH);
    }
    else {
      digitalWrite(Relay2, LOW);
    }
   
    if (number == 87 && value <=64) {       // OUT 2, Tip
      digitalWrite(Relay3, HIGH);
    }
    else {
      digitalWrite(Relay3, LOW);
    }
   
    if (number == 88 && value <=64) {       // OUT 2, Ring
      digitalWrite(Relay4, HIGH);
    }
    else {
      digitalWrite(Relay4, LOW);
    }

}

// -----------------------------------------------------------------------------

void setup()
{
    pinMode(Relay1, OUTPUT);
    pinMode(Relay2, OUTPUT);
    pinMode(Relay3, OUTPUT);
    pinMode(Relay4, OUTPUT);
   
    pinMode(DIP1, INPUT_PULLUP);
    pinMode(DIP2, INPUT_PULLUP);
    pinMode(DIP3, INPUT_PULLUP);
    pinMode(DIP4, INPUT_PULLUP);

    // SET MIDI CHANNEL

    Chan1 = digitalRead(DIP1);      // Check DIP 1
    Chan2 = digitalRead(DIP2);      // Check DIP 2

    // inChannel is variable defined in MIDI library to set MIDI channel
   
    if (Chan1 == LOW && Chan2 == LOW) {        // DIPs at 0/0, OMNI
        inChannel = 0;
    }
    else {}
   
    if (Chan1 == LOW && Chan2 == HIGH) {       // DIPs at 0/1, C1
        inChannel = 1;
    }
    else {}
   
    if (Chan1 == HIGH && Chan2 == HIGH) {     // DIPs at 1/1, C2
        inChannel = 2;
    }
    else{}
   
    if (Chan1 == HIGH && Chan2 == LOW) {      // DIPs at 1/0, C3
        inChannel = 3;
    }
    else{}

    // EXPANSION AREA USING DIP 3/4

    Sw1 = digitalRead(DIP3);      // Check DIP 3
    Sw2 = digitalRead(DIP4);      // Check DIP 4

    // CAN USE VARIABLE SWMODE01/02 TO TOGGLE OPTION
    // BASED ON DIP 3/4 POSITION

    // OUT 1
    if (Sw1 == 1) {
      SwMode01 = 1;
    }
    else {
      SwMode01 = 0;
    }

    // OUT 2
    if (Sw2 == 1) {
      SwMode02 = 1;
    }
    else {
      SwMode02 = 0;
    }
   
   
    MIDI.begin(inChannel);    // Sets channel number
    MIDI.setHandleProgramChange(handleProgramChange);
    // Initiate MIDI communications, listen to all channels
    MIDI.setHandleControlChange(handleControlChange);
    // Initiate MIDI communications, listen to all channels
   
    // Serial.begin(9600); //Set serial to 9600, only for debugging
   
}

void loop()
{
    MIDI.read();
    // RUNS EVERY LOOP TO LISTEN FOR MIDI INPUT
}

potul

Great! It always feels good to see others can get inspiration from my projects.

Thanks for sharing!

pruttelherrie

Hey Matt,

I noticed you have a bunch of these in there:

    if (number == 85 && value <=64) {       // OUT 1, Tip
      digitalWrite(Relay1, HIGH);
    }
    else {
      digitalWrite(Relay1, LOW);
    }


That's probably not what you want: imagine what happens if you have all CC's (#85 till #88) set to 0, and then you set for example CC#85 to 127. Then the blocks coded like above don't filter in the else{ } on the number so #86 till #88 will be set LOW.

Something like the following should work (untested, but so simple I can't imagine it wouldn't):


    if (number == 85) {       // OUT 1, Tip
      digitalWrite(Relay1, value <= 64);
    }

TouringBubble

Yes, you're correct. I caught that yesterday actually. I wrote discreet IF statements for each condition above and below the threshold for each output and it's working. I finished up the prototype today.

TouringBubble

Here is the updated code ... I'm considering using one of the additional inputs to offset the CC range, but I honestly don't think it's needed.


/*
* MIDI 4-Relay Control Switch
* Matt Williams
* Chelsea Guitar Repair
* Adapted from original code by:
* Mateu (Potul) via DIYstompboxes.com
*
* Switches 4 channels to amp ground via
* MIDI CC message.
*
* 2 additional DIP switches can be
* implemented for additional features.
*
* Uses CC channels:
* 85: OUT 1, Tip
* 86: OUT 1, Ring
* 87: OUT 2, Tip
* 88: OUT 2, Ring
*
* Value of 64 or less triggers relay.
*
*/

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>

// PIN ASSIGNMENTS

// 0 RX0    (MIDI IN)
// 1 TX1    (MIDI OUT)
// 2
// 3 ~      (DIP 4)
// 4        (DIP 3)
// 5 ~      (DIP 2)
// 6 ~      (DIP 1)
// 7       
// 8        (Relay 4)
// 9 ~      (Relay 3)
// 10 ~     (Relay 2)
// 11 ~     (Relay 1)
// 12
// 13       
// A0 14
// A1 15
// A2 16
// A3 17
// A4 18   
// A5 19   
// A6
// A7

// DEFINITIONS

#define Relay1 11     //set pin for Relay 1, J1R
#define Relay2 10     //set pin for Relay 2, J1T
#define Relay3 9      //set pin for Relay 3, J2R
#define Relay4 8      //set pin for Relay 4, J2T
#define DIP1 6        //set pin for DIP 1, MIDI Channel
#define DIP2 5        //set pin for DIP 2, MIDI channel
#define DIP3 4        //set pin for DIP 3, OUT 1
#define DIP4 3        //set pin for DIP 4, OUT 2

MIDI_CREATE_DEFAULT_INSTANCE();

// DEFINE INPUTS FOR MIDI CHANNEL
byte Chan1;           // Channel DIP 01
byte Chan2;           // Channel DIP 02
byte Sw1;             // Switch DIP 03
byte Sw2;             // Switch DIP 04

byte inChannel;       // Set MIDI receive channel

// Currently Unused ------
byte SwMode01;        // Var for addnl switch 1
byte SwMode02;        // Var for addnl switch 2
// -----------------------

// PROGRAM CALLS WHEN MIDI MESSAGE IS RECEIVED
// see documentation here:
// http://arduinomidilib.fortyseveneffects.com/a00022.html

void handleProgramChange(byte channel, byte number)
{
    // Can set functions for PC messages here
}

void handleControlChange(byte channel, byte number, byte value){

    // SWITCHING IS HANDLED VIA CC MESSAGE

    // Serial.println("CC MESSAGE RECEIVED");
   
    if (number == 85 && value <=64) {       // OUT 1, Ring
      digitalWrite(Relay1, HIGH);
      // Serial.println("HIGH MESSAGE ON 85");
    }
    if (number == 85 && value >64) {       // OUT 1, Ring
      digitalWrite(Relay1, LOW);
      // Serial.println("LOW MESSAGE ON 85");
    }
   
    if (number == 86 && value <=64) {       // OUT 1, Tip
      digitalWrite(Relay2, HIGH);
      // Serial.println("HIGH MESSAGE ON 86");
    }
    if (number == 86 && value >64) {       // OUT 1, Tip
      digitalWrite(Relay2, LOW);
      // Serial.println("LOW MESSAGE ON 86");
    }
   
    if (number == 87 && value <=64) {       // OUT 2, Ring
      digitalWrite(Relay3, HIGH);
      // Serial.println("HIGH MESSAGE ON 87");
    }
    if (number == 87 && value >64) {       // OUT 2, Ring
      digitalWrite(Relay3, LOW);
      // Serial.println("LOW MESSAGE ON 87");
    }
   
    if (number == 88 && value <=64) {       // OUT 2, Tip
      digitalWrite(Relay4, HIGH);
      // Serial.println("HIGH MESSAGE ON 88");
    }
    if (number == 88 && value >64) {       // OUT 2, Tip
      digitalWrite(Relay4, LOW);
      // Serial.println("LOW MESSAGE ON 88");
    }

}

// -----------------------------------------------------------------------------

void setup()
{
    pinMode(Relay1, OUTPUT);
    pinMode(Relay2, OUTPUT);
    pinMode(Relay3, OUTPUT);
    pinMode(Relay4, OUTPUT);
   
    pinMode(DIP1, INPUT_PULLUP);
    pinMode(DIP2, INPUT_PULLUP);
    pinMode(DIP3, INPUT_PULLUP);
    pinMode(DIP4, INPUT_PULLUP);

    // SET MIDI CHANNEL

    Chan1 = digitalRead(DIP1);      // Check DIP 1
    Chan2 = digitalRead(DIP2);      // Check DIP 2

    // inChannel is variable defined in MIDI library to set MIDI channel
   
    if (Chan1 == LOW && Chan2 == LOW) {        // DIPs at 0/0, C1
        inChannel = 1;
        // Serial.println("MIDI LISTEN ON CH 1");
    }
    else {}
   
    if (Chan1 == LOW && Chan2 == HIGH) {       // DIPs at 0/1, C2
        inChannel = 2;
        // Serial.println("MIDI LISTEN ON CH 2");
    }
    else {}
   
    if (Chan1 == HIGH && Chan2 == HIGH) {      // DIPs at 1/1, C3
        inChannel = 3;
        // Serial.println("MIDI LISTEN ON CH 3");
    }
    else{}
   
    if (Chan1 == HIGH && Chan2 == LOW) {       // DIPs at 1/0, C4
        inChannel = 4;
        // Serial.println("MIDI LISTEN ON CH 4");
    }
    else{}

    // EXPANSION AREA USING DIP 3/4

    Sw1 = digitalRead(DIP3);      // Check DIP 3
    Sw2 = digitalRead(DIP4);      // Check DIP 4

    // CAN USE VARIABLE SWMODE01/02 TO TOGGLE OPTION
    // BASED ON DIP 3/4 POSITION

    // OUT 1
    if (Sw1 == 1) {
      SwMode01 = 1;
    }
    else {
      SwMode01 = 0;
    }

    // OUT 2
    if (Sw2 == 1) {
      SwMode02 = 1;
    }
    else {
      SwMode02 = 0;
    }
   
   
    MIDI.begin(inChannel);    // Sets channel number
    MIDI.setHandleProgramChange(handleProgramChange);
    // Initiate MIDI communications, listen to all channels
    MIDI.setHandleControlChange(handleControlChange);
    // Initiate MIDI communications, listen to all channels
   
    // Serial.begin(31250);
   
}

void loop()
{
    MIDI.read();
    // RUNS EVERY LOOP TO LISTEN FOR MIDI INPUT
}

T Wilcox

Hello guys, I am interested in adding MIDI control to a tube preamp design that has 4 separate footswitch points. I am currently using (2) 1/4" TRS footswitches to control and works great.
To be clear there 4 switchable points. 1Clean/OD, 2Boost, 3Crunch and 4Sizzle

The relays are already running 5vdc so my thought is to intercept the wire at the stereo TRS jack and tie directly to the ULN2803 like in the picture here

and here is a link to the site I found the diagram: https://www.jimkim.de/guitar-projects/arduino-midi-switch/
Both the footswitch and the panel toggles which control are currently LATCHING switches btw ( not sure if this is a problem )

So my intent is to be able to control the 4 points using MIDI but also still be able to use the panel toggles and TRS footswitching
The user should be able to send either a program or CC change to the unit, set the desired relay states using the toggles and then hold the store button for 2-3 seconds and store that as the preset anytime it receives that program or CC message sent in the first step. Additionally just like my ENGL savage head and KHE amp switcher if the relay states are changed while in a preset the led will blink to let you know the preset can be stored/changed

Is the code already shared in this thread capable of doing what I am trying to do?
I drew in a quotation on the above diagram of where I propose to intercept my existing relay and tie it to the ULN2803, does anyone see a problem with that working?

Thank you in advance to anyone that can give me further insight into making this work

Todd




niektb

#57
Actually what I would do, is connect the TRS Footswitches to the microcontroller, you don't have to work out an ORing/ANDing mechanism :)
I don't think there is readily working code in this thread but sounds quite doable to roll it yourself :)
And I think you it doesnt matter if the switches are momentary or latching since you can work that out in software :)

potul

I agree with niektb, what I would develop is something to put between your TRS footswitches and the amp. Basically using the footswitches as an input to the arduino, and then sending the commands from the arduino to the amp via TRS emulating what the footswitches do.
This is going to be much easier to manage if you want both footswitches and MIDI to work at the same time.

Vivek

Thank you, dear Mat/Potul, for your various informative posts and projects.

Respects !