Custom MIDI controller with 18 Illuminated Pushbuttons - LED feedback question

Hello,

My first time posting so apologies in advance for any stupid questions, my lack of knowledge and potential lack of clarify in my question.
Background:
I'm creating a custom midi controller with 18 buttons and 18 LED's.
The plan is to have the unit send MIDI program change messages to a DAW I have (it's actually a virtual arranger...Varranger) and control this various parts (Variation 1-4, Endings 1-4, Intros 1-4, start and stop, etc.)
I'm using the teensy 4.1 and have everything wired up and and have it's sending the MIDI messages perfectly and the LED's are lighting up exactly as I want (code below).
However, what I'm trying to do is get the DAW (which has an LED Feedback feature) to send a message back to my unit and light up the specific button that has the Program Change Assigned.

I've read through a lot of the USBMidi libraries, sample codes, etc. and I think I may need to use void myProgramChange(byte channel, byte program) and usbMIDI.setHandleProgramChange(myProgramChange) functions.

I tried ProgramChangeSelectorLEDs as you can see below with no success and a few other variations of code, but I just can't seem to get it to work.

Any help anyone could provide with be so very much appreciated.

Thanks in advance and I look forward to the replies (I hope).

- Alex

CODE:
Code:
/* Teensy_USB_MIDI_vArranger_7

   You must select MIDI from the "Tools > USB Type" menu

*/

/* Buttons to USB MIDI

   You must select MIDI from the "Tools > USB Type" menu

      This example code is in the public domain.
*/
#include <Control_Surface.h>
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi_usb;
// Instantiate the pipe to connect the interface to Control_Surface
BidirectionalMIDI_Pipe pipe_txrx;

 template <setting_t N>
class ProgramChangeSelectorLEDs
    : public GenericProgramChangeSelector<N, SelectorLEDsCallback<N>> {
  public:
    ProgramChangeSelectorLEDs(Selectable<N> &selectable,
                              MIDIChannelCable address,
                              const PinList<18> &ledPins)
        : GenericProgramChangeSelector<N, SelectorLEDsCallback<N>>{
              selectable,
              {24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41},
              address,
          } {}
};
 


#include <Bounce.h>
// set pins
int ledPin1 = 24;
int ledPin2 = 25;
int ledPin3 = 26;
int ledPin4 = 27;
int ledPin5 = 28;
int ledPin6 = 29;
int ledPin7 = 30;
int ledPin8 = 31;
int ledPin9 = 32;
int ledPin10 = 33;
int ledPin11 = 34;
int ledPin12 = 35;
int ledPin13 = 36;
int ledPin14 = 37;
int ledPin15 = 38;
int ledPin16 = 39;
int ledPin17 = 40;
int ledPin18 = 41;

// set variables


// the MIDI channel number to send messages
const int channel = 16;

// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5);  // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5);  // to rapid touch, you can
Bounce button7 = Bounce(7, 5);  // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
Bounce button12 = Bounce(12, 5);
Bounce button13 = Bounce(13, 5);
Bounce button14 = Bounce(14, 5);
Bounce button15 = Bounce(15, 5);
Bounce button16 = Bounce(16, 5);
Bounce button17 = Bounce(17, 5);
Bounce button18 = Bounce(18, 5);

void setup() {

Control_Surface | pipe_txrx | midi_usb;
    // Initialize everything
Control_Surface.begin();



  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!
  pinMode(1, INPUT_PULLUP);  // set Buttons as INPUT
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP); 
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(ledPin1, OUTPUT);  // set LEDs as OUTPUT
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(ledPin6, OUTPUT);
  pinMode(ledPin7, OUTPUT);
  pinMode(ledPin8, OUTPUT);
  pinMode(ledPin9, OUTPUT);
  pinMode(ledPin10, OUTPUT);
  pinMode(ledPin11, OUTPUT);
  pinMode(ledPin12, OUTPUT);
  pinMode(ledPin13, OUTPUT);
  pinMode(ledPin14, OUTPUT);
  pinMode(ledPin15, OUTPUT);
  pinMode(ledPin16, OUTPUT);
  pinMode(ledPin17, OUTPUT);
  pinMode(ledPin18, OUTPUT);
  
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin3, LOW);
digitalWrite(ledPin4, LOW);
digitalWrite(ledPin5, LOW);
digitalWrite(ledPin6, LOW);
digitalWrite(ledPin7, LOW);
digitalWrite(ledPin8, LOW);
digitalWrite(ledPin9, LOW);
digitalWrite(ledPin10, LOW);
digitalWrite(ledPin11, LOW);
digitalWrite(ledPin12, LOW);
digitalWrite(ledPin13, LOW);
digitalWrite(ledPin14, LOW);
digitalWrite(ledPin15, LOW);
digitalWrite(ledPin16, LOW);
digitalWrite(ledPin17, LOW);
digitalWrite(ledPin18, LOW);

}

void loop() {

  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update();
  button18.update();

  // Check each button for "falling" edge.
  // Send a Program Change message when each button presses
  // Turn ON LED cooresponding to button pressed
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
 if (button1.fallingEdge()) {
    usbMIDI.sendProgramChange(80, 16); // 80=Intro 1
      digitalWrite(ledPin1, HIGH);
}
  if (button2.fallingEdge()) {
    usbMIDI.sendProgramChange(81, 16);  // 81=Intro 2
      digitalWrite(ledPin2, HIGH);
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendProgramChange(82, 16);  // 82=Intro 3/Count In
      digitalWrite(ledPin3, HIGH);
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendProgramChange(92, 16);  // 92=Ending 1
      digitalWrite(ledPin4, HIGH);
  }
  if (button5.fallingEdge()) {
    usbMIDI.sendProgramChange(93, 16);  // 93=Ending 2
      digitalWrite(ledPin5, HIGH);
  }
  if (button6.fallingEdge()) {
    usbMIDI.sendProgramChange(94, 16);  // 94=Ending 3
      digitalWrite(ledPin6, HIGH);
  }
  if (button7.fallingEdge()) {
    usbMIDI.sendProgramChange(108, 16);  // 108=Tempo +
      digitalWrite(ledPin7, HIGH);
  }
  if (button8.fallingEdge()) {
    usbMIDI.sendProgramChange(109, 16);  // 109=Tempo -
      digitalWrite(ledPin8, HIGH);    
  }
  if (button9.fallingEdge()) {
    usbMIDI.sendProgramChange(103, 16);  // 103=Start/Stop (Arranger)
      digitalWrite(ledPin9, HIGH);
  }
  if (button10.fallingEdge()) {
    usbMIDI.sendProgramChange(83, 16);  // 83=Variation 1
          digitalWrite(ledPin10, HIGH);
       }
       else if (button11.fallingEdge())  {
       digitalWrite(ledPin10, LOW);
       }
       else if (button12.fallingEdge())  {
       digitalWrite(ledPin10, LOW);
      }
       else if (button13.fallingEdge())  {
       digitalWrite(ledPin10, LOW);
       }
  if (button11.fallingEdge()) {
    usbMIDI.sendProgramChange(84, 16);  // 84=Variation 2
          digitalWrite(ledPin11, HIGH);
       }
       else if (button10.fallingEdge())  {
       digitalWrite(ledPin11, LOW);
       }
       else if (button12.fallingEdge())  {
       digitalWrite(ledPin11, LOW);
      }
       else if (button13.fallingEdge())  {
       digitalWrite(ledPin11, LOW);
       }
  if (button12.fallingEdge()) {
    usbMIDI.sendProgramChange(85, 16);  // 85=Variation 3
           digitalWrite(ledPin12, HIGH);
       }
       else if (button10.fallingEdge())  {
       digitalWrite(ledPin12, LOW);
       }
       else if (button11.fallingEdge())  {
       digitalWrite(ledPin12, LOW);
      }
       else if (button13.fallingEdge())  {
       digitalWrite(ledPin12, LOW);
       }
  if (button13.fallingEdge()) {
    usbMIDI.sendProgramChange(86, 16);  // 86=Variation 4
          digitalWrite(ledPin13, HIGH);
       }
       else if (button10.fallingEdge())  {
       digitalWrite(ledPin13, LOW);
       }
       else if (button11.fallingEdge())  {
       digitalWrite(ledPin13, LOW);
      }
       else if (button12.fallingEdge())  {
       digitalWrite(ledPin13, LOW);
       }
  if (button14.fallingEdge()) {
    usbMIDI.sendProgramChange(87, 16);  // 87=Fill 1
      digitalWrite(ledPin14, HIGH);
  }
  if (button15.fallingEdge()) {
    usbMIDI.sendProgramChange(88, 16);  // 88=Fill 2
      digitalWrite(ledPin15, HIGH);
  }
  if (button16.fallingEdge()) {
    usbMIDI.sendProgramChange(89, 16);  // 89=Fill 3
      digitalWrite(ledPin16, HIGH);
  }
  if (button17.fallingEdge()) {
    usbMIDI.sendProgramChange(90, 16);  // 90=Fill 4
      digitalWrite(ledPin17, HIGH);
  }
  if (button18.fallingEdge()) {
    usbMIDI.sendProgramChange(91, 16);  // 91=Break
      digitalWrite(ledPin18, HIGH);
  }
  // Check each button for "rising" edge
  // Turn off each LED
  // rising = low (pressed - button connects pin to ground)
  //          to high (not pressed - voltage from pullup resistor)
  if (button1.risingEdge()) {
     digitalWrite(ledPin1, LOW);
}
  if (button2.risingEdge()) {
     digitalWrite(ledPin2, LOW);
}
  if (button3.risingEdge()) {
     digitalWrite(ledPin3, LOW);
}
  if (button4.risingEdge()) {
     digitalWrite(ledPin4, LOW);
}
  if (button5.risingEdge()) {
     digitalWrite(ledPin5, LOW);
}
  if (button6.risingEdge()) {
     digitalWrite(ledPin6, LOW);
}
  if (button7.risingEdge()) {
     digitalWrite(ledPin7, LOW);
}
  if (button8.risingEdge()) {
     digitalWrite(ledPin8, LOW);
}
  if (button9.risingEdge()) {
     digitalWrite(ledPin9, LOW);
}
  if (button14.risingEdge()) {
     digitalWrite(ledPin14, LOW);
}
  if (button15.risingEdge()) {
     digitalWrite(ledPin15, LOW);
}
  if (button16.risingEdge()) {
     digitalWrite(ledPin16, LOW);
}
  if (button17.risingEdge()) {
     digitalWrite(ledPin17, LOW);
}
  if (button18.risingEdge()) {
     digitalWrite(ledPin18, LOW);
}
  Control_Surface.loop();
   {
  usbMIDI.read();
}
}
 
Last edited by a moderator:
Not sure of the answer to the question - cool that it works except the feedback part.

Edited p#1 to include the
Code:
...
tags using the # on toolbar.

That retains code formatting/indentation for readability.

If using the IDE there is a Ctrl+T command that applies a uniform formatting - some of the brace/code indents are not balanced looking.

Doing that here results in this - which doesn't relate to the issue at hand with working code - just readability:
Code:
/* Teensy_USB_MIDI_vArranger_7

   You must select MIDI from the "Tools > USB Type" menu

*/

/* Buttons to USB MIDI

   You must select MIDI from the "Tools > USB Type" menu

      This example code is in the public domain.
*/
#include <Control_Surface.h>
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi_usb;
// Instantiate the pipe to connect the interface to Control_Surface
BidirectionalMIDI_Pipe pipe_txrx;

template <setting_t N>
class ProgramChangeSelectorLEDs
  : public GenericProgramChangeSelector<N, SelectorLEDsCallback<N>> {
  public:
    ProgramChangeSelectorLEDs(Selectable<N> &selectable,
                              MIDIChannelCable address,
                              const PinList<18> &ledPins)
      : GenericProgramChangeSelector<N, SelectorLEDsCallback<N>> {
      selectable,
      {24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41},
      address,
    } {}
};



#include <Bounce.h>
// set pins
int ledPin1 = 24;
int ledPin2 = 25;
int ledPin3 = 26;
int ledPin4 = 27;
int ledPin5 = 28;
int ledPin6 = 29;
int ledPin7 = 30;
int ledPin8 = 31;
int ledPin9 = 32;
int ledPin10 = 33;
int ledPin11 = 34;
int ledPin12 = 35;
int ledPin13 = 36;
int ledPin14 = 37;
int ledPin15 = 38;
int ledPin16 = 39;
int ledPin17 = 40;
int ledPin18 = 41;

// set variables


// the MIDI channel number to send messages
const int channel = 16;

// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5);  // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5);  // to rapid touch, you can
Bounce button7 = Bounce(7, 5);  // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
Bounce button12 = Bounce(12, 5);
Bounce button13 = Bounce(13, 5);
Bounce button14 = Bounce(14, 5);
Bounce button15 = Bounce(15, 5);
Bounce button16 = Bounce(16, 5);
Bounce button17 = Bounce(17, 5);
Bounce button18 = Bounce(18, 5);

void setup() {

  Control_Surface | pipe_txrx | midi_usb;
  // Initialize everything
  Control_Surface.begin();



  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!
  pinMode(1, INPUT_PULLUP);  // set Buttons as INPUT
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(ledPin1, OUTPUT);  // set LEDs as OUTPUT
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(ledPin6, OUTPUT);
  pinMode(ledPin7, OUTPUT);
  pinMode(ledPin8, OUTPUT);
  pinMode(ledPin9, OUTPUT);
  pinMode(ledPin10, OUTPUT);
  pinMode(ledPin11, OUTPUT);
  pinMode(ledPin12, OUTPUT);
  pinMode(ledPin13, OUTPUT);
  pinMode(ledPin14, OUTPUT);
  pinMode(ledPin15, OUTPUT);
  pinMode(ledPin16, OUTPUT);
  pinMode(ledPin17, OUTPUT);
  pinMode(ledPin18, OUTPUT);

  digitalWrite(ledPin1, LOW);
  digitalWrite(ledPin2, LOW);
  digitalWrite(ledPin3, LOW);
  digitalWrite(ledPin4, LOW);
  digitalWrite(ledPin5, LOW);
  digitalWrite(ledPin6, LOW);
  digitalWrite(ledPin7, LOW);
  digitalWrite(ledPin8, LOW);
  digitalWrite(ledPin9, LOW);
  digitalWrite(ledPin10, LOW);
  digitalWrite(ledPin11, LOW);
  digitalWrite(ledPin12, LOW);
  digitalWrite(ledPin13, LOW);
  digitalWrite(ledPin14, LOW);
  digitalWrite(ledPin15, LOW);
  digitalWrite(ledPin16, LOW);
  digitalWrite(ledPin17, LOW);
  digitalWrite(ledPin18, LOW);

}

void loop() {

  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update();
  button18.update();

  // Check each button for "falling" edge.
  // Send a Program Change message when each button presses
  // Turn ON LED cooresponding to button pressed
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
  if (button1.fallingEdge()) {
    usbMIDI.sendProgramChange(80, 16); // 80=Intro 1
    digitalWrite(ledPin1, HIGH);
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendProgramChange(81, 16);  // 81=Intro 2
    digitalWrite(ledPin2, HIGH);
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendProgramChange(82, 16);  // 82=Intro 3/Count In
    digitalWrite(ledPin3, HIGH);
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendProgramChange(92, 16);  // 92=Ending 1
    digitalWrite(ledPin4, HIGH);
  }
  if (button5.fallingEdge()) {
    usbMIDI.sendProgramChange(93, 16);  // 93=Ending 2
    digitalWrite(ledPin5, HIGH);
  }
  if (button6.fallingEdge()) {
    usbMIDI.sendProgramChange(94, 16);  // 94=Ending 3
    digitalWrite(ledPin6, HIGH);
  }
  if (button7.fallingEdge()) {
    usbMIDI.sendProgramChange(108, 16);  // 108=Tempo +
    digitalWrite(ledPin7, HIGH);
  }
  if (button8.fallingEdge()) {
    usbMIDI.sendProgramChange(109, 16);  // 109=Tempo -
    digitalWrite(ledPin8, HIGH);
  }
  if (button9.fallingEdge()) {
    usbMIDI.sendProgramChange(103, 16);  // 103=Start/Stop (Arranger)
    digitalWrite(ledPin9, HIGH);
  }
  if (button10.fallingEdge()) {
    usbMIDI.sendProgramChange(83, 16);  // 83=Variation 1
    digitalWrite(ledPin10, HIGH);
  }
  else if (button11.fallingEdge())  {
    digitalWrite(ledPin10, LOW);
  }
  else if (button12.fallingEdge())  {
    digitalWrite(ledPin10, LOW);
  }
  else if (button13.fallingEdge())  {
    digitalWrite(ledPin10, LOW);
  }
  if (button11.fallingEdge()) {
    usbMIDI.sendProgramChange(84, 16);  // 84=Variation 2
    digitalWrite(ledPin11, HIGH);
  }
  else if (button10.fallingEdge())  {
    digitalWrite(ledPin11, LOW);
  }
  else if (button12.fallingEdge())  {
    digitalWrite(ledPin11, LOW);
  }
  else if (button13.fallingEdge())  {
    digitalWrite(ledPin11, LOW);
  }
  if (button12.fallingEdge()) {
    usbMIDI.sendProgramChange(85, 16);  // 85=Variation 3
    digitalWrite(ledPin12, HIGH);
  }
  else if (button10.fallingEdge())  {
    digitalWrite(ledPin12, LOW);
  }
  else if (button11.fallingEdge())  {
    digitalWrite(ledPin12, LOW);
  }
  else if (button13.fallingEdge())  {
    digitalWrite(ledPin12, LOW);
  }
  if (button13.fallingEdge()) {
    usbMIDI.sendProgramChange(86, 16);  // 86=Variation 4
    digitalWrite(ledPin13, HIGH);
  }
  else if (button10.fallingEdge())  {
    digitalWrite(ledPin13, LOW);
  }
  else if (button11.fallingEdge())  {
    digitalWrite(ledPin13, LOW);
  }
  else if (button12.fallingEdge())  {
    digitalWrite(ledPin13, LOW);
  }
  if (button14.fallingEdge()) {
    usbMIDI.sendProgramChange(87, 16);  // 87=Fill 1
    digitalWrite(ledPin14, HIGH);
  }
  if (button15.fallingEdge()) {
    usbMIDI.sendProgramChange(88, 16);  // 88=Fill 2
    digitalWrite(ledPin15, HIGH);
  }
  if (button16.fallingEdge()) {
    usbMIDI.sendProgramChange(89, 16);  // 89=Fill 3
    digitalWrite(ledPin16, HIGH);
  }
  if (button17.fallingEdge()) {
    usbMIDI.sendProgramChange(90, 16);  // 90=Fill 4
    digitalWrite(ledPin17, HIGH);
  }
  if (button18.fallingEdge()) {
    usbMIDI.sendProgramChange(91, 16);  // 91=Break
    digitalWrite(ledPin18, HIGH);
  }
  // Check each button for "rising" edge
  // Turn off each LED
  // rising = low (pressed - button connects pin to ground)
  //          to high (not pressed - voltage from pullup resistor)
  if (button1.risingEdge()) {
    digitalWrite(ledPin1, LOW);
  }
  if (button2.risingEdge()) {
    digitalWrite(ledPin2, LOW);
  }
  if (button3.risingEdge()) {
    digitalWrite(ledPin3, LOW);
  }
  if (button4.risingEdge()) {
    digitalWrite(ledPin4, LOW);
  }
  if (button5.risingEdge()) {
    digitalWrite(ledPin5, LOW);
  }
  if (button6.risingEdge()) {
    digitalWrite(ledPin6, LOW);
  }
  if (button7.risingEdge()) {
    digitalWrite(ledPin7, LOW);
  }
  if (button8.risingEdge()) {
    digitalWrite(ledPin8, LOW);
  }
  if (button9.risingEdge()) {
    digitalWrite(ledPin9, LOW);
  }
  if (button14.risingEdge()) {
    digitalWrite(ledPin14, LOW);
  }
  if (button15.risingEdge()) {
    digitalWrite(ledPin15, LOW);
  }
  if (button16.risingEdge()) {
    digitalWrite(ledPin16, LOW);
  }
  if (button17.risingEdge()) {
    digitalWrite(ledPin17, LOW);
  }
  if (button18.risingEdge()) {
    digitalWrite(ledPin18, LOW);
  }
  Control_Surface.loop();
  {
    usbMIDI.read();
  }
}
 
I would check what exactly is sent as feedback from the DAW when the message from the Teensy has been sent. Print the raw data to make sure that this is really a program change message or see what it is.

It is only a matter of style then if you use the handles or if you interpret the raw data yourself somehow.

Something like that should give you the data (all variables bytes...)
Code:
if ( usbMIDI.read() ) { 
  midiCh = usbMIDI.getChannel();
  type = usbMIDI.getType();     // which MIDI message, 128-255
  data1 = usbMIDI.getData1();   // first data byte of message, 0-127 (CC number)
  data2 = usbMIDI.getData2();   // second data byte of message, 0-127
  // print...
}
 
Thanks so much for the reply!!

It was a bit of work, but I already started going down the path you recommended and realized the LED Feedback was sending back note messages.
So program change wasn't working for me, shifted to note on/off send/receive.
I was able to rework the code and now everything works perfectly!!

Code:
/* Teensy_USB_MIDI_vArranger_FINAL

   You must select MIDI from the "Tools > USB Type" menu

/* Buttons to USB MIDI
*/

byte midiCh = 1;                                                                                            //* MIDI channel to read
const int LED_NR = 18;                                                                                      //Number of LEDs
const int LED_PINS[LED_NR] = { 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41 };    //Pins with LEDs
const int LED_MIDI_NOTES[LED_NR] = { 16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1 };  //MIDI-Notes for LEDs


#include <Bounce.h>
int ledPin7 = 30;
int ledPin8 = 31;
// Create Bounce objects for each button.  The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons
Bounce button4 = Bounce(4, 5);
Bounce button5 = Bounce(5, 5);  // if a button is too "sensitive"
Bounce button6 = Bounce(6, 5);  // to rapid touch, you can
Bounce button7 = Bounce(7, 5);  // increase this time.
Bounce button8 = Bounce(8, 5);
Bounce button9 = Bounce(9, 5);
Bounce button10 = Bounce(10, 5);
Bounce button11 = Bounce(11, 5);
Bounce button12 = Bounce(12, 5);
Bounce button13 = Bounce(13, 5);
Bounce button14 = Bounce(14, 5);
Bounce button15 = Bounce(15, 5);
Bounce button16 = Bounce(16, 5);
Bounce button17 = Bounce(17, 5);
Bounce button18 = Bounce(18, 5);

void setup() {

  for (int i = 0; i < LED_NR; i++) {
    pinMode(LED_PINS[i], OUTPUT);
  }
  usbMIDI.setHandleNoteOff(OnNoteOff);
  usbMIDI.setHandleNoteOn(OnNoteOn);


  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.  LOW for "on", and HIGH for "off" may seem
  // backwards, but using the on-chip pullup resistors is very
  // convenient.  The scheme is called "active low", and it's
  // very commonly used in electronics... so much that the chip
  // has built-in pullup resistors!
  pinMode(1, INPUT_PULLUP);  // set Buttons as INPUT
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);

  pinMode(ledPin7, OUTPUT);
  pinMode(ledPin8, OUTPUT);
}

void loop() {

  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update();
  button18.update();

  // Check each button for "falling" edge.
  // Send a Program Change message when each button presses
  // Turn ON LED cooresponding to button pressed
  // falling = high (not pressed - voltage from pullup resistor)
  //           to low (pressed - button connects pin to ground)
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(16, 99, 1);  // 16=Intro 1
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(17, 99, 1);  // 17=Intro 2
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendNoteOn(18, 99, 1);  // 18=Intro 3/Count In
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendNoteOn(19, 99, 1);  // 19=Ending 1
  }
  if (button5.fallingEdge()) {
    usbMIDI.sendNoteOn(20, 99, 1);  // 20=Ending 2
  }
  if (button6.fallingEdge()) {
    usbMIDI.sendNoteOn(21, 99, 1);  // 21=Ending 3
  }
  if (button7.fallingEdge()) {
    usbMIDI.sendNoteOn(22, 99, 1);  // 22=Tempo +
    digitalWrite(ledPin7, HIGH);
  }
  if (button8.fallingEdge()) {
    usbMIDI.sendNoteOn(23, 99, 1);  // 23=Tempo -
    digitalWrite(ledPin8, HIGH);
  }
  if (button9.fallingEdge()) {
    usbMIDI.sendNoteOn(8, 99, 1);  // 8=Start/Stop (Arranger)
  }
  if (button10.fallingEdge()) {
    usbMIDI.sendNoteOn(9, 99, 1);  // 9=Variation 1
  }
  if (button11.fallingEdge()) {
    usbMIDI.sendNoteOn(10, 99, 1);  // 10=Variation 2
  }
  if (button12.fallingEdge()) {
    usbMIDI.sendNoteOn(11, 99, 1);  // 11=Variation 3
  }
  if (button13.fallingEdge()) {
    usbMIDI.sendNoteOn(12, 99, 1);  // 12=Variation 4
  }
  if (button14.fallingEdge()) {
    usbMIDI.sendNoteOn(13, 99, 1);  // 13=Fill 1
  }
  if (button15.fallingEdge()) {
    usbMIDI.sendNoteOn(14, 99, 1);  // 14=Fill 2
  }
  if (button16.fallingEdge()) {
    usbMIDI.sendNoteOn(15, 99, 1);  // 15=Fill 3
  }
  if (button17.fallingEdge()) {
    usbMIDI.sendNoteOn(0, 99, 1);  // 0=Fill 4
  }
  if (button18.fallingEdge()) {
    usbMIDI.sendNoteOn(1, 99, 1);  // 1=Break
  }
  if (button7.risingEdge()) {
    digitalWrite(ledPin7, LOW);
  }
  if (button8.risingEdge()) {
    digitalWrite(ledPin8, LOW);
  }
  {
    usbMIDI.read();
  }
  usbMIDI.read(midiCh);
}

void OnNoteOn(byte channel, byte note, byte velocity) {
  if (velocity > 0) {
    for (int i = 0; i < LED_NR; i++) {
      if (note == LED_MIDI_NOTES[i]) {
        digitalWrite(LED_PINS[i], HIGH);
        break;
      }
    }
  }
}

void OnNoteOff(byte channel, byte note, byte velocity) {
  for (int i = 0; i < LED_NR; i++) {
    if (note == LED_MIDI_NOTES[i]) {
      digitalWrite(LED_PINS[i], LOW);
      break;
    }
  }
}
 
Back
Top