MIDI stompbox + expedal (spdt switches - help with code)

Status
Not open for further replies.

Lemonmeth

New member
Greetings all!
First time here and first teensy project.

So im building a stompbox for my bandmate. It is a four button + expedal.
Iv got almost everything working exept the behavior of the switches.

The switches are spdt-switches, the problem is that it only sends midiCC when the switches are in gnd state(pullup) hence i have to press two times (instead of one) for a mapped button in my daw to change (since its a toggleswitch), the code seems to be for momentary buttons.

Im using the code posted by oddson: mod on "manybuttonsknobs"
Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h> 
//usbMIDI.h library is added automatically when code is compiled as a MIDI device

// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 1; // number of Analog PINS
const int D_PINS = 4; // number of Digital PINS
const int ON_VALUE = 127; // note-one velocity sent from buttons (should be 65 to  127)

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A1};
const int CCID[A_PINS] = {21};

// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {7,8,9,10};
const int CC[D_PINS] = {60,61,62,63};
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = false;


//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value
byte CClast[D_PINS];

//************INITIALIZE LIBRARY OBJECTS**************
// not sure if there is a better way... some way run a setup loop on global array??
// use comment tags to comment out unused portions of array definitions

// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true}/*,
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
  {ANALOG_PINS[5],true},
  {ANALOG_PINS[6],true},
  {ANALOG_PINS[7],true},*/
}; 

// initialize the bounce objects 
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0],BOUNCE_TIME), 
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[3], BOUNCE_TIME)/*,
  Bounce(DIGITAL_PINS[4], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[5], BOUNCE_TIME)/*,
  Bounce(DIGITAL_PINS[6], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[7], BOUNCE_TIME),*/
}; 

//************SETUP**************
void setup() {
// loop to configure input pins and internal pullup resisters for digital section
  for (int i=0;i<D_PINS;i++){
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

//************LOOP**************
void loop() {
  getAnalogData();
  getDigitalData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}


//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}



//************DIGITAL SECTION**************
void getDigitalData(){
  for (int i=0;i<D_PINS;i++){
  digital[i].update();
    if (digital[i].fallingEdge()) {
      if (CClast[i]){
        usbMIDI.sendControlChange(CC[i], 0, channel);
        CClast[i] = 0;
      }else{
        usbMIDI.sendControlChange(CC[i], ON_VALUE, channel);
        CClast[i] = ON_VALUE;
      }
    }
    // rising ignored for toggles
  }

}

i dont really know how to do a wiringdiagram but this is basically how the wiring is done.

output.jpg


So, i humbly ask for help regarding the code to make it momentary (since its toggle switches), also dont really know how to make a wiringdiagram..

Any help is appreciated, take care
 
Last edited:
That modified code was to implement toggle behaviour with momentary switches.

If you have toggle switches the stock many-button-and-knobs sketch should work by just replacing the note on/off commands with CC messages at 0 and 127 for off and on.

Code:
//************DIGITAL SECTION**************
void getDigitalData(){
  for (int i=0;i<D_PINS;i++){
  digital[i].update();
    if (digital[i].fallingEdge()) {
     usbMIDI.[COLOR="#FF0000"]sendControlChange[/COLOR](note[i], ON_VELOCITY, channel);  
    }
    // [COLOR="#FF0000"]with a toggle switch we send off with rising edge[/COLOR]
    if (digital[i].risingEdge()) {
      usbMIDI.[COLOR="#FF0000"]sendControlChange[/COLOR](note[i], 0, channel);  
    }
  }
}

You might rename note[] to something more descriptive for CC numbers (you need to alter where it's initialized too) but I think it will work as is. You just put what CC numbers you want the buttons to toggle in the note array or it's replacement.

Re wiring: That diagram suggests you have the pins electrically connected together which I don't think you mean. If the toggles are grounded on one side and connected to the correct digital pin on the other the code should work.

The potentiometer for the expression pedal needs to have the 3.3 volt power on the top end and ground on the bottom with the wiper (middle contact) connected to the analog pin.

...about signal stability.. You might need a very high BOUNCE_TIME if your toggles are slow to settle with the latching mechanism.

And expression pedals can bring a lot of noise on an analog signal. ResponsiveAnalogRead() was used rather naively in this code but it's usually enough to tame for seven-bit MIDI values. You also need to be sure yours is wired as you expect as some use different wiring to the TRS connector.
 
Last edited:
Yeees! That did it!
Thank you for clarifying and explaining, it makes sense now.
i set the bouncetime to 5 ms and did some testing, seems to work fine.
regarding the wiringdiagram , i made it on the phone and tried to scale it down to its essence - but the physical wiring is ok.


Thanks heaps for the quick reply and your time oddson.
Let me know if i can buy you a coffee or something:eek:
 
Hello , I am trying my hand at a toggle type switch midi project, I noticed that this solution worked for you. When i load this sketch onto my teensylc it just spits out midi data from pin 21-26. How did you stop that from happening? Could you share your sketch that ending up working for your project ?

thanks
 
What this guy was doing is pretty specific...

...maybe spell out what YOU are trying to do and I'll see if I can help :)
 
Hello ,

I am trying to add midi output from an analogue speaker switcher. The buttons latch on. I would like to have the on function send a midi message and the off send the same message so I can toggle some software bypass switches. IMG_0694_2.jpg

thank you for your help
 
You have three switches and two wires to your Teensy?

Assuming you know what you're doing with the wiring here's the above code with the digital section altered to CC messages and the analog stuff removed.
Code:
Code:
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h> 

// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int channel = 1; // MIDI channel
[COLOR="#FF0000"]const int D_PINS = 3; // number of Digital PINS[/COLOR]
const int ON_VALUE = 127; // note-one velocity sent from buttons (should be 65 to  127)


// define the pins and notes for digital events
[COLOR="#FF0000"]const int DIGITAL_PINS[D_PINS] = {0,1,2};
const int CC[D_PINS] = {60,61,62};[/COLOR]
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = false;


//******VARIABLES***********
byte CClast[D_PINS];

//************INITIALIZE LIBRARY OBJECTS**************

// initialize the bounce objects 
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0],BOUNCE_TIME), 
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME)
}; 

//************SETUP**************
void setup() {
// loop to configure input pins and internal pullup resisters for digital section
  for (int i=0;i<D_PINS;i++){
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

//************LOOP**************
void loop() {
  getDigitalData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************DIGITAL SECTION**************
void getDigitalData(){
  for (int i=0;i<D_PINS;i++){
  digital[i].update();
    if (digital[i].fallingEdge()) {
     usbMIDI.sendControlChange(note[i], ON_VELOCITY, channel);  
    }
    // with a toggle switch we send off with rising edge
    if (digital[i].risingEdge()) {
      usbMIDI.sendControlChange(note[i], 0, channel);  
    }
  }
}
I've done this in a text editor without compiling so chances are good I've introduced some minor error or missed something.

The red is where you tell it which pins to read and what CC numbers to use.

The idea is to send one CC value for the ON state and zero for the off state on the same CC number.

If you're looking for some other behaviour you'll need to be more specific.
 
Yes, I haven't finished wiring it yet, because I wanted to make sure I could program it before the final soldering and assembly. :)
Thank you so much for your time :).

J
 
So because im super new and know almost nothing about programming, Im getting this error and I don't know how to fix it .

Arduino: 1.8.13 (Mac OS X), TD: 1.53, Board: "Teensy LC, MIDI, 48 MHz, Smallest Code, US English"











Code:
coleman_with_midi_: In function 'void getDigitalData()':
coleman_with_midi_:53: error: 'note' was not declared in this scope
usbMIDI.sendNoteOn(note, ON_VELOCITY, channel);
^
coleman_with_midi_:53: error: 'ON_VELOCITY' was not declared in this scope
usbMIDI.sendNoteOn(note, ON_VELOCITY, channel);
^
coleman_with_midi_:57: error: 'note' was not declared in this scope
usbMIDI.sendControlChange(note, 0, channel);
^
'note' was not declared in this scope
Code:


This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
 
Code:
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h>



// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int D_PINS = 3; // number of Digital PINS
const int ON_VALUE = 127; // note-one velocity sent from buttons (should be 65 to  127)


// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {0, 1, 2};
const int CC[D_PINS] = {60, 61, 62};
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = false;


//******VARIABLES***********
byte CClast[D_PINS];

//************INITIALIZE LIBRARY OBJECTS**************

// initialize the bounce objects
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME)
};

//************SETUP**************
void setup() {
  // loop to configure input pins and internal pullup resisters for digital section
  for (int i = 0; i < D_PINS; i++) {
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

//************LOOP**************
void loop() {
  getDigitalData();
  while (usbMIDI.read()) {
    // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************DIGITAL SECTION**************
void getDigitalData() {
  for (int i = 0; i < D_PINS; i++) {
    digital[i].update();
    if (digital[i].fallingEdge()) {
      usbMIDI.sendControlChange(note[i], ON_VELOCITY, channel);
    }
    // with a toggle switch we send off with rising edge
    if (digital[i].risingEdge()) {
      usbMIDI.sendControlChange(note[i], 0, channel);
    }
  }
}
 
Yeah sorry... like I said I didn't compile.

I used a different name for the ON value being sent.

usbMIDI.sendControlChange(note, ON_VELOCITY, channel);

Change this line by replacing 'ON_VELOCITY' with 'ON_VALUE' since we are not sending a note velocity but CC value.
 
So this is working a charm, thank you so much for your help. Here is the change i made et voila. Is there a way I can send you a gift card or something for your time ?

Code:
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h>




// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int D_PINS = 3; // number of Digital PINS
const int ON_VALUE = 127; // note-one velocity sent from buttons (should be 65 to  127)


// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {0, 1, 2};
const int CC[D_PINS] = {60, 61, 62};
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = false;


//******VARIABLES***********
byte CClast[D_PINS];

//************INITIALIZE LIBRARY OBJECTS**************

// initialize the bounce objects
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME)
};

//************SETUP**************
void setup() {
  // loop to configure input pins and internal pullup resisters for digital section
  for (int i = 0; i < D_PINS; i++) {
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

//************LOOP**************
void loop() {
  getDigitalData();
  while (usbMIDI.read()) {
    // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************DIGITAL SECTION**************
void getDigitalData() {
  for (int i = 0; i < D_PINS; i++) {
    digital[i].update();
    if (digital[i].fallingEdge()) {
      usbMIDI.sendControlChange(CC[i], ON_VALUE, channel);
    }
    // with a toggle switch we send off with rising edge
    if (digital[i].risingEdge()) {
      usbMIDI.sendControlChange(CC[i], 0, channel);
    }
  }
}
 
Status
Not open for further replies.
Back
Top