Teensy 4.0 midi Mackie MCU protocol

sachaV

Member
I'm trying to program a Teensy 4.0 to control my Sounddevices Scorpio.
The scorpio uses the Mackie MCU protocol to communicate with an external controller.

At the moment i am able to get play, pauze, stop, record working. What i want to achieve is to control the value of the faders on channels 1-12 with a potentiometer.
This is the code i have right now:

Code:
#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library if you want to use encoders
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate an array of NoteButton objects that send
// MIDI note events when a push button is pressed/released
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
};

// Instantiate a CCPotentiometer object
CCPotentiometer potentiometer {
  A0,                                   // Analog pin connected to potentiometer
  {MIDI_CC::Channel_Volume, CHANNEL_1}, // Channel volume of channel 1
};




void setup() {
  // Select the correct relative MIDI CC mode:
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

I'm very new to the use of arduino's/ teensy's and coding and i was hoping you could help me get my code working.
 
Not being familiar with the Mackie MCU protocol but a bit with MIDI in general, decided to look into this stuff.
On this page I found the mapping for the faders:

Capture.PNG

Then looked into the Doxygen documentation of the Control Surface library.
The PBPotentiometer Class is the class "that reads the analog input from a potentiometer or fader, and send out 14-bit MIDI Pitch Bend events".

The code example Pitch-Bend-Potentiometer.ino shows this:
Code:
// Instantiate a PBPotentiometer object
PBPotentiometer potentiometer {
  A0,        // Analog pin connected to potentiometer
  CHANNEL_1, // MIDI Channel 1
};

So please replace
Code:
// Instantiate a CCPotentiometer object
CCPotentiometer potentiometer {
  A0,                                   // Analog pin connected to potentiometer
  {MIDI_CC::Channel_Volume, CHANNEL_1}, // Channel volume of channel 1
};
by the code above and hopefully it works.

Paul

PS: that's a very nice Mixer-Recorder
 
Happy to hear that it is working!

Just curious on how this works with your Scorpio: do you need to set the Scorpio to some kind of "remote control mode" and then you're able to control the buttons and channel faders remotely by the appropriate MIDI commands? Are the physical buttons and channel faders on the Scorpio then still operational or are they disabled?

Paul
 
Happy to hear that it is working!

Just curious on how this works with your Scorpio: do you need to set the Scorpio to some kind of "remote control mode" and then you're able to control the buttons and channel faders remotely by the appropriate MIDI commands? Are the physical buttons and channel faders on the Scorpio then still operational or are they disabled?

Paul

Hi Paul,

You don't need to do anything on the Scorpio, it automatically recognises when a controller is connected.
The weird thing is that with the Teensy connected, the physical stay operational.
I also own a icon platform M+ with a custom firmware for the Scorpio.
When the Icon platform is connected the gain knobs and faders are disabled. I assume the firmware has a code to tell the scorpio to disable the faders and gain knobs.
 
Thanks for your reply.
When the Icon platform is connected the gain knobs and faders are disabled. I assume the firmware has a code to tell the scorpio to disable the faders and gain knobs.
Yes, that's also stated in Scorpio & Icon Platform M+ Operational Guide.
Code:
[I]Note: Once the Scorpio establishes connection with the Platform M+,
faders and trims 1-12 are disabled on the Scorpio[/I]

If you want this functionality on your Teensy, you may consider using MIDI-OX or a similar utility to monitor the MIDI data from the Icon M+ to the Scorpio at power-up.

Paul
 
Oh thank you!

This might be helpful.
I also want to test the ability to control gain(trim) and channel banks, i can only program the first 8 channels at the moment.
 
I also want to test the ability to control gain(trim) and channel banks, i can only program the first 8 channels at the moment.
I assume that when using the Icon M+, the "BANK <" & "BANK >" buttons switch 8 faders at a time?
Found 2 sources [here and here] that talk about bank switching over the Mackie MCU protocol. The latter source states :
Code:
namespace Bank {
  enum Note {
    // Move 8/16/32 channel strips. Up to three extension units, each adds 8
    // channel strips to a bank.
    Previous = 46,
    Next     = 47,

    // Move a single channel.
    PreviousChannel = 48,
    NextChannel     = 49,

    Flip = 50,
    Edit = 51,
  };

So went back digging through the Control Surface library again and it seems that bank/channel switching is supported.
So perhaps it is as easy as adding the red lines to your code?
Code:
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
[COLOR="#FF0000"]  { 9, MCU::BANK_LEFT },
  { 10, MCU::BANK_RIGHT },
  { 11, MCU::CHANNEL_LEFT },
  { 12, MCU::CHANNEL_RIGHT },[/COLOR]
};

Paul
 
To check, I hooked up a Teensy 4.0 and some buttons and potmeter to see whether it's working.
It seems to output the correct MIDI messages, see this MIDI-OX output:

MIDI-OX.png

Pressed the buttons on pin 4, 5, 6, 7, 8, 9, 10, 11 & 12 and then rotated the potmeter on pin A0.
Here is the code:
Code:
// https://github.com/tttapa/Control-Surface
// https://forum.pjrc.com/threads/72181-Teensy-4-0-midi-Mackie-MCU-protocol
#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library if you want to use encoders
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate an array of NoteButton objects that send
// MIDI note events when a push button is pressed/released
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
  { 9, MCU::BANK_LEFT },
  { 10, MCU::BANK_RIGHT },
  { 11, MCU::CHANNEL_LEFT },
  { 12, MCU::CHANNEL_RIGHT },
};

// Instantiate a PBPotentiometer object
PBPotentiometer potentiometer {
  A0,        // Analog pin connected to potentiometer
  CHANNEL_1, // MIDI Channel 1
};

void setup() {
  // Select the correct relative MIDI CC mode:
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

Paul
 
By the way, as an alternative to MIDI-OX, the webbrowser-based MIDI Monitor by StudioCode.dev works fine as well.

Paul

The bank switching code worked!

When i connect my icon platform M+ and turn the gain knob of channel 1, i get following readout on the MIDI monitor:
gain.jpg
Do you know how i could implement this in my code on the teensy to control the gain/trim of my channels?
 
Hi Sacha,

Do you know how i could implement this in my code on the teensy to control the gain/trim of my channels?
You need the CCRotaryEncoder class to realize that feature.

Here is the updated code:
Code:
// https://github.com/tttapa/Control-Surface
// https://forum.pjrc.com/threads/72181-Teensy-4-0-midi-Mackie-MCU-protocol
#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library if you want to use encoders
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate an array of NoteButton objects that send
// MIDI note events when a push button is pressed/released
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
  { 9, MCU::BANK_LEFT },
  { 10, MCU::BANK_RIGHT },
  { 11, MCU::CHANNEL_LEFT },
  { 12, MCU::CHANNEL_RIGHT },
};

// Instantiate a PBPotentiometer object
PBPotentiometer potentiometer {
  A0,        // Analog pin connected to potentiometer
  CHANNEL_1, // MIDI Channel 1
};

[COLOR="#FF0000"]// Instantiate a CCRotaryEncoder object
CCRotaryEncoder enc {
  {2, 3},       // pins
  MCU::V_POT_1, // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};[/COLOR]

void setup() {
  // Select the correct relative MIDI CC mode:
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

When connecting a rotary encoder to pins 2 & 3, you will see this on the MIDI monitor:

MIDImonitor.png
3 clicks left, 3 clicks right.

If you have a spare Scorpio laying around gathering dust, feel free to ship it to me for more testing...:cool:

Paul

PS: kudos to PieterP for coding this great library!
 
Thx Paul,

I’ve ordered several rotary encoders.
Will test asap.
Unfortunately i only have 1 Scorpio. Cost me a kidney ;)
 
Hi Sacha,


You need the CCRotaryEncoder class to realize that feature.

Here is the updated code:
Code:
// https://github.com/tttapa/Control-Surface
// https://forum.pjrc.com/threads/72181-Teensy-4-0-midi-Mackie-MCU-protocol
#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library if you want to use encoders
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate an array of NoteButton objects that send
// MIDI note events when a push button is pressed/released
NoteButton buttons[] {
  { 4, MCU::PLAY },  // Push button on pin 4, “play” control
  { 5, MCU::STOP },
  { 6, MCU::RECORD },
  { 7, MCU::REWIND },
  { 8, MCU::FAST_FWD },
  { 9, MCU::BANK_LEFT },
  { 10, MCU::BANK_RIGHT },
  { 11, MCU::CHANNEL_LEFT },
  { 12, MCU::CHANNEL_RIGHT },
};

// Instantiate a PBPotentiometer object
PBPotentiometer potentiometer {
  A0,        // Analog pin connected to potentiometer
  CHANNEL_1, // MIDI Channel 1
};

[COLOR="#FF0000"]// Instantiate a CCRotaryEncoder object
CCRotaryEncoder enc {
  {2, 3},       // pins
  MCU::V_POT_1, // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};[/COLOR]

void setup() {
  // Select the correct relative MIDI CC mode:
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

When connecting a rotary encoder to pins 2 & 3, you will see this on the MIDI monitor:

View attachment 30438
3 clicks left, 3 clicks right.

If you have a spare Scorpio laying around gathering dust, feel free to ship it to me for more testing...:cool:

Paul

PS: kudos to PieterP for coding this great library!

Got it all working!

Thank you for all your help!
 
Great!
Did you perhaps have a change to monitor the output of your Icon with respect to the command that disables the Scorpio controls when connected?
There seems to be a MIDI Controller message ["CC"] 0x78 that sets "Local control On/Off". Perhaps that's the message the Icon sends out when connected to the Scorpio.

Paul
 
I've tried to see if there are any messages the icon is sending on startup. But it takes a while for my pc te recognise the icon. The webbrowser midi monitor doesn't show any activity when it's detecting the icon. My guess is that it's sending the code as soon as the connection is established and therefore the midi monitor is too late to monitor the initial messages.
 
I'm not surprised that the monitor misses one or more initial messages when the USB cable is plugged in. Perhaps MIDI-OX is faster, I will try that some time this weekend.

Paul
 
Perhaps MIDI-OX is faster
No, it's not. MIDI-OX does not support hot-plugging of MIDI devices - you have to manually open the MIDI input after insertion of the USB cable.

Then I tried to measure the time it takes for the browser-based MIDI-monitor to see an inserted Teensy MIDI device and start displaying MIDI messages. This is the code running on the Teensy:
Code:
#include <MIDI.h>

void setup() {
  delay(15);
  usbMIDI.sendControlChange(1, 1, 1); // CC#, value, channel
}

void loop() {
}

By experimenting with the delay() value above, it turned out that you need to delay for ~15ms or more for the MIDI message to show up in the tool.

Thinking further, it's not necessarily the Icon which sends out a MIDI message to disable the Scorpio controls - it might as well be that the Scorpio just recognizes the Icon M+ and subsequently disables its controls.

Did you perhaps try the CC 0x78 "Local control On/Off" message whether that has any effect? Something like usbMIDI.sendControlChange(0x78, 0x7F, 1); to set Local control ON.

Paul
 
Hi Guys, i'm trying to build something very similar. (Controlling the Faders and Trim on channels 7 & 8 on an 833)

For simplicity for the user I want to use Encoders that can switch function between Fader and Trim

The problem i'm having is that CHANNEL_# is only working using PBPotentiometer and i can't seem to find a way to use CCRotaryEncoder

Do you guys have any idea on how i could fix this?

-Maikel
 
The problem i'm having is that CHANNEL_# is only working using PBPotentiometer and i can't seem to find a way to use CCRotaryEncoder
Do you guys have any idea on how i could fix this?
Isn't it as easy as adding a channel number like this:
C++:
// Instantiate a CCRotaryEncoder object
CCRotaryEncoder enc {
  {2, 3},       // pins
  // MCU::V_POT_1, // MIDI address (CC number + optional channel)
  MCU::V_POT_1, CHANNEL_1 // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};

I see a similar approach on this page.
Otherwise you can post a question on this page or @PieterP, writer of the library and member on this forum.

Paul
 
Back
Top