'midi in" project....

ok,

i'm working on it now. i'm starting with midi-in on arduino, simply because i don't have midi-in interface but a keyboard with midi-out.

i'm trying my luck with a 4n28 optocoupler. so far i have an LED blinking when i hit a key on the keyboard. the led circuit is seperated from the midi circuit by the 4n28.
(actually its always blinking and just gets brighter when i hit a key !? any idea, someone?).

i wanted to route the serial midi signal through an arduino with the atmega taken out (tip from massimo). the problem is that zterm (my serial read/write application of choice) doesn't allow 31250 bps. so debugging the optocoupler setup won't work this way :frowning:

the question now is whether arduino serial settings (8-n-1) are compatible to midi-serial-communication which is 10-bit long. containing one start bit and one stop bit.
are arduino's settings changable using "secret power"-c ? or should it just work? i'm only understanding half of this.

/ kuk

hi, did you read this one as well?

http://www.tigoe.net/pcomp/code/archives/arduino/000738.shtml#000738

i got it working.
partwise.
that means im only able to read the second byte of the midi byte stream. like:
if (serbyte == 61) {
digitalWrite(ledPin2, HIGH);
}
if (serbyte == 73) {
digitalWrite(ledPin2, LOW);
}

if (serbyte == 62) {
digitalWrite(ledPin3, HIGH);
}
if (serbyte == 74) {
digitalWrite(ledPin3, LOW);
}

..... and so on
that means its just the note number wich is recognized, neither channel nor volume/noteOn/noteOff bytes.
in this code example i use one note to turn on the LED, anotherone to turn it off...
but im already a little bit happy, like this i can read notes. only problem at the moment: there must not be some other midisignals on the wire if yes--big trouble! because theres no channel separation.

greets
woo

cool. nice to know, you're working on it, too.

i had similar semi-satisfying results. since i couldn't get that optocoupler from the schematics i created a similar circuit with an 4N28 (which is basically slower i think). Still it worked until i blew it up by not spending attention to the wiring :frowning: .

stupid over-sensitive electrical devices :stuck_out_tongue:

but i got myself some more of those 4N28 yesterday.

concerning the midi messages, i lost several hours waiting for a "Note off" (i mixed up "note on" and "note off", because of a wrong table somewhere on the net). which is never sent by my keyboard. instead most midi devices send a "note on with zero velocity" to stop a note...
maybe you're experiencing something similar?

//kuk

oh, here is the code i'm working on.

/* ################################ Basic Midi-in for arduino 0.1 
 * reads midi-data from the serial line and lights individual LEDs for "Note on" messages
 * i am still working on the best wiring:
 * it's based on a 4N28 optocoupler to seperate circuits and invert the logic levels 
 * the main problem here is the speed of the optocoupler to retain a clear digital signal.
 
   BUT IT WORKS!
   
   22/09/2006, kuk
 
   kuki_AT_milksoup.net
 */



//######################### DEFINE PINS ON ARDUINO 
int led1 = 2;
int led2 = 3;
int led3 = 4;
int led4 = 5;
int led5 = 6;
int led6 = 7;
int led7 = 8;
int led8 = 9;
int midiEnable = 10; //this one "powers" the 4N28 to avoid having it on all the time, which interferes with bootloading
int statusLed = 13;

//######################### DECLARE VARIABLES 
byte incomingByte;
byte action = 2; // 0=note off , 1= note on
byte note;
byte velocity;

//######################### SETUP EVERYTHING 
void setup() {
  pinMode(statusLed,OUTPUT);   // declare the LED's pin as output
  pinMode(midiEnable,OUTPUT); 
  Serial.begin(31250);        //midi baudrate
  
  //turn midi input on
  digitalWrite(midiEnable, HIGH);
  
  //do fancy startup signal
  blink();
  blink();
}


//######################### MAIN LOOP 
// read serial data, and collect bytes that belong to the same midi message
void loop () {

      if (Serial.available() > 0) {
            //blinkfast();
            incomingByte = Serial.read();

                // collect data: we receive at least 3 bytes when a key gets hit: 1 statusbyte(channel & on/off/etc), and 2 databytes (key + velocity)
                if (incomingByte== 144){ // note on message channel 1
                  action=1;
                  blink();
                }else if (incomingByte== 128){ // note off message channel 1
                  action=0;
                  //blink();
                }else if (incomingByte== 208){ // aftertouch message channel 1
                 // not implemented yet
                }else if (incomingByte== 160){ // polypressure message channel 1
                 // not implemented yet
                }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
                 note=incomingByte;
                 playNote(note, 0); //turns off the corresponding LED
                 note=0;
                 velocity=0;
                 action=2;
                }else if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (next databyte)
                 note=incomingByte;
                }else if ( (action==1)&&(note!=0) ){ // ...and then the velocity data byte 
                 velocity=incomingByte;
                 // now we have our bytes complete, let's make some visual noise
                 playNote(note, velocity);
                 //reset values
                 note=0;
                 velocity=0;
                 action=0;
                }else{
                 //nada
                }
      
      }

}

void blink(){
    digitalWrite(statusLed, LOW);
  delay(500);
  digitalWrite(statusLed, HIGH);
  delay(500);

}

void blinkfast(){
    digitalWrite(statusLed, LOW);
  delay(200);
  digitalWrite(statusLed, HIGH);
  delay(100);

}


void playNote(byte note, byte velocity){
  int value=LOW;
  if (velocity >10){
      value=HIGH;
  }else{
   value=LOW; 
  }
  
  switch (note){
   case 60: //mid-C
    digitalWrite(led1, value);
    break;
   case 62: // D
    digitalWrite(led2, value);
    break;
    
    
  }
  //blink();
 
}

i just finished building the midi in circuit with the 6n138 on breadboard and tested it with your code, kuk.
seems to work fine. ;D

yeehah,

:smiley:

i'm short on time right now, but i will post my schemetics (with 4n28) this evening, too. i got it working pretty reliable now!

//kuk

as i reported the circuit with the 6n138 worked here on breadboard. but now i soldered the circuit on stripboard and nothing is working anymore :frowning:
i tested the optocoupler (0V on the input -> LED light up on the output. seems to work). no idea what might be wrong now.

update: working now again! :wink:
:sunglasses:

hello
I've been trying for sometime to implement a midi input on Arduino : I'm planning to build a midi module out of the MEGADRIVE (Genesis) sound chip
BUT
I stuck with this midi input...
I made a optocoupler interface no problem, with a 6N138 that seem to receive every midi byte OK but with the code below from Kuk, it sort of work execpt it doen't when you make chords.
It seems that only the first 3 bytes (one note bytes) are seen, which I don't interstand because the program should read all the byte until there is no more in the serial buffer.
how can I use the midi polyphonically ??(excuse my french;-)

thanks for your help

this morning I did this debugging program and I made a interesting discovery.
But still I can't explain :
when Arduino receive one note from my midi kboard (a roland SH101) arduino aknowledge receiving 3 bytes (led13) and reconize it as a note on message.
When I send 2 notes, Arduino says 5 bytes and reconize only one time the note on message (noteon; note#, velocity, note#,velocity)
is it standard procedure for midi note message : I guess so,
a program to command LEDs polyphonicaly may take care of this ie be able to command diodes as long as it as never receive another status message.
but still it is weird.
I find something on the net : A MIDI to RS232 adapter (electronic circuit)
if you look at the beguining of the program in C (?)
it is :setserial 31250, 8, 1, 0, 0 for the midi settings (8 bit, parity 1 I suppose)
how can we setup the serial port the same way ?

/* ################################ Basic Midi-in debugging for arduino
use pin 10 to power the optocoupler
leds on pin 2,3,4
*/

//######################### DEFINE PINS ON ARDUINO

int midiEnable = 10; //this one "powers" the 4N28 to avoid having it on all the time, which interferes with bootloading
int statusLed = 13;

//######################### DECLARE VARIABLES
byte incomingByte;

//######################### SETUP EVERYTHING
void setup() {
pinMode(2,OUTPUT); //led indicates note on message incoming
pinMode(3,OUTPUT); //led indicates note off message incoming
pinMode(4,OUTPUT); //led indicates ctrl change message incoming
pinMode(statusLed,OUTPUT); // led indicates midi incoming
pinMode(midiEnable,OUTPUT);
Serial.begin(31250); //midi baudrate

//turn midi input on
digitalWrite(midiEnable, HIGH);

}

//######################### MAIN LOOP
// read serial data and tells if it is note on,note off or ctrl change message (slowed down display for debugging purpose)
void loop () {

if (Serial.available() > 0) {
blink();
delay(200);
incomingByte = Serial.read();

// collect data: we receive at least 3 bytes when a key gets hit: 1 statusbyte(channel & on/off/etc), and 2 databytes (key + velocity)
if (incomingByte== 144){ // note on message channel 1
//digitalWrite(statusLed, HIGH);
blinknoteon();
}
if (incomingByte== 128){ // note off message channel 1
//digitalWrite(statusLed, HIGH);
blinknoteoff();
}
if (incomingByte== 176){ // control change message channel 1
//digitalWrite(statusLed, HIGH);
blinkctrl();
}
}else{
//nada
}
}

void blink(){
digitalWrite(statusLed, HIGH);
delay(50);
digitalWrite(statusLed, LOW);
delay(50);

}

void blinknoteon(){
digitalWrite(2, HIGH);
delay(200);
digitalWrite(2, LOW);
delay(20);

}
void blinknoteoff(){
digitalWrite(3, HIGH);
delay(200);
digitalWrite(3, LOW);
delay(20);

}
void blinkctrl(){
digitalWrite(4, HIGH);
delay(200);
digitalWrite(4, LOW);
delay(20);

}

this morning I did this debugging program and I made a interesting discovery.
But still I can't explain :
when Arduino receive one note from my midi kboard (a roland SH101) arduino aknowledge receiving 3 bytes (led13) and reconize it as a note on message.
When I send 2 notes, Arduino says 5 bytes and reconize only one time the note on message (noteon; note#, velocity, note#,velocity)
is it standard procedure for midi note message : I guess so,
a program to command LEDs polyphonicaly may take care of this ie be able to command diodes as long as it as never receive another status message.
but still it is weird.

hmm, as far as i remember the code i put on the playground does take this into account. yes it seems to be a standard across all midi keyboards that i've tested, though i've never read anything official about it. it makes sense after all.

I find something on the net : A MIDI to RS232 adapter (electronic circuit)
if you look at the beguining of the program in C (?)
it is :setserial 31250, 8, 1, 0, 0 for the midi settings (8 bit, parity 1 I suppose)
how can we setup the serial port the same way ?

do you mean the serial port of your arduino? In that case Serial.begin(31250); is all you need. If you're talking about the serial port of your computer for debugging midi stuff, there is a ftdi-driver hack for windows (and linux??) described here in the forum, to allow uncommon baud rates. if you're on a mac, i can recommend "MIDI Monitor" to see what you're keyboard is sending. for debugging your arduino code your best off with a couple of LEDs as far as i can tell. or maybe try something like the software-serial library to use another pins than TX (1)for the debugging output.

best, kuk

Hi,
I managed to have it working.
now I can go further into my project(s)
1-driving more notes (via SPI interfaced MAX7221)
2-Midimerge
3-driving YM2612
keep you informed !

/* Midi In Basic 0.2 // kuki 8.2007 modified OlivarPremier 5.2008
*


  • listen for midi serial data, and light leds for individual notes

IMPORTANT:
the optocoupler is powered by pin 10

#####################################################################################################################################################
SOMETHING ABOUT MIDI MESSAGES
midi messages start with one status byte followed by 1 or 2 data bytes, depending on the command

example midi message: 144-36-100
the status byte "144" tells us what to do. "144" means "note on".
in this case the second bytes tells us which note to play (36=middle C)
the third byte is the velocity for that note (that is how powerful the note was struck= 100)

example midi message: 128-36
this message is a "note off" message (status byte = 128). it is followed by the note (data byte = 36)
since "note off" messages don't need a velocity value (it's just OFF) there will be no third byte in this case
NOTE: some midi keyboards will never send a "note off" message, but rather a "note on with zero velocity"

do a web search for midi messages to learn more about aftertouch, poly-pressure, midi time code, midi clock and more interesting things.
#####################################################################################################################################################

HARDWARE NOTE:
The Midi Socket is connected to arduino RX through an opto-isolator to invert the midi signal and seperate the circuits of individual instruments.
connect 8 leds to pin2-pin9 on your arduino.

####################################################################################################################################################

*/

//variables setup

byte incomingByte = 255;
byte note = 255;
byte velocity = 255;

int statusLed = 13; // select the pin for the LED

int action=2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {
pinMode(statusLed,OUTPUT); // declare the LED's pin as output
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);

//start serial with midi baudrate 31250 or 38400 for debugging
Serial.begin(31250);
digitalWrite(statusLed,HIGH);
digitalWrite(10, OUTPUT);
}

//loop: wait for serial data, and interpret the message
void loop () {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();

// wait for as status-byte, channel 1, note on or off
if (incomingByte== 144){ // note on message starting starting
action=1;
}else if (incomingByte== 128){ // note off message starting
action=0;
}else if (incomingByte > 144){ // message is anything but note message
action=2; //nothing happens
//not implemented yet
//}else if (incomingByte== 160){ // polypressure message starting
//not implemented yet
//process second byte
}else if ( (incomingByte<=127) && (action ==1 || action==0)&&(note==255) ){ // if we received note number message load this byte in the note byte
note=incomingByte;
//process Third byte
}else if ( (incomingByte<=127) && (action ==1)&&(note!=255) ){ // if we received noteon message load this byte in the velocity byte
velocity=incomingByte;
playNote(note, velocity);
note=255;
}else if ( (incomingByte<=127) && (action ==0)&&(note!=255) ){ // if we received note message load this byte in the velocity byte
velocity=0;
playNote(note, velocity);
note=255;
}else{
//nada
}
}
}

void blink(){
digitalWrite(statusLed, HIGH);
delay(100);
digitalWrite(statusLed, LOW);
delay(100);
}

void playNote(byte note, byte velocity){
int value=LOW;
if (velocity >10){
value=HIGH;
}else{
value=LOW;
}

//since we don't want to "play" all notes we wait for a note between 36 & 44
if(note>=36 && note<44){
byte myPin=note-34; // to get a pinnumber between 2 and 9
digitalWrite(myPin, value);
}

}

now midi in, out (merges message from midi in with messages made by arduino...)

all midi messages are transmitted except sysex and note aftertouch; that should be enough for most live performance with midi.

the goal of this is to be able to plug a midi keyboard into the arduino then to a expander (or computer). then it is easy to add controlers (nunchuck, pot, rotary encoder...).

enjoy !

see olivar-premier.org and go to Arduino !

hi guys,
i just got an arduino two days ago in hopes of making a midi -> din sync, cv/gate, and dcb converter. i have midi in to cv/gate and din sync working. thought i'd share the code so far if anyone is interested. you should be able to process any desired midi message pretty easily by modifying the processMIDI() function. i also give the error in hz for each output cv note since the pwm outputs are only 256-bit. the only external circuitry is a low pass filter on the pwm output (to get a constant cv voltage) and a nte3093 optoisolator on the midi input.

josh

/* MIDI to CV/Gate converter

Error in HZ due to 256-bit resolution of PWM (f_desired - f_synthesized)

0 A0
0.0988 A#0
-0.2105 B0
-0.1113 C1
0 C#1
0.1245 D1
-0.2652 D#1
-0.1402 E1
0 F1
0.1569 F#1
-0.3341 G1
-0.1767 G#1
0 A1
0.1977
-0.4210
-0.2226
0
0.2490
-0.5304
-0.2805
0
0.3138
-0.6682
-0.3534
0 A2
0.3953
-0.8419
-0.4452
0
0.4981
-1.0607
-0.5610
0
0.6275
-1.3365
-0.7068
0 A3
0.7906
-1.6838
-0.8905
0
0.9961
-2.1215
-1.1219
0
1.2550
-2.6729
-1.4135
0 A4
1.5812
-3.3676
-1.7809
0
1.9922
-4.2430
-2.2438
0
2.5101
-5.3458
-2.8270
0 A5
*/

int gatePin = 4;
int cvPin = 5;
int statusLED = 13;
int midiEnable = 2;
byte notes[] = {0,4,9,13,17,21,26,30,34,38,43,47,
51,55,60,64,68,72,77,81,85,89,94,98,
102,106,111,115,119,123,128,132,136,140,145,149,
153,157,162,166,170,174,179,183,187,191,196,200,
204,208,213,217,221,225,230,234,238,242,247,251,255};
int tempo = 1;

void setup() {
pinMode(gatePin, OUTPUT);
pinMode(cvPin, OUTPUT);
pinMode(statusLED, OUTPUT);
pinMode(midiEnable, OUTPUT);
Serial.begin(31250);
digitalWrite(midiEnable, HIGH);
}

void loop() {
readMIDI();
}

// play a note out to cv
void note(byte note, byte velocity) {
analogWrite(cvPin, notes[note-9]);
if(velocity == 0) {
digitalWrite(gatePin, LOW);
} else {
digitalWrite(gatePin, HIGH);
}
}

void blink(int repeat) {
for(int i=0; i<repeat; i++) {
digitalWrite(statusLED, HIGH);
delay(5);
digitalWrite(statusLED, LOW);
delay(1);
}
}

void readMIDI() {
byte incomingMessage[] = {0,0,0};
byte incomingByte = 0;

if(Serial.available() > 0) {
incomingByte = Serial.read();
delay(3); // not sure why i need to delay here, but doesn't work w/o it
if(incomingByte >= 240) {
readSystem(incomingByte);
} else {
incomingMessage[0] = incomingByte;
}
if(Serial.available() > 0) {
incomingByte = Serial.read();
if(incomingByte >= 240) {
readSystem(incomingByte);
} else {
incomingMessage[1] = incomingByte;
}
if(Serial.available() > 0) {
incomingByte = Serial.read();
if(incomingByte >= 240) {
readSystem(incomingByte);
} else {
incomingMessage[2] = incomingByte;
}
}
}
}

processMIDI(incomingMessage);
}

void readSystem(byte incomingByte) {
byte incomingMessage[] = {0,0,0};

// read in the system message
incomingMessage[0] = incomingByte;
if(Serial.available() > 0) {
incomingMessage[1] = Serial.read();
if(Serial.available() > 0) {
incomingMessage[2] = Serial.read();
}
}

processMIDI(incomingMessage);
}

void processMIDI(byte incomingMessage[]) {
switch(incomingMessage[0]) {
case B10010000: // Note on, channel 1
note(incomingMessage[1], incomingMessage[2]);
break;
case B10000000: // Note off, channel 1
note(incomingMessage[1], 0);
break;
case B11111000: // Time code
tempo++;
if(tempo == 24) {
blink(1);
tempo = 0;
}
break;
}
}

Hi Guys,

Has anyone got any code on how to read midi data played from cubase or with a midi keyboard?

I want to use that data to activate a digital out on my arduino,

I'm very new to coding so please be gentle :slight_smile:

Thanks,

High-Tec

High-Tec , have you seen this thread? http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1187962258

High-Tec , have you seen this thread? http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1187962258

Yes but they are all talking about an external piece of hardware wich I don't have.

I'm thinking very radical: an arduino hooks up via USB to the computer.
My Midi keyboard does to!

Is it possible to make an internal connection via coding?

the 4n28 is nothing but an opto-isolator. Midi is cautiously defined to requre opto-isolators on all component interfaces. You can leave it out for your home experiments, but don't sell anything as "midi" without it.

Also, your computer probably has a midi port already, leave usb out of it.

the 4n28 is nothing but an opto-isolator. Midi is cautiously defined to requre opto-isolators on all component interfaces. You can leave it out for your home experiments, but don't sell anything as "midi" without it.

Also, your computer probably has a midi port already, leave usb out of it.

Hm, so no code eh?