Arduino Uno MIDI Controller

Morning all.

I am attempting to create a MIDI controller using an Arduino Uno board, which has 5 switches as inputs, with the hope of outputting MIDI code via serial (then hopefully via USB direct eventually) to be read on lighting control software. I’ll be honest - I’m getting nowhere!

I’m new to this game so I’m just trying to borrow and adapt codes and guides found on the internet.

I have connected channels 8-12 to a push button each, and also to Gnd via an 11k resistor… The other side of each switch is connected to the 5v pin.

I stumbled across a guide with a code for a 2 channel MIDI controller, which I have modified to incorporate 5 channels.

#define LED 13    // LED pin on Arduino board
#define switch1 8              // 1st Switch
#define switch2 9               // 2nd Switch
#define switch3 10               // 3rd Switch
#define switch4 11               // 4th Switch
#define switch5 12               // 5th Switch
#define MIDI_COMMAND_CONTROL_CHANGE 0xB0
#define MIDI_COMMAND_NOTE_ON 0x90
#define MIDI_COMMAND_NOTE_OF 0x80


//Variables
int switch1LastState = 0;
int switch1CurrentState = 0;
int switch2LastState = 0;
int switch2CurrentState = 0;
int switch3LastState = 0;
int switch3CurrentState = 0;
int switch4LastState = 0;
int switch4CurrentState = 0;
int switch5LastState = 0;
int switch5CurrentState = 0;


// the format of the message to send Via serial 
typedef union {
    struct {
 uint8_t command;
 uint8_t channel;
 uint8_t data2;
 uint8_t data3;
    } msg;
    uint8_t raw[4];
} t_midiMsg;




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);
  pinMode(switch1,INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  Serial.begin(115200);
  
  blinkLed(3);
}


void loop() {
  
t_midiMsg midiMsg1;  // MIDI message for Switch 1
t_midiMsg midiMsg2;  //MIDI message for Swtich 2
t_midiMsg midiMsg3;  //MIDI message for Swtich 3
t_midiMsg midiMsg4;  //MIDI message for Swtich 4
t_midiMsg midiMsg5;  //MIDI message for Swtich 5
switch1CurrentState = digitalRead(switch1);
switch2CurrentState = digitalRead(switch2);
switch3CurrentState = digitalRead(switch3);
switch4CurrentState = digitalRead(switch4);
switch5CurrentState = digitalRead(switch5);


if (switch1CurrentState == 1){
    if(switch1LastState == 0){
                  midiMsg1.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
          midiMsg1.msg.channel = 1;
          midiMsg1.msg.data2   = 1;
          midiMsg1.msg.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg1.raw, sizeof(midiMsg1));                           
         blinkLed(2);           }
                                 }
switch1LastState = switch1CurrentState;


if (switch2CurrentState == 1){
    if(switch2LastState == 0){
                  midiMsg2.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
          midiMsg2.msg.channel = 2;
          midiMsg2.msg.data2   = 2;
          midiMsg2.msg.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg2.raw, sizeof(midiMsg2));                            
         blinkLed(2);           }
                                 } 
    switch2LastState = switch2CurrentState;


if (switch3CurrentState == 1){
    if(switch3LastState == 0){
                  midiMsg3.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
          midiMsg2.msg.channel = 3;
          midiMsg2.msg.data2   = 3;
          midiMsg2.msg.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg3.raw, sizeof(midiMsg3));                            
         blinkLed(2);           }
                                 } 
    switch3LastState = switch3CurrentState;


if (switch4CurrentState == 1){
    if(switch4LastState == 0){
                  midiMsg4.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
          midiMsg4.msg.channel = 4;
          midiMsg4.msg.data2   = 4;
          midiMsg4.msg.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg4.raw, sizeof(midiMsg4));                            
         blinkLed(2);           }
                                 } 
    switch4LastState = switch4CurrentState;


if (switch5CurrentState == 1){
    if(switch5LastState == 0){
                  midiMsg5.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
          midiMsg5.msg.channel = 5;
          midiMsg5.msg.data2   = 5;
          midiMsg5.msg.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg5.raw, sizeof(midiMsg5));                            
         blinkLed(2);           }
                                 } 
    switch5LastState = switch5CurrentState;
}

I verified and uploaded the code, which brought up no errors, but when i have tested it with Serial to Midi convertor, and MIDI-OX monitor software, I seem to be getting nothing! The LED on pin 13 is flashing when I press the buttons so the board does seem to be responding, just not outputting any code.

Can anyone please offer any assistance?
Thanks in advance
Liam

I have connected channels 8-12 to a push button each

Channels? MIDI has channels. The Arduino has pins.

and also to Gnd via an 11k resistor.

You need to draw a circuit diagram, but this sounds wrong. It's far easier to use the internal pullup resistors. Connect one leg to ground. Connect the other leg to a digital pin. Turn on the pullup resistor using INPUT_PULLUP in the pinMode() call.

#define switch1 8              // 1st Switch
#define switch2 9               // 2nd Switch
#define switch3 10               // 3rd Switch
#define switch4 11               // 4th Switch
#define switch5 12               // 5th Switch

const int and an array!

int switch1LastState = 0;
int switch1CurrentState = 0;
int switch2LastState = 0;
int switch2CurrentState = 0;
int switch3LastState = 0;
int switch3CurrentState = 0;
int switch4LastState = 0;
int switch4CurrentState = 0;
int switch5LastState = 0;
int switch5CurrentState = 0;

Two more arrays, not 10 statements.

  Serial.begin(115200);

That's not a MIDI speed.

          Serial.write(midiMsg1.raw, sizeof(midiMsg1));

You want to send sizeof(midiMsgN.raw) bytes. That may not be the same as sizeof(midiMsgN).

Unioning 4 bytes and a 4 byte array is pretty silly. The whole union bit is unnecessary.

         blinkLed(2);           }
                                 }

Nothing on the same line as the }! Your code just screams to have Tools +Auto Format let loose on it. Don't post again without letting it loose.

Paul,
Although I do appreciate the fact you have replied, there really is no need to be so patronising with me....

Channels? MIDI has channels. The Arduino has pins.

Two more arrays, not 10 statements.

That's not a MIDI speed.

Unioning 4 bytes and a 4 byte array is pretty silly

Don't post again without letting it loose.

As I did say I'm new to this so I do apologise if my lack of knowledge and use of wrong codes and terminology offends you. I'll be honest I expected a better welcome to the forum than this.
I was hoping to receive some help on here, not have someone completely pull my first post on the forum to bits and make fun of me.

not have someone completely pull my first post on the forum to bits and make fun of me.

I'm sorry you feel that way.

I presumed that you knew something about MIDI before embarking on this project. Knowing nothing about MIDI and nothing about programming, and being so thin-skinned just aren't going to play well together.

Think I've probably read you wrong then! Apologies for the rant!

My knowledge about MIDI and programming is very limited to be honest, its my first attempt at anything like this! I'll put together a circuit diagram of what I've done then hopefully it will make more sense what I've tried to do :slight_smile:

This is the circuit I have used. Would this work for the application I have described?

Arduino MIDI Controller Circuit.bmp (958 KB)

Would this work for the application I have described?

Looks like it should.

Can you please offer any advice on what I need to do on the coding?

Can you please offer any advice on what I need to do on the coding?

We need to start with knowing what the serial data is being sent to. Typically, MIDI devices need to have the baud rate set to 38400, not 115200. That may be all that is really wrong with your code. It's unnecessarily complicated, but that's a separate issue.

I'm using a piece of software called Freestyer DMX to control a DMX light show. It has capability to be controlled by an external MIDI controller. I am attempting to build my own MIDI controller rather than buying a pre-made one.

As the Arduino UNO (so I've read) does not natively support MIDI through USB, I have installed MIDI Yoke, Serial MIDI converter, and MIDI OX to monitor MIDI signals. When I have got the coding correct and the signals are being received by MIDI OX, I will check that the signals can be received by Freestyler. I have read about a hack which can be done to the Uno to turn it into a native MIDI HID through USB device, which I plan to eventually do when the coding is working.

I have changed the baud rate to 38400, and set the baud rate to 38400 on Serial MIDI Converter, and it's status indicators (both RX and TX) are now flashing green when a button is pressed, but MIDI OX is not receiving any MIDI data.

I have changed the baud rate to 38400, and set the baud rate to 38400 on Serial MIDI Converter, and it's status indicators (both RX and TX) are now flashing green when a button is pressed, but MIDI OX is not receiving any MIDI data.

Then, it would seem that the problem isn't the Arduino code. I don't like how complex your struct is, and I'd fix that, but that may have nothing to do with the problem.

The struct could look like:

typedef struct {
 uint8_t command;
 uint8_t channel;
 uint8_t data2;
 uint8_t data3;
} t_midiMsg;

Then,

   midiMsg1.msg.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg1.msg.channel = 1;
   midiMsg1.msg.data2   = 1;
   midiMsg1.msg.data3   = 0; /* Velocity */

becomes:
midiMsg1.command = MIDI_COMMAND_CONTROL_CHANGE;
midiMsg1.channel = 1;
midiMsg1.data2 = 1;
midiMsg1.data3 = 0; /* Velocity */

and:
          Serial.write(midiMsg1.raw, sizeof(midiMsg1));
becomes:
          Serial.write(midiMsg1, sizeof(midiMsg1));

So the final outcome should look something like this?

#define LED 13    // LED pin on Arduino board
#define switch1 8              // 1st Switch
#define switch2 9               // 2nd Switch
#define switch3 10               // 3rd Switch
#define switch4 11               // 4th Switch
#define switch5 12               // 5th Switch
#define MIDI_COMMAND_CONTROL_CHANGE 0xB0
#define MIDI_COMMAND_NOTE_ON 0x90
#define MIDI_COMMAND_NOTE_OF 0x80


//Variables
int switch1LastState = 0;
int switch1CurrentState = 0;
int switch2LastState = 0;
int switch2CurrentState = 0;
int switch3LastState = 0;
int switch3CurrentState = 0;
int switch4LastState = 0;
int switch4CurrentState = 0;
int switch5LastState = 0;
int switch5CurrentState = 0;


// the format of the message to send Via serial 
typedef struct {
 uint8_t command;
 uint8_t channel;
 uint8_t data2;
 uint8_t data3;
} t_midiMsg;



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);
  pinMode(switch1,INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  Serial.begin(38400);
  
  blinkLed(3);
}


void loop() {
  
midiMsg1.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg1.channel = 1;
   midiMsg1.data2   = 1;
   midiMsg1.data3   = 0; /* Velocity */

          /* Send note on */
          Serial.write(midiMsg1, sizeof(midiMsg1));                            
         blinkLed(2);           }
                                 } 
    switch5LastState = switch5CurrentState;
}

Arduino software doesn't like that! Think I've got the wrong end of the stick somewhere!

Think I've got the wrong end of the stick somewhere!

What happened to the declarations of midiMsg1, etc?

Schoolboy error, I've not repeated the code for each button!

Think I’ve done the correct edits now…

#define LED 13    // LED pin on Arduino board
#define switch1 8              // 1st Switch
#define switch2 9               // 2nd Switch
#define switch3 10               // 3rd Switch
#define switch4 11               // 4th Switch
#define switch5 12               // 5th Switch
#define MIDI_COMMAND_CONTROL_CHANGE 0xB0
#define MIDI_COMMAND_NOTE_ON 0x90
#define MIDI_COMMAND_NOTE_OF 0x80


//Variables
int switch1LastState = 0;
int switch1CurrentState = 0;
int switch2LastState = 0;
int switch2CurrentState = 0;
int switch3LastState = 0;
int switch3CurrentState = 0;
int switch4LastState = 0;
int switch4CurrentState = 0;
int switch5LastState = 0;
int switch5CurrentState = 0;


// the format of the message to send Via serial 
typedef union {
typedef struct {
 uint8_t command;
 uint8_t channel;
 uint8_t data2;
 uint8_t data3;
} t_midiMsg;




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);
  pinMode(switch1,INPUT);
  pinMode(switch2, INPUT);
  pinMode(switch3, INPUT);
  pinMode(switch4, INPUT);
  pinMode(switch5, INPUT);
  Serial.begin(38400);
  
  blinkLed(3);
}


void loop() {
  
t_midiMsg midiMsg1;  // MIDI message for Switch 1
t_midiMsg midiMsg2;  //MIDI message for Swtich 2
t_midiMsg midiMsg3;  //MIDI message for Swtich 3
t_midiMsg midiMsg4;  //MIDI message for Swtich 4
t_midiMsg midiMsg5;  //MIDI message for Swtich 5
switch1CurrentState = digitalRead(switch1);
switch2CurrentState = digitalRead(switch2);
switch3CurrentState = digitalRead(switch3);
switch4CurrentState = digitalRead(switch4);
switch5CurrentState = digitalRead(switch5);


if (switch1CurrentState == 1){
    if(switch1LastState == 0){
   midiMsg1.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg1.channel = 1;
   midiMsg1.data2   = 1;
   midiMsg1.data3   = 0; /* Velocity */


          /* Send note on */
          Serial.write(midiMsg1, sizeof(midiMsg1));                        
         blinkLed(2);           }
                                 }
switch1LastState = switch1CurrentState;


if (switch2CurrentState == 1){
    if(switch2LastState == 0){
   midiMsg2.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg2.channel = 1;
   midiMsg2.data2   = 1;
   midiMsg2.data3   = 0; /* Velocity */



          /* Send note on */
          Serial.write(midiMsg2, sizeof(midiMsg2));                           
         blinkLed(2);           }
                                 } 
    switch2LastState = switch2CurrentState;


if (switch3CurrentState == 1){
    if(switch3LastState == 0){
   midiMsg3.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg3.channel = 1;
   midiMsg3.data2   = 1;
   midiMsg3.data3   = 0; /* Velocity */



          /* Send note on */
          Serial.write(midiMsg3, sizeof(midiMsg3));                          
         blinkLed(2);           }
                                 } 
    switch3LastState = switch3CurrentState;


if (switch4CurrentState == 1){
    if(switch4LastState == 0){
   midiMsg4.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg4.channel = 1;
   midiMsg4.data2   = 1;
   midiMsg4.data3   = 0; /* Velocity */



          /* Send note on */
          Serial.write(midiMsg4, sizeof(midiMsg4));                          
         blinkLed(2);           }
                                 } 
    switch4LastState = switch4CurrentState;


if (switch5CurrentState == 1){
    if(switch5LastState == 0){
   midiMsg5.command = MIDI_COMMAND_CONTROL_CHANGE;
   midiMsg5.channel = 1;
   midiMsg5.data2   = 1;
   midiMsg5.data3   = 0; /* Velocity */



          /* Send note on */
          Serial.write(midiMsg5, sizeof(midiMsg5));                           
         blinkLed(2);           }
                                 } 
    switch5LastState = switch5CurrentState;
}

But its now bringing up an error relating to the ‘}’ at the end.
I’m wondering if I’ve bitten off more than I can chew!!

Get rid of this:

typedef union {

It now isn’t happy with this bit

          Serial.write(midiMsg1, sizeof(midiMsg1));

Thanks for your help by the way :slight_smile:

It now isn't happy with this bit

Try this:
    Serial.write((uint8_t *)&midiMsg1, sizeof(midiMsg1));

It's happily uploading to the Uno now, still not posting any MIDI message though. I'm starting to think I'm maybe doing something else wrong with the serial to midi data processing. With the code as it now is, do you think it should be posting MIDI data when the buttons are pressed?