Atmega328p Midi in problem - lost bytes

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to complete a project and my one problem is intermittent midi data receipt.

I've looked up lots of other folks having the similar issues and tried a lot of the solutions, to no avail so far.

 

What I'm trying to do - read in midi byte stream from a midi keyboard (using old Roland Juno 2 and new Yamaha Motif to test - no difference seen between the two)

 

How - breadboard circuit and c software in AVR Studio 6 using Atmel Ice SPI programmer

 

The problem - completely dropped bytes - always the status (first bytes) which starts with a 1 bit. Never seem to lose the follow on bytes.

If I play keys slowly I can sometimes get all three commands (I get note on, note on vel 0, channel command all notes off) without error, sometimes only the first , the second note on status byte will be missing.

If I hit more than one key I only get the note on status byte for the first, and just the key and vel bytes for the others.

 

What I have tried -

 

Software wise - using ext 20 Mhz xtal, internal 1 Mhz and 8 Mhz and just polling the usart to get the first x bytes and then dumping them to a lcd to make sure the interrupt code wasn't dropping bytes.

No - they don't appear from the usart. No difference between 8 and 20 Mhz (and I'm sure the 20 Mhz was enable as I had to go from 15 to 39 on the baud rate for it to function correctly -

set fuses for no divide by 8 and ext 8 Mhz+ 65 delay for the 20Mhz xtal with 22pf caps)

 

Hardware wise - tried different pull up resisters on the rx line coming from the 6N138 optoisolator. The signal looks good on the scope - a full 5 volts for bits with a 120-220 ohm resister, only a little slope near the top

going back to 5 volts.

 

At this point, I'm not sure what else to test. I am just pulling bytes into a buffer as they are ready and then dumping them, so I can see that I am not getting them all.

But I can't see any issues with the midi in signal either.

 

Midi circuit - midi pin 4 to 220 ohm to pin 2 6N138.

midi pin 5 to OIso pin 3, diode across 2 and 3 cathode on 2

Oiso 1 +5, 5 gnd, 6 to rxIn and a pullup to +5 (currently 120 ohms - 120 and 220 look and work the same)

 

Simplest code test (currently back to 8Mhz so I could use the xtal pins since the xtal didn't change the problem):

 

#define F_CPU 8000000UL 
#define UART_BAUD_RATE 31250

    UBRR0H = 0;
    UBRR0L = 15;  //15 for 8Mhz -  39 for 20Mhz
    UCSR0B = (1<<RXEN0)|(0<<TXEN0); //|(1<<RXCIE0);
    UCSR0C = (3<<UCSZ00);

 //   sei();

 

// and simple code test with interuppts disabled 

short next = 0;
unsigned char testbuf[128];

 

    while(next < 48){
        
        usr  = UCSR0A;
        if((usr & 128) > 0){
            
            data = UDR0;
            testbuf[next++] = data;
        
        }
    }

 

// after falling out of loop, I just show each number slowly on a lcd

 

same result from this test as from my interrupt routine - some bytes, always first command bytes, are missing

 

 

Anyone have suggestions for areas to test and try?

This is a deal breaker for my project.

I have a Atmega1284, with multiple usarts coming just to see if using the second one makes any difference.

 

Thanks,

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
        if((usr & 128) > 0){
            
            data = UDR0;

I don't know how well you RXC test works because you are NOT testing USR0. Try

while (!(UCSR0A & (1<<RXC0)));

 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Switched to that and got the same results - I can go 2 or three notes and then miss a status byte. But if I hit three notes together, so they come one right after another it is

<note on> note vel  note vel note vel - the two orther status bytes don't appear.

 

I thought RXC0 was bit 7 on the 328, I was just working from the spec sheet, so I just used the constant 128 to test the high bit.

 

I've only done midi in PC code where it is coming in from a midi driver, the bytes are all always there.

Can't figure out why I'm losing them here.

On the scope, there is a very short line high between bytes when they are close.

 

A guess was that when there is little separation between the bytes, a new start is not being detected.

That's why I was trying different pull up resistors, in case the rise time was making the  high state between bytes too short for a new incoming byte to be recognized.

I can see the multi bytes groups on the scope, and when I do they are all not getting read.

 

And thanks for looking at my issue. Everything else with this little processor has gone so well.

 

The last time I was working with harware was in the 80's and I had to builld a board full of components to have the processor, bus drivers, ram and eprom for programming,

all of which is now available in a little $5 package. So I was probably expecting this to be a little easier than it has turned out.

 

Still not sure what else to try. The midi in hardware hook ups I have seen are all variations on what I have and I've tried all the variations I could find.

Is there a better optoisolator to use than the 6N138?

 

Thanks,

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As the midi has a strange baud rate have you tried to work out the error at each different clock? Of course the faster the clock the better response as long as the baud error is 0.2% or less.

 

Is there a better optoisolator to use than the 6N138?

Maybe you could post a schematic of how you have the opto wired up to the USART pins??

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At MIDI rate of 31250 bps, you can get a character every 320uS. Is your code fast enough to fetch a character from the uart that often? If not, you'll miss characters.

 

Somehow, that doesn't sound right.

 

31250 bps / 10 = 3125 characters per second or 1 character every 320uS. Yup, that's right.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

Last Edited: Thu. Sep 18, 2014 - 11:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Problem 1 was the fact that midi allows multiple messages without repeating the status byte if it has not changed and follows immediately.

I never found this in any midi docs or book, but found it last night in another post where someone was having problems reading midi files,

the author of the app relplied that status bytes can be skipped in this case. (The post author had never heard this either.)

So that explains most of what I'm seeing.

 

If I play slowly, so that either a note off is sent after the note on, or it seems enough of a time delay has occured, I get the status byte and my device works fine.

So a little recoding going on today.

 

But from looking at the incoming data on the scope, I've ordered and will try the 6N137. It is 2 orders of magnitude faster and should provide a much cleaner signal.

So my hardware seems to be working pretty well, my understanding of some of the details of midi streams, not so much.

Like anything else - the docs only get you started - once you see something in action it's always a little different.

 

Really impressed with the avr studio environment and the atmel ice. Easiest programmer I've even used. And works fine setting fuses, etc.

 

Thanks for the assists.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The schematic I was using from the web (several of them in fact) all showed a 6N138 using a 10K pullup resistor. With a lot of digging, that seems to be the proper pullup for the much faster 6N137. It does not work with the 138. On my scope, when set up that way the bits never reach near 5 volts. I have been able to get the 138 to work now with a 220 ohm pull up. Bits are now up to 5V, though not very sharp, but they work.

I'm still going to try the 137 as soon as it gets in, but my app is now wrking great with the right pull up and understanding th midi code 'short cut' that is not listed in modt of the 'understand midi' docs.

 

I wanted to post my resolution as I have seen lots of similar posts of folks having problems with midi serial data in their projects - check your pullups and try the faster parts.

 

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm fixing a bit of professional gear at the moment. It has a 6N138 with a 10k pullup. 220R sounds way too low - that's 20mA.

 

[edit] I looked at the circuit again.

 

220R for the led

470R for the pullup

10K on the phototransistor base (pin 7)  to 0V

 

Personally, I'd use a Sharp PC900 opto with ic in it.

Last Edited: Sat. Sep 20, 2014 - 07:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Per your note, I went back to 10K. With everything else fixed, it works. The signal level is lower and less sharp but it is working with the mega 328.

220 ohm - 10K is the range I found in online schematics. As long as it works, I'll stick with the higher resistor.

I'll try the 327 when it gets here with the 10K and see what the signal looks like.

 

Thanks for the reply.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
 

Problem 1 was the fact that midi allows multiple messages without repeating the status byte if it has not changed and follows immediately.

I never found this in any midi docs or book, but found it last night in another post where someone was having problems reading midi files,

the author of the app relplied that status bytes can be skipped in this case. (The post author had never heard this either.)

So that explains most of what I'm seeing.

 

If I play slowly, so that either a note off is sent after the note on, or it seems enough of a time delay has occured, I get the status byte and my device works fine.

So a little recoding going on

 

That's very interresting!

 

I have a (maybe) similar problem with a Atmega1284P UART MIDI receiver design (listens to control changes with 6N138 optocoupler (which shows very nice and clean edges, measured with oscilloscope)). If I send the information (from Logic pro) with large pauses (like 3 seconds) I get the 0xC0 code and the 0xnn (control/patch change number) every time, but if the break between each transmitted 2bytes is shorter, then I only get the last byte; 0xnn. I wonder if this can be the case? Where do you have this information from, do you know something about a specific reset-time-limit?

 

And sorry if I hijacked something! (but I guess it must be a bit relevant for some, since I was searching for an answer and ended up in this thread :)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I gather you mean the 'idle' between the two bytes as 'break' means a logic low when talking about uart transmission. From the sounds of it, it is a code problem. When you get a midi command, you process it then return to wait for the next commanf. If your processing takes too long, you'll miss a midi byte. Look at how long you take to process a command. Since you have a logic analyser, you can connect a channel to a spare port pin. In your code you set the port pin when you start to process a command, the reset it when complete. Capture a session along with the midi serial data and you'll be able to see what is happening.

Last Edited: Thu. Nov 5, 2015 - 11:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The original MIDI standard from 1982 had a "feature" called Running Status. This means that if two MIDI messages have the same command byte (0x90 for channel 1) then the second note can skip the command byte and only need send the note value and velocity.

This was because the microprocessors of that era were slow.  The original IBM PC would process 0.5 million instructions per second (MIPS) while today's CPUs do 3000-5000 MIPS.  The 16MHz Arduino AVR does 16 MIPS.

 

So an old keyboard using Running status will send 0x90 0x3c 0x60 0x40 0x60 0x43 0x60 for a C major chord (C3-E3-G3).  Modern MIDI mergers parse the messages and output (usually) the full three byte command for each note. (at least my do).  Notes played slowly get the three byte message while chords get one full Note-on message and remaining notes are Running status.

 

If your MIDI monitor is Rx Interrupt driven and the data bytes are going into a receive buffer, then it is unlikely to be dropping bytes.

 

The  220 ohm resistor is OK because the MIDI pulses at 31250 baud are so short that a good 32 uS blast of current is needed to turn on the opto-isolator's internal LED.  3.3V systems should use 100-150 ohms for the MIDI OUT resistor.

 

The 31250 baud rate is due to a standard 1982 1MHz crystal being divided-by-2 five times.  Opto-isolators in that era were too slow for MIDI, but the Sharp PC900 was designed for MIDI and works well.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:

The original MIDI standard from 1982 had a "feature" called Running Status. This means that if two MIDI messages have the same command byte (0x90 for channel 1) then the second note can skip the command byte and only need send the note value and velocity.

This was because the microprocessors of that era were slow.  The original IBM PC would process 0.5 million instructions per second (MIPS) while today's CPUs do 3000-5000 MIPS.  The 16MHz Arduino AVR does 16 MIPS.

 

So an old keyboard using Running status will send 0x90 0x3c 0x60 0x40 0x60 0x43 0x60 for a C major chord (C3-E3-G3).  Modern MIDI mergers parse the messages and output (usually) the full three byte command for each note. (at least my do).  Notes played slowly get the three byte message while chords get one full Note-on message and remaining notes are Running status.

 

If your MIDI monitor is Rx Interrupt driven and the data bytes are going into a receive buffer, then it is unlikely to be dropping bytes.

 

The  220 ohm resistor is OK because the MIDI pulses at 31250 baud are so short that a good 32 uS blast of current is needed to turn on the opto-isolator's internal LED.  3.3V systems should use 100-150 ohms for the MIDI OUT resistor.

 

The 31250 baud rate is due to a standard 1982 1MHz crystal being divided-by-2 five times.  Opto-isolators in that era were too slow for MIDI, but the Sharp PC900 was designed for MIDI and works well.

 

Thanks a lot for the useful information! I will (hopefully) clear it out later today. I have several ideas for testing it, a Logic analyzer is one of them..

 

Ole.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oleoleo2 wrote:

Simonetta wrote:

 

The original MIDI standard from 1982 had a "feature" called Running Status. This means that if two MIDI messages have the same command byte (0x90 for channel 1) then the second note can skip the command byte and only need send the note value and velocity.

This was because the microprocessors of that era were slow.  The original IBM PC would process 0.5 million instructions per second (MIPS) while today's CPUs do 3000-5000 MIPS.  The 16MHz Arduino AVR does 16 MIPS.

 

So an old keyboard using Running status will send 0x90 0x3c 0x60 0x40 0x60 0x43 0x60 for a C major chord (C3-E3-G3).  Modern MIDI mergers parse the messages and output (usually) the full three byte command for each note. (at least my do).  Notes played slowly get the three byte message while chords get one full Note-on message and remaining notes are Running status.

 

If your MIDI monitor is Rx Interrupt driven and the data bytes are going into a receive buffer, then it is unlikely to be dropping bytes.

 

The  220 ohm resistor is OK because the MIDI pulses at 31250 baud are so short that a good 32 uS blast of current is needed to turn on the opto-isolator's internal LED.  3.3V systems should use 100-150 ohms for the MIDI OUT resistor.

 

The 31250 baud rate is due to a standard 1982 1MHz crystal being divided-by-2 five times.  Opto-isolators in that era were too slow for MIDI, but the Sharp PC900 was designed for MIDI and works well.

 

Thanks a lot for the useful information! I will (hopefully) clear it out later today. I have several ideas for testing it, a Logic analyzer is one of them..

 

Ole.

 

It could look like you where right! I tested the receiver with my homebuild MIDI transmitter that sends the control byte every time (it's a foot controller, so it makes fine sense to do it, I guess, since it would never send tons of control changes after one another). It works fast and apparently everytime. I also tested it with Logic Pro from my labtop, and it works as well (guess it has a different MIDI-setting or the MIDI interface act's differently). I can even manage to sort the data in the interrupt so I only get valid data in the buffer running at 20Mhz, haven't lost a byte yet (it has to be stress tested I guess..).