Adafruit USB MIDI does not create device

Based upon the example of the Adafruit Tiny USB library I wrote this code for my BPI-Leaf-S3 board:

// main.cpp
#include <MIDI.h>
Adafruit_USBD_MIDI midiusb;
MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, midiusb, MIDI);

#include "foo.h"
Foo foo;

void setup()
{
  Serial.setDebugOutput(true);
  Serial.begin(115200);
  foo.Begin();
}

void loop()
{
  if (midiusb.available()) midiusb.read();
}

// foo.cpp
#include <MIDI.h>
extern Adafruit_USBD_MIDI midiusb;
extern MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<Adafruit_USBD_MIDI>> MIDI;

void Foo::Begin()
{
    midiusb.setStringDescriptor("foo");
    MIDI.begin(MIDI_CHANNEL_OMNI);
    while(!TinyUSBDevice.mounted()) delay(1);
    Serial.println(F("MIDI initialized"));
}

It does nothing but it should create the USB MIDI device. I get the MIDI initialized message so I assume all went fine. Anyway, lsusb does not show anything MIDI-related and even:

$ sudo modprobe snd_seq_midi
$ aseqdump -l
 Port    Client name                      Port name
  0:0    System                           Timer
  0:1    System                           Announce
 14:0    Midi Through                     Midi Through Port-0

shows nothing.
Did I forget anything in the setup?

Does the example work without any modifications?

For what it's worth, the Control Surface library I maintain supports MIDI over USB on the ESP32-S3: Control Surface: MIDI over USB, version 3.0.0 of arduino-esp32 adds support for it.

Actually, the provided example does not compile. I had to add:

void handleNoteOn(byte channel, byte pitch, byte velocity);
void handleNoteOff(byte channel, byte pitch, byte velocity);

before the setup() otherwise it cannot find the functions (declared below).
About the MIDI the original code works:

$ aseqdump -l
 Port    Client name                      Port name
  0:0    System                           Timer
  0:1    System                           Announce
 14:0    Midi Through                     Midi Through Port-0
 32:0    BPI-Leaf-S3                      BPI-Leaf-S3 MIDI 1

I wonder what is my mistake in my code.

One possibly significant difference is the order of Serial.begin() and midi.begin().

1 Like

Good catch. I never imagined that opening the serial port would interfere with the MIDI library!
By the way, I don't like at all global variables... do you see any caveat if I put all the stuff in the private section of my Foo class?

Where does the MIDI_CREATE_INSTANCE macro should be placed then?

If the global variable represents an inherently “global” resource (e.g. a hardware serial port or a MIDI interface), then keeping it as a global variable is usually not an issue (and may even be preferred).
Grouping such variables into a class or struct just to reduce the number of global variables is generally not very useful.

That being said, if you have good reasons for encapsulating the variable, you can of course do so. The MIDI_CREATE_INSTANCE macro is a simple convenience wrapper, and you don't have to use it. It is probably easier to look at its definition and use that directly in your class (IIRC, it simply defines two variables).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.