Can't read MIDI message on Arduino Mega Serial

Hi there !

I'm trying as a starter to my project to read incoming MIDI messages from a 5 din midi connector to any of my serial Rx pin of my arduino Mega (ideally I'd like to have it on serial 1 2 or 3).

Here's the code I use :

#include <LiquidCrystal_I2C.h>
#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
//MIDI_CREATE_DEFAULT_INSTANCE(); tried also default serial, didn't work


LiquidCrystal_I2C lcd1(0x21, 16, 2);


void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI);  

  lcd1.init();
  lcd1.backlight();
  lcd1.setCursor(0, 0);
  lcd1.print(F("Start"));
}


void loop() {
  
    if (MIDI.read()) 
    {
      lcd1.clear();
      lcd1.setCursor(0, 1);
      lcd1.print("MIDI !");
      lcd1.setCursor(1, 1);
      lcd1.print(MIDI.getType());
    }
}

Neither I see something on my screen nor I see the Rx led blinking or showing any activity.
I'm using a PC817 optocoupler I've read this one isn't ideal but I saw some threads with people making it work.

Here's what I tried so far to make it work :

  • I added a LED between the optocoupler and the wire going to Rx pin to see if something is happening, and I see something : the led blinks regularly and if I press a key or turn a know on my midi keyboard this LED blink very fast but nothing happens on the screen.

  • I also tried to switch the wiring of pin 3 and 4 of the optocoupler without success. (The led blinks the same but with much less intensity if I connect pin4 to GND and pin 3 to the LED / Resistor / Rx wire stuff

  • I tested the Rx1 port of my Mega on pin 19 by sending messages from another arduino and it worked.

I'm also attaching a picture of what I did and the relevant part of my wiring diagram (without the led)


If anyone have ideas, I guess I'm making a silly mistake but I'm running out of ideas on how to troubleshoot this.

Thanks !

Your schematic is definitely wrong. At least you must interchange R1 and R4, and D1 is the wrong way round.
MIDI-In
And the PC817 isn't a good choice - it may or may not work. Dependig on your individual unit. Usually it is too slow.

The schematic you posted is incorrect as well. Pin 2 should not be connected to ground for a MIDI input.

https://midi.org/5-pin-din-electrical-specs

Also in the code I can't see where you set the baud rate of any of the serial ports you want to use to receive MIDI.

You are right, the shield should only be connected at the output side.

Maybe the MIDI library already knows that? :wink:

Hi !

Thanks for your answers !
I rewired everything from scratch as per the diagram you showed me (didn't wired PIN2 to anything) with no more luck. Therefore I ordered a 6N13x optoisolators and I'll update this post as soon as I'll have tested it.

Regarding the setting of serial baud rate I'm following the doc of the midi library which nevers sets it, therefore I assume either MIDI_CREATE_INSTANCE or MIDI.Begin does that for me.
But just to be sure, I changed my code to something simplier which starts serial1 and read bytes in a do while loop but it doesn't worked neither. (and this code works I can test it with another arduino which sends bytes)

Meanwhile I receive my ne optoisolator I'm curious of one thing :
As the LED I set at the output of the PC817 definitely lights up as I press notes or mode knobs and faders why don't I even any single byte on my serial entry ? Shouldn't I see at least some gibbershish stuff on my screen?
Might be a stupid question but as an IT guy I understand quite well the programming part but the electronic part is quite obscure for me.

Lighting up of the Led doesn't mean there is any useful serial signal the HW can detect. You would need a scope to analyse the signal.

No it doesn't know that because it can not know it is connected to a Mega with four serial ports does it? (rhetorical)

So post your best try and lets see how you tried it.

It is unlikely, from your words, that you approached it correctly.

It does know which serial to use ( and it does set the baudrate internally ):

No, we were talking about baud rate, and baud rate is fixed to 31250 as defined by the MIDI standard. So it doesn't depend on which UART you're using, and it could mean a MIDI library should already and autonomously set the baud rate of the device you pass to the constructor. And the library examples clearly show the baud rate is never externally set.

Yes it is to do with the baud rate, that has to be correct.
BUT it also has to know where the data is coming from in order to set the Baud rate.

Have you done much MIDI stuff?

I see it is done here, passing the serial object to the constructor:

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

The midi library I'm using does set the baudrate by default when using MIDI_CREATE_INSTANCE

This library also provides ways to set custom baudrate arduino_midi_library/examples/CustomBaudRate/CustomBaudRate.ino at master · FortySevenEffects/arduino_midi_library · GitHub

Here's the code I used to read "manually" my serial 1 :

#include <LiquidCrystal_I2C.h>
#include <MIDI.h>

//MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

byte commandByte;
byte noteByte;
byte velocityByte;

LiquidCrystal_I2C lcd1(0x21, 16, 2);


void setup() {
  Serial.begin(31250);
  Serial1.begin(31250);
  //MIDI.begin(MIDI_CHANNEL_OMNI);  
  
  lcd1.init();
  lcd1.backlight();
  lcd1.setCursor(0, 0);
  lcd1.print(F("Start"));
}


void loop() {
  
    //if (MIDI.read()) 
    //{
    //  lcd1.clear();
    //  lcd1.setCursor(0, 1);
    //  lcd1.print("MIDI !");
    //  lcd1.setCursor(1, 1);
    //  lcd1.print(MIDI.getType());
    //}

    do{
      if (Serial.available()){
        commandByte = Serial.read();
        noteByte = Serial.read();
        velocityByte = Serial.read();
          lcd1.setCursor(0, 1);
          lcd1.print("MIDI !");
          lcd1.setCursor(1, 1);
          lcd1.print(commandByte);
      }
    }
    while (Serial.available() > 2);

}

The lib has to know that in any case, not only to set the baud rate. How would it be able to receive MIDI bytes if it didn't know where they come in? And if it knows at which serial line the bytes come in, it's also able to set the baud rate at that line. No need to do that in the sketch by yourself.

But that is exactly what @mponsot13 did in his sketch:-

Yeah, but this is his test sketch where he did not use the MIDI lib at all.

Here is a quick example of setting up a serial input. Note how you have to call the ".begin instant in your code. I see no use of this structure in any code referred to in any example on this thread.

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midi6pin);

void setup() {
    Serial.begin(9600);
    Serial;
    delay(2000);
    Serial.println("Transpose test");
    midi6pin.begin(MIDI_CHANNEL_OMNI); 
}

I'm sorry Mike but I don't get your example,

In my second sketch where I don't use MIDI.h this is exaclty what I'm doing, and this code works as I can read bytes sent from another arduino. It's just that my "custom made midi shield" is silent.

If you use structs and classes from midi.h lib you're not supposed to use "serial. begin()" as it's done by the library.
Here's the content of begin() method from "SerialMidi.h" file included in the lib :

struct DefaultSerialSettings
{
    /*! Override the default MIDI baudrate to transmit over USB serial, to
    a decoding program such as Hairless MIDI (set baudrate to 115200)\n
    http://projectgus.github.io/hairless-midiserial/
    */
    static const long BaudRate = 31250;
};

void begin()
	{
        // Initialise the Serial port
        #if defined(AVR_CAKE)
            mSerial. template open<Settings::BaudRate>();
        #else
            mSerial.begin(Settings::BaudRate);
        #endif
	}

So either I fully use Midi.h and MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midi6pin); knows by definition that midi6pin will use the pin 19 of my Mega (defined by HardwareSerial and Serial1 in the call with a baudrate of 31250 as defined in the lib) as in my first example.

Or I totally forget about this lib and use serial1.begin(xxx) and so on as in my second example (which works in other context that midi).

I'm quite convinced the issue I have comes from the electronic part of my "setup".

So I am wasting my time here then am I?

What exactly do you not "get", about what I posted?

Yes you are.

My example was taken from my working code where I was using the MIDI library to get another serial port for a project I made to get another output.

Yes that is one of your problems. This is another you will come across once / if you can get your hardware right. Which given the opto couplers you have decided to use is very debatable.