How do you make a USB MIDI to CV interface?

This one is simple and does not require any expensive Teensy’s or STM32.

It runs on the ATtiny85 using V-USB.

The ATtiny is programmed with the Micronucleus bootloader and is firmware upgradeable incircuit.


If you don’t want to build the circuit above, a cheap chinese Trinket does the job.



It can be built into an analog synth like the Korg Monotron to give it USB MIDI.


You also need the DigiMIDI library found here:

To be able to receive MIDI from the host, the file DigiMIDI.h requires some modification.

Add this to the function usbFunctionWriteOut:

void usbFunctionWriteOut(uchar * data, uchar len) {

uint8_t note=data[2]; //Get note for key on/off
if (note<36) note=36; //If note is lower than C2 set it to C2
note=note-36; //Subtract 36 to get into CV range
if (note>60) note=60; //If note is higher than C7 set it to C7
if (data[1] == 0x90) { //If note on
digitalWrite(5, HIGH); //Set Gate HIGH
OCR1A = note<<2; //Multiply note by 4 to set the voltage (1v/octave)
if (data[1] == 0x80) { //If note off
digitalWrite(5, LOW); //Set Gate LOW
OCR1A = note<<2; //Multiply note by 4 to set the voltage (1v/octave)


And this is the MIDI2CV.INO sketch:

#include <DigiMIDI.h>

DigiMIDIDevice midi;

void setup() {
pinMode(1,OUTPUT); //Pitch is output
pinMode(5, OUTPUT); //Gate is output
//Setup Timer1 to do PWM DAC for Pitch
TCCR1 = _BV(PWM1A) | _BV(COM1A1) | _BV(CS10);
GTCCR = 0;
OCR1C = 239;
OCR1A = 0; //Set initial Pitch to C2
digitalWrite(5,LOW); //Set initial Gate to LOW;

void loop() {
midi.update(); //Check if any MIDI data is received

8-bits is actually a to low resolution for the pitch but a trick makes it work.

The CV range is set to 0-239 instead of 255 and that makes each seminote exactly 4 steps.

Thats it, very simple and cheap.

If you have no clue about programming and soldering skills only you can buy the preprogrammed Digispark board here:

Order the DIY preprogrammed MIDI2CV Digispark $20



%d bloggers like this: