Wednesday, March 30, 2016

DIY MIDI Ribbon Controller

In a previous age of the world (2011), I built myself a ribbon controller.  I used it to drive my Korg Mono/Poly via CV.  And it was good.  But, that was before "synthhacker" first awoke under the stars on the shores of Cuivienen.  Has its glory been forever lost?  No!  The ribbon lives again!  And it has been updated!  Behold:

The Overall Setup:  This ribbon is just a controller -- it controls a synthesizer.  It doesn't make noise itself.  Those black-and-white keys that are built into the synthesizer are also just a controller.  They tell the brain of the synth to make noise at fixed pitches.  My ribbon controller uses the synth's MIDI interface to tell the synth to make noise across a continuous spectrum of pitches.  More bendy.  More swoopy.  Fun!  My controller has two parts: the ribbon itself, and some electronics (Arduino +  MIDI Shield) to do the ribbon-to-MIDI conversion.

The Ribbon Parts:  The ribbon itself, I built a long time ago.  But, as stores on the internet never forget what you've ordered, I easily went back and looked it up.  The core of the ribbon controller is a 500mm-long "soft pot" (Sparkfun).  This is the part that senses where you touch.  Since it is soft and floppy, however, I also bought a 2-ft long strip of plastic (McMaster) to act as a backbone.  For the electrical connection to the ribbon, I used a headphone jack (Sparkfun) and a small perfboard (Sparkfun).  The only real innovation with my ribbon controller (there are lots of DIY ribbons out there) is that I also added a magnetic strip along its back (McMaster).  Since most of my synths  have a metal front panel, the magnetic strip is a great way of keeping the ribbon in place!

Components of the Ribbon Controller

The soft pot is on the top.  The magnetic strip (partly unrolled) is in my hand.

Assembling the Ribbon:  I started with the plastic strip.  Its edges were surprisingly shart, so I got out some sandpaper to smooth the edges.  Now it's much nicer to touch.  After cleaning off the sandy bits, I spray-painted the whole thing black.  When fully dry, I attached the magnetic strip and the soft pot, both via their adhesive backing.  Then, I carefully soldered the ribbon's terminals (don't melt the soft pot!) to the perfboard and then to the audio connector.  I wired the connector so that the "top" of the pot was to the tip, "bottom" of the pot was to the sleeve, and the "wiper" of the pot was to the ring.  Once it was all soldered together, I epoxied the perfboard to the plastic strip to make it all nice and solid.

Headphone jack is connected to the perfboard, which is connected to the soft pot.  The whole thing is epoxied to the plastic strip, for strength.

Arduino-MIDI Electronics:  The ribbon is just a potentiometer -- it needs electronics to interface to a MIDI synth.  After my previous project making an MIDI-to-trigger converter, I realized that I could re-use that exact same hardware for this ribbon-to-MIDI converter.  Repeating the recipe list from that project, my parts include an Arduino Uno, a MIDI Shield* from Sparkfun, some stackable headers, and a 3.5 mm stereo headphone jack (or maybe one like this).

(* Note: I used the old Sparkfun MIDI Shield but, presumably, the new model linked above works well, too).

Components for the "Brain" of the Ribbon Controller

Assembling the Electronics:  I soldered together the MIDI shield, including soldering on the stackable headers.  I then soldered some wires to the audio jack and soldered those wires (being sneaky) to the header pins sticking down from the MIDI shield (detailed soldering pics here).  Once it was all assembled, I connected the ribbon to the MIDI shield using a standard 3.5 mm audio cable.  I also connected a USB cable to my laptop so that I could power it and program it.  The photo below also shows the MIDI cable connected, but we're not quite ready for that, yet.

Connecting my ribbon controller to the MIDI Shield (the Arduino is under the MIDI shield).

The Ribbon is a Potentiometer:  Touching the ribbon (the "soft pot") is like turning the knob on a potentiometer to a particular spot.  If I touch it near the low end, it'll show a low resistance.  If I touch it near the high end, it'll have a high resistance.  The job of the Arduino, therefore, is to sense the resistance of the ribbon so that it knows what note to play.  In theory, pretty easy.  But, to get some details on how this works, I hooked used my setup to collect some actual data.

The Ribbon's Response via Arduino:  To measure the response of the ribbon with an Arduino, I used the setup described above, which has the wiper of the pot connected to one of the Arduino's analog input pins (A3).  The bottom of the pot is tied to ground.  I activated the input pin's pullup resistor (via pinMode(A3, INPUT_PULLUP)) and started reading ribbon values via AnalogRead(A3).  I printed the values to the serial port so that I could see them on the P and log them to a file.  Sliding my finger to different octave points on the ribbon, I made the plot below,

The AnalogRead() Values Generated by the Arduino when Touching the Ribbon at Different Spots.

Values When Not Touching the Ribbon:  The first thing to notice is what happens when *not* touching the ribbon: the ribbon shows a very high value.  The high value results from the fact that the wiper is floating when you're not touching the ribbon.  As a result, the pull-up resistor on the analog input pin is able to pull the value all the way to the maximum value (which is 1023 on the Arduino Uno).  So, it's easy to know when you're touching the ribbon versus non touching the ribbon -- just look to see if the value is near 1023.

Values When Touching the Ribbon:  The middle of the graph shows the values when I touch the ribbon between its bottom (C1) and its top (C4), Looking at the detailed values, the lowest value seen in my ribbon (C1) is about 12 whereas the highest value (C4) is about 339.  So, I know that I have to program the Arduino to map values between 13-339 to musical notes between C1-C4.

Touching the Ribbon To Record the Arduino's AnalogRead() Value at Different Locations.

Software:  After seeing how the ribbon responds, I wrote my Arduino software.  It's basically a big loop that reads the ribbon value, converts it to a MIDI note number, and sends those MIDI commands to my synth.  While it seems conceptually simple to do an AnalogRead() for the ribbon followed by a Serial.write() to send the corresponding MIDI message, it does actually take some thought to get it to respond the way that you'd like.  Also, to make the ribbon pitches change continuously (and not be quantized like with the piano keys), you need to compute and transmit all the pitch bend commands.  It takes some work to get it right.  If you're interested, my Arduino code is available on my GitHub here.

Linearizing the Response:  One tricky spot is if you want the pitch to track linearly with your finger position on the ribbon.  In my case, I found that the notes were too closely-spaced at the top of the ribbon and too widely-spaced at the bottom.  I didn't like that.  The key to linearizing the response is to recognize that the ribbon and the Arduino's pull-up resistor actually form a voltage divider.  Once you do the math on that voltage divider, you program the Arduino to better deduce the note you want given the apparent voltage at the soft pot's wiper.  It's not perfect, but it's much better than before.

I was lucky at how well the ribbon fits on the face of the synth.  I took the extra effort to make the software fit well, too.
Bend Range:  The ribbon is fun because you can use your finger to sweep through all the pitches in between the normal notes.  Since the MIDI messages assume a piano-like keyboard, you do these "in between" pitches by commanding a note to one of the standard pitches followed by commanding a pitch bend to get the in-between pitch that you actually want.  Ideally, you could set the synth so that its allowable amount of bend would span the whole ribbon.  Unfortunately, on the Prophet 6, the max bend amount is +/- 1 octave.  As a result, with my setup, I get a brief note discontinuity when I try to continuously slide across more than 1 octave.  This is a limitation of the synth, not my ribbon controller. (If the synth's software were open source, I could fix that!)

Wobbling Pitch (ie, Pitch "Noise"):  Another subtlety that I uncovered is related to the fact that one's ear is very sensitive to changes in pitch.  The issue is that any noise in the measurement of the ribbon value will directly translate into wobble (instability) in the pitch commands sent to the synth.  When I was powering my system from the laptop and when the laptop was running on battery, my system sounded great.  But, when I plugged the computer into AC power, the pitch wobbled a lot.  It was quite unpleasant.  My solution was to add a 33 nF capacitor between the ribbon's analog input pin and ground and to add some filtering in software (revised code is here).

Future Work:  It's pretty fun to have my ribbon controller working with my MIDI synth.  Sure, I don't like that there is still a note discontinuity that happens when I try to exceed the 12-step max bend allowed by the Prophet 6, but it's still quite fun.  (Maybe I can sweet talk someone at Dave Smith Instruments to help me out on that one remaining issue :).  Looking for other ways to improve the ribbon, I'm considering adding a DAC so that the the Arduino (or Teensy!) can directly create its own audio without needing to command an external synthesizer.  That'd be fun.  How about a ribbon wavetable synth!  Or, how about a ribbon FM synth?  Fun!

Follow-Up:  I also made a version of this ribbon that outputs CV signals.  Now it can drive my old pre-MIDI synths like my Korg Mono/Poly.  Check it out here!


  1. Hi, love your design! I built this to control soft synths using an Arduino Leonardi for USB midi. I just have question about the pitch end behaviour with midi. When I play a note, it gates and I can pitch bend down while holding that note, but I can't seem to bend up from, this could be a result of admittedly sloppy code conversion, does you original Midi code include the ability to pitch up and down from a held note? Also what is the procedure for tuning the notes that are played up and down the ribbon? I'd like to be able to quantise the ribbon to play only in minor, or major keys someday.

    1. Yes, my ribbon bends up and down equally easily. There was no special logic to bend up as well as down...the code just does them both.

      If you can go one way but not the other, are you using any unsigned data types? If you can't go negative with your values, maybe the result is that it can only end one way?

      Also, check the bend range settings within your soft synth. Some allow different + bends versus - bends. Maybe your + bend is set to zero?

      As for the quantizing / calibration procedure, you'll note that my ribbon is set above the keybed on my synth. So, what I did was to connect my Arduino to my PC and have the Arduino spit out the analog value to the PC whenever I touched the ribbon. I then touched the ribbon immediately above each key on the keybed. Therefore, I know the Arduino value for each key on my keybed. You can then write code that'll quantize the Arduino value to the value that is closest to just those notes (chromatic, major, minor, whatever) that you want!

  2. Hi Chip. Thanks for the reply! I'm not able to do little trills and hammers up and down with the ribbon. Realized that I kind of like not being shackled to the western tempred scale! Still playing round with the code and have gotten a pretty good range of values out of the softpot. That's a good idea with quantizing. I might just pop it into Ableton with a sine wave and a tuner and mark the values down for each note.
    I'm guessing all I would have to do is find some arbitrary values for different pitches and then have the ribbon scroll through those values when going up and down. for example: int chromatic {0, 124, 255, 364} etc and figure out a place to map the raw ribbon data to the quantized values.
    One other problem I'm having is my chubby fingers being unable to trigger the same note twice, so if I am trying to play C3 twice I play C3, then C#, and sometimes Bb. Do you think I could just implement some sort of octave button to the arduino so that I could have it span one octave for finer control?
    Loving all the comments in your code, super fun to experiment with, maybe going a bit over my head as I'm usually an analog synth DIYer but sticking my toes in the waters of Arduino coding is a lot easier when some else has already done the hard work for me! Much appreciated.

  3. Good stuff, been wanting to add a ribbon controller to a synth for years now.

  4. Hey Chip, I wrote you over at Synthtopia in the comments when I realized you posted way back in April. Anyway, here's what I wrote:

    I have been obsessing over doing a two-ribbon setup lately but don’t have a ton of tech know how, just that it CAN be done. I can solder, etc, just can’t design PCBs and all that. I do work in a machine and prototyping shop, however, so I can design and build any manner of case.

    Specifically what I want is to have two ribbons pretty close together, along with a plate on the left that will allow me to “bow”, rather than just have constant sounding when touching the ribbons. Of course I want that too. �� I’m mostly wanting this to control Sample Modeling’s string sounds as well as Finger Fiddle on the iPad.

    On the way in to work I was also daydreaming about a 4-ribbon version of this. One, you can have each ribbon tuned just like a Violin or Cello, so you can play more or less exactly how you would on those instruments, with independent vibrato on each string. Second, you could play 4 monophonic lines from a synth, OR, each ribbon could activate 4 different synths. On the left would still be a touch/bow plate, but it's split into 4 so you can hit each string individually, or bow across all 4 for string or chord playing.

    Hopefully his all makes sense. I'm going a little cuckoo thinking about it. So can we do this?

    Edmund -

    1. Hi!

      You could totally do the hardware for four ribbons in one device with all the other features you were discussing. The harder part is how to encode the results into a MIDI stream...especially if you want it to have the feel of four monophonic synths with the correct sliding behavior between notes.

      You could make something that is mostly convincing with a standard MIDI synth, but what you really want are one of the newer MPE synths that have been developed to interface with multi-touch controllers like the Roli Seaboard, Linnstrument, Continuum, etc. With those synths, you're Arduino or whatever would listen to each ribbon (each "string") and send that ribbon's commands as its own MIDI channel. So, four strings means four MIDI channels. Your MPE synth would then treat the four channels as four monosynths. Rockin.

      So, if I were you, I'd start with a single ribbon to get the hang of how to build the hardware and software. Only once I've had success with the one ribbon would I move on to the multi-ribbon.

      Good luck!


  5. Or, would something like this be possible?

    I would only need it to have the strip, whatever interface, and two modulation wheels. Which, evidently, can only be found through Doepfer. Strange. I wouldn't want it to be a Modular synth, just control synths via MIDI or CV. I'd love to have USB, but the Doepfer Ribbon Controller doesn't support it. Odd.

    So essentially I would want the Ribbon, the two mod wheels underneath, and the whole thing tucked into a hand-made wooden box that goes on my shoulder.

  6. Amazing project! I am stuck and wish if you can help out with one aspect of the code.

    From my understanding the softPot has VCC, DATA (middle), and ground pins. Usually the middle pin is connected to analog A0 with these softpots; however, you have connected them to the analog inputs A1 and A3 in your code. Do you have an image of the connection of the ribbon?

    Furthermore, I have attached those inputs to the 5V and Gnd inputs on the arduino and have a 10k push resistor on the middle pin. Everything compiles fines, but I am not getting a good result as a constant midi note plays until I hit the sensor which triggers a random amalgamation of notes. I am using 35200 BAUD. Any suggestions would be greatly appreciated as I would love to get this working!
    Thank you