Category Archives: Uncategorized

Building custom midi interfaces with arduino for use in in Ableton and TouchDesigner (Part One)

So recently it was my friends birthday and we were considering what to get him as a present. As he’s all about music production myself and Miyu thought it’d be fun to build him his very own MIDI controller.

Since his name is Dominique We decided to call the midi controller the “Domicon”

Domicon Box Art, this is the finished device complete with all the random references one could need.

Stage 1, Design

We figured that the controller should be a simple 4 rotary pots and 4 buttons controller as we had those bits and bobs lying about already and the board was to be an atmega 32u4  based as this allows the device to show up as a native mouse/keyboard and the Midi Library we planned to use happened to be based on that. We happened to have an Arduino Pro Micro lying around too so we figured we’d use that.

So our ingredients became the following:

4x Aussel 10K OHM B10K Linear Potentiometer
4X Random Arcade buttons we had lying around, the came from a kit similar to the linked
1x Kookye Arduino Pro Micro

We opted to 3D print the casing in two parts, one was the lid with embedded logo and holes for our buttons/knobs and the second was the bottom of the box which just included a small hole in the side for the USB cable to pop out of. We measured up our components and came up with the following 3D model:

We printed a test plate to make sure everything fitted through the holes and amazingly enough all our measurements were pretty spot on so we went ahead and set our Ultimaker away printing.

Stage 2, Wiring

I will confess to being absolutely useless at anything practical. The general gist was all the components hooked up to the arduino directly with no need for resistors or anything like that. 4 Analog pins were used for the potentiometers and 4 digital pins were used for the buttons. The potentiometers had to be wired to ground and vcc but the buttons just needed wiring to ground so that was all pretty straight forward. Miyu did all the wiring and soldering/heatshrinking so I didn’t end up breaking anything and everything felt very solid.

Stage 3, Programming

We now had a product but we still needed to program the board to receive information from the components, convert that into some sort of message that the computer can understand and then send that as midi data.

There’s a great library called MIDIUSB that makes this all quite trivial. There’s even an example on there with some basic functions to get you going. I personally sent everything as control changes but it’s pretty easy to send Note commands too. I kept the note functions in even though I’m not using them just in case I decide I want to expand or change anything in future.

Here’s the final code:

#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>

// initialize everything

int slider1val = 0;
int a0val = 0;
int slider2val = 0;
int a1val = 0;
int slider3val = 0;
int a2val = 0;
int slider4val = 0;
int a3val = 0;

int b2 = 0; 
int b2toggle = 0;
int b2down = 0;

int b3 = 0; 
int b3toggle = 0;
int b3down = 0;

int b4 = 0; 
int b4toggle = 0;
int b4down = 0;

int b5 = 0; 
int b5toggle = 0;
int b5down = 0;

// these are the functions from MIDIUSBs demo, I left the noteOn and noteOff in even though we aren't using them.

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();
}

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush();
}


void setup() {
  // I've opened the serial port for logging reasons. You don't need that line really but I just left it in.
  // At this point we also set the pin modes for our 4 buttons. They are set to pullup and are on digital pins 2, 3, 4 and 5.
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
}

void loop() {
  // lets get some data from our buttons via digitalRead and throw them into some variables
  b2 = digitalRead(2);
  b3 = digitalRead(3);
  b4 = digitalRead(4);
  b5 = digitalRead(5);

  // lets check if the button is down, these are toggle buttons so we use b2toggle to remember what state the toggle is in. We do this for each button
  if (b2 == 0) {
    if (b2down == 0) {
      if (b2toggle == 0) {
         // the control change function sends on the same channel but with a different pitch on each button. The velocity is 127 as these are simple "on off" arcade buttons.
         controlChange(0, 5, 127);
         b2toggle = 1;
      } else {
        controlChange(0, 5, 0);
         b2toggle = 0;
      }
      b2down = 1;
    }
  } else {
    b2down = 0;
  }

   if (b3 == 0) {
    if (b3down == 0) {
      if (b3toggle == 0) {
         controlChange(0, 6, 127);
         b3toggle = 1;
      } else {
        controlChange(0, 6, 0);
         b3toggle = 0;
      }
      b3down = 1;
    }
  } else {
    b3down = 0;
  }

     
  if (b4 == 0) {
    if (b4down == 0) {
      if (b4toggle == 0) {
         controlChange(0, 7, 127);
         b4toggle = 1;
      } else {
        controlChange(0, 7, 0);
         b4toggle = 0;
      }
      b4down = 1;
    }
  } else {
    b4down = 0;
  }

     if (b5 == 0) {
    if (b5down == 0) {
      if (b5toggle == 0) {
         controlChange(0, 8, 127);
         b5toggle = 1;
      } else {
        controlChange(0, 8, 0);
         b5toggle = 0;
      }
      b5down = 1;
    }
  } else {
    b5down = 0;
  }
  

  // now lets deal with our sliders. These are on analog pins 0, 1, 2 and 3.
  // first we read them via analogRead and then if the value has changed from the last time we send the MIDI command. 
  // This is so we don't just spam MIDI data all the time constantly (it's a right pain when using MIDI learn if all sliders are pushing)
  // We do this for all sliders

  a0val = (int) analogRead(0)/8;
  if (a0val != slider1val) {
    slider1val = a0val;
    controlChange(0, 0, a0val);
  }

  a1val = (int) analogRead(1)/8;
  if (a1val != slider2val) {
    slider2val = a1val;
    controlChange(0, 1, a1val);
  }

  a2val = (int) analogRead(2)/8;
  if (a2val != slider3val) {
    slider3val = a2val;
    controlChange(0, 2, a2val);
  }

  a3val = (int) analogRead(3)/8;
  if (a3val != slider4val) {
    slider4val = a3val;
    controlChange(0, 3, a3val);
  }

}


 

The Final Domicon

 

Keeping in Touch 03 – SOP Tricks

In this video I go through some SOPs and explain a few tips and tricks you can use when working with 3d objects in TouchDesigner.

Keeping in Touch 01

×