midiusb.read() Am I expecting too much

Hi: after several Arduino MIDI controller projects using nano I have now tried a Leonardo board so that that I can you use USB rather than the DIN plugs.

I installed the library and used the simple examples from GITHUB and successfully have the midis write example playing a middle c over and over on my Mac (MainStage) so far all good.

I have then tried the midi usb read example...when uploaded to the board I am viewing the serial monitor and see nothing when I play any of the keyboards in my midi setup. I have several keyboard connected through audio interfaces which act as a USB Host. All the midi traffic from every component is visible in midi monitor on my Mac...as was the Arduino when it was writing.

what should I see?...I kind of thought that the midi read would become a type of midi monitor simply outputting everything that it sees within the midi environment.

As an aside when I view the arduino in the Mac's audio midi setup and "refresh midi capabilities" I get some activity in the serial monitor (and the midi monitoring software)...which makes me think something is working. This is the output from the serial monitor

09:37:32.255 -> Received: 4-F0-7E-7F
09:37:32.255 -> Received: 4-D-20-0
09:37:32.255 -> Received: 4-7F-7F-7F
09:37:32.255 -> Received: 4-7F-0-0
09:37:32.255 -> Received: 4-0-0-0
09:37:32.255 -> Received: 4-0-0-0
09:37:32.255 -> Received: 4-0-0-0
09:37:32.255 -> Received: 5-F7-0-0
09:37:32.361 -> Received: 4-F0-7E-7F
09:37:32.361 -> Received: 4-D-30-0
09:37:32.361 -> Received: 4-7F-7F-7F
09:37:32.361 -> Received: 4-7F-0-0
09:37:32.361 -> Received: 7-7-68-F7

any help would be appreciated as Im stuck at the moment :slight_smile:

.I kind of thought that the midi read would become a type of midi monitor simply outputting everything that it sees within the midi environment.

No is just shows you how to read the midi stream and use it to trigger various functions that deal with that message type when they occur. You could modify it to print a message if you want.

thanks...that's what I thought it was doing with these lines...

void loop() {
midiEventPacket_t rx;
do {
rx = MidiUSB.read();
if (rx.header != 0) {
Serial.print("Received: ");
Serial.print(rx.header, HEX);
Serial.print("-");
Serial.print(rx.byte1, HEX);
Serial.print("-");
Serial.print(rx.byte2, HEX);
Serial.print("-");
Serial.println(rx.byte3, HEX);
}
} while (rx.header != 0);
}

but it doesn't output anything

andigoodman:
I have then tried the midi usb read example...when uploaded to the board I am viewing the serial monitor and see nothing when I play any of the keyboards in my midi setup. I have several keyboard connected through audio interfaces which act as a USB Host.

The MIDI messages from the keyboards are sent to your computer. Unless you have some MIDI software running on your computer that routes them to the Arduino, the Arduino is not going to receive anything.

andigoodman:
what should I see?...I kind of thought that the midi read would become a type of midi monitor simply outputting everything that it sees within the midi environment.

There is no "MIDI environment", MIDI is a connection between two devices, it doesn't broadcast anything.

The MIDIUSB library doesn't actually parse any MIDI messages, it just gives you the raw USB packets. If you want to do actual MIDI, you need a MIDI parser on top of that.
The MIDI read example just prints these USB packets.

The Control Surface library I maintain has a MIDI USB parser so you don't have to worry about raw USB traffic, just MIDI messages.

Here are some examples:

If you want to use the Arduino as a MIDI monitor, you can use the following:

#include <Control_Surface.h>

USBMIDI_Interface midiusb;
USBDebugMIDI_Interface midimonitor;
 
BidirectionalMIDI_Pipe pipe;
 
void setup() {
  midiusb | pipe | midimonitor; // Connect USB MIDI interface and MIDI monitor
  // The pipe is bidirectional, so MIDI input from the USB MIDI interface is 
  // printed in the MIDI monitor, and text input from the MIDI monitor is sent
  // to the USB MIDI interface as real MIDI messages.
  midiusb.begin();
  midimonitor.begin();
}
 
void loop() {
  midiusb.update();
  midimonitor.update();
}

It prints the MIDI messages it receives to the Serial monitor, and it allows you to enter hexadecimal MIDI messages in the Serial monitor that are then sent over USB as MIDI messages.

Pieter

that's what I thought it was doing with these lines...

No its not.

Where is the MIDI coming from?

I installed the library and used the simple examples from GITHUB

Can you post a link to that please.

Can you post all your code, and please use the copy for forum option on the IDE when you paste it in.

I have several keyboard connected through audio interfaces which act as a USB Host.

Have you?
Why would a keyboard look like a USB host, that would mean you could not connect it to a computer. The are normally clients are you getting the two terms mixed up.

Pieter:- Have you got some sort of special dispensation from the rules that allow you to post code in quote tags and not code tags? You never seem to use code tags when you are pushing that library you are so devoted to.

The MIDIUSB library doesn't actually parse any MIDI messages, it just gives you the raw USB packets.

That is not true.

Grumpy_Mike:
Pieter:- Have you got some sort of special dispensation from the rules that allow you to post code in quote tags and not code tags? You never seem to use code tags when you are pushing that library you are so devoted to.

I don't use the standard code tags for short snippets of code, because I believe the highlighted code is much easier to read that way. For larger snippets I do use code tags of course. As long as it doesn't turn my entire post into italics or emoticons, I don't see any problem with it.

Grumpy_Mike:
That is not true.

It is, MIDIUSB handles device/endpoint descriptors, parses USB packets, and just buffers the 32-bit MIDI USB data packets and forwards them to the user. It doesn't parse or handle any MIDI data, it has no logic to check the contents of the MIDI USB packets, it just stores or sends them. To make sense of the MIDI data, you still have to parse them yourself to extract meaningful data, to make sure the cable number makes sense, to combine SysEx data, etc.

Grumpy_Mike:
Why would a keyboard look like a USB host, that would mean you could not connect it to a computer. The are normally clients are you getting the two terms mixed up.

In the USB jargon, "client" refers to software on the host that communicates with functions on a device.
Keyboards are usually USB devices, not clients, nor hosts.

""There is no "MIDI environment", MIDI is a connection between two devices, it doesn't broadcast anything.""

...in my experience this is not correct...all midi devices send midi signals with channels etc...there is no destination.

I have 3 keyboards, a midi foot pedal and a midi pad...each sends out (broadcasts) midi messages to "the environment" and any device set to receive on that channel reacts accordingly....midi isn't sent from one device to another...

andigoodman:
""There is no "MIDI environment", MIDI is a connection between two devices, it doesn't broadcast anything.""

...in my experience this is not correct...all midi devices send midi signals with channels etc...there is no destination.

I have 3 keyboards, a midi foot pedal and a midi pad...each sends out (broadcasts) midi messages to "the environment" and any device set to receive on that channel reacts accordingly....midi isn't sent from one device to another...

No, the keyboards send unicast MIDI messages to your computer's MIDI driver. The MIDI driver allows programs to subscribe to those messages. The driver will not send the MIDI data to any other MIDI devices, unless you specifically connect them using a software patch bay, for example.

Using DIN MIDI, you can connect a device to a MIDI through output, but that's still not a broadcast.

There is a destination: the way you connect them determines the destination.

Mike: here's my code..hope I copied it correctly. My setup is 2 keyboards, 1 drum pad and a home made midi pedal...all connected to 2 audio interfaces and then to a Mac which is running MainStage.(didn't mean to imply that the keyboard was a host)

Everything works perfectly and it "feels" like a midi environment...everything sees all the messages that are running about and careful use of midi channels makes sure that it works correctly.

Ive been using MIDI for almost as long as its been around and in every setup ive had, ive just plugged it all in and managed the data using different channels...ive never had to "route" anything

/*
 * MIDIUSB_test.ino
 *
 * Created: 4/6/2015 10:47:08 AM
 * Author: gurbrinder grewal
 * Modified by Arduino LLC (2015)
 */ 

#include "MIDIUSB.h"

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void setup() {
  Serial.begin(115200);
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

void loop() {
  midiEventPacket_t rx;
  do {
    rx = MidiUSB.read();
    if (rx.header != 0) {
      Serial.print("Received: ");
      Serial.print(rx.header, HEX);
      Serial.print("-");
      Serial.print(rx.byte1, HEX);
      Serial.print("-");
      Serial.print(rx.byte2, HEX);
      Serial.print("-");
      Serial.println(rx.byte3, HEX);
    }
  } while (rx.header != 0);

PieterP: I have tried control surface and the result is exactly the same...I'm at a loss now. The arduino quite happily transmits to my Mac and plays sounds but won't receive messages from any other part of the rig

I am at a loss :frowning:

Like I said earlier, you have to actually send MIDI messages to the Arduino, it doesn't happen automatically. You'll have to route the MIDI data using a software patch bay, or set up some connections in your DAW.

all connected to 2 audio interfaces

Can you explain what these are please?

To make sense of the MIDI data, you still have to parse them yourself to extract meaningful data, to make sure the cable number makes sense, to combine SysEx data, etc.

I must be using a different library to what you are thinking about because the one I am using does parse the MIDI stream.

Grumpy_Mike:
I must be using a different library to what you are thinking about because the one I am using does parse the MIDI stream.

I'm talking about the official arduino-libraries/MIDIUSB library.

@PieterP

Either use code tags or please dont bother posting code at all and we will all use our crystal balls.

And as a reminder ( although you should not need one at this point )

Could you also take a few moments to Learn How To Use The Forum.
It will help you get the best out of the forum in the future.
Other general help and troubleshooting advice can be found here.

ballscrewbob:
@PieterP

Either use code tags or please dont bother posting code at all

Apologies, I didn't realize it was a hard rule, the "how to use this forum" thread simply explains that it's a way to make the code more readable and prevent accidental BBC tags from messing up the rest of the post, both of which my post achieved, so I didn't expect it to be an issue. Will use code tags from now on.

ballscrewbob:
and we will all use our crystal balls.

I'm not sure what that refers to?

PieterP:
I'm talking about the official arduino-libraries/MIDIUSB library.

Then pray tell what is the AllEvents example is about then if it does not parse an incoming MIDI data stream from the USB socket?

The MIDIUSB library doesn't include an "AllEvents" example. Please post a link to the one you have in mind.

Please also look at the source file for MIDIUSB I linked to and point me to the section where it parses MIDI data.

I see 5 examples named buzzer, clock, loop, read, write.

None of them seem to be named "AllEvents".

Apologises gentlemen. I was confusing the MIDIUSB library with the totally different library USBMIDI.
Maybe it is my dyslexia striking again. After all:-

Dyslexia rules KO

The answer to andigoodman's problem is to use the AllEvents example code from the USBMIDI library. This will print out on the serial monitor any MIDI command it receives on channel 1. If you want it to print out all the channels then simply replace the MIDI.begin(1) with MIDI.begin().

It also sends out random note on and off commands every second as well as a real time clock message. You can stop this from happening by commenting out the send commands.

But in order for it to work you must direct MIDI messages into the Arduino. I have never used MainStage so I don't know how you do this but I know how to do it in Ableton.