Basic MIDI Code Examples w/ Genuino Micro

Been looking around for some examples / guidelines for MIDI code for use with a Genuino Micro based controller.

There’s tons of examples around but there’s often caveats that specify that they’re for specific Arduino’s only other than the Micro.

Just looking for code examples that show how to send potentiometer and button press CC information to a 5-pin MIDI output socket.

Thanks for any leads or useful examples for the Micro.

If you want to use a regular MIDI socket, you can use whatever Arduino board you like, the code does not change.

If you want to control your computer directly over USB, take a look at my tutorial on how to build an Arduino MIDI controller. You can follow the instructions for the Leonardo (it has the same chip as the micro).

With that board you can connect directly to the PC using USB and have it look like a MIDI device.

You can use the libraries here https://github.com/arduino-libraries/MIDIUSB With Docs at:- https://www.arduino.cc/en/Reference/MIDIUSB

This is some test code that fires off random notes.

/*
 * 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() {
    int val;
  val = random(20,100);
    noteOn(0, val, 64);
    MidiUSB.flush();
    delay(100);
    noteOff(0, val, 64);
    MidiUSB.flush();
   delay(100);
  // controlChange(0, 10, 65); // Set the value of controller 10 on channel 0 to 65
}

Thanks, that’s good to know the board can be used for MIDI using the USB or a 5-pin DIN socket.

I’m principally looking to control hardware synthesisers that have a 5-pin din input, so that would be the Micro’s main use.

So you will need to have an external physical MIDI interface. See this project:- http://www.thebox.myzen.co.uk/Hardware/MIDI_Shield.html

Ah, OK. Was under the impression that a 5-pin DIN output socket can be wired to the Micro via a 220 ohm resistor and the various pots and switches connected to the analogue in/outs as per this example:

http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/

Is that not the case? It would be an output only controller and not connected to the external synths while the code sketch was being uploaded.

Yes, the MIDI connector is connected as shown in that Instructable, to pin 1 of the Arduino.

But why are you using analog inputs? And the Arduino doesn't have analog outputs, only digital (PWM is also digital).

On the Micro, it doesn't matter if you connect something to pins 0 & 1 while uploading, because the USB connection is used for upload. Other boards like the Uno or Mega do need pins 0 & 1 for uploading. In your MIDI sketches, you should replace Serial with Serial1 for the same reason: Serial is the USB connection, and Serial1 is the serial connection on pins 0 & 1.

PieterP: But why are you using analog inputs?

What I'm doing is making a MIDI controller which has 4 x potentiomters, 2 x joysticks and 2 x momentary switches and connecting these to the analogue connectors on the Micro.

I then need to come up with some code that can send CC messages out to a hardware synth from the Micro via a 5-pin MIDI DIN connector, hence me looking around for code examples for MIDI CC that will work with the Micro.

PieterP: In your MIDI sketches, you should replace Serial with Serial1 for the same reason: Serial is the USB connection, and Serial1 is the serial connection on pins 0 & 1.

Thanks, will bear this in mind.

_pmj: What I'm doing is making a MIDI controller which has 4 x potentiomters, 2 x joysticks and 2 x momentary switches and connecting these to the analogue connectors on the Micro.

I then need to come up with some code that can send CC messages out to a hardware synth from the Micro via a 5-pin MIDI DIN connector, hence me looking around for code examples for MIDI CC that will work with the Micro.

Of course, I'm sorry, I confused this with another MIDI thread ;) .

The big problem with Instructables is that by and large they are written by people who do not know what they are doing. We are rather fed up with acting as Instructables correctors here. My advice is never look to that site unless you know more than the person who wrote it so you can spot the mistakes. That method of directly outputting to a MIDI socked is a bit of a fudge. It will work a lot of the time but there are some devices where it will not work because the voltage / current requirement of the MIDI standard is not met.

Grumpy_Mike: That method of directly outputting to a MIDI socked is a bit of a fudge. It will work a lot of the time but there are some devices where it will not work because the voltage / current requirement of the MIDI standard is not met.

So safer / less of a fudge if I was to either use the MIDIUSB connection as you outlined or employ the MIDI shield? I know far less than whoever wrote that instructable so any help appreciated.

So safer / less of a fudge if I was to either use the MIDIUSB connection as you outlined or employ the MIDI shield

Yes I always use that configuration when I need a 5 pin MIDI socket. As you only want to send then it is just the send side of the circuit. There is no point buying a MIDI shield as you only need part of it.

The code example I posted should get you started as it contains an example of sending CC messages.

Grumpy_Mike: The code example I posted should get you started as it contains an example of sending CC messages.

Yes, I uploaded that sketch and it worked fine, many thanks.

I can see the structure of the sketch and what it's doing but not sure how to relate that to the output from a potentiomenter. I'm guessing that you define the number of potentiometers and then apply the CC commands as per your example but unsure how to bolt all that together at this stage.

Read a pot with the analogRead command, this gives a value between 0 and 1023 so divide that by eight to get it in the range 0 to 127 and use that number as the value prameter to the CC message.

Thanks again - found one of your other posts with this code which looks like it should do the job.

AnalogValue0 = analogRead(0);
 //  convert to a range from 0 to 127:
 cc = AnalogValue0/8;
 // check if analog input has changed
 if (abs(lastAnalogValue0 - cc)>1 {
   MIDI.sendControlChange(16,cc,1);
   // update lastAnalogValue zero variable
   lastAnalogValue0 = cc;

AnalogValue1 = analogRead(1);
 //  convert to a range from 0 to 127:
 cc = AnalogValue1/8;
 // check if analog input has changed
 if (abs(lastAnalogValue1 - cc)>1 {
   MIDI.sendControlChange(17,cc,1);
   // update lastAnalogValue one variable
   lastAnalogValue1 = cc;

// and so on

Where MIDI.sendControlChange parameters = (CC number, Control Value, MIDI Channel) - that correct?

Yes but note that was using a different library to the one you need to use so check the order of the parameters .

Ah, so that example was using the MIDI rather than the MIDIUSB library?

Need to get my head around the differences there, will read up on it.

If it can be of any use: This is the code I use to send MIDI messages without extra libraries. Using libraries doesn't really help understanding what you are doing. They are extremely handy, don't get me wrong, but I just like to know what's going on under the hood as well.

I'd suggest that you read up on the MIDI protocol if you haven't already, here are some links to get you started: http://www.instructables.com/id/Custom-Arduino-MIDI-Controller/step6/Code-time-Well-almost-/#MIDI_messages (It's an Instructable, I know, but I did know what I was talking about, agreed, there's a lot of bad information on there, but some really well documented, well researched articles as well.) https://www.midi.org/specifications/item/table-1-summary-of-midi-message (They have recently updated their site, and the actual specification seems to have disappeared, maybe they'll add it again in the future ...) https://www.nyu.edu/classes/bello/FMT_files/9_MIDI_code.pdf (Really good slides, taught me a lot.)

And finally: my code:

/* These are constants (actually preprocessor macros): whenever we put one of these 3 words (the ones in capitals) in our code, the precompiler will replace it by the 0xsomething after the word. 
 This makes our code more readable, instead of typing the meaningless 0x90, we can now just type NOTE_ON, if we want a note to be on. */
#define NOTE_OFF       0x80
#define NOTE_ON        0x90
#define CC             0xB0

/* This is also a constant value (preprocessor macro). If you want to change the number of analog inputs, you can simply do it once on this line, instead of changing it everywhere in your code.*/ 
#define NUMBER_OF_ANALOG_INPUTS  6 // The Uno has 6 analog inputs, we'll use all of them in this example. If you only need 4, change this to 4, and you'll be able to use A4 & A5 as normal I/O pins. 
// NOTE: if you change this value, also change the controllers array, to match the number of inputs and the number of controllers.

#define CHANNEL  1 // Send all messages on channel 1.

/* The list with the corresponding controller numbers: for example, the values of the potentiometer on A0 will be sent as the first controller number in this list, A1 as the second, etc... 
 Here's the list with all controller numbers:  http://midi.org/techspecs/midimessages.php#3  You can change them if you want.*/
int controllers[NUMBER_OF_ANALOG_INPUTS] = { 
  0x10, 0x11, 0x12, 0x13, 0x14, 0x15
};  

int analogVal[NUMBER_OF_ANALOG_INPUTS];  // Declare an array for the values from the analog inputs

int analogOld[NUMBER_OF_ANALOG_INPUTS];  // Declare an array for the previous analog values. (To know if the knob has been turned since the last measurement)


/* The format of the message to send via serial. We create a new data structure, that can store 3 bytes at once.  This will be easier to send as MIDI. */
typedef struct {
  uint8_t status;   // first  byte   : status message (NOTE_ON, NOTE_OFF or CC (controlchange) and midi channel (0-15)
  uint8_t data1;    // second byte   : first value (0-127), controller number or note number
  uint8_t data2;    // third  byte   : second value (0-127), controller value or velocity
} 
t_midiMsg;          // We call this structure 't_midiMsg'

void setup() // The setup runs only once, at startup.
{
  pinMode(13, OUTPUT);   // Set pin 13 (the one with the LED) to output
  digitalWrite(13, LOW); // Turn off the LED
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // We make all values of analogOld -1, so it will always be different from any possible analog reading.
    analogOld[i]=-1;
  }
  Serial1.begin(31250);  // Start a serial connection @31250 baud or pulses per second on digital pin 0 and 1, 31250 baud is the original MIDI speed. The MIDI output is on pin 1 (TX)
  digitalWrite(13, HIGH);// Turn on the LED, when the loop is about to start.
}

void loop() // The loop keeps on repeating forever.
{
  t_midiMsg msg;                                     // create a variable 'msg' of data type 't_midiMsg' we just created
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    if(analogVal[i] != analogOld[i]){                // Only send the value, if it is a different value than last time.
      msg.status = CC;                               // Controll Change
      msg.status = msg.status | CHANNEL-1;           // Channels are zero based (0 = ch1, and F = ch16). Bitwise or to add the status message (s) and channel (c) together: 
                                                    /* status     = 0bssss0000 
                                                     * channel    = 0b0000cccc 
                                                     * | --------------------- (bitwise or)
                                                     * msg.status = 0bsssscccc       
                                                     */
      msg.data1   = controllers[i];                  // Get the controller number from the array above.
      msg.data2   = analogVal[i];                    // Get the value of the analog input from the analogVal array.
      Serial1.write((uint8_t *)&msg, sizeof(msg));   // Send the MIDI message. (send three bytes, starting at the address of msg)
      analogOld[i] = analogVal[i];                   // Put the analog values in the array for old analog values, so we can compare the new values with the previous ones.
      delay(10);                                     // Wait for 10ms, so it doesn't flood the computer/synth with MIDI-messages
    }
  }
}

I think it's fairly well documented, but if anything is unclear, don't hesitate to ask for help!

Pieter

(It's an Instructable, I know, but I did know what I was talking about, agreed, there's a lot of bad information on there, but some really well documented, well researched articles as well.)

That is why I said:- by and large they are written by people who do not know what they are doing.

There is so much bad stuff the blanket advice must be to avoid the site at all costs. After you have been here a bit you will see how much crap we have to try and mop up from that site. The problem with it and the similar hackster.io is that there is absolutely no quality control. Anyone can put up anything.

Grumpy_Mike: That is why I said:- by and large they are written by people who do not know what they are doing.

There is so much bad stuff the blanket advice must be to avoid the site at all costs. After you have been here a bit you will see how much crap we have to try and mop up from that site. The problem with it and the similar hackster.io is that there is absolutely no quality control. Anyone can put up anything.

I know, that's definitely a problem, and I totally agree with you on that.

I think that part of the problem is that the really good documentation is too much and too complicated for beginners, so new users will go read articles that they can understand, and that are more practical, like on Instructables.

But a lot of these Instructables are grossly oversimplified, or encourage bad practices, like omitting LED resistors, driving motor's directly from the I/O pins, no flyback diodes ... all that kind of things. If you don't know what the actual purpose of something is, it's easy to just forget it, or simply ignore it.

But on the other hand, if you write an article explaining why you should use all those extra components, it'll be quite hard to digest for many new users.

Also, the documents at https://www.arduino.cc/en/Tutorial/ often don't make it on the first page of a Google search. I think it would help if they were easier to find, for example links to those pages in the built-in examples (not just a url in the comments that you have to copy and paste), a message when you first open the software. Even on the Getting started page, there's no real help for new users. I mean, when you're new to Arduino, you don't care about libraries, cores, or an introduction, you want to know how you can write code, and make it do something.

I remember myself 'getting started' with Arduino, I opened up the IDE, and it was like Chinese to me: I didn't know anything, didn't know what a compiler was, didn't know what a COM port was ... It would be nice to see an official page explaining those basics, and point you to some specific examples to get started, like blink. There should ideally be some structure, just a list of separate examples is not very handy: you don't know what the reader already knows, for example, if you offer the examples in a particular order, you can gradually explain things, you don't have to explain the basics in every example, etc ...

And I know that's exactly what those books do, but they can be pricey, I didn't really want to spend €20-€30 on a book without knowing if it was any good, and there were just too many choices. One or two recommendations on the Getting started page would be much easier for beginners.

Anyway, that was enough complaining for an entire week, I'm sorry ;) .