This circuit
NOTE: According to several dozens of posts all over the web, the circuit started to work properly when you take out the 100k resistor off pin 8. This is indeed that case and I started receiving the messages. Who knows maybe the same optocouplers made by different companies? since the OP usually says his circuit works too even with the 100k in place.
I have also tried the circuit from instructables using the 6n138 optocoupler. I get the same problem consistently.
The problem: It appears that some of the messages do not make it to the controller OR they do but there's some interference or noise. The source of the issue is unknown as at one point it works just fine (led on pin 13 lights up when I press the Middle C note and turns off when I let go of the middle C note) and periodically it doesn't. I can stil see the RX onbopard led flashing so the midi timecode messages and note messages ARE coming in. It appears though that the data may be different or too muddy to interpreted by the arduino.
I've tested this with 2 midi controllers and an MIDI interface, sending data from daw. Same effect can be observed everywhere.
I also tried this with using a power supply instead of powering the Uno via usb (as usb power is a rad more noisy) - same deal.
2 different midi cables too.
This is the code:
byte commandByte;
byte noteByte;
byte velocityByte;
byte noteOn = 144;
byte noteOff = 128;
void setup(){
Serial.begin(31250);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
digitalWrite(13,LOW);
digitalWrite(12,LOW);
}
void loop(){
while (Serial.available() > 2){
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){
digitalWrite(13,HIGH);//turn on led
}
if (noteByte == 61){
digitalWrite(12,HIGH);//turn on led
}
}
else if (commandByte == noteOff){//if note on message
//check if note == 60 and velocity > 0
if (noteByte == 60){
digitalWrite(13,LOW);//turn on led
}
if (noteByte == 61){
digitalWrite(12,LOW);//turn on led
}
}
}
I know the code works.
Video cuts out a bit too early. I was saying that First I check if there is a note On and then I check which note was pressed since it all comes in one message of [status, data byte, data byte].
So I had 2 more variations of the code (most of which I got from here or instructubles):
-
Just turning the led if the Note On message comes in, regardless of which note - that works with 100% accuracy but it just triggers front any note, I needed to do something else for every note.
-
Since the data comes in in packets, I simply check which note it is as soon as the serial data comes in. Since this would only change IF a message came it, I just made a Boolean that toggled between on and off state whenever the midi message with this specific note came in. It technically did the trick. I was actually able to get the two leds to light up separately since the midi messages send 2 messages (one for when key is pressed and another for when key is let go, both containing the "which key" data), however there was is still an occasion when a message would not come in or interpreted right and the led would effectively invert. So it seems that I get slightly better results if I'm using only one piece of data for checks. As soon as I start checking if the incoming message is a note On message AND if this message is a specific note - that's when this issue become more frequent.
=========================================================
PS: Here are some things I've been finding and testing myself:
cbradburne:
Ok, back so soon!!I forgot to mention, I also had issues reading MIDI while I still had a USB cable plugged in to the Arduino I guess because it was conflicting with the Rx pin.
So I'd definitely recommend you try running your Arduino from a battery or another PSU, not USB.
Cheers,
Col