johnlane
Posts: 63
Joined: Fri Jul 20, 2012 8:26 pm

MIDI UART Interface using 6N138 Optocoupler

Thu Mar 07, 2019 12:06 am

Hello, I have been experimenting with MIDI on the Pi and my latest endaevour has been to input MIDI through the UART (instead of taking the easy option of a USB dongle). I have breadboarded the circuit below and it does work but it is very slow and solving that is what I hope someone may be able to advise me on. I am strictly a beginner when it comes to building circuits to interface to the Pi.
midi-schematic.png
midi-schematic.png (29.66 KiB) Viewed 1098 times
I took inspiration for this from various internet searches, in particular this article.

I have it connected up to a Pi 3 Model B+ and tested it using the Python example program on the above linked site. I have also connected it via ALSA to FluidSynth using ttymidi. I am running ArchLinux and have the following in my /boot/config.txt

Code: Select all

enable_uart=1
dtoverlay=pi3-miniuart-bt
dtoverlay=midi-uart0 
I have disabled the getty on ttyAMA0 and I have removed consoles from /boot/cmdline.txt that were configured for ttyAMA0. The GPIO pins used are 1 (3V3), 6 (GND) and 10 (RxD).

Now it basically works but it is slow. What I mean by that is I can press keys on my Midi keyboard and the correct notes are received and played by FluidSynth as long as I play slowly. If I attempt to press keys at a "normal playing speed" then it does not work - commands get dropped resulting in missed note on/off commands.

The ttymidi (or Python test program) output the received data to the screen and I can see that when it goes wrong it's receiving bad data, usually reported as an unknown midi command with the first byte usually being 08 in such cases.

I feel so near and yet so far... Is there anyone who has done this who might be able to advise where I'm going wrong?
Raspberry Pi Utilities: https://github.com/johnlane/rpi-utils
For Raspberry Pi and Arch Linux

Silverlock
Posts: 87
Joined: Wed Apr 10, 2013 3:51 am

Re: MIDI UART Interface using 6N138 Optocoupler

Thu Mar 07, 2019 1:25 am

At a glance, the circuit looks reasonable. It's almost identical to the input side of a MIDI-USB adaptor that I built around a 32u4 Pro Micro (and that's plugged into my rPi now). Just out of curiosity, if you take out the 10K resistor, does anything change?
RPi3+external HDD/Raspbian Stretch

User avatar
PeterO
Posts: 4722
Joined: Sun Jul 22, 2012 4:14 pm

Re: MIDI UART Interface using 6N138 Optocoupler

Thu Mar 07, 2019 8:30 am

It's a long time since I touched anything midi, but my feeleing is that if the note data is being received correctly, then the problems at higher note rates are going to be with the software not the hardware.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

johnlane
Posts: 63
Joined: Fri Jul 20, 2012 8:26 pm

Re: MIDI UART Interface using 6N138 Optocoupler

Thu Mar 07, 2019 9:08 am

@silverlock, I took out the 10K resistor and it behaves exactly the same. I also tried different values for R2 and R3 but only succeeded in making it not work at all. I don't understand the choice of value for those resistors.

In case it helps shed any light, here is the 6N138 datasheet . I bought a few of these last week in case one was faulty. I have tried more than one with the same outcome.

@PeterO I also suspected it might be software performace related which was one reason for using the latest Pi for this. If there is any alternative to ttymidi that serves the same purpose then I could try that?

When I run ttymidi, it outputs lines looking like this

Code: Select all

0xf0 Unknown MIDI cmd 008 064 035
I believe the first byte is wrong and the others are correct (by comparing with "good" notes where the first byte is 003).


I did try the small Python program but that exhibited the same behaviour.
Raspberry Pi Utilities: https://github.com/johnlane/rpi-utils
For Raspberry Pi and Arch Linux

Silverlock
Posts: 87
Joined: Wed Apr 10, 2013 3:51 am

Re: MIDI UART Interface using 6N138 Optocoupler

Thu Mar 07, 2019 7:32 pm

Since removing the 10K resistor didn't do anything, it doesn't appear to be a problem of too little gain. It was unlikely anyhow, given that the circuit doesn't give you any problems when you play slowly. But it was worth ruling out.

If you have a scope, you could check that the signal on the RxD line is clean. Might be that the 1K resistor needs to be changed out for a different value to get a clean low and high at 3.3V (1K works great for me at 5V).

But my inclination is to side with PeterO here; if it works with data coming in at a slow rate but not a high rate, I'd concentrate on the Pi side of things, and start with the least amount of software and work up from there. Here's one idea; an Arduino hooked up to the optocoupler's input and sending a MIDI key press/release sequence over and over again. Start with a slow repitition rate, and then ramp that up until you start getting communication trouble. Now take the MIDI software on the Pi out of the loop and just use a test program that does nothing put dump the hex values from the serial port. Is the data correct? Or is it missing the occasional byte, but the bytes that are being shown are the same values being sent by the Arduino? Or are there totally different values being displayed? Whatever result you saw would tell you in direction your problem was.
RPi3+external HDD/Raspbian Stretch

johnlane
Posts: 63
Joined: Fri Jul 20, 2012 8:26 pm

Re: MIDI UART Interface using 6N138 Optocoupler

Sat Mar 09, 2019 10:12 am

Well it turns out that the problem is the software. I wrote my own test program in a few lines of Python to dump the byte stream and noticed that there were MIDI Clock (0xF8 = 248) status bytes in the stream and these were not handled neither by the Python example nor ttymidi. In fact, they just served to royally mess things up!

The keyboard I was testing with, an old Roland synth, was sending these - probably because it has a built-in sequencer. Luckily, I have another keyboard which is pure a Midi keyboard with no bells and whistles (actually the target for this project). It was easier to move the Pi and breadboard to another room than move that keyboard (88-key weighted hammer action, very heavy) and I am glad I did because IT WORKS!!! :D :D :D

Right now, I don't have the 10K resistor in place. Does that matter? I believe it's there to make the logic level change quickly. I don't have a scope or any other means to test that though.

This has had the unfortunate consequence of piquing my interest. I now want to get the other keyboard to work too, so I'm going off to learn about Midi and write my own serial to alsa bridge that actually works. But, as far as this question is concerned, problem solved - the circuit works with the Pi UART.
Raspberry Pi Utilities: https://github.com/johnlane/rpi-utils
For Raspberry Pi and Arch Linux

Silverlock
Posts: 87
Joined: Wed Apr 10, 2013 3:51 am

Re: MIDI UART Interface using 6N138 Optocoupler

Sat Mar 09, 2019 7:30 pm

Hmm. Why did the clock message only cause problems when you were sending lots of key press/release messages, I wonder? In any case, it works now and that's what matters in the end. Congrats!

I know my Roland keyboard sent out timing clock messages as well. I ignored them in my adaptor code and didn't pass them along.

If it works with the 10K in there, I'd say leave it in there. It does decrease both gain and delay a little but since too little gain doesn't seem to be an issue, take the decreased delay and call it a day.

There's a handy guide to all things MIDI messages and micros at Arduino MIDI. Granted, it's aimed at Arduinos but I think you might find the section on MIDI input useful. There's a flowchart and sample code for parsing and handling MIDI messages. And it just happens to ignore both SYSEX and all real time (like the timing clock) messages too.
RPi3+external HDD/Raspbian Stretch

alberto.gianelli
Posts: 1
Joined: Wed May 15, 2019 8:22 pm

Re: MIDI UART Interface using 6N138 Optocoupler

Wed May 15, 2019 8:30 pm

Hi,
I am facing a similar problem. I think a trick to speed up the edges could be supplying the optocoupler Vcc Pin (PIN 8) with 5V from the Rasperry Pi and then pulling up the output at 3V3 to still be consistent with the voltage rating of the UART, like you are currently doing. In this way there is more current flowing in the Darlington and the switching should happen faster.
I have seen it here https://www.pjrc.com/teensy/td_libs_MIDI.html applied for the Teensy (first diagram). Let me know!

Best,

Alberto

drgeoff
Posts: 9343
Joined: Wed Jan 25, 2012 6:39 pm

Re: MIDI UART Interface using 6N138 Optocoupler

Sat May 18, 2019 12:50 pm

MIDI clock rate is only about 32 kHz. Hardware switching speed of an optocoupler circuit should not be an issue.

hippy
Posts: 5326
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: MIDI UART Interface using 6N138 Optocoupler

Tue May 21, 2019 11:13 am

drgeoff wrote:
Sat May 18, 2019 12:50 pm
MIDI clock rate is only about 32 kHz. Hardware switching speed of an optocoupler circuit should not be an issue.
I was about to say the same. One would need slew of around 16us to be problematic.
Silverlock wrote:
Sat Mar 09, 2019 7:30 pm
Hmm. Why did the clock message only cause problems when you were sending lots of key press/release messages, I wonder?
I would guess it's a case of screwing-up Running Status.

System Real-Time messages (F8-FF) should not affect Running Status but perhaps they do in the implementation being used.

System Real-Time Messages can also appear within other messages, for example within a Note On message, between Status Byte and Note Number or between Note Number and Velocity, but some implementations may not be expecting that, may consequently be causing the current message to be aborted and subsequent messages to be lost or misinterpreted when that happens.

Playing slowly would force the sender to send Status Bytes which it would not do when playing faster and the sender is relying on Running Status working as per specification.

Play slowly and every Note On and Note Off will, more often than not, be preceded by a Status Byte. Play fast and they won't necessarily be.

hippy
Posts: 5326
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: MIDI UART Interface using 6N138 Optocoupler

Tue May 21, 2019 11:52 am

Silverlock wrote:
Sat Mar 09, 2019 7:30 pm
There's a handy guide to all things MIDI messages and micros at Arduino MIDI. Granted, it's aimed at Arduinos but I think you might find the section on MIDI input useful. There's a flowchart and sample code for parsing and handling MIDI messages. And it just happens to ignore both SYSEX and all real time (like the timing clock) messages too.
That code has the flaws which I described in the above post; System Real-Time messages screw-up the Running Status, prematurely aborts messages and loses subsequent messages when it shouldn't. It isn't even an accurate implementation of the official MIDI recommended flowchart they show :roll:

Code: Select all

  if (Serial.available()) {
    uint8_t newByte = Serial.read();
    if (newByte & 0b10000000) {    // Header byte received
      runningStatus = newByte;
I do wonder how many people have copied this or similarly flawed implementations without realising they are flawed, aren't MIDI specification compliant ?

My guess is quite a few. Most people simply copy what others have done, rely on others presenting correct implementations. But it so often seems those producing implementations haven't read or understood the official MIDI specifications, probably don't even have an official copy of them.

Some, as in this case, can't even implement a provided flowchart correctly, or they have not understood the consequences and implications of altering that or applying flawed optimisations.

Of course, most times a flawed implementation appears to work, which reinforces a false belief that they are correct implementations.
johnlane wrote:
Thu Mar 07, 2019 12:06 am
I have ... tested it using the Python example program on the above linked site. I have also connected it via ALSA to FluidSynth using ttymidi.
Both of those have flawed implementations, aren't compliant with the official MIDI specification, exhibit the flaws described above.

Return to “Graphics, sound and multimedia”