Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USBMIDI crashes on XIAO BLE Sense (mbed enabled core) when the board is powered but has no USB connection #1066

Open
putzlicht opened this issue Aug 30, 2024 · 5 comments

Comments

@putzlicht
Copy link

Hello,

I am using a XIAO BLE Sense (NRF52840) board to map IMU data into MIDI CC.
Yes I know this might be special topic because of the "core", so this is for information only.

Long story short. Except for one case, everything is working fine.
If the board is powered by an active USB hub but there is no PC on the other side,
then it hangs after a few attempts to send something.

The problem does not occur with the same code running on a Teensy LC for example.
So this is NOT a general problem with the library.
What I've already tried to do is figure out where it's hanging. If the code only runs update() without sendCC(), the problem does not occur. But that's probably because update() doesn't do anything if there's nothing to send...

The code simply repeats sending a CC and flashes the onboard LED to check if the board is still running.

#include <Arduino.h>
#include <Control_Surface.h>

USBMIDI_Interface midi_usb;

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    midi_usb.begin();
}

void loop() {
    static uint32_t testtime;
    static boolean  teststate;

    if (millis() - testtime > 250) {
        testtime = millis();
        teststate = !teststate;
  
        if (teststate) {
            midi_usb.sendCC((1, Channel_1), 127);
            digitalWrite(LED_BUILTIN, LOW);
        } else {
            midi_usb.sendCC((1, Channel_1), 0);
            digitalWrite(LED_BUILTIN, HIGH);
        }
        midi_usb.update();
    }
  
}

If anyone out there knows how to prevent this, I would be very grateful :-)

@putzlicht
Copy link
Author

Ok, after poking around in the library I found out that the problem is in the backend:

https://github.com/tttapa/Control-Surface/blob/main/src/MIDI_Interfaces/USBMIDI/USBMIDI_Arduino_mbed.hpp

For example, the Adafruit_TinyUSB_USBDeviceMIDIBackend checks whether the USB device is mounted before the backend
can send something.
But the Arduino_mbed_USBDeviceMIDIBackend simply sends the data without checking.

Fortunately, the backend class has inherited the connected() function.
With an own backend and the additional query, everything now works as it should.

The code simply repeats sending a CC and flashes the onboard LED to check if the board is still running.

#include <Arduino.h>
#include <Control_Surface.h>


struct MyUSBMIDIBackend {

    using MIDIUSBPacket_t = AH::Array<uint8_t, 4>;

    MIDIUSBPacket_t read() { return u32_to_bytes(backend.read()); }

    void write(MIDIUSBPacket_t data) {
      /* This checks whether there is a USB connection to the host before the backend can write data */
      if (backend.connected()) {
        backend.write(bytes_to_u32(data));
      }
    }

    void sendNow() { backend.send_now(); }
    bool preferImmediateSend() { return false; }
    PluggableUSBMIDI backend;
};

struct MyUSBMIDI_Interface : GenericUSBMIDI_Interface<MyUSBMIDIBackend> {
  MyUSBMIDI_Interface() = default;
  using MIDIUSBPacket_t = MyUSBMIDIBackend::MIDIUSBPacket_t;
};


MyUSBMIDI_Interface midi_usb;

void setup() {
    pinMode(LED_BUILTIN, OUTPUT);
    midi_usb.begin();
}

void loop() {
    static uint32_t testtime;
    static boolean  teststate;

    if (millis() - testtime > 250) {
        testtime = millis();
        teststate = !teststate;
  
        if (teststate) {
            midi_usb.sendControlChange((1, Channel_1), 127);
            digitalWrite(LED_BUILTIN, LOW);
        } else {
            midi_usb.sendControlChange((1, Channel_1), 0);
            digitalWrite(LED_BUILTIN, HIGH);
        }
        midi_usb.update();
    }

}
...

@tttapa
Copy link
Owner

tttapa commented Sep 1, 2024

I pushed a fix to the usb-midi-backend-check-connection branch, you might want to try it out (although I haven't had the time to test it yet): 8c884a2

I'm leaving the issue open until the fix is merged.

@tttapa tttapa reopened this Sep 1, 2024
@putzlicht
Copy link
Author

Very nice! I'm at work right now, but I'll check it tonight.

@putzlicht
Copy link
Author

putzlicht commented Sep 1, 2024

Hello Pieter,

your changes are correct. The library branch does the same as my little fix in the backend.
But the problem becomes even more delicate.
What I haven't tried yet is the expected switch-on sequence that the musician I'm programming the small device for will do later.
I can imagine that you have more than enough to do with your library project. But if you're interested, here's what I found:

  1. A Computer (running Win 10) is not yet powered. An active USB hub connected to the computer receives power.
  2. The XIAO BLE Sense Board is connected to the USB hub and the example code runs without any problems.
  3. The computer is now also supplied with power. The code continues to run.
  4. Now the Windows boot animation appears and the code no longer runs! <---------------------------------------------
  5. After a few seconds, the code will be executed again.
  6. The login screen appears and the code no longer runs.

Since I have very limited knowledge of USB, I could only make assumptions here. But I'll stick with the problem and report back if I can figure something out.

Best
Martin

EDIT: What I can definitely say is that the board does not a reset at point 5.

@tttapa
Copy link
Owner

tttapa commented Sep 10, 2024

Thanks for the detailed description. The USB code could definitely use some improvements, cancellation and USB resets are not properly supported at the moment. It's on my TODO list, but I'm quite busy with other things, unfortunately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants