Pages: [1] 2 3 ... 11   Go Down
Author Topic: works: MIDI-IN: code + schematics  (Read 47568 times)
0 Members and 1 Guest are viewing this topic.
berlin
Offline Offline
Sr. Member
****
Karma: 0
Posts: 295
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi everybody,

below comes a basic ciruit and sketch for MIDI IN on arduino.
8 leds are lid up to corresponding midi notes

NOTE:
 - make sure that you are not sending midi data after resetting the board. this will keep arduino from starting the program. best keep the midi cable unplugged during a restart

i use a 4n28 optoisolator to both isolate the circuits, and invert the midi signal.



and here the code:
Code:
/* Midi In Basic  0.2 // kuki 8.2007
 *
 * -----------------
 * listen for midi serial data, and light leds for individual notes
 
 IMPORTANT:
 your arduino might not start if it receives data directly after a reset, because the bootloader thinks you want to uplad a new progam.
 you might need to unplug the midi-hardware until the board is running your program. that is when that statusLed turns on.
 
#####################################################################################################################################################
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;
byte note;
byte velocity;


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);
  
  //start serial with midi baudrate 31250 or 38400 for debugging
  Serial.begin(31250);        
  digitalWrite(statusLed,HIGH);  
}

//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== 208){ // aftertouch message starting
       //not implemented yet
    }else if (incomingByte== 160){ // polypressure message starting
       //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);
      note=0;
      velocity=0;
      action=2;
    }else if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
    }else if ( (action==1)&&(note!=0) ){ // ...and then the velocity
      velocity=incomingByte;
      playNote(note, velocity);
      note=0;
      velocity=0;
      action=0;
    }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);
 }

}


i think the code might geht optimized, but it works fine.  smiley

// kuk

Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cool.  I love the schematic.   smiley

Also, with the latest version of the bootloader (i.e. the one that comes on the Diecimila or that you burn onto an NG from Arduino 0009) you shouldn't need to disconnect anything or stop sending data when you reset.  It's smart enough to timeout if you give it bad data.
Logged

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

thank you mr. mellis!
if there are enough people interested, i'll silkscreen it and sell t-shirts of it. 12 euros plus shipping :-)
i could do acrylic on canvas as well.

nice to hear about the smart bootloader. i wonder if it would be possible to fully "circumvent" the bootloader in a future version. maybe if pin 13 was connected to +5v the board would just start the user program. still the new version is a great improvement. thank you for that as well. now i just need to find out the easiest(cheapest) way to burn a bootloader on os x.

//kuk


Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I like the idea of connecting pin 13 to +5V to skip the bootloader.  You might need to disconnect it to upload code, but that's better than needing to disconnect RX just to reset the board.  Especially because pin 13 is probably only rarely used as an input (although it is one of the SPI pins, which might mean that it gets tied high sometimes).

As for burning the bootloader, you might try the USBtinyISP from adafruit industries: http://www.adafruit.com/index.php?main_page=product_info&cPath=16&products_id=46.  It's not yet supported from the Arduino environment, but I just got one and hope to add support at some point.  For now, it should work from the command line with their custom version of avrdude, but I haven't tried it yet.
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

the schematic rocks!!!

D

PS: what's the 100K resistor for? It doesn't seem to make sense electrically, as it's connected to the base of the transistor, which would need a positive voltage to turn it on. Is there any difference if you just ground that pin, or leave it unconnected?
« Last Edit: August 24, 2007, 12:51:14 pm by Daniel » Logged

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

the 100k resistor is for a cleaner signal. the 4n28 contains a phototransistor, the resistor to ground helps discharge the base. it wouldn't work reliably until i found this solution somewhere. there might be better suited optocouplers though.
Logged

Daniel
Guest
 Bigger Bigger  Smaller Smaller  Reset Reset

there should some way to get rid of it, it doesn't make sense electrically.  

Anyway... have you tried a PC900? that's the opto with a digital output.
Logged

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

Quote
there should some way to get rid of it, it doesn't make sense electrically.  

Anyway... have you tried a PC900? that's the opto with a digital output.

actually i used a 4n28, because i use them for anything ;-) i got them quite cheap, and still have plenty lying around. on the other hand, i like the idea of having "standard parts". having found the 100k-solution, even more binds me to my little 6-leggers, as i begin to get a feeling for what they can do, and what they can't. :-?
still i put the pc900 on my shopping list.

i found this pdf, explaining the base resistor: http://www.jaycar.com.au/images_uploaded/optocoup.pdf
on page 2 it says:
Quote
(alternatively...) " tie the base down to ground (or the emitter) via a resistor Rb to assist in removal of stored charge. this can extend the opto's bandwidth usefully (though not dramatically)"..."typically you start with a resistor value of 1mOhm and reduce it gradually down to about 47kOhm to see if the desired bandwidth can be reached."

i know i shouldn't believe everything i read on the internet. but it made sense to me, and worked from the beginning. i'm not sure though, whether i tried much values between 1megaOhm and the 100k  :smiley
right now, it does not work without the 100k resistor (on a bread board that is).

thank you for questioning though. i already forgot about the resistor.

//kuk




Logged

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ooooh,
Quote
I like the idea of connecting pin 13 to +5V to skip the bootloader.  You might need to disconnect it to upload code, but that's better than needing to disconnect RX just to reset the board.  Especially because pin 13 is probably only rarely used as an input (although it is one of the SPI pins, which might mean that it gets tied high sometimes).
I nerver dared to ask for this, because I always thought this idea was put down a long time ago when I didn't even knew the Arduino existed!
This would be my : "top notch, favourite,I waited for this all my life" enhancement to the Arduino. Acutually it's the only one that comes to my mind!
Let's go, hunt that startup-delay down with an on-board jumper
Eberhard

 
Logged

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

Can you confirm that the diode is not strictly needed. My understanding is that it is to protect the photocoupler from accidental reverse voltage.

I'm having trouble with the circuit and am trying to make things as simple as possible. Ie. midi pin 4 directly to 220 res to pin 1 and midi pin 5 directly to pin 2.

Thanks.

Logged

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

Also, can anyone confirm that a 4n37 should work the same as the 4n28. They appear to have the same pinout:

http://rocky.digikey.com/WebLib/Lite-on/Web%20Data/4N35(37).pdf

I just cannot seem to get this to work. smiley-sad

« Last Edit: November 09, 2007, 01:12:32 am by tr909 » Logged

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

tr909,
as you wrote, the diode is to protect the optocoupler from reverse voltage. i didn't test it without, but it should work.

other optocouplers should works as well, as long as they aren't much slower. there should be graphs or numbers in the dateasheet. i used a 4n28 because i once bought a couple of them for another project.

it might be, that my drawing of the midi socket is misleading, or rather that it shows the plug, not the socket. i'm sorry for that. it was a quick drawing when it worked for me. i noticed it some days ago when building another device, but forget to get deeper into it. simply try reversing TX and ground on the socket. please remember the diode in that case because of GOTO LINE 1.

i started on a midi library + real instructions with real images, but this will take me a while. please let me know if you could get it working.

kuk
Logged

FR
Offline Offline
Full Member
***
Karma: 0
Posts: 105
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did it with a 4N35.

I spent a lot of time trying to get it work 'til I understand that the midi connector was reversed.
Try to wire it rear and face view as Kuk explained

Nicolas
« Last Edit: November 09, 2007, 06:38:34 am by nrolland » Logged

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

i'm sorry for that. i've rebuilt this thing several times by now, but always used my original setup as reference not my drawing.
glad i didn't invest in printing t-shirts :-)
Logged

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

hello everyone,  first time posting in these forums so hopefully I won't ask to many silly questions smiley-wink

I've been trying to get kuk's midi input circuit going but I'm having problems, and the most frustrating thing is that it's unclear to me how to debug this.  I'm a novice at this stuff, and I'm trying to use midi input with the arduino for an art project / interactive music installation so any guidance would be greatly appreciated.

As of right now, I'm never getting Serial.Available on the RX input pin (using digtial pin 0).

Some of the steps I've tried:
1) I've verified my input pin works using a simple potentiometer.  I can get Serial.Available to read an input byte with that set-up
2) I've tried both midi plug wiring options as described in this thread.
3) I've tried the circuit with and without the diode.

Now I had access to several 2W resistors.  These things are funny looking becuase they are so fat.  Is it possible these could be overbuilding the circuit and causing it to fail?

I do not have access to a scope, but I do have a multimeter.  Are there any obvious debugging points that I should try?  

Thanks for any help you guys can give,
ccgibson
Logged

Pages: [1] 2 3 ... 11   Go Up
Jump to: