I was having some peculiar errors playing a keyboard through Twister into the NanoEgg synthesizer prototype. Namely, it would often lose note off commands, resulting in stuck notes. That really sucked, and made for some terrible demos, so I finally decided to sit down and hack through it.
The initial symptoms:
- If the E-MU keyboard is attached to MIDI IN on Twister, and the out is attached to NanoEgg, stuck notes will often result.
- If E-MU is attached directly to NanoEgg there are no problems.
- If output is from Twister to another MIDI device, no problems.
- If input is a different MIDI keyboard, no problems.
I put lots of print statements in the Twister code, and confirmed that Twister, at least, is receiving and thinks it is sending the correct data.
And print statements in NanoEgg indicate that it isn't getting the note off.
Since it worked with a direct keyboard, I assumed that there was an electrical problem. I wasn't in a good place to debug circuit problems, because of a lack of test equipment. I actually own an oscilloscope from my father's workshop, but that vacuum tube beast from 1968 lacks the modern features like waveform capture necessary to really understand what is going on.
Fortunately my friend Arclight from 23b Shop offered to lend me an oscilloscope to track the problem down. Thank you so very much!
The first thing I noticed was that the levels from the E-MU seemed to be tremendously lower than those coming off Twister.
I had to crank the time resolution way down to determine the lag between input and output, which was 11.18ms . The input signal was only about 320mV, while the output was 1.45V. I started to suspect noise might be a problem, and started to think about biasing the signal higher to avoid it.
I tried different MIDI sources and different power sources with some crazy results. Here is a Casio portable keyboard using an old Sega Genesis power supply:
The power supply is basically leaking 33.6VAC peak-to-peak out the MIDI jack! But it actually doesn't matter, because both pins are getting it so it cancels out in the optoisolator. This is the wonder that is MIDI.
So, time to do some serious debugging.
Let's look at the signals and see what we get:
The E-MU to the Teensy synth works fine, so let's see what that looks like:
Approximately 280mV peak-to-peak, but the transitions seem clean enough.
Does it change when attached to Twister?
No, that looks about the same, and it's fine.
So, does anything change when we attach the synth?
So, what does the output from Twister look like then?
Some interesting peaks, but otherwise very clean 1V signal.
So, let's compare the output from Twister to what comes to the RX line on the Teensy 3. This is for the occasion of a note that "stuck" and didn't receive the off command, which is displayed below.
So, the optocoupler leaves gives some interesting leading edge curves. Is that a problem?
What does an OK signal look like?
I'm displaying at a different time base, but it is pretty much the same.
So, I'm drawing a blank here, but I keep playing with it and I notice that there is a little glitch on the ones where the note got stuck. It turns out that my MIDI keyboard has "aftertouch", where it sends continuous velocity data after the note is hit. Generally there is a threshold and a delay before such data is sent, but on this keyboard it is possible to get it even on a quick key press.
Aftertouch looks like this:
Now, I put all sorts of print statements in the Twister code to make sure that it is decoding the aftertouch messages correctly. It is.
So I tried making sure that it doesn't echo the aftertouch data AT ALL. And that does fix the problem. So it is definitely aftertouch. Probably definitely.
So I put prints in the MIDI library where it receives and sends the data and confirmed that the data is sent correctly. It is.
I start looking at the NanoEgg prototype suspiciously: If Twister is doing everything OK, and the problem only exists on NanoEgg, could NanoEgg be the problem, even though it only has problems when Twister is in the signal chain?
So I put print statements in the MIDI library on the Teensy for NanoEgg and confirm that it is receiving the commands! But it isn't processing them correctly. Sometimes.
Now, I didn't write the MIDI library, that comes from Francois Best at FortySevenEffects. It has been modified for the Teensy by its creator Paul Stroffregen. But it is running version 3.2, and the Arduino version is up to 4.2. So I go look at the change log on GitHub:
16/04/2014 : Version 4.1 released. Bug fixes regarding running status.That might just be my problem!
But 4.2 hasn't been ported to the Teensy! I don't want to do that work! Meh.
After a few forum posts and bug requests, I finally give up and resign myself to making it work.
So I download the original version 3.2 of the library and do a WinDiff with the Teensy version of 3.2. Really isn't that different, except for some extra code to make sure it uses the correct version of the serial ports, and perhaps some support for USB MIDI?
So I go look at the 4.2 source, which is very different, but seems structured around templating from a serial port class that you pass in. Paul's changes might not even be necessary!
Let's just try it!
I put it in, and it compiles, but it somehow refuses to use it because it is an "invalid Arduino library" or some such. Hmmm.
Generally, Arduino libraries just have the source in the root directory, but this one has it in a subdirectory called "src".
Do any other projects do that?
Why, yes! The LedControl library does that!
How is it different then?
It has a file called "library.properties". It looks like this:
name=LedControl version=1.0.6 author=Eberhard Fahle <email@example.com> maintainer=Eberhard Fahle <firstname.lastname@example.org> sentence=A library for the MAX7219 and the MAX7221 Led display drivers. paragraph=The library supports multiple daisychained drivers and supports Led-Matrix displays as well as 7-Segment displays. category=Display url=http://wayoda.github.io/LedControl/ architectures=*Well, let's make one and add it to the MIDI directory. I made this:
name=Arduino-MIDI version=4.2 author=Francois Best <email@example.com> maintainer=Francois Best <firstname.lastname@example.org> sentence=This library enables MIDI I/O communications on the Teensy serial ports paragraph=This library enables MIDI I/O communications on the Teensy serial ports category=audio url=https://github.com/FortySevenEffects/arduino_midi_library/ architectures=*And it works!
And the bug is gone!
So, to recap: I thought there was a hardware problem in one of two platforms, but it turned out to be a software problem in the platform I wasn't even debugging, and it was fixed by updating my software.
Sometimes, debugging is like that.