MIDI communication between arduinos

HI,

I’ve done many search, and just can’t find the answer.

I’m trying to use 2 arduino nano (potentially 5) to communicate each other with MIDI.

I want to use MIDI communication to send NoteOn to control leds by switch on other nano. And vice-versa….

for now , i’m only starting to test communication between 2 nano to setup my basic.

code for the sender:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST;
//int note;
//int velocity;
//int channel;


int NIGHTSW;
int NIGHTStatus;
int LASTNIGHTStatus;
int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

void HandleNoteOn(byte channel, byte note, byte velocity) {
  if (note == 1) {
    digitalWrite(MASTEROUT, velocity * 2);
  }
 
}
void setup() {

Serial.begin(31250);

  
  MIDI.begin(MIDI_CHANNEL_OMNI);

        TEST = 11;
        pinMode(TEST, OUTPUT);
        MASTEROUT = 8;
        pinMode(MASTEROUT, OUTPUT);
        
        MASTERSW = 12;
        pinMode(MASTERSW, INPUT_PULLUP);
        

        MIDI.setHandleNoteOn(HandleNoteOn);

}

void loop() {
MIDI.read();

MASTERStatus = digitalRead(MASTERSW);
if (MASTERStatus != LASTMASTERStatus) {
    if (MASTERStatus == HIGH){
      digitalWrite(MASTEROUT, HIGH);
      MIDI.sendNoteOn(1, 1, 127); 
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
    }
    else { 
      digitalWrite(MASTEROUT, LOW);
      MIDI.sendNoteOn(1, 1, 0);}
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
}
LASTMASTERStatus = MASTERStatus;

digitalWrite(TEST, HIGH);
}

code for the receiver

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST;
//int note;
//int velocity;
//int channel;


int NIGHTSW;
int NIGHTStatus;
int LASTNIGHTStatus;
int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

void HandleNoteOn(byte channel, byte note, byte velocity) {
  if (note == 1) {
    digitalWrite(MASTEROUT, velocity * 2);
  }
 
}
void setup() {

Serial.begin(31250);

  
  MIDI.begin(MIDI_CHANNEL_OMNI);

        TEST = 4;
        pinMode(TEST, OUTPUT);
        MASTEROUT = 6;
        pinMode(MASTEROUT, OUTPUT);
        TEST = 8;
        pinMode(TEST, OUTPUT);
        

        MIDI.setHandleNoteOn(HandleNoteOn);

}

void loop() {
MIDI.read();



digitalWrite(TEST, HIGH);
}

i’ve connected the TX from the sender to the RX of the receiver and TX from the receiver to the RX of the sender.

so far, my led on the sender respond to the switch, but the led on the receiver have no reaction…

suggestion?

Welcome to the forum

I don't know much about MIDI but your receiver code seems just to do a MIDI read then unconditionally set the LED pin HIGH

void loop()
{
    MIDI.read();
    digitalWrite(TEST, HIGH);
}

Should it not at least be checking that something has been received and, if so, that it indicates that the LED should be turned on (or off if that is what you want to do) ?

1 Like

thanks for the reply,

the TEST led is just for making sure my board is working. It’s not related to the MIDI.

the MASTEROUT is the LED that i’m trying to activate with my MASTERSW

As I said I don't know much about MIDI but how and where is the HandleNoteOn() function called ?

It's a callback set by:
MIDI.setHandleNoteOn(HandleNoteOn);

Please share your schematic. A picture of hand drawn is fine.

Have a look at the examples included with the MIDI.h library.

For instance 'input'

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

// -----------------------------------------------------------------------------

// This example shows the old way of checking for input messages.
// It's simpler to use the callbacks now, check out the dedicated example.

#define LED 13                   // LED pin on Arduino Uno

// -----------------------------------------------------------------------------

void BlinkLed(byte num)         // Basic blink function
{
    for (byte i=0;i<num;i++)
    {
        digitalWrite(LED,HIGH);
        delay(50);
        digitalWrite(LED,LOW);
        delay(50);
    }
}

// -----------------------------------------------------------------------------

void setup()
{
    pinMode(LED, OUTPUT);
    MIDI.begin();           // Launch MIDI, by default listening to channel 1.
}

void loop()
{
    if (MIDI.read())                // Is there a MIDI message incoming ?
    {
        switch(MIDI.getType())      // Get the type of the message we caught
        {
            case midi::ProgramChange:       // If it is a Program Change,
                BlinkLed(MIDI.getData1());  // blink the LED a number of times
                                            // correponding to the program number
                                            // (0 to 127, it can last a while..)
                break;
            // See the online reference for other message types
            default:
                break;
        }
    }
}

Also keep in mind that by default, MIDITHRU is enabled, so connecting tx-> rx and rx -> tx you will create an infinite transmission the moment you send anything from anywhere.

So be sure to add in setup()

 MIDI.turnThruOff();

after begin();

here<s the draw

i redo my sender code:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST; // to see if my board is OK
//int note;
//int velocity;
//int channel;


//int NIGHTSW;
//int NIGHTStatus;
//int LASTNIGHTStatus;
//int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

//void HandleNoteOn(byte channel, byte note, byte velocity) {
//  if (note == 1) {
//    digitalWrite(MASTEROUT, velocity * 2);
//  }
 
//}
void setup() {

Serial.begin(31250);

  
  MIDI.begin(MIDI_CHANNEL_OMNI);

        TEST = 11;
        pinMode(TEST, OUTPUT);
        MASTEROUT = 8;
        pinMode(MASTEROUT, OUTPUT);
        
        MASTERSW = 12;
        pinMode(MASTERSW, INPUT_PULLUP);
        

        //MIDI.setHandleNoteOn(HandleNoteOn);

}

void loop() {
MIDI.read();

MASTERStatus = digitalRead(MASTERSW);
if (MASTERStatus != LASTMASTERStatus) {
    if (MASTERStatus == LOW){
      digitalWrite(MASTEROUT, HIGH);
      MIDI.sendNoteOn(1, 127, 1); 
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
    }
    else { 
      digitalWrite(MASTEROUT, LOW);
      MIDI.sendNoteOn(1, 0, 1);}
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
}
LASTMASTERStatus = MASTERStatus;

digitalWrite(TEST, HIGH); // test if board is OK
}

my redo of the receiver:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST; // to see if my board is OK
//int note;
//int velocity;
//int channel;


//int NIGHTSW;
//int NIGHTStatus;
//int LASTNIGHTStatus;
//int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

void HandleNoteOn(byte note, byte velocity, byte channel) {
  if (note == 1) {
    digitalWrite(MASTEROUT, velocity * 2);
  }
 
}



void setup() {
MIDI.turnThruOff();
Serial.begin(31250);

  
  MIDI.begin(MIDI_CHANNEL_OMNI);

        //TEST = 4;
        //pinMode(TEST, OUTPUT);
        MASTEROUT = 6;
        pinMode(MASTEROUT, OUTPUT);
        TEST = 8;
        pinMode(TEST, OUTPUT);
        

        MIDI.setHandleNoteOn(HandleNoteOn);

}

void loop() {
MIDI.read();



digitalWrite(TEST, HIGH); // test if board is OK
}

So far,

my sender is working well: TEST led is ON, MASTEROUT(led) is on or off depending on MASTERSW state.

my receiver RX TEST led is ON, RX led blink when i activate MASTERSW on my sender, but the MASTEROUT of my receiver stay OFF always.

Sorry, on my receiver, it’s the TX led that blink 1 time when i play with my MASTERSW on my sender

and on my sender , LED & TX led blink 1time everytime i change the state of my MASTERSW

Ok, about your code.

Serial.begin(31250);

this line is redundant. MIDI.begin() takes care of starting the UART at the right speed.

Also the order in which you attach the callback in the receiver to the function and call begin() is opposite to what is in the example.

void setup()
{
    // Connect the handleNoteOn function to the library,
    // so it is called upon reception of a NoteOn.
    MIDI.setHandleNoteOn(handleNoteOn);  // Put only the name of the function

    // Do the same for NoteOffs
    MIDI.setHandleNoteOff(handleNoteOff);

    // Initiate MIDI communications, listen to all channels
    MIDI.begin(MIDI_CHANNEL_OMNI);
}

you use digitalWrite() and then add a value instead of just HIGH & lOW

digitalWrite(MASTEROUT, velocity * 2);

It should anyway work, but it is not correct.

Also you should make a callback for noteOff. Why don't you start with the example and modify that until you have something that does what you want ?

That is not what is supposed to happen, it is supposed to blink briefly at any change.

That doesn't make any sense.

All of this said, since you are not really using MIDI hardware, why do you want to use MIDI to communicate between 2 boards ? you can just use Serial instead if you want.

Hi,

I<m using MIDI, because I’ll be using more function when my communication will work. I’ve try with Serial but didn’t work.

I redo my sketch with your info:

sender:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST; // to see if my board is OK
//int note;
//int velocity;
//int channel;


//int NIGHTSW;
//int NIGHTStatus;
//int LASTNIGHTStatus;
//int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

//void HandleNoteOn(byte channel, byte note, byte velocity) {
//  if (note == 1) {
//    digitalWrite(MASTEROUT, velocity * 2);
//  }
 
//}
void setup() {



  
  MIDI.begin(MIDI_CHANNEL_OMNI);

        TEST = 11;
        pinMode(TEST, OUTPUT);
        MASTEROUT = 8;
        pinMode(MASTEROUT, OUTPUT);
        
        MASTERSW = 12;
        pinMode(MASTERSW, INPUT_PULLUP);
        

        //MIDI.setHandleNoteOn(HandleNoteOn);

}

void loop() {
MIDI.read();

MASTERStatus = digitalRead(MASTERSW);
if (MASTERStatus != LASTMASTERStatus) {
    if (MASTERStatus == LOW){
      digitalWrite(MASTEROUT, HIGH);
      MIDI.sendNoteOn(1, 127, 1); 
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
    }
    else { 
      digitalWrite(MASTEROUT, LOW);
      MIDI.sendNoteOff(1, 0, 1);}
      digitalWrite(LED, HIGH);
      delay(250);
      digitalWrite(LED, LOW);
}
LASTMASTERStatus = MASTERStatus;

digitalWrite(TEST, HIGH); // test if board is OK
}

receiver:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST; // to see if my board is OK
//int note;
//int velocity;
//int channel;


//int NIGHTSW;
//int NIGHTStatus;
//int LASTNIGHTStatus;
//int NIGHTOUT;
int MASTERSW;
int MASTERStatus;
int LASTMASTERStatus;
int MASTEROUT;

void HandleNoteOn(byte note, byte velocity, byte channel) {
  if (note == 1) {
    digitalWrite(MASTEROUT, HIGH);
  }

}

void HandleNoteOff(byte note, byte velocity, byte channel) {
  if (note == 1) {
    digitalWrite(MASTEROUT, LOW);
  }

}

void setup() {
MIDI.turnThruOff();


  
  

        //TEST = 4;
        //pinMode(TEST, OUTPUT);
        MASTEROUT = 6;
        pinMode(MASTEROUT, OUTPUT);
        TEST = 8;
        pinMode(TEST, OUTPUT);
        

        MIDI.setHandleNoteOn(HandleNoteOn);
        MIDI.setHandleNoteOff(HandleNoteOff);
        MIDI.begin(MIDI_CHANNEL_OMNI);

}

void loop() {
MIDI.read();



digitalWrite(TEST, HIGH); // test if board is OK
}

when switching the MASTERSW:

sender:

  • MASTEROUT (sender) respond
  • LED blink 1 time
  • TX blink 1 time

receiver:

  • TX blink 1 time

just made this change on my receiver:

void setup() {
MIDI.turnThruOff();
Serial.begin(31250);

        //TEST = 4;
        //pinMode(TEST, OUTPUT);
        MASTEROUT = 6;
        pinMode(MASTEROUT, OUTPUT);
        TEST = 8;
        pinMode(TEST, OUTPUT);
        

        MIDI.setHandleNoteOn(HandleNoteOn);
        MIDI.setHandleNoteOff(HandleNoteOff);
        //MIDI.begin(MIDI_CHANNEL_OMNI);

}

now the TX led is not blinking anymore when MASTERSW(sender) is switching

but no change on my MASTEROUT (receiver)

i’ve try different way’s sender

MIDI.sendNoteOn(1, 1, 1);

MIDI.sendNoteOff(0, 0, 0);

with receiver:

void HandleNoteOn(byte note, byte velocity, byte channel) {

if (note == 1) {

digitalWrite(MASTEROUT, HIGH);

}

}

void HandleNoteOff(byte note, byte velocity, byte channel) {

if (note == 0) {

digitalWrite(MASTEROUT, LOW);

}

}

but nothing react on my sender.

so there must be something in my communication ….

new redo code receiver: (more clean)

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define LED 13
int TEST; // to see if my board is OK

int MASTEROUT;

void HandleNoteOn(byte note, byte velocity, byte channel) {
  if (note == 1) {
    digitalWrite(MASTEROUT, HIGH);
  }
}

void HandleNoteOff(byte note, byte velocity, byte channel) {
  if (note == 1) {
    digitalWrite(MASTEROUT, LOW);
  }
}

void setup() {
MIDI.turnThruOff();
MASTEROUT = 6;
pinMode(MASTEROUT, OUTPUT);
TEST = 8;
pinMode(TEST, OUTPUT);
MIDI.setHandleNoteOn(HandleNoteOn);
MIDI.setHandleNoteOff(HandleNoteOff);
MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
MIDI.read();
digitalWrite(TEST, HIGH); // test if board is OK
}

TX(receiver) only blink 1 time when MASTEROUT(sender) is going from LOW to HIGH

nothing from HIGH to LOW

just redo my wire, find a ground loop

now TX(receiver) blink 1 time on every change of state MASTERSW

think i’m getting crazy :wink:

maybe it’s in my:

sender:

MIDI.sendNoteOn(1, 127, 1);

and receiver:

void HandleNoteOn(byte note, byte velocity, byte channel) 

the order might be in wrong order?

i have note(pitch) , velocity, channel

i’ve try different order, still nothing

To be able to debug your code, please switch the MIDI communication to use SoftwareSerial and free the UART, so you can use to receive messages from the board to your PC. The SoftwareSerial works fine with MIDI because of the low speed required, so keep a high speed (e.g. 115200 baud) for Serial, and 31250 for the SoftwareSerial.

Note: make sure you correctly initialize MIDI to use a SoftwareSerial object instead of the internal UART, check the MIDI library references/docs. I did it before, I commented "MIDI_CREATE_DEFAULT_INSTANCE();" out, and set Transport this way:

//MIDI_CREATE_DEFAULT_INSTANCE();
#include <SoftwareSerial.h>
using Transport = MIDI_NAMESPACE::SerialMIDI<SoftwareSerial>;
SoftwareSerial mySerial = SoftwareSerial(MIDI_RX, MIDI_TX);
Transport serialMIDI(mySerial);
MIDI_NAMESPACE::MidiInterface<Transport> MIDI((Transport&)serialMIDI);

thx

do you have a complete code, i’m not sure to fully understand how to handle the Serial(115200) and the 31250

A full code? Obviously not, I can only show some snippets from an old project I made, like the one on my post #19 above, anyway after the MIDI constructor and configuration, you can set the Serial with the stadard way, then use the MIDI library (the MIDI speed is handled by the library itself, you don't need to specify it).
Example:

// Default channel to be used
#define MIDI_CHANNEL 1
// The alternate pin for SoftwareSerial
#define MIDI_RX 2
#define MIDI_TX 3

#include <MIDI.h>
//MIDI_CREATE_DEFAULT_INSTANCE();
#include <SoftwareSerial.h>
using Transport = MIDI_NAMESPACE::SerialMIDI<SoftwareSerial>;
SoftwareSerial mySerial = SoftwareSerial(MIDI_RX, MIDI_TX);
Transport serialMIDI(mySerial);
MIDI_NAMESPACE::MidiInterface<Transport> MIDI((Transport&)serialMIDI);
...
//then you other constants and variables...
...
void setup()
{
  Serial.begin(115200); // Use the serial for debugging!
  Serial.println("STARTED");
  MIDI.begin(MIDI_CHANNEL);
...
  // then do what you need to do when starting...
}

void loop()
{
  // handle MIDI the way you need... 
  // In my case I use the read() instead of the events
  if (MIDI.read())
  {
    byte Type = MIDI.getType();
    byte Data1 = MIDI.getData1(); // Note
    byte Data2 = MIDI.getData2(); // Velocity
    byte Channel = MIDI.getChannel();
    // Debug printing of received data
    Serial.print("< Type ");Serial.print(Type);
    Serial.print(" ");Serial.print(Data1);
    Serial.print(" ");Serial.print(Data2);
    ...
    // do what else is needed...
    ...
}

I don't know your skills or experience, and I don't know your requirements (e.g. distance between arduino, type of cable, frequency of this messaging) but I really don't understand why you have chosen MIDI.
Let me say I used a serial communication between arduinos on many projects before, with a simple protocol I designed. I don't see MIDI first because you're forced to keep to that fixed standard (made for music), and second, because sometimes I needed higher speed than 31250 (using a Mega or an Arduino R4 could let you keep serial/USB free for debug/signaling), and third because I can use Bluetooth (it's mapped to Serial) or even switch to WiFi and TCP or UDP packets, to make things easier and more extendable...