Program Change Solution for 2 separate midi device

musicgit

Member
Hi all, I am new to the forum and new to coding and using teensyduino.

Bought a midi controller recently and wanting to control to guitar Strymon pedals. The code I have its for only 1 set of bank preset. I manage to add an extra MIDI channel for TRS MIDI

How do I send 2 separate set of PC to 2 different device?

Advice needed. Thanks!


Code:
//************LIBRARIES USED**************
// 'include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle'
#include <MIDI.h>
#include <Bounce.h> 
//'usbMIDI.h library is added automatically when code is compiled as a MIDI device'

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

// ******CONSTANT VALUES******** 


//********** PIN DEFINITIONS
const int D_PINS = 5; // number of Digital PINS in main group (excl tap/bank)
const int DIGITAL_PINS[D_PINS] = {0,1,2,3,4}; // pins to switchs 
const int RED_LED_PINS[D_PINS] = {6,22,10,17,19};
const int GREEN_LED_PINS[D_PINS] = {24,9,16,18,20};
const int MODE_TAP_PIN = 5;  // momentary switch to set tempo and select bank
const int MODE_TAP_LED_PIN = 15; // pin to LED for tempo/bank indicator


       //********** MIDI DEFINITIONS*************
// MODIFY THIS SECTION TO CUSTOMISE YOUR MIDISTOMP SIX 

//const int firstchannel = 0; // MIDI channel for USB MIDI
const int secondchannel = 1; // MIDI channel for TRS MIDI
const int thirdchannel = 2; // MIDI channel for TRS MIDI
const int MODE_COUNT = 2; // number of rows of banks
//CC configuration matrix!!
const int MIDI_PC_NUMS[MODE_COUNT][D_PINS] = { //rows are banks up to MODE_COUNT
    {0,1,2,3,4},
    {5,6,7,8,9}
    
};
const int TAP_CC = 93;
const int ON_Value = 127; // note-one velocity sent from buttons (should be 65 to  127)


//********** PHYSICAL DEFINITIONS 
const int BOUNCE_TIME = 30; // 5 ms is usually sufficient
const int modeThreshold = 800; // how long to hold before mode changes
const int flashOnTime = 150; // how long flashed LED is on
const int flashOffTime = 250; // how long flashed LED is off
const bool LED_ON = LOW; // LOW for active LOW wiring
const bool LED_OFF = HIGH; // HIGH for active LOW wiring
const int onClocks = 4; // number of clock messages with LED on for tempo flash
const int waitflash = 2; // number of dark flash cylces after bank change before tempo flash resumes

//******VARIABLES***********
// a data array to remember the current state of each switch
boolean state[MODE_COUNT][D_PINS];
elapsedMillis modeTimer,flashTimer;
boolean modeSelectActive = false;
int bank = 0 ; 
int flashcount= (-1*waitflash); // default is effective sequence stop of flash counter
int shiftUp; // keeps track of whether the mode change needs to be handled (true) or was (false)
int modeLED; // keeps track of whether LED is on without testing it..
int ClockCount; // for tempo tracking
boolean tempoFlashOn = true;// tempo flash defaults to on

//************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),
    Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
    Bounce(DIGITAL_PINS[4], BOUNCE_TIME)
}; 
Bounce modeTap = Bounce(MODE_TAP_PIN, BOUNCE_TIME);

//************SETUP**************
void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI);
  
  //'set a handle for returning control change messages'
//  usbMIDI.setHandleProgramChange(OnProgramChange);
  usbMIDI.setHandleSongPosition(onSongPosition);
  usbMIDI.setHandleClock(onClock);
  usbMIDI.setHandleStart(onStart);
  //'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);
    pinMode(RED_LED_PINS[i], OUTPUT);
    pinMode(GREEN_LED_PINS[i], OUTPUT);
  }
  pinMode(MODE_TAP_PIN, INPUT_PULLUP);
  pinMode(MODE_TAP_LED_PIN, OUTPUT);
  digitalWrite(MODE_TAP_LED_PIN, LED_OFF);

  for (int i=0;i<D_PINS;i++){
    digitalWrite(GREEN_LED_PINS[i], LED_OFF);   // - GREEN OFF
    digitalWrite(RED_LED_PINS[i], LED_ON);   // - RED ON
  }
}

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

  }
}


//************DIGITAL SECTION**************
void getMain(){
  for (int i=0;i<D_PINS;i++){
    digital[i].update();
    if (digital[i].fallingEdge() || digital[i].risingEdge()) {
      if (state[bank][i]) {
       // usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel); 
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], thirdchannel); 
        digitalWrite(RED_LED_PINS[i], LED_ON);
        digitalWrite(GREEN_LED_PINS[i], LED_OFF);
      }else{
       //usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel);   
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], thirdchannel); 
        digitalWrite(RED_LED_PINS[i], LED_OFF);
        digitalWrite(GREEN_LED_PINS[i], LED_ON);
      }
      state[bank][i] = !state[bank][i] ;
    }
  }
}

//************MODE/TAP SECTION**************
void getModeTap(){
  modeTap.update();
  if (modeTap.fallingEdge()) {
  //  usbMIDI.sendControlChange(TAP_CC, ON_Value, firstchannel);
    MIDI.sendControlChange(TAP_CC, ON_Value, secondchannel); 
 //   MIDI.sendControlChange(TAP_CC, ON_Value, thirdchannel); 
    modeTimer = 0;
    shiftUp = true;
    tempoFlashOn = false; 
    flashcount = 0; // is this error or magic?
    Serial.println("suspend tempo on tap");
  }    
  if (modeTap.risingEdge()){
    shiftUp = false;
    if (modeTimer<modeThreshold){
      tempoFlashOn = true; 
    Serial.println("resume tempo no mode change");
    }
  }
  if (modeTimer>modeThreshold && shiftUp) {
    shiftUp = false;
    bank++;
    bank = bank%MODE_COUNT;
    for (int i = 0; i < D_PINS ; i++){
      digitalWrite(GREEN_LED_PINS[i], !state[bank][i]);
      digitalWrite(RED_LED_PINS[i], state[bank][i]); 
    }
    // set counter of flashes 'owed' -- count them down after main part
    flashcount = bank + 1;
    flashTimer = 0 ; // is this needed?
  }
}

void flasher(){
  if (flashcount>= -1*waitflash){
    if (flashcount> 0){
      if (flashTimer>(flashOnTime+flashOffTime)){ 
        flashcount-- ;// decrement flashcount
        flashTimer = 0;
        if (modeLED){
          modeLED = false;
          digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
        }
      }else{
        if (modeLED == false && flashTimer>flashOnTime){
          modeLED = true;
          digitalWrite(MODE_TAP_LED_PIN, LED_ON);
        }
      }
    }else{
      if (flashTimer>(flashOnTime+flashOffTime)){ 
        flashcount-- ;// decrement flashcount
        flashTimer = 0;
      }
    }
  }else{
    if (!tempoFlashOn){
      tempoFlashOn = true;
      Serial.println(flashcount);
      Serial.println("resume tempo after bank select");
    }
  }
}

void OnProgramChange(byte rcvChannel, byte controller, byte value) {
  if (rcvChannel == secondchannel){
    for (int i = 0; i < D_PINS ; i++){
      if (MIDI_PC_NUMS[bank][i] == controller) {
        if (value >= 64) {
          digitalWrite(GREEN_LED_PINS[i], LED_ON);
          digitalWrite(RED_LED_PINS[i], LED_OFF); //'receiving >64 turns green on and red off'
          state[bank][i] = true;
        }else{
          digitalWrite(GREEN_LED_PINS[i], LED_OFF);
          digitalWrite(RED_LED_PINS[i], LED_ON); //'receiving <64 turns red on and green off'
          state[bank][i] = false;
        } // 'if not the controller for i then skip this loop'    
      }
    }
  }
}

void onClock() {
  if (tempoFlashOn){
    if (ClockCount<=onClocks){
      digitalWrite(MODE_TAP_LED_PIN, LED_ON);
    }else{
      digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
    }
  }
  ClockCount = (ClockCount+1)%24;
}

void onStart(){
  ClockCount = 0;
}


void onSongPosition(uint16_t semiQ){
  ClockCount= semiQ*6 ; 
}
 
First you need to add Midi IO circuitry to Teensy's TX/RX2 then in code add:-

Code:
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI2);

Then to send to it:-

Code:
 MIDI2.sendProgramChange(whateverStuffYouWantToSend);

If you are not using the Teensy's RX1 and or RX2 then enable pullups for those pins so they don't pick up garbage.

Hope this helps.
 
Back
Top