If you know absolutely nothing about MIDI note, velocity, and pitchbend or are confused about what MIDI does and why you would want to use it, check out my What is MIDI? instructable.
Remove these ads by
Signing UpStep 1: Bytes and Bits
11010111
Each 1 or 0 in this byte is a bit. The leftmost bit is called the most significant bit (or MSB) and the rightmost bit is called the least significant bit (or LSB).
Bytes of the form above are binary numbers because they are expressed using only 1's and 0's. We can convert this number to base ten as well:
11010111 in binary (base 2) = 215 in decimal (base 10)
If you need help converting numbers from binary to decimal or vice versa check out Wolfram Alpha. Type in a binary number followed with "from binary to decimal" to get the decimal equivalent. Wolfram Alpha is also great for converting to and from hexadecimal.
Wikipedia is a good resource for more information about bytes and binary.















































Visit Our Store »
Go Pro Today »




http://en.wikipedia.org/wiki/MIDI_beat_clock
scroll down to the "system real-time messages" in this table:
http://www.midi.org/techspecs/midimessages.php
you just need to check to see what type of messages you are receiving with the midi in, if they are equal to 11111000, then you know it is a timing clock message and you can have this modulate the timing of your midi out. does that make sense?
Thanks for this instructable. It's been really handy. I had problems with the MIDI input, with some MIDI devices. I discovered that this was to do with MIDI active sensing. Here's my code for reading the MIDI port that takes into account for MIDI active sensing.
byte incomingByte=0;
byte notebyte=0;
byte velocitybyte=0;
byte statusbuffer=0;
boolean arp_triggernext=false;
boolean firstbyte;
void MIDI_Poll(){
if (Serial.available() > 0) {
do {
// read the incoming byte:
incomingByte = Serial.read();
if (incomingByte>247) {
// this is where MIDI clock stuff is done
switch (incomingByte){
}
}
else if (incomingByte>240) {
statusbuffer = 0;
//sysex stuff done here
}
else if (incomingByte>127) {
statusbuffer = incomingByte;
firstbyte = true;
notebyte = 0;
velocitybyte = 0;
}
else if (statusbuffer!=0) {
if (firstbyte == true) {
// must be first byte
notebyte = incomingByte;
firstbyte = false;
}
else {
// so must be second byte then
velocitybyte = incomingByte;
//process the message here
if (statusbuffer == NOTE_ON && velocitybyte != 0) {
//MIDI note on subroutine
}
else if (statusbuffer == NOTE_OFF || (statusbuffer == NOTE_ON && velocitybyte == 0)) {
//MIDI note off subroutine
}
else if (statusbuffer == PITCH_WHEEL){
//pitch bend wheel
}
else if (statusbuffer == CONTROLLER){
if (notebyte==1) {
//MIDI_modwheel_level = velocitybyte;
}
}
//now clear them for next note
notebyte = 0;
velocitybyte = 0;
firstbyte = true;
}
}
} while (Serial.available() > 0);
}
}
Thanks for the Instructable - the MIDI out section's fantastic, and the tutorial as a whole inspired me to buy an Arduino. Great work!
I've not been able to get MIDI in messages to light an LED though. It's to do with the non-Arduino components, I think: I took a risk and connected the MIDI In directly to my Arduino Nano, and it then works fine - so the issue's not Arduino compatibility. I've tested continuity where I can (resistors, diode) and tried 2 different optocouplers. My optocoupler was Lite-On brand, but I've compared the specs and the pinout/internal circuitry are the same as the device you specify. No oscilloscope here I'm afraid!
http://arduino.cc/en/Reference/SoftwareSerial
but if your incoming midi is coming in with separate channels, then you can read them both from pin 0. do the following:
byte commandByte;
byte noteByte;
byte velocityByte;
void setup(){
Serial.begin(31250);
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;// = (16*10^6) / (7812.5*8) - 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
MIDImessage(commandByte,noteByte,velocityByte);
}
}
while (Serial.available() > 24);//when three bytes available
}
//send MIDI message
void MIDImessage(int command, int data1, int data2) {
Serial.write(command);//send command byte
Serial.write(data1);//send data byte #1
Serial.write(data2);//send data byte #2
}
void loop(){
//do whatever here
}
does that work? are your keys and drums coming into the arduino on separate channels?
byte commandByte;
byte noteByte;
byte velocityByte;
byte newCommandByte = 0;
byte newNoteByte = 0;
byte newVelocityByte = 0;
boolean newote = false;
void setup(){
Serial.begin(31250);
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;// = (16*10^6) / (7812.5*8) - 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
channel = commandByte&B00001111;//last four bits of commandByte
if (channel ==10){//midi channel of your drums
newCommandByte = commandByte &B11110000;//change newCommandByte to commandByte with midi channel 0
noteByte = Serial.read();//read next byte, this gets thrown away
newVelocityByte = Serial.read();//read final byte and set to newVelocityByte
newNote = true;//let's us know there is a new note to send out
} else {//midi channel of your keys
newNoteByte = Serial.read();//read next byte and set newNoteByte
velocityByte = Serial.read();//read final byte, this gets thrown away
}
if (newNote){//
newNote = false;
//send out combined midi on channel 0
MIDImessage(newCommandByte,newNoteByte,newVelocityByte);
}
}
}
while (Serial.available() > 24);//when three bytes available
}
//send MIDI message
void MIDImessage(int command, int data1, int data2) {
Serial.write(command);//send command byte
Serial.write(data1);//send data byte #1
Serial.write(data2);//send data byte #2
}
void loop(){
//do whatever here
}
byte commandByte;
byte noteByte;
byte velocityByte;
byte noteByte1;
byte noteOn = 144;
//light up led at pin 13 when receiving noteON message with note = 60
void setup(){
Serial.begin(31250);
// pinMode(13,OUTPUT);
//digitalWrite(13,LOW);
}
void checkMIDI(){
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
//if (commandByte == noteOn){//if note on message
//check if note == 60 and velocity > 0
//if (noteByte == 60 && velocityByte > 0){
//digitalWrite(13,HIGH);//turn on led
//}
//}
}
}
while (Serial.available() > 24);//when three bytes available
}
void loop(){
if (Serial.available()){
checkMIDI();
MIDImessage(commandByte, noteByte, velocityByte);
}
}
void MIDImessage(int commandByte, int noteByte, int velocityByte) {
Serial.write(commandByte);//send note on or note off command
Serial.write(noteByte);//send pitch data
Serial.write(velocityByte);//send velocity data
}
println (commandByte);
to the loop(), can you copy what gets printed and post it?
By Amanda Ghassaei
July 2012
http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
byte commandByte;
byte noteByte;
byte velocityByte;
byte noteByte1;
byte noteOn = 144;
void setup(){
Serial.begin(31250);
}
void checkMIDI(){
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
}
}
while (Serial.available() > 24);//when three bytes available
}
void loop(){
if (Serial.available()){
checkMIDI();
if (commandByte == noteOn){
noteByte1=noteByte;
}
MIDImessage(commandByte, noteByte1, velocityByte);
}
}
void MIDImessage(int commandByte, int noteByte1, int velocityByte) {
Serial.write(commandByte);//send note on or note off command
Serial.write(noteByte1);//send pitch data
Serial.write(velocityByte);//send velocity data
}
By Amanda Ghassaei
July 2012
http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*/
byte commandByte;
byte noteByte;
byte velocityByte;
byte noteByte1;
byte noteOn = 144;
//light up led at pin 13 when receiving noteON message with note = 60
void setup(){
Serial.begin(31250);
// pinMode(13,OUTPUT);
//digitalWrite(13,LOW);
}
void checkMIDI(){
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
//if (commandByte == noteOn){//if note on message
//check if note == 60 and velocity > 0
//if (noteByte == 60 && velocityByte > 0){
//digitalWrite(13,HIGH);//turn on led
//}
//}
}
}
while (Serial.available() > 24);//when three bytes available
}
void loop(){
if (Serial.available()){
checkMIDI();
if (commandByte == noteOn){
noteByte1=noteByte;
}
//delay(250);
//digitalWrite(13,LOW);//turn led off
MIDImessage(commandByte, noteByte1, velocityByte);
}
}
void MIDImessage(int commandByte, int noteByte, int velocityByte) {
Serial.write(commandByte);//send note on or note off command
Serial.write(noteByte);//send pitch data
Serial.write(velocityByte);//send velocity data
}
I did 2 circuits with 2 - 6N138, one gets the midi drums, the other receives midi keyboard according to the Tx, however I can not manipulate the bytes, the sound gets all mixed up, I can not put the note on the keyboard of my message Midi end. MidiMessage (Status, note, velocity)
The battery comes on channel 10, channel 1 on the keyboard. I can not make the arduino identify one another, and finally put the note on my keyboard, the final message (Status, note keyboard, drums velocity)
Please help me with this code. Thank you.
Hi Amanda
Congratulations on the publication of their work. I'm sure they inspire many people.
I play with my son ten years. He plays drums and I play electronic keyboard. I would like to put a third person in this group and it would be a bassist, but he would own the arduino. lol
Through midi cable, because the battery of my son's electronics.
My idea is as follows. when he touched the kick drum, the bass on my keyboard touch, but he would play the same note I'm playing. For example, my hand would be on the C note, my son would play 123 ... 123, bass keyboard touch C, C, C. .. C, C, C. If I touched the note G, the arduino would do the same thing, he would catch the rhythm of the drum of my son, and put the note in the middle of the sun from midi message.
I think the code of arduino should have a variable which would take note of my keyboard, and replace the bass drum note from my son (because the bass drum is always the same note, if I'm not mistaken is C2 or C3)
I looked at many sketches of arduinos midi, but there are so many bits and Bytes I got a little lost. I am a layman on the subject, but with your help I believe I can. And you can take this idea and create something through their creativity. Thank you.
I'm new to all of this so I'm not quite sure what I can check on MIDI In for continuity. I've noticed that testing Pin4 on my MIDI Out against the TX send tests fine, but none of the Pins on the MIDI in test against the RX pin. Not sure how the optocoupler affects basic continuity testing though.