felis / USB_Host_Shield_2.0

Revision 2.0 of USB Host Library for Arduino.
https://chome.nerpa.tech
1.79k stars 779 forks source link

USB Host Shield Mini, not reconnecting. #593

Open jhsa opened 3 years ago

jhsa commented 3 years ago

Hi, If I disconnect the USB device from the shield and reconnect, or connect another USB device, most of the times I don't get a connection unless I reboot the Arduino and Shield assembly. Here is a picture of how I connected an Arduino Pro-Mini 8Mhz at 3.3V to the shield. the green numbers are the Arduino Pins. Any ideas why this would happen? Thank you very much for your help...

UT89srLXWRXXXagOFbX8

Lauszus commented 3 years ago

Did you remember to cut the VBUS jumper?

jhsa commented 3 years ago

You can see the cut on the picture above. that is how I did it. My board is exactly the same as the one in the picture. I did cut it where indicated. No jumper, just cut the track. If I hadn't cut it, the MAX chip would be already destroyed :)

Lauszus commented 3 years ago

Sorry I missed the picture! What devices are you trying to use?

Please also enable serial debugging: https://github.com/felis/USB_Host_Shield_2.0#enable-debugging, so it gives me more information on what is going on.

jhsa commented 3 years ago

Before I do anything else, please watch this little video I have made showing the problem. Also, the arduino was a 16Mhz, and i replaced the crystal with an 8Mhz and burnt the correct fuses and the correct bootloader, so i don't think the arduino is the problem.. Thanks for looking into this.

https://www.youtube.com/watch?v=wQCUh8RX5ZQ

Lauszus commented 3 years ago

Adding a VBUS power switch migth solve the problem: https://chome.nerpa.tech/mcu/vbus-power-control-on-usb-host-shield/.

jhsa commented 3 years ago

That link gives me this error

502 Bad Gateway

jhsa commented 3 years ago

Funny, just checked again, and only that commercial device seems to trigger that problem. If I connect my other devices that I built myself, an midi to USB converter (device) and my DIY guitar effect switcher, it seems to work ok.. Could it be that Boss ME-80 have a pullup on another USB data pin? I read that older equipment and newer equipment might be detected in different ways. But if i reboot the shield, the Boss device is detected. Weird.

Lauszus commented 3 years ago

That link gives me this error 502 Bad Gateway

Weird. Can you try again?

Could it be that Boss ME-80 have a pullup on another USB data pin? I read that older equipment and newer equipment might be detected in different ways. But if i reboot the shield, the Boss device is detected. Weird.

The shield should work with both low and full speed devices, so that should not be the issue. Regarding the pull up resistor on D+ and D-, then it is simply used to identify a low and full speed device. You can read more about it here: https://www.beyondlogic.org/usbnutshell/usb2.shtml.

jhsa commented 3 years ago

Still get the same "502 Bad Gateway" error. But thank you anyway.

The shield does work, the problem is that with the Boss pedalboard if I disconnect it, it doesn't connect to it anymore unless I reboot it. This thing can send Audio over USB and MIDI. I am using MIDI at the moment. Thanks

xxxajk commented 3 years ago

Some devices only support high-speed USB, see if adding a powered hub solves the problem. The hub will translate full-speed to high-speed. This trick also works for super-speed only devices.

jhsa commented 3 years ago

I didn't even know we could connect a hub with more devices to this shield :) Actually, I did try one (very) old hub I have here but it didn't work. So I assumed it doesn't work with USB Hubs.

Lauszus commented 3 years ago

Yes it's super easy. Just add this to your sketch:

#include <usbhub.h>
USBHub Hub1(&Usb);
jhsa commented 3 years ago

Ahh, ok thanks. So, that will allow a Hub, and I could connect several devices to it, right? Or that Hub1 is just for one extra device connected to the Hub.. Sorry if it is a stupid question but I am a beginner in coding and certainly this USB stuff is new to me :) Thank you again.

Lauszus commented 3 years ago

Most hubs support 4 devices. Note a 7 port hub usually have two hub ICs inside where one of the downstream ports of the first IC is connected to the upstream port of the second hub, but you can simply just create two instances and the library will take care of the rest:

USBHub Hub1(&Usb);
USBHub Hub2(&Usb);

You can simply repeat that for as many as you need.

jhsa commented 3 years ago

Cool, thank you so much.. Will try it tomorrow. Will then report.

jhsa commented 3 years ago

Yes it's super easy. Just add this to your sketch:

#include <usbhub.h>
USBHub Hub1(&Usb);

Hi, question, do i need to add some more code? because i added this to the sketch and it is still not passing data on the Hub. I have:

/*
 *******************************************************************************
 * Legacy Serial MIDI and USB Host bidirectional converter
 * Copyright (C) 2013-2020 Yuuichi Akagawa
 *
 * for use with Arduino MIDI library
 * https://github.com/FortySevenEffects/arduino_midi_library/
 *
 * Note:
 * - If you want use with Leonardo, you must choose Arduino MIDI library v4.0 or higher.
 * - This is sample program. Do not expect perfect behavior.
 *******************************************************************************
 */

#include <MIDI.h>
#include <usbh_midi.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

//Arduino MIDI library v4.2 compatibility
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif

// Set to 1 if you want to wait for the Serial MIDI transmission to complete.
// For more information, see https://github.com/felis/USB_Host_Shield_2.0/issues/570
#define ENABLE_MIDI_SERIAL_FLUSH 0

//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////

USB Usb;
USBH_MIDI Midi(&Usb);
USBHub Hub1(&Usb);

void MIDI_poll();

//If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE

#ifdef USBH_MIDI_SYSEX_ENABLE
//SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
  Midi.SendSysEx(sysexmsg, sizeofsysex);
}
#endif
/*
void myClock(void)
{

}
*/
void setup()
{
 MIDI.begin(MIDI_CHANNEL_OMNI);

  MIDI.turnThruOff();
//  MIDI.setHandleClock(myClock);
#ifdef USBH_MIDI_SYSEX_ENABLE
  MIDI.setHandleSystemExclusive(handle_sysex);

#endif
  if (Usb.Init() == -1) {
    while (1); //halt
  }//if (Usb.Init() == -1...
  delay( 200 );
}

void loop()
{
  uint8_t msg[4];

  Usb.Task();
  if ( Midi ) {
    MIDI_poll();
    if (MIDI.read()) {
      msg[0] = MIDI.getType();
      switch (msg[0]) {
        case midi::ActiveSensing :
          break;
        case midi::SystemExclusive :
          //SysEx is handled by event.
          break;
        default :
          if( msg[0] < 0xf0 ){
              msg[0] |= MIDI.getChannel() -1;
          }
          msg[1] = MIDI.getData1();
          msg[2] = MIDI.getData2();
          Midi.SendData(msg, 0);
          break;
      }
    }
  }
}

// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll()
{
  uint8_t size;
#ifdef USBH_MIDI_SYSEX_ENABLE
  uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
  uint8_t rcode = 0;     //return code
  uint16_t  rcvd;
  uint8_t   readPtr = 0;

  rcode = Midi.RecvData( &rcvd, recvBuf);

  //data check
  if (rcode != 0) return;
  if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
    return ;
  }

  uint8_t *p = recvBuf;
  while (readPtr < MIDI_EVENT_PACKET_SIZE)  {
    if (*p == 0 && *(p + 1) == 0) break; //data end

    uint8_t outbuf[3];
    uint8_t rc = Midi.extractSysExData(p, outbuf);
    if ( rc == 0 ) {
      p++;
      size = Midi.lookupMsgSize(*p);
      _MIDI_SERIAL_PORT.write(p, size);
      p += 3;
    } else {
      _MIDI_SERIAL_PORT.write(outbuf, rc);
      p += 4;
    }
#if ENABLE_MIDI_SERIAL_FLUSH
      _MIDI_SERIAL_PORT.flush();
#endif
    readPtr += 4;
  }
#else
  uint8_t outBuf[3];
  do {
    if ( (size = Midi.RecvData(outBuf)) > 0 ) {
      //MIDI Output
      _MIDI_SERIAL_PORT.write(outBuf, size);
#if ENABLE_MIDI_SERIAL_FLUSH
      _MIDI_SERIAL_PORT.flush();
#endif
    }
  } while (size > 0);
#endif
}
xxxajk commented 3 years ago

Powered hub may be required.

jhsa commented 3 years ago

ok, let me see if I find a power supply that fits this old hub. I do have a another hub but it has a different connector and i don't have an adapter for it :(

jhsa commented 3 years ago

No, it doesn't work even with it powered. Is the code I posted above ok? Should it just work like that? Thanks.

jhsa commented 3 years ago

Forgot to say, when I insert the device connector in the hub slot, the corresponding LED turns ON. So, it seems it might be detected, but there is no data flowing as far as I can see

YuuichiAkagawa commented 3 years ago
USB Usb;
USBHub  Hub1(&Usb);
USBH_MIDI Midi(&Usb);
jhsa commented 3 years ago

It doesn't work.. At least with the hub I have.. Does it have to be some special sort of hub? Thanks

Lauszus commented 3 years ago

No any hub should be supported.

@jhsa can you try the following example: https://github.com/felis/USB_Host_Shield_2.0/blob/master/examples/hub_demo/hub_demo.ino?

jhsa commented 3 years ago

Sure. But it doesn't compile. It seems some file is missing. The error is:

pgmstrings.h: No such file or directory

EDIT: I have jut created the pgmstrings.h file from github, and saved it in the sketch directory. It compiled now.

jhsa commented 3 years ago

I guess you want to see the output from the IDE Monitor.

Start

41
--
String Descriptors:
Product:        USB2.0 Hub

Device descriptor: 
Descriptor Length:  12
Descriptor type:    01
USB version:        0200
Device class:       09
Device Subclass:    00
Device Protocol:    00
Max.packet size:    40
Vendor  ID:     05E3
Product ID:     0608
Revision ID:        0702
Mfg.string index:   00
Prod.string index:  01
Serial number index:    00
Number of conf.:    01

Configuration descriptor:
Total length:       0019
Num.intf:       01
Conf.value:     01
Conf.string:        00
Attr.:          E0
Max.pwr:        32

Interface descriptor:
Intf.number:        00
Alt.:           00
Endpoints:      01
Intf. Class:        09
Intf. Subclass:     00
Intf. Protocol:     00
Intf.string:        00

Endpoint descriptor:
Endpoint address:   81
Attr.:          03
Max.pkt size:       0001
Polling interval:   FF

Addr:41(1.0.1)
jhsa commented 3 years ago

And, what does the monitor output mean? Thanks.

YuuichiAkagawa commented 3 years ago

I tested bidirectional_converter via HUB. It's working fine.

I don't know why it doesn't work in your environment.

promini_ZoomG1on promini_ZoomG1onMonitor jpg

jhsa commented 3 years ago

Hi, thanks for your help.. I updated the library to the latest, flashed the code you linked above, uncommented line 47, the HUB is recognized as before, but it doesn't pass data to the USB MIDI adapter or to my guitar effect board. Both work when connected directly to the Host bidirectional converter. Just not through the hub. Need to find another Hub to test. This one might be too old. It does work when connected to a PC though..

xxxajk commented 3 years ago

USB hubs are "dumb" devices, and simply pass along the data. The only problems I have run into with hubs on UHS2 are: 1: Not enough power, use a powered hub 2: UHS2 hub enumeration can sometimes goof up bad if you disconnect in a certain order. Child hubs are not properly unallocated. Use a single hub in this instance.

jhsa commented 3 years ago

Hi, the HUB I have works fine directly connected to the computer.

xxxajk commented 3 years ago

Computers normally supply enough power for a single device, sometimes they supply a little extra. How are you powering your project? Have you checked it on an oscilloscope to make sure that there is no power droops? Voltage on the output of the hub at least 4.75V?

jhsa commented 3 years ago

Ok, found an OTG Hub in my junk box. It works with this one, so the other is probably too old? I have noticed something though.. it only passes the data from the first device connected to the hub. Is this expected? Or should I define a hub per port on the sketch? Thanks

xxxajk commented 3 years ago

Nope! It possibly consumes too much power, and doesn't leave enough remaining power for what you are attaching, or is dropping the voltage too low, or totally lacks power conditioning inside, or some kind of combination of these. You should only need one hub set up. If you have more than one MIDI device, you need to do multiples of them.

jhsa commented 3 years ago

I don't think I have a power issue. I am feeding the hub from a LiPo battery through a 2A voltage converter. This has for sure more than enough juice to feed a couple USB/Midi converters :) Now, I don't really understand what your last phrase means, I do apologize fore that.

jhsa commented 3 years ago

How would I do multiple midi devices? This is the reason for using a Hub, right? If I can connect only one device to the host via the hub, then the hub is doing nothing :) Is there an example for multiple midi devices? Thank you.

xxxajk commented 3 years ago

You will need a midi instance per device connected. e.g.

USBH_MIDI Midi1(&Usb);
USBH_MIDI Midi2(&Usb);
jhsa commented 3 years ago

ahhhh, thanks.. and just copy the code of the "Midi1" and paste changing it to Midi2?

jhsa commented 3 years ago

I think I can see an example of this.. Checking now, thank you.

xxxajk commented 3 years ago

Yes, if that's what you want it to do. If the midi devices talk to each other, you have to code that.

jhsa commented 3 years ago

Hi guys, well, it seems the junk hub I found works :)I Now I am trying to code some multiple devices on the hub, based on both the bidirectional converter example and also the Multi converter example. But I am not being successful :( It seems to work when receiving MIDI via USB, but if I send midi on the serial inputs then I need to send the same midi event twice to trigger a change on the receiving USB device. Any ideas? here is the code, and thank you.. I tried everything to my knowledge which is not that much...

EDIT: The normal Bidirectional MIDI converter seems to work fine. This happens when I try to add more hub devices.

#include <MIDI.h>
#include <usbh_midi.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

//Arduino MIDI library v4.2 compatibility
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
MIDI_CREATE_DEFAULT_INSTANCE();
#endif
#ifdef USBCON
#define _MIDI_SERIAL_PORT Serial1
#else
#define _MIDI_SERIAL_PORT Serial
#endif

// Set to 1 if you want to wait for the Serial MIDI transmission to complete.
// For more information, see https://github.com/felis/USB_Host_Shield_2.0/issues/570
#define ENABLE_MIDI_SERIAL_FLUSH 0

//////////////////////////
// MIDI Pin assign
// 2 : GND
// 4 : +5V(Vcc) with 220ohm
// 5 : TX
//////////////////////////

USB Usb;
USBHub  Hub1(&Usb);
USBH_MIDI  Midi1(&Usb);
USBH_MIDI  Midi2(&Usb);

void MIDI_poll();
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);

//If you want handle System Exclusive message, enable this #define otherwise comment out it.
#define USBH_MIDI_SYSEX_ENABLE

#ifdef USBH_MIDI_SYSEX_ENABLE
//SysEx:
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
  Midi1.SendSysEx(sysexmsg, sizeofsysex);
  Midi2.SendSysEx(sysexmsg, sizeofsysex);
}
#endif

void setup()
{
  // _MIDI_SERIAL_PORT.begin(31250);

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();
#ifdef USBH_MIDI_SYSEX_ENABLE
  MIDI.setHandleSystemExclusive(handle_sysex);
#endif

  if (Usb.Init() == -1) {
    while (1); //halt
  }//if (Usb.Init() == -1...
  delay( 200 );
}

void loop()
{
  uint8_t msg[4];
 // uint8_t msg1[4];

  Usb.Task();
  uint32_t t1 = (uint32_t)micros();

  if ( Midi1 ){

    MIDI_poll(Midi1);
   if (MIDI.read()) {
      msg[0] = MIDI.getType();
      switch (msg[0]) {
        case midi::ActiveSensing :
          break;
        case midi::SystemExclusive :
          //SysEx is handled by event.
          break;
        default :
          // If this is a channel messages, set the channel number.
          if ( msg[0] < 0xf0 ) {
            // The getchannel() returns 1-16, but the MIDI status byte starts at 0.
            msg[0] |= MIDI.getChannel() - 1;
          }
          msg[1] = MIDI.getData1();
          msg[2] = MIDI.getData2();
          Midi1.SendData(msg, 0);
          Midi2.SendData(msg, 0);

          break;
      }
    }
  }

  if ( Midi2 ) {

    MIDI_poll(Midi2);
    if (MIDI.read()) {
      msg[0] = MIDI.getType();
      switch (msg[0]) {
        case midi::ActiveSensing :
          break;
        case midi::SystemExclusive :
          //SysEx is handled by event.
          break;
        default :
          // If this is a channel messages, set the channel number.
          if ( msg[0] < 0xf0 ) {
            // The getchannel() returns 1-16, but the MIDI status byte starts at 0.
            msg[0] |= MIDI.getChannel() - 1;
          }
          msg[1] = MIDI.getData1();
          msg[2] = MIDI.getData2();
          Midi1.SendData(msg, 0);
          Midi2.SendData(msg, 0);

          break;
      }
    }
  }

  //delay(1ms)
  doDelay(t1, (uint32_t)micros(), 1000);
}

// Poll USB MIDI Controler and send to serial MIDI
void MIDI_poll(USBH_MIDI &Midi)
{
  uint8_t size;
#ifdef USBH_MIDI_SYSEX_ENABLE
  uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
  uint8_t rcode = 0;     //return code
  uint16_t  rcvd;
  uint8_t   readPtr = 0;

  rcode = Midi.RecvData( &rcvd, recvBuf);

  //data check
  if (rcode != 0) return;
  if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
    return ;
  }

  uint8_t *p = recvBuf;
  while (readPtr < MIDI_EVENT_PACKET_SIZE)  {
    if (*p == 0 && *(p + 1) == 0) break; //data end

    uint8_t outbuf[3];
    uint8_t rc = Midi.extractSysExData(p, outbuf);
    if ( rc == 0 ) {
      p++;
      size = Midi.lookupMsgSize(*p);
      _MIDI_SERIAL_PORT.write(p, size);
      p += 3;
    } else {
      _MIDI_SERIAL_PORT.write(outbuf, rc);
      p += 4;
    }
#if ENABLE_MIDI_SERIAL_FLUSH
      _MIDI_SERIAL_PORT.flush();
#endif
    readPtr += 4;
  }
#else
  uint8_t outBuf[3];
  do {
    if ( (size = Midi.RecvData(outBuf)) > 0 ) {
      //MIDI Output
      _MIDI_SERIAL_PORT.write(outBuf, size);
#if ENABLE_MIDI_SERIAL_FLUSH
      _MIDI_SERIAL_PORT.flush();
#endif
    }
  } while (size > 0);
#endif
}

// Delay time (max 16383 us)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
  uint32_t t3;

  t3 = t2 - t1;
  if ( t3 < delayTime ) {
    delayMicroseconds(delayTime - t3);
  }
}
jhsa commented 3 years ago

Could someone please try this? I am starting to think the library has a problem and that it isn't curently possible to code a bidirectional MIDI converter with more than 1 device, which makes the use of a hub pretty much useless :( I have tried everything I could within my little knowledge, but I can't make it work unless I use only one device. As soon as try to add a second device, Midi messages get messed up. Thanks for your help.

jhsa commented 3 years ago

I have made a couple videos showing the problem. On the first one I had I had the second device MIDI code commented. On the second video both devices were active, and that is when the problems can be seen.

https://www.youtube.com/watch?v=RXVvIKSfn4k

https://www.youtube.com/watch?v=x75pnx0LL8U

Lauszus commented 3 years ago

Please start by removing your doDelay, as you need to call Usb.Task() as fast as possible.

I do not have any MIDI devices, so I can't test the code. @YuuichiAkagawa have you ever tried the code with multiple MIDI devices via a USB hub?

jhsa commented 3 years ago

Please start by removing your doDelay, as you need to call Usb.Task() as fast as possible.

Already tried that. No joy

I do not have any MIDI devices, so I can't test the code. @YuuichiAkagawa have you ever tried the code with multiple MIDI devices via a USB hub?

I tried that example as well. It works but it works only on one direction. I need biderectional midi. From serial to ALL USB ports on the HUB (3 devices normally), and from All USB to serial. This part is what the "Multi" example does, and it seems to work.

jhsa commented 3 years ago

Weird, it looks like Control change is being sent every time, but not Program Change messages..

jhsa commented 3 years ago

Very strange if a control change is sent together with a program change message, sometimes the program change is not sent. But if i comment the line "Midi2.SendData(msg, 0);" all seems to work well. I just can't find why this happens. Both Midi1 and Midi2 should be sent the same data.

` Usb.Task(); uint8_t msg[4]; uint32_t t1 = (uint32_t)micros();

if (MIDI.read()) { msg[0] = MIDI.getType(); switch (msg[0]) { case midi::ActiveSensing : break; case midi::SystemExclusive : //SysEx is handled by event. break; default :

      // If this is a channel messages, set the channel number.
      if ( msg[0] < 0xf0 ) {
        // The getchannel() returns 1-16, but the MIDI status byte starts at 0.
        msg[0] |= MIDI.getChannel() - 1;
      }
      msg[1] = MIDI.getData1();
      msg[2] = MIDI.getData2();

       break;
  }
     Midi1.SendData(msg, 0);
      Midi2.SendData(msg, 0); 

}`
YuuichiAkagawa commented 3 years ago

I don't have multiple MIDI instruments, so I need to make a dummy device for testing. However, I am too busy with work to test until the weekend.

  1. It looks like your application doesn't need bidirectional. Right?
  2. Try the development version. https://github.com/YuuichiAkagawa/USBH_MIDI/blob/master/usbh_midi.cpp https://github.com/YuuichiAkagawa/USBH_MIDI/blob/master/usbh_midi.h
  3. What is the return value of the SendData()? return value is 0:Success non-zero:Error(MAX3421E HRSLT)
  4. It is necessary to check if it is available.
    if( Midi1 ) Midi1.SendData(msg, 0);
    if( Midi2 ) Midi2.SendData(msg, 0); 
jhsa commented 3 years ago
I don't have multiple MIDI instruments, so I need to make a dummy device for testing.
However, I am too busy with work to test until the weekend.

Thank You for your answer.

1. It looks like your application doesn't need bidirectional. Right?

Yes, I do need bidirectional, that is why I am trying this, otherwise the "Multi" example would have been fine.

3. What is the return value of the SendData()?
   return value is
   0:Success
   non-zero:Error(MAX3421E HRSLT)

Not sure I understand what you mean. How do i check that? I only have an Arduino Pro-Mini, so, only one serial port. I do have some STM32F103CB but this library doesn't seem to run on them at the moment.

4. It is necessary to check if it is available.

    if( Midi1 ) Midi1.SendData(msg, 0);
    if( Midi2 ) Midi2.SendData(msg, 0); 

I did try this without success, but together with the Poll function as in the original bidirectional example. Will try separately later. Thanks a lot for your help. I am sure this will help others too.

jhsa commented 3 years ago

This also doesn't work. even with one device connected directly to the Host I need to send the MIDI Program Change at least twice for it to react.

void loop()
{
  // uint8_t msg[4];
  // uint8_t msg1[4];

  Usb.Task();
  uint8_t msg[4];
  uint32_t t1 = (uint32_t)micros();

  if (MIDI.read()) {
    msg[0] = MIDI.getType();
    switch (msg[0]) {
      case midi::ActiveSensing :
        break;
      case midi::SystemExclusive :
        //SysEx is handled by event.
        break;
      default :

        // If this is a channel messages, set the channel number.
        if ( msg[0] < 0xf0 ) {
          // The getchannel() returns 1-16, but the MIDI status byte starts at 0.
          msg[0] |= MIDI.getChannel() - 1;
        }
        msg[1] = MIDI.getData1();
        msg[2] = MIDI.getData2();

        break;
    }
    if ( Midi1 ) Midi1.SendData(msg, 0);
    if ( Midi2 ) Midi2.SendData(msg, 0);

  }

  if ( Midi1 ) {

    MIDI_poll(Midi1);

  }

  if ( Midi2 ) {

    MIDI_poll(Midi2);

  }

  //delay(1ms)
  //doDelay(t1, (uint32_t)micros(), 1000);
}
jhsa commented 3 years ago

I used the "usbh_midi.h" and "usbh_midi.cpp" files you have linked, it is better but the problem is still there. I think the library might have some problems when there is more than 1 device and it has to send Midi data with DataByte1 and DataByte2, like for example Control Change or Note.

And it seems device number 1 to suffer from this problem. I have just swapped both devices connected to the hub, and the problem also moved to the other device, meaning that device 1 is affected.