DIYstompboxes.com

DIY Stompboxes => Digital & DSP => Topic started by: potul on November 04, 2015, 01:21:57 PM

Title: Arduino MIDI Switcher
Post by: potul on November 04, 2015, 01:21:57 PM
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 device

Device 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.
(http://i471.photobucket.com/albums/rr74/mateu_ros/placa_r3_nano_atmega328p_compatible_arduino_290_290.jpg)
I bought it here, really cheap: http://www.banggood.com/ATmega328P-Nano-V3-Controller-Board-Compatible-Arduino-p-940937.html (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.
(http://i471.photobucket.com/albums/rr74/mateu_ros/_12.jpg)
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? (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:
(http://i471.photobucket.com/albums/rr74/mateu_ros/midiswitch.jpg)

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 :)

(http://i471.photobucket.com/albums/rr74/mateu_ros/IMG_20151027_173459718_HDR.jpg)

Guts shot:

(http://i471.photobucket.com/albums/rr74/mateu_ros/IMG_20151027_173520149_HDR.jpg)


Software

And, 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.aspx (http://www.mathertel.de/Arduino/OneButtonLibrary.aspx)
MIDI Library: To send/receive MIDI messages. http://playground.arduino.cc/Main/MIDILibrary (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
Title: Re: Arduino MIDI Switcher
Post by: LC_legend on November 26, 2015, 10:56:44 AM
Wow! Congratulations on the project and detailed write-up!  I´m looking for something like this but with a little twist.

I have the same setup as you, pod hd500 to poweramp to cab. But i´m allways wanting more from the tone (don´t we all?) I get from the pod´s amp models. A while ago I built a dr. boogie wich i really like and i´m having great fun plugging it in the loop of the hd500. I also have a Harley Benton (or Joyo) american sound wich i really like with the same setup (these are based on tech21 charater series). Both of them sound and feel analog and IMHO sound more pleasant to the hear at any given volume. I´m also planning to build two more pedals to work as preamps (azabache and humble from ROG)

This got me thinking: what if i could send a ProgramChange from the hd500 to an arduino module that would store presets and change these pedals On and Off? They wouldn´t even have to be in the form of pedals. They could be in a single enclosure and work as channels on a head.

Your project looks perfect for this, but i´m wondering if it could have at least two more channels... at least :icon_twisted:
Also, could it store presets? When we change presets on the hd500 it sends PC message over midi (up to 64, i think). If the arduino could match the same preset would be GRWEAT.

what do you think? is it possible?
Title: Re: Arduino MIDI Switcher
Post by: potul on November 26, 2015, 12:35:33 PM
Hi

In fact, the project  as it is with some modifications can be adapted to your needs esasily.

-Presets: This functionality is already there. The on/of combinations (for channel/reverb, etc...) are stored in the arduino. The POD only sends PC messages.

-Control loops intead of amp channel: In order to do this, you only would need to change the type of relays. My project is using SPDT relays, while you would need DPDT. In the arduino world these are usually called "signal relays"

-More channels: If you need more than 2 channels, some things need to be done:

1-Adapt the software to deal with more outputs. A change in the logic to store presets is required as well.
2-You will probably need another type of "programming" interface... now with only one button works well for 2 channels (only 4 combinations), but if you double this, you go to 16 combinations. I would probably have one button per channel.

BTW, the project you described is also one I've had in my head for a long time.... If you want to go on with it let me know and I can try to help you as much as possible. I can do the programming for you, as I'm familiar with the software.

Mat

If you
Title: Re: Arduino MIDI Switcher
Post by: andersm on May 25, 2016, 01:17:12 AM
Brilliant, I have been looking for this for ages!
Since I'm a bloody noob in dyi midi things, please forgive me if I ask silly questions.
Basically, I play a Laney Ironheart head, which has a 4 switch stompbox via midi cable (although the amp has no actual midi), but alternatively can be toggled by 2 foot switches with 2 buttons each (one is lead vs clean and clean vs crunch, the other toggles reverb and boost, through a stereo 1/4" jack). I only really need to toggle clean vs lead, given the music I play.
So I do get this right? with this and my trusty old rfx midi buddyI could simultaneously switch patches on my multi fx and toggle amp channels, right?
I may need some guidance but this is precisely what I was looking for.
Title: Re: Arduino MIDI Switcher
Post by: potul on May 25, 2016, 02:11:19 AM
Yes, that's the idea. Being able to change your amp channel through midi.

A couple of things to consider:

-If you want to control your FX and the midi switcher at the same time you need to send the same program change to both devices. Does your FX unit have a "MIDI through"?

-You need to check that your amp is not using some sort of digital control. Is the jack footswitch simply a couple of  switches and LED? or is there some electronics in?

Mat
Title: Re: Arduino MIDI Switcher
Post by: potul on May 25, 2016, 02:21:14 AM
I just checked your amp.. if I'm not mistaken it can use the FS2 footswitch that is completely passive, so you should be ablt to control it.
Title: Re: Arduino MIDI Switcher
Post by: andersm on May 25, 2016, 04:42:27 AM
Yes, the manual specifically suggests those passive switches and there's a wiring diagram on the rear panel of the amp.
I need to dig out my old midi controller but if I remember right it has a midi through. also the fx unit I was gonna buy has a midi out, would that work too?
Title: Re: Arduino MIDI Switcher
Post by: potul on May 25, 2016, 11:12:38 AM
Great,

regarding your FX unit, it depends on what the midi out does. If it just sends PC message when you press buttons in it... it might not work. If it relays all incoming messages, or send PC messages every time the unit changes patch, it will work.

what FX unit is it? Maybe I can dig into the MID specs
Title: Re: Arduino MIDI Switcher
Post by: andersm on May 25, 2016, 01:21:19 PM
I haven't bought it yet, but I would love to get the Line6 M5. Mostly because it's small, affordable and yet has midi.
I had another idea but this may make things more complicated. I need the M5 mostly for modulating and time based effects and therefore put it in the fx loop of the amp head. now, since the distortions of the M5 are not en par with the rest of the effects and I like the overdrive of my Laney best anyway - after all I chose that amp for a reason - I might still need a couple of stomp boxes before the preamp (noise gate and my electro harmonix metal muff, in cases when I have to play someone else's amp).

So what I basically need for that is a way to bypass a pre-fx loop via midi. Do I make any sense?
I could use a simple A/B switch box for that, but that means tapdancing again. Would be cool if I could just build an additional A/B switch in the same enclosure with the rest of the hardware.

by the way, I double checked, the floor board has a midi through, they just call it "share" for some reason but the manual says it's a through
Title: Re: Arduino MIDI Switcher
Post by: fwbulldog on May 26, 2016, 01:14:38 PM
Thanks for posting this!  It's a huge head start.  I currently use a GCX Loop Switch to control my Blackstar Ht60.  It requires three momentary switches to select clean, OD1, OD2.  In my current setup this takes up three loops from my GCX.  I'd like to get these loops back for fx, and I'm looking for a cheaper alternative to the RJM Mini Amp Gizmo ($229 + cable). 

Your layout is fantastic and very easy to follow.  At first I did not understand the need for the 6N138 Optocoupler.  I did some research, and I'd like to pass on what I learned.

There is a great page that explains MIDI signaling, even down to the HW interface.  https://learn.sparkfun.com/tutorials/midi-tutorial/all.  Some people that come here might have a high level understanding of what MIDI does, but need some more background on how the signaling works if they're going to build this circuit.

You don't want to directly (i.e. electrically) connect an external voltage driver to your Arduino GPIO.  Voltage spikes (or current sinks) could damage the chip or cause ground loops, noise, etc.  Since MIDI uses a 5V circuit to transmit data, you need to isolate the signal from the UART on the Arduino.  This is accomplished with the 61N38 Optocoupler that potpul has selected.  This chip isolates the incoming 5V MIDI signal by using a LED/phototransitor circuit.  There is no electrical connection between the MIDI input and output.  It's optically isolated. 

The following schematic (from the MIDI spec), shows the diode and optocoupler.  The diode (D1) is connected between MIDI pins 4 and 5 to form the current loop.  Note that the direction of the diode is important.  The diode is there to prevent current from flowing the wrong direction.

(http://i451.photobucket.com/albums/qq235/kurt_shetler/midihw_zpsiorlu9sg.gif)


Midi use connector pins 4 and 5 to create a 5V loop.  At the transmitter,Pin 4 is pulled up to 5V through a weak pull-up resistor.  Pin 5 is connected to the MIDI device transmit UART.   When the MIDI device wants to send traffic it outputs a logical 1 or 0 on the UART TX pin.  The website explains it very well.


(http://i451.photobucket.com/albums/qq235/kurt_shetler/signaling-one_zpsrnpi7pqd.png)


"At the output, pin 4 is pulled high through a small resistor, and pin 5 is the buffered UART transmit line. On the input, these lines are tied to the anode and cathode of the LED in the opto-isolator. Since the UART output is high when not transmitting, both pins 4 and 5 will be at the same voltage, no current flows through the LED, thus it is not illuminated. When the LED is dark, the phototransistor is off, and the UART receives the voltage through the pullup, resulting in a logic one.
When the UART starts transmitting a byte, the start bit will pull pin 5 low, and current flows through the LED, illuminating it. When the LED is on, the phototransistor turns on, swamping the pullup, pulling the UART input to ground, and signaling a zero."

You can read about the MIDI out and through circuits there as well.   MIDI was designed to be a low-cost signaling interface, and it's pretty simple to implement if you understand what the reference circuit does.  I'm fine with this project being the end of my MIDI chain, so I don't really care about out and through. 

Since I need to switch three channels I'll have to use a four channel relay (http://www.banggood.com/3Pcs-5V-4-Channel-Relay-Module-For-Arduino-PIC-ARM-DSP-AVR-MSP430-Blue-p-983480.html).  I'm a little concerned about the 5V current draw of all four relays at the same time, so I may need to also build a 5V regulator circuit for separately powering the relays (as opposed to taking the 5V output from the Adruino board).  I'll be powering the box using my Voodoo Labs Pedal Power Iso 5.  No batteries involved. 

I'll probably have to experiment with the code to see what the minimum momentary pulse time is for the Blackstar and tweak the code for three outputs instead of two. 

Very cool project!  Thanks again. 
Title: Re: Arduino MIDI Switcher
Post by: potul on May 31, 2016, 01:57:40 AM
Quote from: andersm on May 25, 2016, 01:21:19 PM
So what I basically need for that is a way to bypass a pre-fx loop via midi. Do I make any sense?
I could use a simple A/B switch box for that, but that means tapdancing again. Would be cool if I could just build an additional A/B switch in the same enclosure with the rest of the hardware.
you can do it, but if you want to do it properly you will need a different type of relay board. The one I posted is a simple spdt, for bypassing you should use dpdt. Still.. you could do it with an spdt if you are not concerned about true bypass.
Quote from: andersm on May 25, 2016, 01:21:19 PM
by the way, I double checked, the floor board has a midi through, they just call it "share" for some reason but the manual says it's a through
I don't think this would work. you need to pass the same midi messages to 2 different devices. This is usually done by using the midi through to daisy chain them. I don't think the midi through of the floor will output the messages generated by itself. You might need to look into the manual to clarify.
The ideal would be if the FX unit has a midi through. If not, we can implement a midi through from the arduino. It should not be complicated.
Title: Re: Arduino MIDI Switcher
Post by: potul on May 31, 2016, 02:08:44 AM
Quote from: fwbulldog on May 26, 2016, 01:14:38 PM
Since I need to switch three channels I'll have to use a four channel relay (http://www.banggood.com/3Pcs-5V-4-Channel-Relay-Module-For-Arduino-PIC-ARM-DSP-AVR-MSP430-Blue-p-983480.html).  I'm a little concerned about the 5V current draw of all four relays at the same time, so I may need to also build a 5V regulator circuit for separately powering the relays (as opposed to taking the 5V output from the Adruino board).  I'll be powering the box using my Voodoo Labs Pedal Power Iso 5.  No batteries involved. 
you might want to check with both the relays and arduino spec sheet. 4 relays will draw something like 200mA. I don't recall how much the arduino regulator can handle. But I've had some bad experience in the past with relays and regulators, so having an extra one will not hurt.
Quote from: fwbulldog on May 26, 2016, 01:14:38 PM
I'll probably have to experiment with the code to see what the minimum momentary pulse time is for the Blackstar and tweak the code for three outputs instead of two. 

Very cool project!  Thanks again.
If you need more relays you might want to change the user interface. I decided to go cheap and use a single button, which works for 2 relays (ony 4 possible combinations). For 3 relays, that would be 8 combinations... you might want to consider a different way to manage it. Maybe adding 2 more buttons, one for each relay.
Title: Re: Arduino MIDI Switcher
Post by: andersm on May 31, 2016, 11:18:25 AM
Quote from: potul on May 31, 2016, 01:57:40 AM
you can do it, but if you want to do it properly you will need a different type of relay board. The one I posted is a simple spdt, for bypassing you should use dpdt. Still.. you could do it with an spdt if you are not concerned about true bypass.

Hm okay, I have no experience on whether true bypass would really make a sound difference here.
You're of course right about the midi through of the board. Isn't the midi out of the fx unit meant to daisychain units though?

Title: Re: Arduino MIDI Switcher
Post by: potul on May 31, 2016, 05:41:54 PM
yes if your FX unit has a midi out it might work.
Title: Re: Arduino MIDI Switcher
Post by: fwbulldog on June 01, 2016, 05:22:18 PM
Quote from: potul on May 31, 2016, 02:08:44 AM

If you need more relays you might want to change the user interface. I decided to go cheap and use a single button, which works for 2 relays (ony 4 possible combinations). For 3 relays, that would be 8 combinations... you might want to consider a different way to manage it. Maybe adding 2 more buttons, one for each relay.

I've been thinking about it, and I don't think I need any buttons.  For my application, I need three program changes that momentarily grounds a relay.  Only one will ever be active at a time.  I don't need eight combinations, just three.   And since only one relay will ever be active at once, I think I can get away with just using the 5V output from the Arduino, same as you did. 

Some slight code changes from your application, shouldn't be too hard.

Title: Re: Arduino MIDI Switcher
Post by: potul on June 02, 2016, 01:50:01 AM
up to you.

But if you don't have any button you will need to "hardcode" your presets. I would go for one button, and you cycle through your 3 channels when pushing it.

Remember to modify the code to make it momentary.

Title: Re: Arduino MIDI Switcher
Post by: andersm on June 13, 2016, 10:28:52 PM
Okay, so while I'm waiting for the rest of my hardware to arrive, I came up with a way to organise the fx loops.
Since I found a relay board with 8 channels and can therefore use 2 switchable fx loops I brainstormed a bit.
The easiest way would have been to just hook up the 2 loops in line and use them for pre fx like noise gate and distortion (handy, as I always wanted an "automatic" noise gate that disappears whenever I play solo or clean sounds...
But then I thought about using one of the loops for an additional post fx unit that doesn't otherwise respond to midi, which means I would have to keep the signal paths discrete. Luckily, one way of achieving this includes a true bypass option. Which is something I wanted to have anyhow...

Basically what I'm doing is this: I put a manual (how is a FOOT switch ever manual?!) foot switch before each of the relays, which acts as a true bypass. the one after the first loop is a 4PDT that does the signal routing for me so pre and post signals don't mix up.

Now there are different scenarios in which I can use it.
Loop A will only work for PRE fx. I will probably put my noise gate here. I will then not true-bypass it and only use the relay-bypass for clean and solo sounds.

Loop B can now be used either for another PRE fx, like a Wah or be true-bypassed, as I don't like using the Wah in my metal band anyway ;)
If I true-bypass it though, and put a POST fx unit in Loop B, the unit will be active for the post fx loop that so far cointains only my Line6. So basically, if you put any fx unit in Loop B, the true-bypass button will actually let you route either the pre signal or the post signal through that Loop. I admit, it makes everything a tad complicated but it could lead to an intresting use of effects.

The downsides is: if you're not going to use Loop B at all, the only way to maintain true bypass for both pre and post signal would be to put a patch cable in the loop (or leave the post fx unit out of this box alltogether). I can live with that though, because for my use, it's not a question of needing to change that setup during a set, but rather whether I want to use them in principleor not; so I can prepare the routing before a set.

So, here's my diagram, a bit on the wonky side, but hey, I'm a dabbler in that. If you find any flaws, please do point them out.
I haven't wired in any LEDs here, yet, but they will be vital. Oh and I haven't bothered drawing in the obvious grounds connections.
I added a version with colour coded signal paths, too. If it doesn't work, by amazing coincidnce you can also use it as a tube map in London. Obviously for guitarists, the tube sounds better than the metro  :icon_mrgreen:

https://dl.dropboxusercontent.com/u/23918855/FX%20loop.jpg
https://dl.dropboxusercontent.com/u/23918855/FX%20loop%20plus%20colour%20coded%20signal%20paths.jpg

Title: Re: Arduino MIDI Switcher
Post by: potul on June 14, 2016, 06:31:58 AM
I must admit you lost me.   ;D

I will review your diagrams tonight and will give you my feedback.

Mat
Title: Re: Arduino MIDI Switcher
Post by: potul on June 14, 2016, 08:30:54 AM
sorry but I don't undestand  the concept.

where would you connect POST FX IN and POSTFX OUT?
OUTPUT goes to the amp input, or to the power amp input (usually the return of the amp)?
loop B... is this going to be used before or after the amp pre-amp?
What is the purpose of the 4PDT?

Sorry to ask, but I want to understand what you try to achieve.

In addition,... you mentioned you have 8 relays.... but you are only using 2 in the schem. (you need 4 for the amp, right?, so you have 2 spare ones)

Title: Re: Arduino MIDI Switcher
Post by: potul on June 14, 2016, 08:52:41 AM
Ok,... I think I got it... your coloured one helped... Please correct me if I'm wrong.

-You want 2 controllable independend loops via MIDI (A and B). You will put some FX there.
-You want to choose if LOOP B goes before the AMP, or in the FX loop of the amp.
-You added an extra swithc for truebypass of LOOPA.
-OUTPUT will go to the AMP INPUT (where you usually place your guitar)
-POST FX OUT goes to AMP RETURN
-POST FX IN goes to AMP SEND

If this is it, I think you overcomplicated... :). Or maybe not... and the issue is that I don't picture it.

If I'm not wrong, you can do the same with a 3PDT (or a 4PDT if you want LED)

Question: Do you need to switch on the fly the LOOP B from PRE to POST? Or is this something you could simply wire differently upfront before the show?



Title: Re: Arduino MIDI Switcher
Post by: andersm on June 14, 2016, 11:46:08 AM
Sorry for making it so overcomplicated  :D
But yes, you got everything right. The 4PDT was necessary to keep the signal paths discrete and not to create any short circuits.
I had indeed forgotten that there were relays left, maybe I could use thm to contol the bubble machine and the flame thrower on stage XD

As for the question about the use of Loop B, I guess it depends on what effect I put there. I don't think I would need to switch this on the fly, really. But then again, this way I could if need be. And some effects work both ways but sound differently.
But I guess if I can fit an enclosure into my floorboard that's big enough for all the switches I might just give the post fx their own loop, while I'm at it.
Title: Re: Arduino MIDI Switcher
Post by: potul on June 15, 2016, 02:23:18 AM
So here it goes, my 2 cents....

If you don't need to move loop B from pre to post in the middle of a show, I would skip completely the 4PDT (I will explain later). If it's needed, it can be done with a 3PDT using the FX juggler schematic from Geofex.

Option 1: No relocation of loop B on the fly

-Wire both Loop A and Loop B as true bypass using 2 relays each.
-You then don't need the additional true bypass for loop A. If you still want to control independently Loop A, you can add a button and control it via the Arduino.
-Instead of sending the output of loop A to the input of Loop B, just send the output of Loop A to a jack and the input of Loop B to another jack. This way, you have two separated loops, not connected to each other.
-You have then 2 ways to connect it

Guitar -> LoopA -> preamp -> LoopB -> power amp
Guitar -> LoopA -> Loop B -> Amp

You can simply use a cable patch from LoopA to LoopB, or even better, using a switching jack, you can make this connection automatic when there is nothing inserted in the post-fx jack.
Each loop is trubypass and controlled via MIDI. If you want to change position of LoopB you need to rewire.

Option 2: Loop B switching

if switching is needed without re-wiring, I would do:
-Basically same as option 1. But in this case, think about post-fx being another loop (at the end it is a loop that goes to the preamp of your amp and returns)
-You keep the 2 relays for LoopA and LoopB for true bypass. post-fx loop is always on.
-You add the FX juggler so that you can change the order of LoopB and post-fx.
http://www.geofex.com/article_folders/juggler/juggler.htm (http://www.geofex.com/article_folders/juggler/juggler.htm)
You can use a rotary 4PDT and add a status LED
This will enable you to change the order of the post-fx and loopB loops, that is in essence placing the loopB before or after your preamp.

Title: Re: Arduino MIDI Switcher
Post by: potul on June 15, 2016, 03:34:59 AM
If you need it I can draw something....
Title: Re: Arduino MIDI Switcher
Post by: andersm on June 15, 2016, 05:44:28 AM
Wow. That is pretty cool, although I have to admit I'm not sure I understood all the technicalities.
I would go with option A, since most effects are either pre or post, really.

Basically there are 2 aspects I haven't quite understood yet.
) How do you wire 2 relays to create a true bypass? Doesn't the actual signal still have to run through them?
) The switching jack, I assume, would be the SEND jack for the B Loop, right? How would that relate to whether it's a post or pre effect?
Sorry for the hassle, maybe a schematic would help me indeed. You do have an online tip jar for coffee I hope ;)
Title: Re: Arduino MIDI Switcher
Post by: potul on June 15, 2016, 05:58:10 AM
Ok,... gimme some time. This evening when I'm  at home I will draw something.

Mat
Title: Re: Arduino MIDI Switcher
Post by: andersm on June 15, 2016, 06:44:17 AM
Take your time dude, I appreciate this!
Title: Re: Arduino MIDI Switcher
Post by: potul on June 16, 2016, 11:43:15 AM
Here it goes, this is what I would do, without fancy switching:

Relay 1 and 2 get activated at the same time.
Relay 3 and 4 get activated at the same time.

(http://i471.photobucket.com/albums/rr74/mateu_ros/switching.png) (http://s471.photobucket.com/user/mateu_ros/media/switching.png.html)

How to connect it..

Option 1: LoopB is "post" (so, in the FX loop of the amp)

Guitar -> IN
LOOPA Send -> Stompbox IN
Stompbox OUT -> LOOP A return
Preamp Send -> Amp IN
Amp FX send -> Preamp Return
LOOP B send -> Stompbox IN
Stompbox OUT -> LOOP B return
OUT -> Amp Fx return

With this connections, LOOP A is pre, LOOP B is post.

Option 2: LoopB is "Pre" (so, before Amp input)

Guitar -> IN
LOOPA Send -> Stompbox IN
Stompbox OUT -> LOOP A return
Preamp Send -> Nothing
Nothing -> Preamp Return
LOOP B send -> Stompbox IN
Stompbox OUT -> LOOP B return
OUT -> AMP IN

With these connections, both LOOPs are PRE. Nothing inserted in the Preamp Send/Return, or you could put there something you want between loops, without switching capability.
Note that the Preamp Send jack has a switch, so when no jack is inserted, the whole Preamp loop is bypassed.


Take a look a it and see if this fulfills your needs.

Mat




Title: Re: Arduino MIDI Switcher
Post by: potul on June 16, 2016, 11:54:39 AM
It's still possible to add "on-the-fly switching" to change LoopB from Pre to Post, using a 3pdt or 4pdt if LED needed.
Title: Re: Arduino MIDI Switcher
Post by: andersm on June 16, 2016, 01:22:37 PM
Alright, I get it now  8)
Yes I will definitely go for this. I didn't even know those switched jacks existed. Brilliant!
Thank you for the schematic.
Title: Re: Arduino MIDI Switcher
Post by: potul on June 17, 2016, 03:47:14 AM
Yep, you have the open type, like this one:

(https://upload.wikimedia.org/wikipedia/commons/a/af/Jack-plug--socket-switch.jpg)
(http://www.prestonelectronics.com/audio2/ttip/images/jack.gif)

And the neutrik style:

(http://www.midikits.net/foot_pedal/mono_skt_wiring.JPG)

Title: Re: Arduino MIDI Switcher
Post by: jimmyq on March 09, 2017, 07:08:17 AM
Wow, this looks awesome!
I've been looking for this kind of thing for a while and this looks the closest to what I've been looking for.
There might be some adjustments I'd need to make though as I'm trying to modify a standard A/B box, so that I can switch it via midi commands from a floor controller.
I'm a complete newbie in this area, but I'm thinking that each relay could route the signal to A or B. Each relay would have to stay on until I change channel so would I need a specific relay type?
I'd have to install a switch on the unit to latch from manual mode to midi mode unless I could wire it so that stomping on it overrides the midi signal. I'd appreciate your thoughts?
Title: Re: Arduino MIDI Switcher
Post by: potul on March 09, 2017, 08:18:38 AM
Hi

For a pure A/B switch you only need one Relay. If you want A/B/Y then it gets more tricky, it could probably be done with 2 relays (without buffering).

If you want to "override" with a stomp, what I would do is add a momentary switch, and do it via software. So you can switch from the stomp, and switch via MIDI. Last one to be actuated wins.

Mat
Title: Re: Arduino MIDI Switcher
Post by: caldersm on March 20, 2017, 03:24:58 PM
Agree with you on using the momentary switch and do the code in the chip.

I just finished some software software using a Teensy.....for a project with 8 momentary switches in and 8 relays out, a Mini OLED display, a rotary encoder with switch, USB Midi and Hardwired Midi with a remote stomp via a cable.  Via the menu you can change PC and CC Channels and the CC Command registers.....also Latching vs Momentary outputs.  About 700 lines code....

Title: Re: Arduino MIDI Switcher
Post by: achben on August 26, 2017, 01:40:54 PM
I have everything working save for being able to change the state of the pins with note on/off or PC.
What code do I put where to change the states of the digital pins with PC 01 and PC 02?
Title: Re: Arduino MIDI Switcher
Post by: potul on August 27, 2017, 02:42:09 AM
It should be easy to add it. I am away from my PC this week. Tonight I will be back home and I will take a look at the code.
Title: Re: Arduino MIDI Switcher
Post by: potul on August 27, 2017, 11:21:38 AM
Quote from: achben on August 26, 2017, 01:40:54 PM
I have everything working save for being able to change the state of the pins with note on/off or PC.
What code do I put where to change the states of the digital pins with PC 01 and PC 02?

Can you clarify? Do you want to change the state with note on/off, or with PC messages?

If note on/off,  what notes do you want to use for each relay?
Title: Re: Arduino MIDI Switcher
Post by: jmrwoods on February 16, 2018, 02:12:41 PM
Resurrecting this thread.  Here is a version for amps with momentary (non-latching) footswitches.

(https://farm5.staticflickr.com/4652/40258881122_2445354b60_b.jpg)

HUGE thanks to potul for his help with coding, advice, and troubleshooting.

As you can see, this version incorporates LEDs. It senses and shows the amps current state. It senses which is on/off so it knows which relay(s) to engage when memory is recalled. Instead of a normal push button, I elected for a momentary footswitch. In this case, I can set it next to my POD when I'm programming (and tap with my foot) – or it works just as well sitting on top of the amp when setup more for performance. The button works the exact same was as potul described in his first post (cycles through the four possible states – press of >1sec saves to memory).

Sensing circuit was simple (one for each channel) – and basically based on the footswitch that came with the amp. A simple voltage divider (with or without LED) would work, too. The end result should be getting around 3V (for an ON state) to the proper Arduino pin, or ~0V for an OFF state. Here is the original sketch, but I ended up with different values for the zeners and added resistors (circuit is at the very bottom of the circuit board in the gut shot).

(https://farm5.staticflickr.com/4760/40258880002_08e7905de1_b.jpg)

(https://farm5.staticflickr.com/4618/40258879702_5a5e571876_b.jpg)

(https://farm5.staticflickr.com/4668/40258884362_99b89aac7e_b.jpg)

(https://farm5.staticflickr.com/4701/40258882662_99340c408f_b.jpg)


Updated 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 SW1 12  //set pin for button (Cycle states & Save)
#define LED1 11 //set pin for Relay1 (Reverb)
#define LED2 10 //set pin for Relay2 (Channel)
#define REV 9   //Set pin for reading Reverb
#define CHAN 8  //set pin for reading Channel

//#define BUT 7 //pin for debugging
//#define BUTUP 6 //pin for debugging
MIDI_CREATE_DEFAULT_INSTANCE();

byte curr_program;  //current PC value

// Setup a new OneButton on pin 11. 
OneButton button1(SW1, true);
//OneButton button2(BUT, true); //debugging
//OneButton button3(BUTUP, true); //debugging

// -----------------------------------------------------------------------------
// 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))
   {
    if (!digitalRead(REV))
      {
        digitalWrite(LED1,LOW);
        delay(50);
        digitalWrite(LED1,HIGH);
      }
   }
   else
   {
      if (digitalRead(REV))
      {
        digitalWrite(LED1,LOW);
        delay(50);
        digitalWrite(LED1,HIGH);   
      }
   }
  //activate relay 2 if needed
  if (getBit(value,2))
   {
    if (!digitalRead(CHAN))
      {
        digitalWrite(LED2,LOW);
        delay(50);
        digitalWrite(LED2,HIGH);
      }
   }
   else
   {
      if (digitalRead(CHAN))
      {
        digitalWrite(LED2,LOW);
        delay(50);
        digitalWrite(LED2,HIGH);   
      }
   }

}
//debug start
//void click2(){
//  handleProgramChange(1, curr_program-1);
//  }
//  void click3(){
//  handleProgramChange(1, curr_program+1);
//  }
//debug end

// This function will be called when the button1 was pressed 1 time.
void click1() {
  //toggle Relay1
  byte value;
  value=digitalRead(REV)+digitalRead(CHAN)*2;
  value++;
    if (getBit(value,1))
   {
    if (!digitalRead(REV))
      {
        digitalWrite(LED1,LOW);
        delay(50);
        digitalWrite(LED1,HIGH);
      }
   }
   else
   {
      if (digitalRead(REV))
      {
        digitalWrite(LED1,LOW);
        delay(50);
        digitalWrite(LED1,HIGH);   
      }
   }
  //activate relay 2 if needed
  if (getBit(value,2))
   {
    if (!digitalRead(CHAN))
      {
        digitalWrite(LED2,LOW);
        delay(50);
        digitalWrite(LED2,HIGH);
      }
   }
   else
   {
      if (digitalRead(CHAN))
      {
        digitalWrite(LED2,LOW);
        delay(50);
        digitalWrite(LED2,HIGH);   
      }
   }
} // 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(REV))
  {
    setBit(value,1);
  }
  if (digitalRead(CHAN))
  {
    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);
    digitalWrite(LED1,HIGH);
    pinMode(LED2, OUTPUT);
    digitalWrite(LED2,HIGH);
    pinMode(CHAN, INPUT);
    pinMode(REV, INPUT);
    pinMode(SW1, INPUT_PULLUP);
//    pinMode(BUT, INPUT_PULLUP); //debug
//    pinMode(BUTUP, INPUT_PULLUP);  //debug
    //write inital presets, only for debugging.
//    for (int i=0;i<128;i++)
//    {
//      EEPROM.write(i,i);
//    }
   
    //Define button handling functions
//    button2.attachClick(click2); //debug
//    button3.attachClick(click3); //debug
    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();
//    button2.tick();  //debug
//    button3.tick();  //debug
}

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);
}
Title: Re: Arduino MIDI Switcher
Post by: Hatredman on March 21, 2018, 01:57:48 PM
What a lovely Strat!

.sig goes here.

Title: Re: Arduino MIDI Switcher
Post by: potul on March 22, 2018, 03:31:18 AM
Quote from: jmrwoods on February 16, 2018, 02:12:41 PM
Resurrecting this thread.  Here is a version for amps with momentary (non-latching) footswitches.

I just wanted to step in to highlight the remote collaborative job we did, Mike and I. It was fun to troubleshoot the software and hardware from the other side of the world.

This version will work with a Bugera amp (I don't remember the exact model), but it could maybe work with other brands. The key here is that the circuit is monitoring the status of the channels by looking at the voltage that comes from the amp through the footswitch cable. This only works in those amps that use momentary switches, and have LEDs on the footswitch. For other brands/models, some minor adjustments on the hardware might be needed (adjusting the zener or similar)

Good Job!
Title: Re: Arduino MIDI Switcher
Post by: jmrwoods on April 09, 2018, 12:15:50 PM
Quote from: Hatredman on March 21, 2018, 01:57:48 PM
What a lovely Strat!

.sig goes here.

Thanks! That's actually a JTV69s Tyler Variax that I refinished. It started out Shoreline Gold, but I wanted to highlight more of the offset design (i.e. Jaguar, Jazzmaster) and less strat. Walnut stain and hand-rubbed oil finish. Turned out great!


Quote from: potul on March 22, 2018, 03:31:18 AM
Quote from: jmrwoods on February 16, 2018, 02:12:41 PM
Resurrecting this thread.  Here is a version for amps with momentary (non-latching) footswitches.

I just wanted to step in to highlight the remote collaborative job we did, Mike and I. It was fun to troubleshoot the software and hardware from the other side of the world.

This version will work with a Bugera amp (I don't remember the exact model), but it could maybe work with other brands. The key here is that the circuit is monitoring the status of the channels by looking at the voltage that comes from the amp through the footswitch cable. This only works in those amps that use momentary switches, and have LEDs on the footswitch. For other brands/models, some minor adjustments on the hardware might be needed (adjusting the zener or similar)

Good Job!

It WAS a lot of fun - and best of all - works like a charm.
Title: Re: Arduino MIDI Switcher
Post by: 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.
Title: Re: Arduino MIDI Switcher
Post by: potul on July 27, 2018, 06:33:56 AM
Great!

Happy to see my work is an inspiration for others.

Mat
Title: Re: Arduino MIDI Switcher
Post by: bogdancat on December 11, 2018, 01:07:53 AM
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.
Title: Re: Arduino MIDI Switcher
Post by: EeroN on December 21, 2018, 10:57:54 AM
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!

Title: Re: Arduino MIDI Switcher
Post by: 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!
Title: Re: Arduino MIDI Switcher
Post by: EeroN on January 02, 2019, 06:59:37 AM
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.
Title: Re: Arduino MIDI Switcher
Post by: EeroN on January 03, 2019, 08:43:26 AM
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.
Title: Re: Arduino MIDI Switcher
Post by: 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.
Title: Re: Arduino MIDI Switcher
Post by: EeroN on January 05, 2019, 07:19:27 AM
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).

(https://i.postimg.cc/zVTYC5m9/IMG-0198-1.jpg) (https://postimg.cc/zVTYC5m9)

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.

Title: Re: Arduino MIDI Switcher
Post by: philos on July 30, 2019, 03:36:30 PM
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!
Title: Re: Arduino MIDI Switcher
Post by: potul on July 31, 2019, 09:12:00 AM
I can try to help, but I will need to understand what your needs are.
Title: Re: Arduino MIDI Switcher
Post by: TouringBubble on January 02, 2022, 04:20:28 PM
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
}
Title: Re: Arduino MIDI Switcher
Post by: potul on January 03, 2022, 02:48:33 AM
Great! It always feels good to see others can get inspiration from my projects.

Thanks for sharing!
Title: Re: Arduino MIDI Switcher
Post by: pruttelherrie on January 03, 2022, 11:33:55 AM
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);
    }
Title: Re: Arduino MIDI Switcher
Post by: TouringBubble on January 08, 2022, 04:41:53 PM
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.
Title: Re: Arduino MIDI Switcher
Post by: TouringBubble on January 11, 2022, 08:32:45 PM
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
}
Title: Re: Arduino MIDI Switcher
Post by: T Wilcox on March 24, 2022, 06:38:45 PM
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
(https://i.postimg.cc/62JjLFs2/arduino-midi-switch-vs1-Schaltplan.png) (https://postimg.cc/62JjLFs2)
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



Title: Re: Arduino MIDI Switcher
Post by: niektb on March 25, 2022, 04:19:42 AM
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 :)
Title: Re: Arduino MIDI Switcher
Post by: potul on March 25, 2022, 05:14:08 AM
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.
Title: Re: Arduino MIDI Switcher
Post by: Vivek on March 25, 2022, 07:32:01 AM
Thank you, dear Mat/Potul, for your various informative posts and projects.

Respects !

Title: Re: Arduino MIDI Switcher
Post by: ElectricDruid on March 25, 2022, 04:55:15 PM
Quote from: potul on March 25, 2022, 05:14:08 AM
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.

I agree too, BUT ONLY in the case where the footswitches do something other than a momentary short-to-ground. For that particular situation, it's dead easy to have the footswitches and the MIDI-controlled transistors in parallel. You press a footswitch, it switches. You send a MIDI signal, a transistor goes on, it switches.

BUT, as I said, that does depend on the momentary, non-latching character of the footswitches, and that that's what the amp is expecting.

Overall, the footswitches-go-to-processor-then-processor-controls-amp set up is much more versatile, since it can deal with latching/momentary and normal/inverted polarity just by changing firmware.

HTH
Title: Re: Arduino MIDI Switcher
Post by: T Wilcox on March 25, 2022, 06:29:40 PM
Quote from: niektb on March 25, 2022, 04:19:42 AM
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 :)

Thank you for your feedback!
I've done just a couple very simple arduino programs over a year ago so was hoping to grab some existing code that is close and then edit it to my needs. I have no problem taking the time to re-learn it though so I will spend some time getting familiar again.
My concern with the latching toggles and footswitches is that the toggle or footswitch positions wont match the state of the relays(iow if the toggle is in the up/on position then you send MIDI command to turn it off the toggle is still up. All my other MIDI controlled devices do use momentary switches and it would be easy enough to swap them for momentary
Title: Re: Arduino MIDI Switcher
Post by: T Wilcox on March 25, 2022, 06:39:52 PM
Quote from: potul on March 25, 2022, 05:14:08 AM
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.
Thank you for your reply!
Yes, indeed it would be ideal for the toggles, footswitch and MIDI to all work at the same time
So basically I would want the toggles and footswitches (they are parallel but toggles are disabled by the stereo jack when 1/4" plug is inserted) to connect straight to the arduino as digital inputs?
Then connect the return leg of the relay circuit to the outputs which will send that point to ground when activated?
If thats correct, then I just need to wrap my head around the programming which will take me a bit
Thanks again!
Title: Re: Arduino MIDI Switcher
Post by: T Wilcox on March 25, 2022, 07:45:02 PM
Quote from: ElectricDruid on March 25, 2022, 04:55:15 PM
Quote from: potul on March 25, 2022, 05:14:08 AM
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.

I agree too, BUT ONLY in the case where the footswitches do something other than a momentary short-to-ground. For that particular situation, it's dead easy to have the footswitches and the MIDI-controlled transistors in parallel. You press a footswitch, it switches. You send a MIDI signal, a transistor goes on, it switches.

BUT, as I said, that does depend on the momentary, non-latching character of the footswitches, and that that's what the amp is expecting.

Overall, the footswitches-go-to-processor-then-processor-controls-amp set up is much more versatile, since it can deal with latching/momentary and normal/inverted polarity just by changing firmware.

HTH
Thank you! The preamp currently has latching but it would not be hard to swap them out for momentary and it would make more sense now with MIDI and presets so I'll try that first.
Now that I have a better idea of what how to re-design the hardware I will breadboard this so I can start messing with the software before committing a new pcb design
Thanks again for your input!
Title: Re: Arduino MIDI Switcher
Post by: acatlow on April 29, 2022, 10:44:17 PM
I made a diagram over at https://wokwi.com/projects/330329978730185299

Basically its a 4 button footswitch, not sure if midi works but ive tested the circuit and with momuntary buttons its working fine, but I have only tried with the 8 relay board connecting IN pins to LED pins, I have yet to test with normal DPDT relays.

I made a test bench so I could test it out yesterday which i've added pictures

Here is the code to make it more simple, would love to get feedback also as this is my first sketch with arduino

Thanks Guys



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

MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut);

int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {

Serial.begin(9600);      // INITIALISE SERIAL
pinMode(2,INPUT_PULLUP); //CLEAN CHANNEL TOGGLE
pinMode(3,INPUT_PULLUP); //CRUNCH CHANNEL TOGGLE
pinMode(4,INPUT_PULLUP); //LEAD CHANNEL TOGGLE
pinMode(5,INPUT_PULLUP); //BOOST CHANNEL TOGGLE
pinMode(6,OUTPUT); // D6,
pinMode(7,OUTPUT); // D7,
pinMode(8,OUTPUT); // D8,
pinMode(9,OUTPUT); // D9,

//Initial Output States. Init to Clean Mode
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
digitalWrite(8,LOW);
digitalWrite(9,LOW);
digitalWrite(9, ledState);
}

void loop() {
  delay(10); //wait for 10 milliseconds for states to settle
  int reading = digitalRead(5);

  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
  digitalWrite(9, ledState);
  lastButtonState = reading;
 
//Clean Mode
if(!digitalRead(2)){
  // LEDS
  digitalWrite(6,HIGH);
  digitalWrite(7,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  midiOut.sendControlChange(85,127,1);
  }

//Crunch Mode
if(!digitalRead(3)){
  // LEDS
  digitalWrite(6,LOW);
  digitalWrite(7,HIGH);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  midiOut.sendControlChange(86,127,1);
  }

//Lead Mode
if(!digitalRead(4)){
  // LEDS
  digitalWrite(6,LOW);
  digitalWrite(7,LOW);
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
  midiOut.sendControlChange(87,127,1);
  }


}


(https://i.postimg.cc/jD3rvqLX/20220430-125617.jpg) (https://postimg.cc/jD3rvqLX)

(https://i.postimg.cc/hJJRYFmq/20220430-125635.jpg) (https://postimg.cc/hJJRYFmq)
Title: Re: Arduino MIDI Switcher
Post by: pruttelherrie on May 02, 2022, 12:24:15 PM
Quote from: acatlow on April 29, 2022, 10:44:17 PM

Here is the code to make it more simple, would love to get feedback also as this is my first sketch with arduino


#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut);

[snip]
void setup() {
Serial.begin(9600);      // INITIALISE SERIAL



If you're using MIDI on an AVR with one HW serial you can't use the standard Serial at the same time, it's either/or.

Also, you're only debouncing pin 5, not the other inputs? Probably no problem right now but you might see a flurry of CC's coming past.
Might be that I don't understand your switches, pin 5 is the toggle (for boost) and the others are momentary pushbuttons?
Title: Re: Arduino MIDI Switcher
Post by: potul on May 02, 2022, 12:34:07 PM
Yep, the Serial begin sentence should be removed, the UART will already be initialized by the MIDI instance

On the other hand... you are doing debouncing on pin 5 only, and it's not clear to me what this button does.
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 02, 2022, 08:13:35 PM
oh apologies, i should update the code already, I changed this to midi create default instance without any custom midiout or serial

but i want to edit the code to be more like this

clean channel 1 toggle (k2 relay 1 = high, relay 2 = low) switches green led
gain channels 2/3 toggle (k4 relay 1 = low, relay 2 = low / relay 1 = low , relay 2 = high)  switches between bicolour blue red led)
boost channel toggle (k7 relay, can turn on or off independently across all channels)

anybody can help me with this?



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

MIDI_CREATE_DEFAULT_INSTANCE();

byte inChannel;

int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

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

void handleControlChange(byte channel, byte number, byte value){
   
    if (number == 85 && value <=64) {
      digitalWrite(8, HIGH);
    }
    else {
      digitalWrite(8, LOW);
    }
   
    if (number == 86 && value <=64) {
      digitalWrite(9, HIGH);
    }
    else {
      digitalWrite(9, LOW);
    }
   
    if (number == 87 && value <=64) {
      digitalWrite(10, HIGH);
    }
    else {
      digitalWrite(10, LOW);
    }
   
    if (number == 88 && value <=64) {
      digitalWrite(11, HIGH);
    }
    else {
      digitalWrite(11, LOW);
    }
}
void setup() {
MIDI.begin (MIDI_CHANNEL_OMNI);
pinMode(2,INPUT_PULLUP); //CLEAN CHANNEL TOGGLE
pinMode(3,INPUT_PULLUP); //GAIN CHANNEL TOGGLE
pinMode(4,INPUT_PULLUP); //BOOST CHANNEL TOGGLE
pinMode(5,OUTPUT); // D5 - K2 RELAY
pinMode(6,OUTPUT); // D6 - K4 RELAY
pinMode(7,OUTPUT); // D7 - K7 RELAY
pinMode(8,OUTPUT); // D8 - LED 1
pinMode(9,OUTPUT); // D9 - LED 2
pinMode(10,OUTPUT); // D10 - LED 3
pinMode(10,OUTPUT); // D11 - LED 4

}
void loop() {
  delay(5);
 
//Clean Mode
if(!digitalRead(2)){
  // LEDS
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  }

//Gain Mode
if(!digitalRead(3)){
  // LEDS
  digitalWrite(8,LOW);
  digitalWrite(9,HIGH);
  digitalWrite(10, ledState);
  }

//BOOST ON/OFF
  int reading = digitalRead(4);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
  digitalWrite(10, ledState);
  lastButtonState = reading;
}

Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 11, 2022, 07:15:44 PM
Hi all,

Thought I'd share with you all that I managed to finish my version which I've currently fit into a Peavey 2 button footswitch, that I drilled out the middle hole to add the third monument switch.

I emailed potul, who confirmed with me that my issue wasn't in the code itself but the wokwi diagram code, so thanks potul for the confirmation.

the next thing I will be doing is adding the oled display menu to show visually what channel is currently active etc

here is the simulation of the code

https://wokwi.com/projects/330813583919153748



#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>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiWire.h>

#define LED1 8   //set pin for LED 1 (CLEAN)
#define LED2 9   //set pin for LED 2 (GAIN 1)
#define LED3 10  //set pin for LED 3 (GAIN 2)
#define LED4 11  //set pin for LED 4 (BOOST)
#define RELAY1 5 //set pin for RELAY 1 (K2 Relay - Clean=HIGH)
#define RELAY2 6 //set pin for RELAY 2 (K4 Relay - Gain1=LOW|Gain2=HIGH)
#define RELAY3 7 //set pin for RELAY 3 (K7 Relay - Boost Toggle)
#define SW1 2    //set pin for SWITCH 1
#define SW2 3    //set pin for SWITCH 2
#define SW3 4    //set pin for SWITCH 3

// OLED Display 128x64
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;

MIDI_CREATE_DEFAULT_INSTANCE();

byte curr_program;    //Current PC Value
byte curr_change;     //Current CC Value

OneButton button1(SW1, true);
OneButton button2(SW2, true);
OneButton button3(SW3, true);

void handleNoteOn(byte channel, byte pitch, byte velocity)
{
}

void handleNoteOff(byte channel, byte pitch, byte velocity)
{
}

void handleProgramChange(byte channel, byte number)
{
  byte value;
  curr_program=number; //stores the PC number for later
  value=EEPROM.read(number);
  //Activate LED1
  if (getBit(value,1))
   {
    digitalWrite(LED1,HIGH);
   }
   else
   {
    digitalWrite(LED1,LOW);
   }
  //Activate LED2
  if (getBit(value,2))
   {
    digitalWrite(LED2,HIGH);
   }
   else
   {
    digitalWrite(LED2,LOW);
   }
  //Activate LED3
  if (getBit(value,3))
   {
    digitalWrite(LED3,HIGH);
   }
   else
   {
    digitalWrite(LED3,LOW);
   }
  //Activate LED4
  if (getBit(value,4))
   {
    digitalWrite(LED4,HIGH);
   }
   else
   {
    digitalWrite(LED4,LOW);
   }
}
void handleControlChange(byte channel, byte number, byte value){
  if (number == 85 && value <=64) {
    digitalWrite(LED1,HIGH);
  }
  if (number == 85 && value >64) {
    digitalWrite(LED1,LOW);
  }
  if (number == 86 && value <=64) {
    digitalWrite(LED2,HIGH);
  }
  if (number == 86 && value >64) {
    digitalWrite(LED2,LOW);
  }
  if (number == 87 && value <=64) {
    digitalWrite(LED3,HIGH);
  }
  if (number == 87 && value >64) {
    digitalWrite(LED3,LOW);
  }
  if (number == 88 && value <=64) {
    digitalWrite(LED4,HIGH);
  }
  if (number == 88 && value >64) {
    digitalWrite(LED4,LOW);
  }
}

void click1() {
  //Toggle Relay 1
  byte value;
  value=digitalRead(LED1);
  value++;
    if (getBit(value,1))
   {
     digitalWrite(LED1,HIGH);
     digitalWrite(LED3,LOW);
     digitalWrite(RELAY1,HIGH);
     MIDI.sendControlChange(1,85,127);
   }
   else
   {
      digitalWrite(LED1,LOW);
      digitalWrite(LED3,LOW);
      digitalWrite(RELAY1,LOW);
   }
  //Activate Relay 2
  if (getBit(value,2))
   {
     digitalWrite(LED2,HIGH);
     digitalWrite(LED3,LOW);
     digitalWrite(RELAY1,LOW);
     MIDI.sendControlChange(1,86,127);
   }
   else
   {
      digitalWrite(LED2,LOW);
      digitalWrite(LED3,LOW);
      digitalWrite(RELAY1,HIGH);
   }
} // click1

void click2() {
  //Toggle Relay 2
  byte value;
  value=digitalRead(LED2);
  value++;
  if (getBit(value,1))
   {
     digitalWrite(LED1,LOW);
     digitalWrite(LED2,HIGH);
     digitalWrite(RELAY2,LOW);
   }
   else
   {
      digitalWrite(LED1,LOW);
      digitalWrite(LED2,LOW);
      digitalWrite(RELAY2,HIGH);
   }
  if (getBit(value,2))
   {
     digitalWrite(LED1,LOW);
     digitalWrite(LED3,HIGH);
     digitalWrite(RELAY2,HIGH);
     MIDI.sendControlChange(1,87,127);
   }
   else
   {
      digitalWrite(LED1,LOW);
      digitalWrite(LED3,LOW);
      digitalWrite(RELAY2,LOW);
   }
} // click2

void click3() {
  //Toggle Relay 3
  byte value;
  value=digitalRead(LED4);
  value++;
  if (getBit(value,1))
   {
     digitalWrite(LED4,HIGH);
     MIDI.sendControlChange(1,88,127);
   }
   else
   {
      digitalWrite(LED4,LOW);
      MIDI.sendControlChange(1,88,0);
   }
} // click3

void doubleclick1() {}

void longPressStart1() {
  //save preset
  byte value=1;
  if (digitalRead(LED1))
  {
    setBit(value,1);
  }
  if (digitalRead(LED2))
  {
    setBit(value,2);
  }
  if (digitalRead(LED3))
  {
    setBit(value,3);
  }
  if (digitalRead(LED4))
  {
    setBit(value,4);
  }
  EEPROM.write(curr_program,value);
}

void longPress1() {}

void longPressStop1() {}

void setup()
{
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT);
    pinMode(LED4, OUTPUT);
    pinMode(RELAY1, OUTPUT);
    pinMode(RELAY2, OUTPUT);
    pinMode(RELAY3, OUTPUT);
    pinMode(SW1, INPUT_PULLUP);
    pinMode(SW2, INPUT_PULLUP);
    pinMode(SW3, INPUT_PULLUP);

    for (int i=0;i<128;i++)
    {
      EEPROM.write(i,i);
    }
   
    //Initial Output States. Init to Clean Mode
    digitalWrite(8,HIGH);
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);

    button1.attachClick(click1);
    button2.attachClick(click2);
    button3.attachClick(click3);

    button1.attachDoubleClick(doubleclick1);
    button1.attachLongPressStart(longPressStart1);
    button1.attachLongPressStop(longPressStop1);
    button1.attachDuringLongPress(longPress1);
   
    MIDI.setHandleNoteOn(handleNoteOn);
    MIDI.setHandleNoteOff(handleNoteOff);
    MIDI.setHandleProgramChange(handleProgramChange);
    MIDI.setHandleControlChange(handleControlChange);

    // Initiate MIDI
    MIDI.begin(MIDI_CHANNEL_OMNI);
}
void loop()
{
    MIDI.read();

    // Call button tick to check button status
    button1.tick();
    button2.tick();
    button3.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);
}


Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 19, 2022, 02:39:58 AM
Back again,

Just to make it more exciting, I wrote up something different, adding in OLED display.
If you get an error in Arduino IDE, add the library "Adafruit BusIO"

you can simulate the code here --> https://wokwi.com/projects/331591906805940818




#include <SPI.h>
#include <Wire.h>
#include <MIDI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int sw1Pin = 2;
const int sw2Pin = 3;
const int sw3Pin = 4;
const int sw4Pin = A0;
const int LED1 = 8;  //set pin for LED 1 (CLEAN)
const int LED2 = 9;   //set pin for LED 2 (GAIN 1)
const int LED3 = 10;  //set pin for LED 3 (GAIN 2)
const int LED4 = 11;  //set pin for LED 4 (BOOST)
const int LED5 = 13;  //set pin for LED 5 (PLEXI)
const int RELAY1 = 5; //set pin for RELAY 1 (K2 Relay - Clean=HIGH)
const int RELAY2 = 6; //set pin for RELAY 2 (K4 Relay - Gain1=LOW|Gain2=HIGH)
const int RELAY3 = 7; //set pin for RELAY 3 (K7 Relay - Boost Toggle)
const int RELAY4 = 12; //set pin for RELAY 4 (K3 Relay - Plexi Toggle)

int sw1Push = 0;
int sw2Push = 0;
int sw3Push = 0;
int sw4Push = 0;
boolean sw1State = LOW;
boolean sw2State = LOW;
boolean sw3State = LOW;
boolean sw4State = LOW;
boolean sw1StateLast = LOW;
boolean sw2StateLast = LOW;
boolean sw3StateLast = LOW;
boolean sw4StateLast = LOW;

//DEFINITIONS
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR   0x3C
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);

const unsigned char NaN [] PROGMEM = {
0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03,
0x80, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00,
0x00, 0x00, 0x03, 0xf8, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x3f, 0xe0, 0x00, 0x00, 0x00,
0x03, 0xf8, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf8,
0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0xe0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x1f, 0xe0, 0x00,
0x00, 0x07, 0xfc, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x03,
0xfc, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00,
0x00, 0x04, 0x7f, 0xe0, 0x03, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x01, 0xfc, 0x00, 0x00, 0xff,
0xff, 0xf0, 0x00, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x0c, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x03, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0x83, 0xf0,
0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe3, 0x80, 0x00, 0x00,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xf7, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf7, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x8f, 0xf0, 0x00, 0x00,
0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x80, 0x00, 0x00
};

uint8_t midi_channel = 0;
MIDI_CREATE_DEFAULT_INSTANCE();

void midiCtrlChange(byte c, byte v){
  Serial.write(0xB0 | midi_channel); // CC message
  Serial.write(c); // number
  Serial.write(v); // value

  if (c == 85 && v >64) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("CLEAN ");
    display.display();
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
    digitalWrite(RELAY3,LOW);
  }
  if (c == 85 && v <=64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 1");
    display.display();
  digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 86 && v >64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 1");
    display.display();
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 86 && v <=64) {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("CLEAN ");
    display.display();
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 87 && v >64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 2");
    display.display();
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,HIGH);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,HIGH);
  }
  if (c == 87 && v <=64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 0);
    display.println(" SIRIUS AMPLIFICATION");
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 1");
    display.display();
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 88 && v >64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 45);
    display.print("BOOST: ");
    display.setTextSize(1);
    display.setCursor(45, 45);
    display.print("ON ");
    display.display();
    digitalWrite(LED4,HIGH);
    digitalWrite(RELAY3,HIGH);
  }
  if (c == 88 && v <=64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 45);
    display.print("BOOST: ");
    display.setTextSize(1);
    display.setCursor(45, 45);
    display.print("OFF");
    display.display();
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY3,LOW);
  }
  if (c == 89 && v >64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 55);
    display.print("PLEXI: ");
    display.setTextSize(1);
    display.setCursor(45, 55);
    display.print("ON ");
    display.display();
    digitalWrite(LED5,HIGH);
    digitalWrite(RELAY4,HIGH);
  }
  if (c == 89 && v <=64) {
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 55);
    display.print("PLEXI: ");
    display.setTextSize(1);
    display.setCursor(45, 55);
    display.print("OFF");
    display.display();
    digitalWrite(LED5,LOW);
    digitalWrite(RELAY4,LOW);
  }
}

void setup() {
  pinMode(sw1Pin, INPUT);
  pinMode(sw2Pin, INPUT);
  pinMode(sw3Pin, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);

  // Initiate MIDI
  MIDI.begin(MIDI_CHANNEL_OMNI);

// INITIATE DISPLAY SPLASHSCREEN
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(" SIRIUS AMPLIFICATION");
  display.drawBitmap(40, 15, NaN, 50, 50, WHITE);
  display.display();
  delay(5000);
  midiCtrlChange(85,127);
}

void loop() {

MIDI.read();

// read the state of the pushbutton value:
  sw1State = digitalRead(sw1Pin);
  if (sw1State != sw1StateLast) {
    if (sw1State == HIGH){
      sw1Push++;
      if (sw1Push > 1){sw1Push = 0;}
      switch (sw1Push)
      {
        case 1:
          midiCtrlChange(85,127);
        break;
        delay(200);
        case 0:
          midiCtrlChange(86,127);
        break;
        delay(200);
      }
    }
    sw1StateLast = sw1State;
    delay(200);
  }

sw2State = digitalRead(sw2Pin);
if (sw2State != sw2StateLast) {
    if (sw2State == HIGH){
      sw2Push++;
      if (sw2Push > 1){sw2Push = 0;}
      switch (sw2Push)
      {
        case 1:
          midiCtrlChange(87,127);
        break;
        delay(200);
        case 0:
          midiCtrlChange(86,127);
        break;
        delay(200);
      }
    }
    sw2StateLast = sw2State;
    delay(200);
  }

sw3State = digitalRead(sw3Pin);
if (sw3State != sw3StateLast) {
    if (sw3State == HIGH){
      sw3Push++;
      if (sw3Push > 1){sw3Push = 0;}
      switch (sw3Push)
      {
        case 0:
          midiCtrlChange(88,0);
        break;
        delay(200);
        case 1:
          midiCtrlChange(88,127);
        break;
        delay(200);
      }
    }
    sw3StateLast = sw3State;
    delay(200);
  }

sw4State = digitalRead(sw4Pin);
if (sw4State != sw4StateLast) {
    if (sw4State == HIGH){
      sw4Push++;
      if (sw4Push > 1){sw4Push = 0;}
      switch (sw4Push)
      {
        case 0:
          midiCtrlChange(89,0);
        break;
        delay(200);
        case 1:
          midiCtrlChange(89,127);
        break;
        delay(200);
      }
    }
    sw4StateLast = sw4State;
    delay(200);
  }
}

Title: Re: Arduino MIDI Switcher
Post by: potul on May 19, 2022, 04:35:46 AM
Nice,

just a comment: you are using the MIDI library but not using the sendControlChange() function and instead you are accessing Serial directly. Any reason for that?
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 19, 2022, 07:10:56 PM
Quote from: potul on May 19, 2022, 04:35:46 AM
Nice,

just a comment: you are using the MIDI library but not using the sendControlChange() function and instead you are accessing Serial directly. Any reason for that?

In my tests when trying to use the switches to change the channels, it actually wasn't working at all and I was scratching my head wondering what exactly was happening... and also because this was my first or second sketch, I'm not exactly proficient in coding at all...

but I wanted to be able to use standalone switch functions without a midi footswitch, if I decide to incorporate it into an amp pcb design, and as the other way wasn't working, I got a little creative
Title: Re: Arduino MIDI Switcher
Post by: potul on May 20, 2022, 05:26:07 AM
Quote from: acatlow on May 19, 2022, 07:10:56 PM
Quote from: potul on May 19, 2022, 04:35:46 AM
Nice,

just a comment: you are using the MIDI library but not using the sendControlChange() function and instead you are accessing Serial directly. Any reason for that?

In my tests when trying to use the switches to change the channels, it actually wasn't working at all and I was scratching my head wondering what exactly was happening... and also because this was my first or second sketch, I'm not exactly proficient in coding at all...

but I wanted to be able to use standalone switch functions without a midi footswitch, if I decide to incorporate it into an amp pcb design, and as the other way wasn't working, I got a little creative

Not sure if I get the point. My question was regarding using this:

  Serial.write(0xB0 | midi_channel); // CC message
  Serial.write(c); // number
  Serial.write(v); // value


When you could use this:


MIDI.sendControlChange(c,v,0xB0 | midi_channel);
Title: Re: Arduino MIDI Switcher
Post by: Sweetalk on May 20, 2022, 05:30:29 AM
Quote from: potul on May 20, 2022, 05:26:07 AM

When you could use this:


MIDI.sendControlChange(c,v,0xB0 | midi_channel);


Just a little correction, you have to use midi_channel directly, like this:


MIDI.sendControlChange(c, v, midi_channel);
Title: Re: Arduino MIDI Switcher
Post by: potul on May 20, 2022, 08:41:37 AM
Quote from: Sweetalk on May 20, 2022, 05:30:29 AM

Just a little correction, you have to use midi_channel directly, like this:


MIDI.sendControlChange(c, v, midi_channel);


oops, yes you are right. ... I just copy-pasted without thinking.
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 21, 2022, 11:11:02 PM
just tested that and it works, Thanks!!
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 23, 2022, 03:01:49 AM
So I've tested 100% and although a little clunky with switching, its pretty cool and I have a good base to work from...

I've made a custom PCB for it with OLEDand its working great, but I decided to change it a little to add MIDI in and MIDI out from headers to save space with the PCB

Here is the current PCB with the sketch working...

https://www.instagram.com/p/Cd3VOLbvSzB/?utm_source=ig_web_copy_link

And here is my updated code... also available to simulate here --> https://wokwi.com/projects/331591906805940818



#include <SPI.h>
#include <Wire.h>
#include <MIDI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);

//CHANGE PINS TO SUIT YOUR ARDUINO PINOUT
const int sw1Pin = A0;
const int sw2Pin = A1;
const int sw3Pin = A2;
const int sw4Pin = A3;
const int LED1 = 6;  //set pin for LED 1 (CLEAN)
const int LED2 = 7;   //set pin for LED 2 (GAIN 1)
const int LED3 = 8;  //set pin for LED 3 (GAIN 2)
const int LED4 = 9;  //set pin for LED 4 (BOOST)
const int RELAY1 = 2; //set pin for RELAY 1 (K2 Relay - Clean=HIGH)
const int RELAY2 = 3; //set pin for RELAY 2 (K4 Relay - Gain1=LOW|Gain2=HIGH)
const int RELAY3 = 4; //set pin for RELAY 3 (K7 Relay - Boost Toggle)
const int RELAY4 = 5; //set pin for RELAY 4 (K1 Relay - Plexi Toggle)

int sw1Push = 0;
int sw2Push = 0;
int sw3Push = 0;
int sw4Push = 0;
boolean sw1State = LOW;
boolean sw2State = LOW;
boolean sw3State = LOW;
boolean sw4State = LOW;
boolean sw1StateLast = LOW;
boolean sw2StateLast = LOW;
boolean sw3StateLast = LOW;
boolean sw4StateLast = LOW;

const unsigned char NaN [] PROGMEM = {
  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03,
  0x80, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00,
  0x00, 0x00, 0x03, 0xf8, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x3f, 0xe0, 0x00, 0x00, 0x00,
  0x03, 0xf8, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf8,
  0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
  0xe0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x1f, 0xe0, 0x00,
  0x00, 0x07, 0xfc, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x03,
  0xfc, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00,
  0x00, 0x04, 0x7f, 0xe0, 0x03, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x01, 0xfc, 0x00, 0x00, 0xff,
  0xff, 0xf0, 0x00, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x0c, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfc,
  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x03, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0x83, 0xf0,
  0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe3, 0x80, 0x00, 0x00,
  0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff,
  0xf7, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf7, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0,
  0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x8f, 0xf0, 0x00, 0x00,
  0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x80, 0x00, 0x00
};

uint8_t midi_channel = 0;
MIDI_CREATE_DEFAULT_INSTANCE();

//MIDI CC FUNCTIONS
void midiCtrlChange(byte c, byte v){
MIDI.sendControlChange(c,v,0xB0 | midi_channel);

  if (c == 80 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 80 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 81 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 81 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 82 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 82 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 83 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 83 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }

  if (c == 85 && v >64) {
    //Channel CC MSG
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("CLEAN   ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
    digitalWrite(RELAY3,LOW);
    digitalWrite(RELAY4,LOW);
  }
  if (c == 85 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 86 && v >64) {
    //Channel CC MSG
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 1  ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 86 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 87 && v >64) {
    //Channel CC MSG
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 2  ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,HIGH);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,HIGH);
  }
  if (c == 87 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 88 && v >64) {
    //Channel CC MSG
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 50);
    display.print("BOOST:  ");
    display.setTextSize(1);
    display.setCursor(40, 50);
    display.print("ON ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED4,HIGH);
    digitalWrite(RELAY3,HIGH);
  }
  if (c == 88 && v <=64) {
    //Channel CC MSG
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 50);
    display.print("BOOST:  ");
    display.setTextSize(1);
    display.setCursor(40, 50);
    display.print("OFF");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY3,LOW);
  }
  if (c == 89 && v >64) {
    //Toggle CC MSG
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("PLEXI   ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,HIGH);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY4,HIGH);
  }
  if (c == 89 && v <=64) {
    //Toggle CC MSG
    digitalWrite(LED2,LOW);
    digitalWrite(RELAY4,LOW);
  }
  if (c == 90 && v >64) {
    //Toggle CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 90 && v <=64) {
    //Toggle CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 91 && v >64) {
    //Reverb Volume CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 91 && v <=64) {
    //Reverb Volume CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 92 && v >64) {
    //Tremelo Volume CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 92 && v <=64) {
    //Tremelo Volume CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 102) {
    //EEPROM Reset CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 103) {
    //Set MIDI Channel CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 104) {
    //Store Preset CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 105) {
    //MUTE Function Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
}

void setup() {
  Serial.begin(9600);
 
  pinMode(sw1Pin, INPUT);
  pinMode(sw2Pin, INPUT);
  pinMode(sw3Pin, INPUT);
  pinMode(sw4Pin, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);

  // Initiate MIDI
  MIDI.begin(MIDI_CHANNEL_OMNI);
// INITIATE DISPLAY SPLASHSCREEN
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(" SIRIUS AMPLIFICATION ");
  display.drawBitmap(40, 15, NaN, 50, 50, WHITE);
  display.display();
  delay(5000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(" SIRIUS AMPLIFICATION ");
  midiCtrlChange(88,0);
  midiCtrlChange(85,127);
  delay(200);
  display.display();
}

void loop() {
MIDI.read();

//SWITCH READOUT FUNCTIONS
sw1State = digitalRead(sw1Pin);
if (sw1State != sw1StateLast) {
  if (sw1State == HIGH){
    sw1Push++;
    if (sw1Push > 1){sw1Push = 0;}
    switch (sw1Push)
    {
      case 0:
        midiCtrlChange(89,127);
       break;
      delay(200);
      case 1:
        midiCtrlChange(88,0);
        midiCtrlChange(85,127);
      break;
      delay(200);
    }
  }
  delay(200);
  sw1StateLast = sw1State;
}

sw2State = digitalRead(sw2Pin);
if (sw2State != sw2StateLast) {
    if (sw2State == HIGH){
      sw2Push++;
      if (sw2Push > 1){sw2Push = 0;}
    switch (sw2Push)
    {
  case 0:
        midiCtrlChange(87,127);
        break;
        delay(200);
      case 1:
        midiCtrlChange(86,127);
        break;
        delay(200);
    }
  }
    sw2StateLast = sw2State;
delay(200);
}

sw3State = digitalRead(sw3Pin);
if (sw3State != sw3StateLast) {
    if (sw3State == HIGH){
      sw3Push++;
      if (sw3Push > 1){sw3Push = 0;}
      switch (sw3Push)
      {
        case 0:
          midiCtrlChange(88,0);
        break;
        delay(200);
        case 1:
          midiCtrlChange(88,127);
        break;
        delay(200);
      }
    }
    delay(200);
    sw3StateLast = sw3State;
  }

sw4State = digitalRead(sw4Pin);
if (sw4State != sw4StateLast) {
    if (sw4State == HIGH){
      sw4Push++;
      if (sw4Push > 1){sw4Push = 0;}
      switch (sw4Push)
      {
        case 1:
          midiCtrlChange(89,0);
          midiCtrlChange(85,127);
        break;
        delay(200);
        case 0:
          midiCtrlChange(89,127);
        break;
        delay(200);
      }
    }
    delay(200);
    sw4StateLast = sw4State;
  }
}

Title: Re: Arduino MIDI Switcher
Post by: niektb on May 23, 2022, 05:54:42 AM
I have some comments on your switch handling code. But first a small stylistic suggestion:
You have the following code:

sw2Push++;
if (sw2Push > 1){sw2Push = 0;}

But as the values can only change between 1 and 0, you might as well write the following which is a bit cleaner:
sw2Push = !sw2Push;
or even (but the first suggestion is better I think):
sw2Push ^= 1;

But now the major part: I'm a bit confused about your delays in the switch case statement. Doesnt this code mean that you will always have a 200ms delay when the sw1Push is '1'?
break;
delay(200);
case 1:


Also, about this code piece:
  if (c == 85 && v >64) {
    //Channel CC MSG
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("CLEAN   ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
    digitalWrite(RELAY3,LOW);
    digitalWrite(RELAY4,LOW);
  }

I assume you want people to be able to switch channel whilst playing a song. I'm not sure how fast the display responds (and also the code calculating the graphics) but I'd rather not find out that it delays a bit and switches channels too late. So I would advice to fírst have the digitalWrite(RELAYx, ...) statements and thén run the display code :)
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 24, 2022, 01:58:58 AM
Thanks for the reply niektb,

none of your suggestions for sw2Push actually worked. I need to change between channels and your way didnt "Go back to first case switch" so to speak... and I was still not sure about adding additional case switches to the buttons, which all i need to do is change the value from 1 to 3 for example...

I changed the digitalwrite functions to the start of the CC function, before the display message, but it wouldn't make a difference as there is no delay.

I did correct the delays in between the breaks though...

the delays were because the pads were too sensitive but I managed to figure out it was due to INPUT_PULLUP which i just needed to change the switches to LOW instead of HIGH and they aren't as sensitive anymore.

Here i've updated my code



#include <SPI.h>
#include <Wire.h>
#include <MIDI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);

//CHANGE PINS TO SUIT YOUR ARDUINO PINOUT
const int sw1Pin = A0;
const int sw2Pin = A1;
const int sw3Pin = A2;
const int sw4Pin = A3;
const int LED1 = 6;  //set pin for LED 1 (CLEAN)
const int LED2 = 7;   //set pin for LED 2 (GAIN 1)
const int LED3 = 8;  //set pin for LED 3 (GAIN 2)
const int LED4 = 9;  //set pin for LED 4 (BOOST)
const int RELAY1 = 2; //set pin for RELAY 1 (K2 Relay - Clean=HIGH)
const int RELAY2 = 3; //set pin for RELAY 2 (K4 Relay - Gain1=LOW|Gain2=HIGH)
const int RELAY3 = 4; //set pin for RELAY 3 (K7 Relay - Boost Toggle)
const int RELAY4 = 5; //set pin for RELAY 4 (K1 Relay - Plexi Toggle)

int sw1Push = 0;
int sw2Push = 0;
int sw3Push = 0;
int sw4Push = 0;
boolean sw1State = LOW;
boolean sw2State = LOW;
boolean sw3State = LOW;
boolean sw4State = LOW;
boolean sw1StateLast = LOW;
boolean sw2StateLast = LOW;
boolean sw3StateLast = LOW;
boolean sw4StateLast = LOW;

const unsigned char NaN [] PROGMEM = {
  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x03,
  0x80, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x1f, 0xc0, 0x00,
  0x00, 0x00, 0x03, 0xf8, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x3f, 0xe0, 0x00, 0x00, 0x00,
  0x03, 0xf8, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf8,
  0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
  0xe0, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x1f, 0xe0, 0x00,
  0x00, 0x07, 0xfc, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x03,
  0xfc, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00,
  0x00, 0x04, 0x7f, 0xe0, 0x03, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xe0, 0x01, 0xfc, 0x00, 0x00, 0xff,
  0xff, 0xf0, 0x00, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xf8, 0x0c, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xfc,
  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x03, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0x83, 0xf0,
  0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe3, 0x80, 0x00, 0x00,
  0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff,
  0xf7, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf7, 0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0,
  0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x1f, 0xfe, 0x8f, 0xf0, 0x00, 0x00,
  0x00, 0x1f, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x80, 0x00, 0x00
};

uint8_t midi_channel = 0;
MIDI_CREATE_DEFAULT_INSTANCE();

//MIDI CC FUNCTIONS
void midiCtrlChange(byte c, byte v){
MIDI.sendControlChange(c,v,0xB0 | midi_channel);

  if (c == 80 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 80 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 81 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 81 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 82 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 82 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 83 && v >64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 83 && v <=64) {
    //Generic ON/OFF Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }

  if (c == 85 && v >64) {
    //Channel CC MSG
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
    digitalWrite(RELAY3,LOW);
    digitalWrite(RELAY4,LOW);
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("CLEAN   ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 85 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 86 && v >64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 1  ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 86 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,HIGH);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 87 && v >64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,HIGH);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,HIGH);
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("GAIN 2  ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 87 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY2,LOW);
  }
  if (c == 88 && v >64) {
    //Channel CC MSG
    digitalWrite(LED4,HIGH);
    digitalWrite(RELAY3,HIGH);
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 50);
    display.print("BOOST:  ");
    display.setTextSize(1);
    display.setCursor(40, 50);
    display.print("ON ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 88 && v <=64) {
    //Channel CC MSG
    digitalWrite(LED4,LOW);
    digitalWrite(RELAY3,LOW);
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(0, 50);
    display.print("BOOST:  ");
    display.setTextSize(1);
    display.setCursor(40, 50);
    display.print("OFF");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 89 && v >64) {
    //Toggle CC MSG
    digitalWrite(LED1,HIGH);
    digitalWrite(LED2,HIGH);
    digitalWrite(RELAY1,LOW);
    digitalWrite(RELAY4,HIGH);
    display.setTextSize(2);
    display.setCursor(0, 20);
    display.println("PLEXI   ");
    display.setTextSize(1);
    display.setTextColor(WHITE, BLACK);
    display.setCursor(90, 50);
    display.print("CC:");
    display.setTextSize(1);
    display.setCursor(110, 50);
    display.print(c);
    display.display();
  }
  if (c == 89 && v <=64) {
    //Toggle CC MSG
    digitalWrite(LED2,LOW);
    digitalWrite(RELAY4,LOW);
  }
  if (c == 90 && v >64) {
    //Toggle CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 90 && v <=64) {
    //Toggle CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 91 && v >64) {
    //Reverb Volume CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 91 && v <=64) {
    //Reverb Volume CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 92 && v >64) {
    //Tremelo Volume CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 92 && v <=64) {
    //Tremelo Volume CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
  if (c == 102) {
    //EEPROM Reset CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 103) {
    //Set MIDI Channel CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 104) {
    //Store Preset CC MSG
    //Use digitalWrite(OUTPUT,HIGH); for direct functions
  }
  if (c == 105) {
    //MUTE Function Switch CC MSG
    //Use digitalWrite(OUTPUT,LOW); for direct functions
  }
}

void setup() {

//INITIATE INPUT & OUTPUTS
  pinMode(sw1Pin, INPUT_PULLUP);
  pinMode(sw2Pin, INPUT_PULLUP);
  pinMode(sw3Pin, INPUT_PULLUP);
  pinMode(sw4Pin, INPUT_PULLUP);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);

// INITIATE CLEAN CHANNEL
  digitalWrite(LED1,HIGH);
  digitalWrite(RELAY1,HIGH);

  // INITIATE MIDI
  Serial.begin(9600);
  MIDI.begin(MIDI_CHANNEL_OMNI);

// INITIATE DISPLAY SPLASHSCREEN
  Wire.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(" SIRIUS AMPLIFICATION ");
  display.drawBitmap(40, 15, NaN, 50, 50, WHITE);
  display.display();
  delay(5000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE, BLACK);
  display.setCursor(0, 0);
  display.println(" SIRIUS AMPLIFICATION ");
  display.display();
  midiCtrlChange(88,0);
  midiCtrlChange(85,127);
}

void loop() {
MIDI.read();

//SWITCH 1 FUNCTIONS
sw1State = digitalRead(sw1Pin);
if (sw1State != sw1StateLast) {
  if (sw1State == LOW){
    sw1Push++;
    if (sw1Push > 1){sw1Push = 0;}
    switch (sw1Push)
    {
      case 0:
        midiCtrlChange(89,127);
       break;
      case 1:
        midiCtrlChange(88,0);
        midiCtrlChange(85,127);
      break;
    }
  }
  delay(200);
  sw1StateLast = sw1State;
}

//SWITCH 2 FUNCTIONS
sw2State = digitalRead(sw2Pin);
if (sw2State != sw2StateLast) {
    if (sw2State == LOW){
      sw2Push++;
      if (sw2Push > 1){sw2Push = 0;}
    switch (sw2Push)
    {
  case 0:
        midiCtrlChange(87,127);
        break;
      case 1:
        midiCtrlChange(86,127);
        break;
    }
  }
    sw2StateLast = sw2State;
delay(200);
}

//SWITCH 3 FUNCTIONS
sw3State = digitalRead(sw3Pin);
if (sw3State != sw3StateLast) {
    if (sw3State == LOW){
      sw3Push++;
      if (sw3Push > 1){sw3Push = 0;}
      switch (sw3Push)
      {
        case 0:
          midiCtrlChange(88,0);
        break;
        case 1:
          midiCtrlChange(88,127);
        break;
      }
    }
    delay(200);
    sw3StateLast = sw3State;
  }

//SWITCH 4 FUNCTIONS
sw4State = digitalRead(sw4Pin);
if (sw4State != sw4StateLast) {
    if (sw4State == LOW){
      sw4Push++;
      if (sw4Push > 1){sw4Push = 0;}
      switch (sw4Push)
      {
        case 1:
          midiCtrlChange(89,0);
          midiCtrlChange(85,127);
        break;
        case 0:
          midiCtrlChange(89,127);
        break;
      }
    }
    delay(200);
    sw4StateLast = sw4State;
  }
}

Title: Re: Arduino MIDI Switcher
Post by: niektb on May 24, 2022, 02:55:17 AM
Quote from: acatlow on May 24, 2022, 01:58:58 AM
Thanks for the reply niektb,

none of your suggestions for sw2Push actually worked. I need to change between channels and your way didnt "Go back to first case switch" so to speak... and I was still not sure about adding additional case switches to the buttons, which all i need to do is change the value from 1 to 3 for example...

I changed the digitalwrite functions to the start of the CC function, before the display message, but it wouldn't make a difference as there is no delay.

I did correct the delays in between the breaks though...

the delays were because the pads were too sensitive but I managed to figure out it was due to INPUT_PULLUP which i just needed to change the switches to LOW instead of HIGH and they aren't as sensitive anymore.

Here i've updated my code

[...]

Hmm weird, it should definitely work:
QuoteThe not (!) operator returns either 0 or 1, depending on whether the input is non-zero or 0 respectively.
from https://stackoverflow.com/questions/21056180/c-not-operator-applied-to-int

QuoteI changed the digitalwrite functions to the start of the CC function, before the display message, but it wouldn't make a difference as there is no delay.
I wouldn't expect the delays to be thát big to instantly noticeably but maybe during a song.
I have not performed any measurements but you could :) https://www.tutorialspoint.com/calculate-time-of-operation-in-arduino

I'm just a little worried if the display will álways respond in-time. What if the i2c bus is very noisy or the power supply? (dunno where all the amps will be used but power won't be as clean as in the lab) doing the digital writes first eliminates the dependence on external hardware :)
Title: Re: Arduino MIDI Switcher
Post by: acatlow on May 24, 2022, 09:50:03 PM
Quote from: niektb on May 24, 2022, 02:55:17 AM
Quote from: acatlow on May 24, 2022, 01:58:58 AM
Thanks for the reply niektb,

none of your suggestions for sw2Push actually worked. I need to change between channels and your way didnt "Go back to first case switch" so to speak... and I was still not sure about adding additional case switches to the buttons, which all i need to do is change the value from 1 to 3 for example...

I changed the digitalwrite functions to the start of the CC function, before the display message, but it wouldn't make a difference as there is no delay.

I did correct the delays in between the breaks though...

the delays were because the pads were too sensitive but I managed to figure out it was due to INPUT_PULLUP which i just needed to change the switches to LOW instead of HIGH and they aren't as sensitive anymore.

Here i've updated my code

[...]

Hmm weird, it should definitely work:


I should explain better... it did work, but only stopped functions after 1 press, and didn't cycle 0 to 1, 1 to 0

this isn't what I wanted, but it is working perfectly now and very quick functions from momentary switches.

so thanks very much for the help from everyone here too