Arduino Pro Micro Midi HUI MCU Device

Hey there.

I am trying to make a simple script to read record and stop status from a device that uses MCU Mackie HUI control.

I can get it to see MCU::RECORD and MCU::STOP, so I can trigger it. But I can not figure out how to see the status changes to trigger events.

Currently just trying to fire LED to show status. I've searched the forums here and found multiple approaches but none of them seem to work for me.

One Attempt:

#include <MIDI.h>

int ExpressionContr1 = 1;
int ExpressionContr2 = (0xC << 7) | 0x2C ;
int ExpressionContr3 = (0xE<< 7) | 0x45 ;
int ExpressionContr4 = (0xE<<7) | 0x5;
int controlRecieved;
byte ccMessage12Value;
byte ccMessage44Value;
boolean ledState;

//MIDI_CREATE_DEFAULT_INSTANCE();
MIDI_CREATE_INSTANCE(decltype(Serial), Serial,  MIDI);

void setup(){
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
digitalWrite(10, HIGH);
MIDI.begin();
MIDI.setHandleControlChange(MyCC);
}

void loop() {
MIDI.read();
}

void MyCC( byte channel, byte controller, byte value ) {
 // build up your full message
  if(controller == 44){
  ccMessage44Value = value;
  ccMessage12Value = 0; // blank MSB of message to stop rapid on / off of LEDs
 }

 if(controller == 12){
  ccMessage12Value = value;

// now put them together into one variable
controlRecieved = (ccMessage12Value << 7) | ( ccMessage44Value & 0x7F);
// now see if you have anything of intrest
// here you seem to test the same thing to turn it on or off so you need a variable to hold the state you last put the LED
if( (ledState == false) && (controlRecieved == ExpressionContr1 || controlRecieved == ExpressionContr2 ||controlRecieved == ExpressionContr3) ){
      digitalWrite(9,HIGH);
      digitalWrite(10, LOW);
      ledState = true;
    } else {
if( (ledState == true) && (controlRecieved == ExpressionContr1 || controlRecieved == ExpressionContr2 ||controlRecieved == ExpressionContr4) ){
      digitalWrite(9,LOW);
      digitalWrite(10, HIGH);
      ledState = false;
     }
    }
  }
}

Another Attempt:

#include <Control_Surface.h>

const auto record_led_pin = 9;
const auto stop_led_pin = 10;


// The MIDI over USB interface to use
USBMIDI_Interface midi;

// Custom MIDI callback that keeps track of the selected HUI zone.
struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
  static constexpr uint8_t zone_select_command = 0x0C; // Taken from HUI.pdf (https://forum.cockos.com/showthread.php?t=101328)
  static constexpr uint8_t switch_port_command = 0x2C;
  static constexpr uint8_t record_zone = 0x0e;
  static constexpr uint8_t record_port = 5;
  uint8_t zone = 0xFF;

  // Function that is called whenever a MIDI Control Change message is received.
  void onControlChange(Channel channel, uint8_t controller, uint8_t value, Cable) {
    if (channel != Channel_1)
      return;
    if (controller == zone_select_command) {
      zone = value;
    } else if (controller == switch_port_command) {
      uint8_t port = value & 0x0F;
      bool led_state = value & 0x40;
      if (zone == record_zone && port == record_port)
        digitalWrite(record_led_pin, led_state ? HIGH : LOW);
        digitalWrite(stop_led_pin, led_state ? HIGH : LOW);
    }
  }

} callback;

void setup() {
  pinMode(record_led_pin, OUTPUT);
  pinMode(stop_led_pin, OUTPUT);
  digitalWrite(stop_led_pin, HIGH);
  midi.begin();                // Initialize the MIDI interface
  midi.setCallbacks(callback); // Attach the custom callback
}

void loop() {
  midi.update(); // Continuously handle MIDI input
}

I took the above script and added it sending commands, and it is connecting and triggering.

#include <Control_Surface.h>

const auto record_led_pin = 9;
const auto stop_led_pin = 10;
int looper = 0;

// The MIDI over USB interface to use
USBMIDI_Interface midi;
constexpr uint8_t MCU_RECORD_NOTE = 0x5F; 
const int MCU_STOP_NOTE = MCU::STOP;

// Custom MIDI callback that keeps track of the selected HUI zone.
struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
  static constexpr uint8_t zone_select_command = 0x0C; // Taken from HUI.pdf (https://forum.cockos.com/showthread.php?t=101328)
  static constexpr uint8_t switch_port_command = 0x2C;
  static constexpr uint8_t record_zone = 0x0e;
  static constexpr uint8_t record_port = 5;
  uint8_t zone = 0xFF;

  // Function that is called whenever a MIDI Control Change message is received.
  void onControlChange(Channel channel, uint8_t controller, uint8_t value, Cable) {
    if (channel != Channel_1)
      return;
    if (controller == zone_select_command) {
      zone = value;
    } else if (controller == switch_port_command) {
      uint8_t port = value & 0x0F;
      bool led_state = value & 0x40;
      if (zone == record_zone && port == record_port)
        digitalWrite(record_led_pin, led_state ? HIGH : LOW);
    }
  }

} callback;

void setup() {
  pinMode(record_led_pin, OUTPUT);
  pinMode(stop_led_pin, OUTPUT);

  digitalWrite(stop_led_pin, HIGH); // Indicate that the system is ready
  midi.begin();                // Initialize the MIDI interface
  midi.setCallbacks(callback); // Attach the custom callback
  
}

void loop() {
  midi.update(); // Continuously handle MIDI input
  if (looper < 5){
    midi.update(); // Continuously handle MIDI input
    midi.sendNoteOn(MCU_RECORD_NOTE, 127);  // SEND RECORD ON
    delay(500);
    midi.sendNoteOff(MCU_RECORD_NOTE, 0);  // RELEASE RECORD
    delay(8000);
    midi.update(); // Continuously handle MIDI input
    midi.sendNoteOn(MCU_STOP_NOTE, 127);  // SEND RECORD ON
    delay(1500);
    midi.sendNoteOff(MCU_STOP_NOTE, 0);  // RELEASE RECORD
    delay(1000);
    looper = looper + 1;
  }

  
}

Any suggestions on what I am doing wrong?

You'll have to add some Serial.print statements in the onControlChange function. Does the device actually send anything back when the recording status changes?

I haven’t added any serial because I don’t have the ability to monitor the serial console, atleast I haven’t figured out a way.

The device is a standalone recording machine that excepts HUI MCU control. I have connected it to a hui machine and it does display the record light on that machine.

This machine just had a USB A input only. It is possible to use one Arduino like a serial middle man? Or can I save logs to EEProm and offload them after?

I tried connecting the Arduino running the 2nd example above with a protools rig and it does work. Although I get this error:

Despite the error the red LED light does come on and off going in and out of record.

Is there something I need to add to the code to appear like an active HUI?

It does seem like I will need to figure out a way to sniff out what the recording device is sending, if anything.

So I took a stab at storing the data in the EEPROM, and its not storing anything. Interesting experiment. I am not sure if I am doing something wrong or this machine does not respond with anything.

#include <Control_Surface.h>
#include <EEPROM.h>

const auto record_led_pin = 9;
const auto stop_led_pin = 10;

const int EEPROM_SIZE = 1024;
const int MIDI_DATA_SIZE = 2;
int writeAddress = 0;
const int DATA_MARKER_ADDRESS = EEPROM_SIZE - 1;
const uint8_t DATA_MARKER = 0xAB; // Arbitrary marker value indicating data has been logged
byte doOnce = 0;

USBMIDI_Interface midi;

constexpr uint8_t MCU_RECORD_NOTE = 0x5F;

struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
  static constexpr uint8_t record_note = MCU_RECORD_NOTE;

  void onNoteOn(Channel channel, uint8_t note, uint8_t velocity, Cable) {
    if (note == record_note && channel == Channel_1) {
      digitalWrite(record_led_pin, HIGH);
      logToEEPROM(note, velocity);
    }
  }

  void onNoteOff(Channel channel, uint8_t note, uint8_t velocity, Cable) {
    if (note == record_note && channel == Channel_1) {
      digitalWrite(record_led_pin, LOW);
    }
  }

  void logToEEPROM(uint8_t note, uint8_t velocity) {
    if (writeAddress < EEPROM_SIZE - MIDI_DATA_SIZE - 1) { // Leave space for marker
      EEPROM.write(writeAddress, note);
      EEPROM.write(writeAddress + 1, velocity);
      writeAddress += MIDI_DATA_SIZE;
      EEPROM.write(DATA_MARKER_ADDRESS, DATA_MARKER); // Set marker to indicate data is present
    }
  }
};

MyMIDI_Callbacks callback;

void setup() {
  pinMode(record_led_pin, OUTPUT);
  pinMode(stop_led_pin, OUTPUT);
  digitalWrite(stop_led_pin, HIGH);

  midi.begin();
  midi.setCallbacks(callback);
  Serial.begin(115200);
  unsigned long startTime = millis();
  while (!Serial && millis() - startTime < 3000);  // Wait until Serial is active
  Serial.println("");
  Serial.println("--------------INITILIZED-----------------");
  Serial.println("");
  midi.sendSystemReset();
  
}

void loop() {
  midi.update();
  if (millis() > 20000 && doOnce == 0) {
    midi.sendNoteOn(MCU_RECORD_NOTE, 127);  // SEND RECORD ON
    delay(500);
    midi.sendNoteOff(MCU_RECORD_NOTE, 0);  // RELEASE RECORD
    doOnce = 1;
  }
  if (Serial && EEPROM.read(DATA_MARKER_ADDRESS) == DATA_MARKER) {
    Serial.println("Dumping MIDI data from EEPROM:");
    for (int i = 0; i < writeAddress; i += MIDI_DATA_SIZE) {
      uint8_t note = EEPROM.read(i);
      uint8_t velocity = EEPROM.read(i + 1);
      Serial.print("Note: ");
      Serial.print(note);
      Serial.print(", Velocity: ");
      Serial.println(velocity);
    }

    Serial.println("Clearing EEPROM...");
    for (int i = 0; i < EEPROM_SIZE - 1; i++) { // Clear data area
      EEPROM.write(i, 0);
    }
    EEPROM.write(DATA_MARKER_ADDRESS, 0); // Reset marker
    writeAddress = 0;
    Serial.println("EEPROM cleared.");
  } else if (Serial) {
    if (millis() > 2000 && millis() < 2100) {
      Serial.println("EEPROM is empty");
    }
  }
}

You'll see I trigger one record event 20 seconds after start and that does work as expected.

EDIT:

This doesn't record anything from protools either, so I guess I am doing it wrong.

This works with my protools but not with my HUI device to provide logging over EEPROM.

I guess I might assume that the device is mute and doesn't send responses, but it does connect to several off the shelf interfaces and show record and stop status.

#include <Control_Surface.h>
#include <EEPROM.h>

const auto record_led_pin = 9;
const auto stop_led_pin = 10;

const int EEPROM_SIZE = 1024;
const int MIDI_DATA_SIZE = 2;
int writeAddress = 0;
const int DATA_MARKER_ADDRESS = EEPROM_SIZE - 1;
const uint8_t DATA_MARKER = 0xAB; // Arbitrary marker indicating data has been logged

USBMIDI_Interface midi;

struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
  static constexpr uint8_t zone_select_command = 0x0C;
  static constexpr uint8_t switch_port_command = 0x2C;
  static constexpr uint8_t record_zone = 0x0e;
  static constexpr uint8_t record_port = 5;
  uint8_t zone = 0xFF;

  void onControlChange(Channel channel, uint8_t controller, uint8_t value, Cable) {
    Serial.print("Controller: ");
    Serial.print(controller);
    Serial.print(", Value: ");
    Serial.println(value);

    if (channel != Channel_1)
      return;

    if (controller == zone_select_command) {
      zone = value;
    } else if (controller == switch_port_command) {
      uint8_t port = value & 0x0F;
      bool led_state = value & 0x40;
      if (zone == record_zone && port == record_port) {
        digitalWrite(record_led_pin, led_state ? HIGH : LOW);
        logToEEPROM(controller, value); // Log the controller and value to EEPROM
      }
      digitalWrite(stop_led_pin, led_state ? HIGH : LOW);
    }
  }

  // Function to log MIDI data to EEPROM
  void logToEEPROM(uint8_t controller, uint8_t value) {
    if (writeAddress < EEPROM_SIZE - MIDI_DATA_SIZE - 1) { // Leave space for marker
      EEPROM.write(writeAddress, controller);
      EEPROM.write(writeAddress + 1, value);
      writeAddress += MIDI_DATA_SIZE;
      EEPROM.write(DATA_MARKER_ADDRESS, DATA_MARKER); // Set marker to indicate data is present
    }
  }
};

MyMIDI_Callbacks callback;

void setup() {
  pinMode(record_led_pin, OUTPUT);
  pinMode(stop_led_pin, OUTPUT);
  digitalWrite(stop_led_pin, HIGH); // Indicate that the system is ready

  midi.begin();                 // Initialize the MIDI interface
  midi.setCallbacks(callback);  // Attach the custom callback
  Serial.begin(115200);         // Initialize Serial communication

  unsigned long startTime = millis();
  while (!Serial && millis() - startTime < 3000);  // Wait until Serial is active
  Serial.println("");
  Serial.println("--------------INITILIZED-----------------");
  Serial.println("");
}

void loop() {
  midi.update();

  // Check if Serial is connected and data exists in EEPROM before dumping
  if (Serial && EEPROM.read(DATA_MARKER_ADDRESS) == DATA_MARKER) {
    Serial.println("Dumping MIDI data from EEPROM:");
    for (int i = 0; i < writeAddress; i += MIDI_DATA_SIZE) {
      uint8_t controller = EEPROM.read(i);
      uint8_t value = EEPROM.read(i + 1);
      Serial.print("Controller: ");
      Serial.print(controller);
      Serial.print(", Value: ");
      Serial.println(value);
    }

    // Clear EEPROM and reset writeAddress
    Serial.println("Clearing EEPROM...");
    for (int i = 0; i < EEPROM_SIZE - 1; i++) { // Clear data area
      EEPROM.write(i, 0);
    }
    EEPROM.write(DATA_MARKER_ADDRESS, 0); // Reset marker
    writeAddress = 0;
    Serial.println("EEPROM cleared.");
  } else if (Serial) {
    if (millis() > 2000 && millis() < 2100) {
      Serial.println("EEPROM is empty");
    }
  }
}

Yes, you can find multiple threads discussing this online.

You'll probably have to respond to the pings you receive. See HUI.pdf from I FREAKIN FOUND THE HUI DOCS!!!!! - Cockos Incorporated Forums.

So I found that you've already created a sketch to interpret data.
https://tttapa.github.io/Control-Surface/Doxygen/d3/d85/Mackie-Control-Universal-Reverse-Engineering_8ino-example.html

This sees my DAW, so thats good.

I combined it with this: Control Surface: USBHostMIDI_Interface-Passthrough.ino

And the two together do finally allow me to use the Teensy in-between the devices and they connect! Promising, I still dont see which direction the serial output is coming from, or how to make this output to sofware serial, but I will keep trying. If you have any suggestions to move me along I appreciate it!

#include <Control_Surface.h>
#include <MIDI_Interfaces/USBHostMIDI_Interface.hpp>
 
USBHost usb;
USBHub hub {usb};
 
USBMIDI_Interface devicemidi;
USBHostMIDI_Interface hostmidi {usb};
USBDebugMIDI_Output devicedebug {"(dev) "}, hostdebug {"(host)"};
 
BidirectionalMIDI_Pipe p;
MIDI_Pipe debugpipes[2];
 
void setup() {
  delay(1500); 
  hostmidi | p | devicemidi;
  devicemidi >> debugpipes[0] >> devicedebug;
  hostmidi >> debugpipes[1] >> hostdebug;
  usb.begin();
  MIDI_Interface::beginAll();
  MIDIOutputOnly::beginAll();
}
 
void loop() {
  MIDI_Interface::updateAll();
}

Why Software Serial? The Teensy has plenty of hardware serial ports. You can use HardwareSerialDebugMIDI_Output instead of USBDebugMIDI_Output.

*So that version is far more verbose thank you. It doesn't work unless I initiate the connection with the version I made by cobbling your two examples together. *
Then I can flash the Teensy with this version and it works with Protools.
UPDATE: It works its just a bit finicky for me... but I can get it to pass through on the Protools in HUI mode

#include <Control_Surface.h>
#include <MIDI_Interfaces/USBHostMIDI_Interface.hpp>
#include <SoftwareSerial.h>

#define TX 14
#define RX 15

SoftwareSerial SoftSerial(RX, TX);
 
// Create the ports for USB devices plugged into Teensy's 2nd USB port (via hubs)
USBHost usb;
USBHub hub {usb};
 
// USB Device MIDI (primary USB port)
USBMIDI_Interface devicemidi;
// USB Host MIDI (second USB port)
USBHostMIDI_Interface hostmidi {usb};
// Alternatively, use `USBHostMIDI_Interface_BigBuffer'
//USBHostMIDI_Interface_BigBuffer hostmidi {usb};
 
// Pipe to route MIDI data between two USB ports
BidirectionalMIDI_Pipe p;
 
bool channelMessageCallback(ChannelMessage cm) {
  MIDIMessageType type = cm.getMessageType();
  if (type == MIDIMessageType::NoteOn || type == MIDIMessageType::NoteOff) {
    Serial << hex << cm.header << ' ' << cm.data1 << ' ' << cm.data2 << dec
           << "\t(" << MCU::getMCUNameFromNoteNumber(cm.data1) << ")"
           << F(" on cable ") << cm.cable.getOneBased() << endl;
  } else {
    Serial << hex << cm.header << ' ' << cm.data1 << ' ' << cm.data2 << dec
           << F(" on cable ") << cm.cable.getOneBased() << endl;
  }
  return false; // Return true to indicate that handling is done,
                // and Control_Surface shouldn't handle it anymore.
                // If you want Control_Surface to handle it as well,
                // return false.
}
 
bool sysExMessageCallback(SysExMessage se) {
  Serial << F("System Exclusive message: [") << se.length << "] " //
         << AH::HexDump(se.data, se.length)                       //
         << F(" on cable ") << se.cable.getOneBased() << endl;
  return false; // Return true to indicate that handling is done,
                // and Control_Surface shouldn't handle it anymore.
                // If you want Control_Surface to handle it as well,
                // return false.
}
 
bool sysCommonMessageCallback(SysCommonMessage sc) {
  Serial << F("System Common message: ") << hex << sc.getMessageType();
  if (sc.getNumberOfDataBytes() >= 1)
    Serial << sc.getData1();
  if (sc.getNumberOfDataBytes() >= 2)
    Serial << sc.getData2();
  Serial << dec << F(" on cable ") << sc.cable.getOneBased() << endl;
  return false; // Return true to indicate that handling is done,
                // and Control_Surface shouldn't handle it anymore.
                // If you want Control_Surface to handle it as well,
                // return false.
}
 
bool realTimeMessageCallback(RealTimeMessage rt) {
  Serial << F("Real-Time: ") << hex << rt.message << dec << F(" on cable ")
         << rt.cable.getOneBased() << endl;
  return false; // Return true to indicate that handling is done,
                // and Control_Surface shouldn't handle it anymore.
                // If you want Control_Surface to handle it as well,
                // return false.
}
 
void setup() {

  delay(1500);
  hostmidi | p | devicemidi; // Connect the interfaces using a MIDI pipe
  usb.begin();               // Initialize the USB Host
  hostmidi.begin();          // Initialize the MIDI interfaces
  devicemidi.begin();

  
  // Make sure that the Serial interface is fast enough, so it doesn't stall the
  // MIDI application
  Serial.begin(1000000);
  SoftSerial.begin(115200);
  Control_Surface.begin();
  Control_Surface.setMIDIInputCallbacks(channelMessageCallback,   //
                                        sysExMessageCallback,     //
                                        sysCommonMessageCallback, //
                                        realTimeMessageCallback); //
}
 
void loop() {
  Control_Surface.loop();
  hostmidi.update();
  devicemidi.update();
}


The reason I was thinking SoftwareSerial is probably for completely novice reasons, its the only way I've successfully send data between two devices for logging, so I am more familiar, but if you say I can use regular serial I can try to figure that out instead.

The end goal of seeing the handshake between this control surface and my portable recorder is still elusive, when I use either of these sketches, the control surface says failed to connect and tells me to power cycle, that information is being displayed from the portable recorder though so there is some success. Some of the faders work in that state. Record and Stop button also work in that state, but I don't get any feedback.

This controller is the Waves FIT ... in protools it has two 8 channel banks, and works in HUI mode, when connected to the recorder, it put into MCU mode.

How do I forward the USBDebugMIDI_Output out that is going to Serial to also go to Serial1?

It seems the serial output is part of the USBDebugMidi_Output, I can not figure out how to re-route it or mirror it to Serial1

HardwareSerialDebugMIDI_Output devicedebug {Serial1, 115'200, "(dev) "},
                               hostdebug {Serial1, 115'200, "(host)"};

Thanks! That works. So connected to my Protools I get midi data. So it works...

But connected to my recording device I get this:

08:32:11.218 -> �������������������������������������������������������������������������������������������������������������΀����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ύ�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ύ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ό���������������������������������������������������������������������������������������������������������������������������������������������������������Ό���Ό����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������s������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
:��Wbs^._�K*፱�ٕͥ�[7]	F0 00 00 66 1u��s����x��a�g���~e [7]	F0 00 00 66 141����o�������(dev)  S���������w������������������������������������������ S�2��� 20 20 20 20 20 20 20 20 20 20 20 2������w���������������������7�Ӟ����
08:32:21.811 -> �j�67 2E 2E 2E 20 20 20 20 20 20 20 �w�����s����������������������N�S��{!6M���20 50 6C 65 61 73 65 20 50 6F 77 6������w������������������w!200�ɂ��B��Ɂ 20 20 20 20 20 20 20 20 20 �������������������������������������΍�~r����.JData 2: 0x41

08:32:41.143 -> (ho�t) �ˋ��o!l��gg`bc�����

Are these unrecognized characters?

This looks like either a hardware or a baud rate issue. What device do you have connected to the Serial1 port of the Teensy? How is it connected? If it's an Arduino, what's the code running on it?

I am connecting a Arduino Micro to the Teensy. I am using the stock RX TX pins 0 and 1.

The Code on the Arduino Micro:


void setup() {
  Serial.begin(115200);       // Serial connection to the computer
  delay (5000);
  Serial.println();
  Serial.println("Hello World");
  Serial1.begin(115200); // Serial1 for receiving
}

void loop() {
  
  if (Serial1.available()) {
    Serial.write(Serial1.read());
  }

}

When connected to my Protools as a HUI the controller communicates and I get this from the Micro Serial output:


Hello World
(host) Control Change   Channel: 1	Data 1: 0x10	Data 2: 0x41
(host) Control Change   Channel: 1	Data 1: 0x15	Data 2: 0x41
(dev)  System Exclusive [2]	F0 F7
(dev)  Note On          Channel: 1	Data 1: 0x00	Data 2: 0x00

Then when I connect the controller to the target device I get this stuff:

���em Exclusive [7]	F0 00 00 66 14 00 F7
(֗���?������Q��usive [7]	F0 00 00 66 14 00 F7
(dev)  Syst�m�Ex�][�ٕ�u�%F0 00 00 66 14 00 F7
(dev)  System E^.��z��������W˕�[7]	F0 00 00 66 14 00 F7
(dev)  Sys��m Gx��}sicclus�ve [120]	F0 00 00 66 14 12 00 53 6F 75 6EH���`6� ���'��;�����������������������������8�?���0���啁[120]	F0 00 00 66 14 12 00 43 6F 6E 6E 65 67����� &򘒂�������������������������8 20��8 ����0����H�S�g����������2�
(dev)  System Excl�sZ���B��L����������2�
(dev)  System Exclusive �S	F���0 \���Q���W˕�[7]	F0 00 00 66 14 00 F7
(dev)  S�.WV E���u�v%�����?W��]	F0 00 00 66 14 00 F7
(dev)  Sys|m� ~���>�usi� [7]	F0 00 00 66 14 00 F7

Did you connect the grounds? How are you shifting the voltage levels? The Arduino Micro is a 5V device: connecting its TX pin directly to the Teensy will damage it, and the 3.3V TX signal from the Teensy may not be strong enough for the Micro to receive it without errors, especially at high baud rates.

Added the ground, and removed the Rx into the Teensy. I didnt realize I could be damaging the Teensy, but it seems to be still working as normal doing other operations.

Those changes did allow me to get some readable data from the serial communications

(dev)  System Exclusive [7]	F0 00 00 66 14 00 F7
(dev)  System Exclusive [7]	F0 00 00 66 15 00 F7
(dev)  System Exclusive [7]	F0 00 00 66 14 00 F7
(dev)  System Exclusive [7]	F0 00 00 66 15 00 F7
(dev)  System Exclusive [7]	F0 00 00 66 14 00 F7
(dev)  System Exclusive [7]	F0 00 00 66 15 00 F7
(dev)  System Exclusive [120]	F0 00 00 66 14 12 00 53 6F 75 6E 64 20 44 65 76 69 63 65 73 20 53 63 6F 72 70 69 6F 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 43 6F 6E 6E 65 63 74 69 6E 67 2E 2E 2E 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 F7
(dev)  System Exclusive [120]	F0 00 00 66 14 12 00 43 6F 6E 6E 65 63 74 20 46 61 69 6C 65 64 20 50 6C 65 61 73 65 20 50 6F 77 65 72 20 20 43 79 63 6C 65 20 43 6F 6E 74 72 6F 6C 20 53 75 72 66 61 63 65 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 F7

The System Exclusive [120] correspond with the display, first line is when it says Connecting, and the second line it says connection failed and to power cycle.

So it seems like the pipe on the Teensy is blocking the handshake from happening, it does work with the HUI on protools.

Have you tried reducing the delay in the setup?

If I reduce or remove the delay I have same effect. I see serial output so its getting past the setup portion before it fails. If I connect the control surface directly to the recorder, it will pretty quickly re-init without power cycling. If I then put the Teensy back in the middle it will allow me some control... faders 9-16 work but incorrectly control 1-8, and 1-8 do nothing. Record, Stop, and Play work but the LED status lights do not.