Question on instantiating Multiple USB & Serial Interfaces

This line does two things:

  • It causes all MIDI messages sent by the MIDI control elements (potentiometers, buttons ...) in your code to be sent to the output of serialmidi2.
  • It makes the MIDI input elements in your code (LEDs, displays ...) listen to MIDI messages that are received on the input of serialmidi2.

It doesn't affect the other MIDI interfaces at all. If you don't need serialmidi2 to interact with the potentiometers and LEDs on the Teensy, you don't have to add that line.

This sends all messages received from the USB interface to serialmidi2.

This probably means that there's a mistake in your code and Control Surface throws a fatal error.
Try enabling debug mode: edit the following file to define DEBUG_OUT as Serial.

So it should look like this:

// #define DEBUG_OUT
#define DEBUG_OUT Serial

Then add this to the beginning of your setup:

void setup() {
  Serial.begin(115200);
  while (!Serial);
  // ...
}

I suspect you're trying to use the same pipe twice somewhere.

I have tested the physical connectors on my breadboard for both serialmidi & serialmidi2 and they work. The RX1 pin on the Teensy is the only one that actually receives the input from serialmidi. When I send the TX1 pin to serialmidi2 out, there's nothing even though I set the RX & TX pins for Serial2. Here's the code:

#include <Control_Surface.h>
 
// Create two MIDI interfaces
USBMIDI_Interface usbmidi;
HardwareSerialMIDI_Interface serialmidi {Serial1, MIDI_BAUD};
HardwareSerialMIDI_Interface serialmidi2 {Serial2, MIDI_BAUD};

// Create a MIDI pipe factory to connect the MIDI interfaces to Control Surface
BidirectionalMIDI_PipeFactory<2> pipes;

 
// Custom MIDI callback that prints incoming messages.
struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
  // Note how this ^ name is identical to the argument used here ^
 
  void onNoteOff(Channel channel, uint8_t note, uint8_t velocity, Cable cable) {
    Serial << "Note Off: " << channel << ", note " << note << ", velocity "
           << velocity << ", " << cable << endl;
  }
  void onNoteOn(Channel channel, uint8_t note, uint8_t velocity, Cable cable) {
    Serial << "Note On: " << channel << ", note " << note << ", velocity "
           << velocity << ", " << cable << endl;
  }
  void onKeyPressure(Channel channel, uint8_t note, uint8_t pressure,
                     Cable cable) {
    Serial << "Key Pressure: " << channel << ", note " << note << ", pressure "
           << pressure << ", " << cable << endl;
  }
  void onControlChange(Channel channel, uint8_t controller, uint8_t value,
                       Cable cable) {
    Serial << "Control Change: " << channel << ", controller " << controller
           << ", value " << value << ", " << cable << endl;
  }
  void onProgramChange(Channel channel, uint8_t program, Cable cable) {
    Serial << "Program Change: " << channel << ", program " << program << ", "
           << cable << endl;
  }
  void onChannelPressure(Channel channel, uint8_t pressure, Cable cable) {
    Serial << "Channel Pressure: " << channel << ", pressure " << pressure
           << ", " << cable << endl;
  }
  void onPitchBend(Channel channel, uint16_t bend, Cable cable) {
    Serial << "Pitch Bend: " << channel << ", bend " << bend << ", " << cable
           << endl;
  }
   
} callback;

// Add some MIDI elements to show that the MIDI interfaces actually work
CCPotentiometer pot {A17, MIDI_CC::General_Purpose_Controller_1};
CCPotentiometer pot1 {A16, {0x12, CHANNEL_1}};
NoteLED led {LED_BUILTIN, 0x3C};


MIDI_Pipe passthrough;
void setup() {
  Serial2.setRX(34);
  Serial2.setTX(35);
  Serial.begin(115200);        // For printing the messages
  // Manually connect the MIDI interfaces to Control Surface
  Control_Surface | pipes | usbmidi; // Main communication between T4.1 and USB
  serialmidi >> passthrough >> usbmidi;
  usbmidi | pipes | serialmidi2;
  
  usbmidi.setCallbacks(callback); // Attach the custom callback
  serialmidi.setCallbacks(callback); // Attach the custom callback
  serialmidi2.setCallbacks(callback); // Attach the custom callback
  
  // Initialize Control Surface _after_ connecting the interfaces
  Control_Surface.begin();
  }
 
void loop() {
  Control_Surface.loop();
    }
 

Does it work with the standard RX2 and TX2 pins? Do you see any data using Serial2.read()?

ok I got it working, the only thing now is that every Note On and Note Off shows up 3 times in the monitor. This is middle C:

Note On: Channel 1, note 60, velocity 65, Cable 1
Note On: Channel 1, note 60, velocity 64, Cable 1
Note On: Channel 1, note 60, velocity 64, Cable 1
Note On: Channel 1, note 60, velocity 0, Cable 1
Note On: Channel 1, note 60, velocity 0, Cable 1
Note On: Channel 1, note 60, velocity 0, Cable 1

My routing is probably circular somehow. And also, at boot up, the synth now sends multiple notes like a chord and the notes get stuck without sounding.

These are my interfaces:

// Create two MIDI interfaces
USBMIDI_Interface usbmidi; //
HardwareSerialMIDI_Interface serialmidi {Serial1, MIDI_BAUD};   // (RX1)MIDI in to T4.1 from KBD
HardwareSerialMIDI_Interface serialmidi2 {Serial2 , MIDI_BAUD}; // (RX2, TX2) MIDI in & out of my DAW

// Create a MIDI pipe factory to connect the MIDI interfaces to Control Surface
BidirectionalMIDI_PipeFactory<2> pipes;
MIDI_Pipe RX1; 

The I initialize them:

void setup() {
  Serial.begin(115200);        // For printing the messages
  // Manually connect the MIDI interfaces to Control Surface
  Control_Surface | pipes | usbmidi; // Main communication between T4.1 and USB
  serialmidi >> RX1 >> usbmidi;      // Keyboard controller MIDI in to T4.1
  serialmidi2 | pipes | usbmidi;     // MIDI In & Out between T4.1 & DAW
  
  usbmidi.setCallbacks(callback); // Attach the custom callback
  serialmidi.setCallbacks(callback); // Attach the custom callback
  serialmidi2.setCallbacks(callback); // Attach the custom callback
  
  // Initialize Control Surface _after_ connecting the interfaces
  Control_Surface.begin();
  }

Is there a MIDI loop somehow?

I've done some tests and the MIDI that comes into the RX2 (pin 7) on the Teensy from the DAW is working. But the TX2 (pin 8) is not getting the MIDI data out to the DAW when I play the keyboard. The only way is when I physically hook up the serialmidi MIDI connector IN to the serialmidi2 MIDI connector OUT, then it reaches the DAW. So the MIDI that comes in from the keyboard and the pots & buttons on the controller do not reach the DAW through the TX2 pin.

I thought that with this line serialmidi2 | pipes | usbmidi; that everything that comes in and out of the usbmidi (like the serialmidi IN or the pots and buttons) would be routed to serialmidi2?

Is this how this works?

If I do serialmidi >> RX1 >> usbmidi; then usbmidi >> RX2 >> serialmidi2; isn't the data from serialmidi going to serialmidi2 via the usbmidi interface?

You'll have to draw a diagram with the different endpoints (keyboard, DAW, pots & buttons, etc.) the different interfaces (USB MIDI, Serial1, Serial2) and arrows between them.

Because they're not connected in your code:

To get data from the keyboard (Serial1) to the DAW (Serial2), you need the following connection:

serialmidi1 >> pipe1 >> serialmidi2;

And to get the messages from the pots and buttons (Control Surface) to the DAW (Serial2), you need:

Control_Surface >> pipe2 >> serialmidi2;

No, everything that comes into usbmidi over USB is routed to serialmidi2 and is sent out of TX2, and everything that comes into serialmidi2 via RX2 is routed to usbmidi and sent out over USB.
That doesn't mean that whatever is going out of usbmidi is also routed to the other interfaces.

No, that's not the case.

Is this close to what you want to do?

If so, then all you have to do is make the colored connections:

HardwareSerialMIDI_Interface midiA { Serial1 };
HardwareSerialMIDI_Interface midiB { Serial2 };
USBMIDI_Interface midiC;

BidirectionalMIDI_Pipe red;
MIDI_Pipe yellow, green, blue;

void setup() {
  Control_Surface |  red    |  midiC;
  Control_Surface >> blue   >> midiB;
  midiA           >> green  >> midiC;
  midiA           >> yellow >> midiB;
  Control_Surface.begin();
}

Note that each MIDI interface consists of two separate halves: for example, the data that enters midiC through the green connection is sent to the synth, but it does not get transmitted over the red connections, there is no implicit connection between the left half and the right half of each of the rectangles in my drawing.

Yeah that's close. Here's the way everything is hooked up:

MIDI A is working, MIDI C is working, MIDI B RX2 from the DAW is working but I can't get data out MIDI TX2 to record in the DAW. The only way I found to record is physically connecting a wire from the MIDI A DIN connector to the MIDI B Out DIN connector and that only records what comes out of the keyboard. The main goal is to be able to record everything that comes from the keyboard & control surface so I can automate all the CC messages.

At first I was thinking that since the synth puts out everything from Notes to CC and SysEx, that I could record / capture what's coming out of the synth into the DAW. I kind of need this because there are a number of Sysex codes for patch dumps, etc...that are triggered by buttons on the control surface.

Since MIDI C is receiving everything that comes from the synth already, (I already use SysEx messages to control the LEDs and LCD) I was trying to connect MIDI C to MIDI B to go to the DAW instead of connecting MIDI A and Control Surface separately to MIDI B. This would work but would not include any SysEx. Hope this makes sense.

Control_Surface >> blue  >> midiB; 

doesn't work, nothing comes out of the TX pin no matter what I do. Nothing I send to the TX pins actually goes out, I tried several of the 8 Serial ports on the Teensy 4.1. Not sure what's going on, could the board be damaged?

Well I found the problem, I needed to choose "Serial + MIDIx4" as the USB type. All connections work perfectly. I have to say though, the pipe class in the Control Surface library is pretty amazing and simple once you understand it!

Thanks for your help!

Glad to hear you were able to get it working!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.