0% found this document useful (0 votes)
25 views

Building A Minimoog MIDI Controller - Loophole Letters Arduino

Building a Minimoog MIDI Controller _ Loophole Letters Arduino

Uploaded by

segurah
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views

Building A Minimoog MIDI Controller - Loophole Letters Arduino

Building a Minimoog MIDI Controller _ Loophole Letters Arduino

Uploaded by

segurah
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

loophole letters �

Building a Minimoog MIDI


Controller
diy electronics arduino

June 11, 2020

Last week, a friend a I built a MIDI Controller for the Arturia Mini V3 VST:

Front Panel Controls

At �rst, we identi�ed the di�erent 44 controls we needed:

• 21 potentiometers (with 2 21mm and 19 19mm bakelit knobs)


• 6 rotary switches (with chicken head knobs)

• 17 �ip switches

We decided to omit the following rather useless controls:

• A440 rocker switch

• soft clipping switch + button

• all keyboard controls

• �ip switch + overload leds

Also, we decided to use �ip switches only + we added 2 extra �ip switches below the 3 pots
on the left.

This is the front panel with all the pots and switches in place:

for comparison:
MIDI Brain

To read the positions of all controls, we ended up using the Arduino Micro:

• it has a ATmega32U4 microcontroller, which makes it usable as a USB device

• it has up to 12 analog inputs and up to 20 digital inputs

Analog Input Multiplexing

As we have 44 controls and only 12 analog inputs, we used seven cd4051 ics:
• pins 6 7 & 8 can be connected to ground

• pin 16 is connected to 5V

• the "channel in" pins are connected to the controls

• via the select pins a b and c, we can control which "channel in" is routed to the "com
out". This is done by splitting the three digits of a binary number (000-111) to the
three select pins.

• by constantly looping through all inputs, we can read all 8 controls in a short
amount of time

• this "trick" is also called time multiplexing, which makes the cd4051 a
multiplexer

• so with the 12 analog inputs of the arduino, we can connect up to 12x8 = 96 controls

The Board

To connect all 44 controls with the multiplexers to the arduino, I drew this board plan:
• the copper strips go from left to right

• black boxes: cd4051 multiplexers

• blue vertical lines: 8 pole plug jacks

• red: 5V

• white: ground

• shades of blue: select bits a b and c

• red vertical marks: copper cuts

• green: output cables


By rotating the middle row of ics by 180 degrees, we can spare some cables for ground and
the select pins.

After soldering it together, the board looked like this:


Problems

As this was our �rst real electronics project, we ran into some unforseen problems.

Problem 1: Mirroring

• After the plan was made, we started using it on the copper side (top image) to solder
the 16 pin jacks and the plug jacks.

• When we were done soldering, we realized that if we now attach the ics from the
plastic side (down image), they will be mirrored, having wrong pin placements!

• Wo rkaro und: To �x the problem, we painstakingly bent all the ic legs to the other
side to "mirror" them...

• F ut ure Learning : Use two plans, where one is the mirrored version of the other, for
both sides of the board

Problem 2: Empty Inputs

• Another thing that we realized too late was all the multiplexers inputs must be
connected to the circuit to make them work

• Wo rkaro und: We connected all empty inputs via 10k pull up resistors to ground

• F ut ure Learning : It's better to use up as much inputs as possible

Wiring the controls


• the middle pins of each pot + one of the pins of each switch are connected to ic inputs

• all other pins of the switches + one of the outer pot pins are connected to 5V

• all remaining pins are connected to ground

• all the 5V pins of the switches are connected to ground with a 10k resistor

• we transformed the rotary switches to potentiometers by connecting the outer pins


via resistors

For the switches and the empty inputs (see Problem 2), we added the resistors directly on
the board, before the plugs:
• F ut ure Learning : Add the resistors directly to the 5V pin

Programming the Arduino

The controls can be identi�ed like this:

const int NControls = 44;


int connected[] = {
184, // polyphonic switch
185, // volume poti
186, // unison switch
187, // voice detune poti
191, // osc3 volume poti
193, // ext volume switch
195, // keyboard ctrl 1 switch
196, // amp attack poti
197, // filter mod switch
198, // osc1 switch
201, // osc2 tune poti
203, // osc1 range rotary switch
204, // noise volume poti
205, // osc2 switch
206, // osc3 switch
207, // noise switch
208, // osc2 range rotary switch
211, // vcf cutoff poti
213, // vcf decay poti
214, // osc2 vol poti
215, // osc1 vol poti
216, // osc2 waveform rotary switch
217, // osc3 waveform rotary switch
218, // vcf emphasis poti
221, // external volume poti
223, // keyboard ctrl 2 switch
224, // osc1 frequency sync switch
225, // osc3 tune poti
226, // osc1 waveform rotary switch
227, // osc3 range rotary switch
228, // white/pink switch
231, // effect 2 switch
232, // effect 1 switch
233, // osc2 ctrl switch
234, // master tune poti
235, // osc modulation switch
236, // glide poti
237, // mod mix poti
238, // osc3 ctrl switch
274, // vcf sustain poti
276, // vcf contour poti
277, // amp sustain poti
275, // amp decay poti
194 // vcf attack poti
};

• The �rst two digits are the analog input of the ic (a0 - a5 = 18 - 23, a9 = 27)

• The third digit is where the control is connected to the ic (1-8)

For easier access, we can seperate the two numbers into two arrays:

int analogInput[NControls]; // holds aX for every index


int selectByte[NControls]; // holds select byte for every index (controls ic)
void setup() {
for(byte i = 0; i < NControls; i++) {
analogInput[i] = floor(connected[i]/10);
selectByte[i] = connected[i]%10;
}
}

In the loop function, we can now read all the voltages:


void loop() {
for(byte i = 0; i < NControls; i++) { // loop through all connected controls
// select correct byte for current control
digitalWrite(10, bitRead(selectByte[i],0));
digitalWrite(11, bitRead(selectByte[i],1));
digitalWrite(12, bitRead(selectByte[i],2));
int voltage = analogRead(analogInput[i]); // 0-1023
voltageToMidi(voltage, i);
}
}

Now we can transform the raw voltage value to MIDI messages:

int midiCh = 9;
int cc = 1;
int voltageChangeThreshold = 8;
int TIMEOUT = 300;
unsigned long PTime[NControls] = {0}; // previous time the voltage changed (more than
int midiPState[NControls]; // previous sent midi value for control i
int voltagePState[NControls]; // voltage of control i at last midi send

void voltageToMidi(int voltage, int i) {


if(abs(voltage-voltagePState[i]) > voltageChangeThreshold) {
PTime[i] = millis();
}
if((millis() - PTime[i]) < TIMEOUT) {
// here the voltage changed significantly and "stayed there" for more than 300 ms
int midiValue;
if(isInverted(connected[i])) {
midiValue = map(voltage, 0, 1023, 127, 0); // flipped last 2 numbers to invert
} else if(connected[i] == 227) {
midiValue = rotaryMidi(voltage, 6, 7, 1);
} else {
midiValue = map(voltage, 0, 1023, 0, 127);
}
// only send midi if it changes (0-127)
if(midiPState[i] != midiValue) {
controlChange(midiCh, cc+i, midiValue); // send midi
MidiUSB.flush(); // force send midi immediately
voltagePState[i] = voltage; // remember last voltage where midi was sent
midiPState[i] = midiValue; // update last sent midi
}
}
}

• to compensate for voltage jitter, we ignore voltage changes that are lower than a
threshold of 8

• if the voltage change is above the the theshold, the time is remembered

• for 300ms after a signi�cant voltage change, the voltage is mapped to a midi value
(0-127)

• if the calculated midi value is di�erent from the last, the value is sent out, using
MIDIUSB lib

• isInverted inverts the mapping for controls with inverted voltages (depends on
wiring of 5v and ground)

• rotaryMidi maps the 6 step rotary switch to the target 7 step midi value of osc3 range
(ignoring the �rst step)

show complete code

Conclusion

After 4 days of soldering, and learning a lot about electronics, the basic controller was
�nished. I also built a prototype case:
Huge thanks goes out

• !! Goetz Müller Dürholt for his DIY Midi Controller Series

• Gustavo Silveira for the mapping idea

• Mr Fid for the rotary switch idea

I already know that this was not the last MIDI controller to build for myself. Next time, I
will try to build a controller for the Prophet V (maybe also including keys).

TBD

• build proper case

• add labels

minor midi mapping issues

Felix Roos 2024

You might also like