MIDI messages received not as expected

Hi, I'm new with Arduino and my first project is try to receive MIDI messages from a DAW to control a pair of relays.
I've tried two different circuits to interface the MIDI IN to ARDUINO, and tried with the library MIDI.h, and using bytes with Serial.Read(), but in both cases I'm not receiving what I expected.
With all possibilities I'm receiving the same results.

Sending "ProgramChanges" from the DAW: the Serial Port (translating the bytes) give me back "PitchBenders".
I don't know if someone has had a similiar issue, or can give me a hand.

Any help appreciated.
Thanks in advance!

What would help is if we knew what you did, with schematic and code.
A program change is only two bytes where as a pitch bend is three so it is hard to confuse them.

No I haven’t had, or seen this as a problem before.

Thanks for the response.
Finally I've been following this instructable:

The Wiring for the MIDI IN module is:

And the test code I'm working with:

byte commandByte;
byte noteByte;
byte velocityByte;

void setup(){

//Serial.begin(31250);
Serial.begin(9600);
Serial.println("SETUP");
cli();//stop interrupts

//set timer2 interrupt every 128us
TCCR2A = 0;// set entire TCCR2A register to 0
TCCR2B = 0;// same for TCCR2B
TCNT2 = 0;//initialize counter value to 0
// set compare match register for 7.8khz increments
OCR2A = 255;// = (1610^6) / (7812.58) - 1 (must be <256)
// turn on CTC mode
TCCR2A |= (1 << WGM21);
// Set CS11 bit for 8 prescaler
TCCR2B |= (1 << CS11);
// enable timer compare interrupt
TIMSK2 |= (1 << OCIE2A);

sei();//allow interrupts

}

ISR(TIMER2_COMPA_vect) {//checks for incoming midi every 128us
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
Serial.println("INCOMING");
Serial.println("COMMANDBYTE: " + String(commandByte, BIN));
Serial.println("NOTEBYTE: " + String(noteByte, BIN));
Serial.println("VELOCITYBYTE: " + String(velocityByte, BIN));
}
}
while (Serial.available() > 2);//when at least three bytes available
}

void loop(){
//do whatever here
}

Thanks

Please read the how to use this forum sticky post to learn about posting code, see your code has a 8) which you did not use. Posting in code tags prevents this sort of thing.

Finally I've been following this instructable:

You know my heart sinks when ever I read this. That site is the biggest pile of crap ever. Almost all projects contain mistakes.

That code contains more than most, it is simply rubbish.
You should never print inside an ISR, there is no need for such a convoluted structure for the code. Polling in the loop function is more than adequate.
But your immediate problem is this line:-

while (Serial.available() > 2);//when at least three bytes available

Than means the two byte program change message never gets through. But don’t bother to fix it get some decent code.

Use one of the MIDI libraries the Arduino has and look at the examples on receiving messages that come with them all.
Like this one GitHub - FortySevenEffects/arduino_midi_library: MIDI for Arduino

You're right, I've been too fast without reading all the rules... My fault.

Kind of demotivational, isn't it? If all is crap within those projects...

My first attempt was using this library from Fortyseveneffects, but the MIDI.read() gave exactly the same issue, so I just tried another way to check it with Serial.read() and debug it inside the ISR (only debugging).

Thanks

My first attempt was using this library from Fortyseveneffects, but the MIDI.read() gave exactly the same issue,

OK, if you are willing, then I think we should start with that and work to get it going. You post the code and say what it does on your system and I can check it out with mine. Can you say what your DAW is and maybe even post a file ( MIDI ) so I could try feeding this with my DAW.

No prob. Any help will be appreciated.

Test code:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  // put your setup code here, to run once:
  MIDI.begin(MIDI_CHANNEL_OMNI);
  Serial.begin(9600);
  Serial.println("SETUP");
}

void loop() {
  // put your main code here, to run repeatedly:
  if(MIDI.read()) {
    Serial.println(String(MIDI.getType(), BIN));
  }
}

I'm using CUBASE 5 and CUBASE 10.
I cannot save properly the MIDI file, but basically it has four bars sending a ProgramChange every bar at 73, 85, 99 and 103.
Run 4 times in loop, this is the result:
19:07:51.247 -> ⸮jn11100000
19:07:57.223 -> ⸮11111010
19:07:59.225 -> ⸮11111110
19:08:01.241 -> ⸮ff11100000
19:08:07.235 -> ⸮jn11100000
19:08:09.214 -> 11110110
19:08:13.218 -> ⸮11111010
19:08:15.092 -> ⸮11111010

The MIDI.read() is not been raised every time it sends the ProgramChange, it is sending "randomly" (?).

It's quite simple, so I don't know where could be failing.

Thanks

MIDI_CREATE_DEFAULT_INSTANCE() uses the Serial port (pins 0 and 1). These pins are also connected to the USB-to-Serial converter of the Arduino. When using the Serial port for MIDI, you cannot also use it to print to the Serial monitor.
You have to delete all other uses of "Serial" in your code, especially the Serial.begin(9600), which changes the baud rate to an incorrect value for MIDI. MIDI.begin() calls Serial.begin(31250), which is the correct baud rate for MIDI, but then you override it.

You could try using SoftwareSerial for MIDI, but this is far from ideal. I'd recommend using an Arduino board that either has multiple serial ports, or a board where pins 0 and 1 are not connected to the USB Serial port, like the Arduino Leonardo.

If your goal is to connect the Arduino to your DAW, it's probably easiest to just get a board that has native MIDI over USB support. You can find an overview of boards that support MIDI over USB here.

Pieter

Thanks a lot Pietr!!!
It has opened my eyes.

Way to work?
I found it on https://www.limulo.net/website/coding/physical-computing/midi-interface.html

#include <SoftwareSerial.h>

const byte rxPin = 3;
const byte txPin = 4; // not used for the moment

SoftwareSerial mySerial(rxPin, txPin);

// SETUP ///////////////////////////////////////////
void setup()
{
  pinMode( rxPin, INPUT );
  pinMode( txPin, OUTPUT);
  mySerial.begin( 31250 );

  Serial.begin( 9600 );
}


// LOOP ////////////////////////////////////////////
void loop()
{
  while( mySerial.available() > 0 )
  {
    unsigned char c = mySerial.read();
    Serial.println( c, DEC );
  }
}

So simple as it is, changing the ports.

I still use the Default Serial from the NANO at 9600, only for debug, but I define another virtual Serial on port 3 at 31250.

It works like a charm, getting the correct 192 (11000000) for the program change, and then the number of the program.

Thanks for the help!

Pieter beat me to it, but as you found this is the right solution.
An alternative solution is to use something like Hairless, this is an application that converts serial data into MIDI data inside your computer. You have to use:-

Serial.begin(115200);  // Hairless speed

But then you could also use the serial monitor without changing the speed, although MIDI messages are not in text and will not show up as anything readable.

Nah, don't think he beat you.
It's not a competition.
Thanks both for the help.
I've already connected the relays and they are working taking care of the program change sent.
:smiley:

It's not a competition.

Yes I know, but I saw your post just before I had to make the evening meal so I knew what was wrong. When I was done it was answered. I don’t mind at all and only happy you got your answer sooner.

You might want to see this project I did many many years ago.
http://www.thebox.myzen.co.uk/Hardware/Glockenspiel.html

Great working with you, if you need any more help then just ask.