Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 13 of 13

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

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    2

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

    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.

    Click image for larger version. 

Name:	output.jpg 
Views:	66 
Size:	57.0 KB 
ID:	17952


    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 by Lemonmeth; 10-18-2019 at 07:42 PM. Reason: spelling

  2. #2
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,407
    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.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);  
        }
      }
    }
    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 by oddson; 10-18-2019 at 08:15 PM.

  3. #3
    Junior Member
    Join Date
    Oct 2019
    Posts
    2
    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

  4. #4
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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

  5. #5
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,407
    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

  6. #6
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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. Click image for larger version. 

Name:	IMG_0694_2.jpg 
Views:	28 
Size:	115.3 KB 
ID:	22383

    thank you for your help

  7. #7
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,407
    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:
    // 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);  
        }
      }
    }
    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.

  8. #8
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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

  9. #9
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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"











    coleman_with_midi_: In function 'void getDigitalData()':
    coleman_with_midi_:53: error: 'note' was not declared in this scope
    usbMIDI.sendNoteOn(note[i], ON_VELOCITY, channel);
    ^
    coleman_with_midi_:53: error: 'ON_VELOCITY' was not declared in this scope
    usbMIDI.sendNoteOn(note[i], ON_VELOCITY, channel);
    ^
    coleman_with_midi_:57: error: 'note' was not declared in this scope
    usbMIDI.sendControlChange(note[i], 0, channel);
    ^
    'note' was not declared in this scope
    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

  10. #10
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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);
        }
      }
    }

  11. #11
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,407
    Yeah sorry... like I said I didn't compile.

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

    usbMIDI.sendControlChange(note[i], ON_VELOCITY, channel);

    Change this line by replacing 'ON_VELOCITY' with 'ON_VALUE' since we are not sending a note velocity but CC value.

  12. #12
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    No apologies necessary, you’re being very helpful and kind.

    Thank you again

  13. #13
    Junior Member
    Join Date
    Nov 2020
    Location
    Stratford ON, Canada
    Posts
    7
    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);
        }
      }
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •