Pages: 1 2 [3] 4   Go Down
Author Topic: 'midi in" project....  (Read 13232 times)
0 Members and 1 Guest are viewing this topic.
Lyon, France
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 : http://www.compuphase.com/electronics/midi_rs232.htm
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);

}
Logged


berlin
Offline Offline
Sr. Member
****
Karma: 0
Posts: 295
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.

Quote

I find something on the net : http://www.compuphase.com/electronics/midi_rs232.htm
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

Logged

Lyon, France
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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);
 }

}

 


Logged


Lyon, France
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 !
Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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;
  }
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley

Thanks,

High-Tec
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

High-Tec , have you seen this thread? http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1187962258
« Last Edit: July 03, 2008, 11:21:20 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote

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?
Logged

0
Offline Offline
God Member
*****
Karma: 1
Posts: 513
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: July 03, 2008, 01:04:50 pm by dcb » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 4
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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?
Logged

0
Offline Offline
God Member
*****
Karma: 1
Posts: 513
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mem pointed you in the right direction for the code I thought.  
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 111
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you must do the USB route, probably simplest to make a helper application in Processing that will read the MIDI stream and  echo it (or some abstraction thereof) to the Arduino.   MAX/msp also has ability to send specific data to serial ports on MIDI command.

I'd really look into going with MIDI cables, though; if you are going to be using an external keyboard, that would mean you could pick up the data on your Arduino without needing to plug both into another computer just to handle the USB issues.
Logged

Augsburg/Munich, Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 68
&quot;Stay hungry. Stay foolish.&quot;
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.  
[..]
/* 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
[...]
}

Hey, cool idea, doing it with PWM! But how audible is the Hz error in the upper octaves? Has anybody meassured the real errors using a 10bit DAC chip or high accuracy resistor ladder version?
I guess the errors would stay easily below 1% even on a 0-10V range... I'd like to emulate smooth  glides/portamento with an analog feeling smiley How good are commercial MIDI to CV converters?

Cheers, Oli, planing to build a MIDI/CV converter for his tenorion :-D
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 31
What's that sound?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was just writing my own MIDI2CV sketch and ran across this one - very excellent.  thanks for posting it!

The PWM works fairly well once smoothed with an RC-lowpass filter but (predictably) lags a tad in response time, relative to the capacitor used.

I was thinking about using an R2R DAC ladder instead - will post results.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok I have been trying out the code for the midi/cv converter. What values are you guys using for the R-C filter for the pwm output? anyone have a diagram of that bit?

thanks!
Logged

Pages: 1 2 [3] 4   Go Up
Jump to: