usb-host and hub question

Status
Not open for further replies.

lokki

Well-known member
hi there, for testing i adapted the 16x16 midi example to send a simple note-on and note-off to my usb clients.
this works as it is below, BUT i cannot choose on which ports the midi messages arrive. if i put anything else then a [0] in this part
Code:
midilist[0]->sendNoteOn(data1, data2, channel);
(to access the other ports) there are no midi messages sent to any port. if i set it to 0 the midi data is sent to all 7 ports of my hub. do i need to change this part?
Code:
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
MIDIDevice midi01(myusb);
MIDIDevice midi02(myusb);
MIDIDevice midi03(myusb);
MIDIDevice midi04(myusb);
MIDIDevice midi05(myusb);
MIDIDevice midi06(myusb);
MIDIDevice midi07(myusb);
MIDIDevice * midilist[07] = {
  &midi01, &midi02, &midi03, &midi04, &midi05, &midi06, &midi07
};

Full Code (the delay() will of course not stay in the final program, it's just for testing now)
Code:
/* Create a "class compliant " USB to 6 MIDI IN and 6 MIDI OUT interface,
   plus 10 more USB connected devices.  Admittedly, you could just plug
   those 10 devices directly into your computer, but this example is meant
   to show how to forward any MIDI message between the 3 different MIDI
   libraries.  A "real" application might do something more interesting,
   like translate or modify the MIDI messages....

   MIDI receive (6N138 optocoupler) input circuit and series resistor
   outputs need to be connected to Serial1-Serial6.  A USB host cable
   is needed on Teensy 3.6's second USB port, and obviously USB hubs
   are needed to connect up to 10 USB MIDI devices.  That's a *LOT* of
   extra hardware to connect to a Teensy!

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

   This example code is in the public domain.
*/

#include <MIDI.h>        // access to serial (5 pin DIN) MIDI
#include <USBHost_t36.h> // access to USB MIDI devices (plugged into 2nd USB port)

// Create the Serial MIDI ports
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI2);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, MIDI3);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI4);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial5, MIDI5);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial6, MIDI6);
//midi::MidiInterface &SerialMidiList[6] = {MIDI1, MIDI2, MIDI3, MIDI4, MIDI5, MIDI6};

// Create the ports for USB devices plugged into Teensy's 2nd USB port (via hubs)
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHub hub3(myusb);
USBHub hub4(myusb);
MIDIDevice midi01(myusb);
MIDIDevice midi02(myusb);
MIDIDevice midi03(myusb);
MIDIDevice midi04(myusb);
MIDIDevice midi05(myusb);
MIDIDevice midi06(myusb);
MIDIDevice midi07(myusb);
MIDIDevice * midilist[07] = {
  &midi01, &midi02, &midi03, &midi04, &midi05, &midi06, &midi07
};

// A variable to know how long the LED has been turned on
elapsedMillis ledOnMillis;


void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT); // LED pin
  digitalWrite(13, LOW);
  MIDI1.begin(MIDI_CHANNEL_OMNI);
  MIDI2.begin(MIDI_CHANNEL_OMNI);
  MIDI3.begin(MIDI_CHANNEL_OMNI);
  MIDI4.begin(MIDI_CHANNEL_OMNI);
  MIDI5.begin(MIDI_CHANNEL_OMNI);
  MIDI6.begin(MIDI_CHANNEL_OMNI);
  // Wait 1.5 seconds before turning on USB Host.  If connected USB devices
  // use too much power, Teensy at least completes USB enumeration, which
  // makes isolating the power issue easier.
  delay(1500);
  Serial.println("Interface_16x16 Example");
  delay(10);
  myusb.begin();
}


void loop() {
  bool activity = false;
      uint8_t type =       0x90;
      uint8_t data1 =      60;
      uint8_t data2 =      100;
      uint8_t channel =    1;
      
      
midilist[0]->sendNoteOn(data1, data2, channel);
/*midilist[1]->sendNoteOn(data1, data2, channel);
//midilist[2]->sendNoteOn(data1, data2, channel);
midilist[3]->sendNoteOn(data1, data2, channel);
//midilist[4]->sendNoteOn(data1, data2, channel);
midilist[5]->sendNoteOn(data1, data2, channel);
//midilist[6]->sendNoteOn(data1, data2, channel); */
digitalWriteFast(13, HIGH);

      delay(2000);
      digitalWriteFast(13, LOW);
    //  activity = true;
      data2 =      0;
midilist[0]->sendNoteOff(data1, data2, channel);
/*midilist[1]->sendNoteOff(data1, data2, channel);
//midilist[2]->sendNoteOff(data1, data2, channel);
midilist[3]->sendNoteOff(data1, data2, channel);
//midilist[4]->sendNoteOff(data1, data2, channel);
midilist[5]->sendNoteOff(data1, data2, channel);
//midilist[6]->sendNoteOff(data1, data2, channel); */
 delay(2000);

}
 
Can you try each one to work using the device directly and not from the array to see if they are ready and working as expected?

for :: midi01, midi02, midi03, midi04, midi05, midi06, midi07
 
like so?

Code:
&midi01->sendNoteOn(data1, data2, channel);
&midi02->sendNoteOn(data1, data2, channel);

this does not compile and neither does this:


Code:
midi01->sendNoteOn(data1, data2, channel);
midi02->sendNoteOn(data1, data2, channel);

both give me a "base operand of '->' has non-pointer type 'MIDIDevice'" error while compiling.
 
Warning I am not a MIDI person:

Try:
Code:
midi01.sendNoteOn(data1, data2, channel);
midi02.sendNoteOn(data1, data2, channel);
As they I believe are the real object and not a pointer to the object.

Sometimes I forget what all the operator ordering is, so sometimes I force it.
like:
Code:
(&midi01)->sendNoteOn(data1, data2, channel);
(&midi02)->sendNoteOn(data1, data2, channel);

Note: I am also not sure of the relationships with the objects here between your objects:
midi1, midi2... versus midi01 02...

So maybe this is supposed to be midi1.sendNoteOn(...)
 
My understanding mirrors KurtE's … at best - so I left it 'up to the reader'

Not clear how :
Code:
// Create the Serial MIDI ports
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);

Maps to:
Code:
MIDIDevice midi01(myusb);

and:
Code:
MIDI1.begin(MIDI_CHANNEL_OMNI);

I wasn't sure if somehow for all of the array indexes was mapping out to the MIDI1:
Code:
midilist[0]->sendNoteOn(data1, data2, channel);
 
so...

this:

Code:
// Create the Serial MIDI ports
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);

is only in there from the example and is used for hardware serial midi din connections. not relevant in my example.

in the meantime i gave this some thought and it dawned on me, that a usb hub does not differentiate between physical ports. so as long as only one midi device is connected no matter at which port, it will always be device 0. i now connected two and more devices and it is all working as expected. sorry for the noise...

this however brings me to my next question. how do i differentiate usb-devices, when they are port independent? i guess that is where some unique ID of each device comes in. let's just hope that my synths (two of which are an axoloti) have different IDs and that i can somehow route my midi data based on that ID
 
from the USB Host 3.6 keywords.txt:

Code:
# Common Functions
Task	KEYWORD2
idVendor	KEYWORD2
idProduct	KEYWORD2
manufacturer	KEYWORD2
product	KEYWORD2
serialNumber	KEYWORD2

serialNumber() is indeed different for two Axolotis! so i can use that to differentiate between multiple connected axolotis. nice! i have to say working with teensy has been a very smooth experience so far, great.
 
Status
Not open for further replies.
Back
Top