• Alex

MIDI to CV (part one)

I love my MS20 mini. It makes such a beautiful racket and the filters in particular are a delight. Just sitting and riding the cutoff with the resonance cranked up it sounds the way a synthesiser should.

Now while it’s always fun to twiddle knobs sometimes it‘s useful to have the computer twiddle them for you. The good people at Korg were at pains to make the Mini as authentic as possible so it doesn’t have any MIDI CC capability. It does though have the rather wonderful patch bay 🎛. In fact, several of those little sockets take a 5v analogue signal and manipulate the associated parameter. The good lords of synthesis call this Control Voltage (CV). So what if we convert digital MIDI signals into CV. There are lots of boxes out there that will do that for you. But what would be the fun in that!


So let’s set out to build our own. Our electronics platform of choice will of course be Arduino, so first thing to do is to choose which one to use. My constraints:

  1. Mini. I want The device to have a small footprint so it can sit on top of the MS20.

  2. Native support for MIDI over USB. I just want to use a midi library. Not get into parsing and sending serial messages.

  3. 5V outputs. Some of the newer boards are 3.3V and that wouldn’t let me hit max deflection on the MS20.

I’ll be honest that my understanding of Arduino and micro-controllers is pretty light so I didn’t even know that (2) was a thing until I bought a Nano Every and found myself in MIDI hell. So after all that I ended up with an Arduino Micro which suits me very nicely thank you.

So I thought this should be easy. The Micro has analogue 5V out pins (which sounds a lot like CV to me!) so I can just parse MIDI and set the value of one of these pins and then plug it into the MS20. Time for microcontroller lesson two 🤦‍♂️. These analogue outputs (on pretty much all the Arduinos) are just nowhere near stable enough to drive a CV unless you want your modulation to wobble randomly. What to do? Use the digital pins of course!


The digital pins on an Arduino output a pulse wave. You can set the width of the pulse from 0 (essentially 0V continuous) to 1 (essentially 5V continuous). Sounds good for 0V and 5V. What about in between? Well if you set the pulse width to 50% then you get a pulse that oscillates between 0V half the time and 5V the other half. If we could find some way to average that voltage then we’d get 2.5V which is what we want. Good news. There’s a very simple circuit we can build that will do this for us. It’s called an RC Filter and is a really simple low pass filter that uses a capacitor (and a resistor) to smooth out an input signal.


Okay. With all that knowledge we should get on to designing this thing. First things first, the standard pulse wave output by the Arduino Micro is 490Hz. Not bad, but we want to be able to have lots of high resolution modulation, so let's up that to its maximum by messing with the clock. Warning - I do not claim to deeply understand this stuff so proceed with caution. I learnt a lot from here and here. What I've done works on the Micro (and should work on the Leonardo or any other Arduino that uses the ATmega42u4). If you have anothe Arduino or a different MCU, your mileage may (will!) vary.


Basically the output frequency of the pins is controlled by a timer whose speed in turn is derived from the MCU clock. The standard divisor is 64, meaning that the clock runs at 16MHz / 64 = 250kHz. The clocks we are using generate a triangle wave using an 8 bit register so a cycle is 512 (256 up and 256 down) counts long. That's our 490Hz! To get things running faster we just need to reduce the value of the divisor. This divisor is stored in a register for each clock. The following code puts a value of 1 (rather than 64) in those registers by setting bit CS00 to 1 giving us a frequency of 16MHz / 1 / 512 = 31.25kHz. Probably overkill, but who cares.

TCCR1B = _BV(CS00); // change the PWM frequency to 31.25kHz   - pins 9 & 10 
TCCR4B = _BV(CS00); // change the PWM frequency to 31.25kHz   - pin 6

So, now we have a 31kHz pulse we need to setup our RC filter. RC filters are dirt simple (see left). Just a resistor and a capacitor. You can calculate the frequency and step response of the here.


After some playing around and reading up I settled on 1kΩ and 10µF giving a cutoff of 15kHz (which will nicely smooth out our 30kHz square wave) and a step response of 20µs (which is approx 1/1000th of a beat at 160bpm - seams fine!)


Finally we write some very simple code (thanks to our choice of the Arduino Micro and this marvellous MIDI library) to listen for MIDI and send appropriate values to our output PWM pins.

#include <MIDIUSB.h>
byte YellowCVPin = 9;
byte YellowCC = 20;
byte GreenCVPin = 6;
byte GreenCC = 21;
byte PinkCVPin = 10;
byte PinkCC = 22;

void setup() {
  TCCR1B = _BV(CS00); // change the PWM frequency to 31.25kHz   - pins 9 & 10 
    TCCR4B = _BV(CS00); // change the PWM frequency to 31.25kHz   - pin 6    
  Serial.begin(9600);
  Serial.println("Serial started");
  pinMode(YellowCVPin, OUTPUT);
  pinMode(GreenCVPin, OUTPUT);
  pinMode(PinkCVPin, OUTPUT);
}

void loop() {
  midiEventPacket_t rx;
  
  do {
    rx = MidiUSB.read();
    if (rx.header == 11) {
      if(rx.byte2 == YellowCC) {
        Serial.println(rx.byte3);
        int val = map(rx.byte3, 0, 127, 0, 255);
        analogWrite(YellowCVPin, val);
      }
      if(rx.byte2 == GreenCC) {
        int val = map(rx.byte3, 0, 127, 0, 255);
        analogWrite(GreenCVPin, val);
        Serial.println(val);
      }
      if(rx.byte2 == PinkCC) {
        int val = map(rx.byte3, 0, 127, 0, 255);
        analogWrite(PinkCVPin, val);
        Serial.println(val);
      }
    }
  } while (rx.header != 0);
}

And we breadboard a little circuit. The wires on the left go to a colourful little 3.5mm jack I found on Amazon. And the USB on the right goes to my computer. Ableton is set it up to recognise the Micro as a USB MIDI device (actually this all happened automatically). I made clip that sent MIDI CC on the appropriate channel and hit play. At this stage I strongly suggest you grab an oscilloscope (here's a nice cheap one on Amazon) and check your signal rather than hook up to your expensive synth. Once you oscilloscope matches the clip you see in Ableton hook it up to the synth...



Next time - move to Perf Board, get soldering and build an enclosure!