
The project called “Arduino MIDI Controller Project”, it’s succeeded to exhibit at Maker Faire in Bay Area.
As for record and help for undestanding what this project made, here I wrote some explanatinos.
First of all, let’s see the video of first prototyping.
What Arduino does?
For ease of understand, here is the case only six switches and one slider.
#include "assign_map.h"
#include <MIDI.h>
uint8_t switch_state[6] = {0, 0, 0, 0, 0, 0};
uint8_t temp[6] = {0, 0, 0, 0, 0, 0};
uint16_t ad_value = 0;
#define DEBUG 0
#define ANALOG_SLIDER_ENABLE 1
void setup()
{
Serial.begin(38400);
delay(5000);
for(int i = 0; i < 6; i++){
pinMode(pins[i], INPUT);
digitalWrite(pins[i], HIGH);
switch_state[i] = digitalRead(pins[i]);
}
#if ANALOG_SLIDER_ENABLE
ad_value = analogRead(PIN_AD0);
#endif
#if DEBUG
Serial.print("AD_MAX = ");
Serial.println(AD_MAX);
Serial.print("AD_DIV = ");
Serial.println(AD_DIV);
#endif
}
void loop()
{
uint8_t data[3];
uint16_t ad_temp = analogRead(PIN_AD0);
#if DEBUG
Serial.print("AD = ");
Serial.println(ad_temp);
#endif
#if ANALOG_SLIDER_ENABLE
if(abs(ad_temp - ad_value) > 2* AD_DIV){
Serial.print('$');
Serial.print(MIDI_AD0_0);
Serial.print(',');
Serial.print(MIDI_AD0_1);
Serial.print(',');
ad_value = ad_temp;
ad_temp = (uint8_t)((double)ad_temp/AD_DIV);
if(ad_temp > 0x7F){ad_temp = 0x7F;}
Serial.print(ad_temp);
Serial.println('$');
}
#endif
for(int i = 0; i < 6; i++){
temp[i] = digitalRead(pins[i]);
if(temp[i] != switch_state[i] && temp[i] == 0){
Serial.print("$");
Serial.print(mapping[3*i]);
Serial.print(",");
Serial.print(mapping[3*i + 1]);
Serial.print(",");
Serial.print(mapping[3*i + 2]);
Serial.println('$');
delay(1);
}
switch_state[i] = temp[i];
}
delay(50);
}
assign_map.h describes just pin confgurations as below.
#ifndef _ASSIGN_MAP_H_
#define _ASSIGN_MAP_H_
#define PIN_SW0 2
#define PIN_SW1 1
#define PIN_SW2 3
#define PIN_SW3 4
#define PIN_SW4 6
#define PIN_SW5 5
#define PIN_AD0 A0
#define MAX_RES 50
#define PULLUP_RES 10
#define AD_MAX 1024
double AD_DIV = (double)AD_MAX/128;
const char pins[6] = {PIN_SW0, PIN_SW1, PIN_SW2, PIN_SW3, PIN_SW4, PIN_SW5};
#define MIDI_0_0 0xb0
#define MIDI_0_1 0x01
#define MIDI_0_2 0x7f
#define MIDI_1_0 0xb0
#define MIDI_1_1 0x02
#define MIDI_1_2 0x7f
#define MIDI_2_0 0xb0
#define MIDI_2_1 0x03
#define MIDI_2_2 0x7f
#define MIDI_3_0 0xb0
#define MIDI_3_1 0x04
#define MIDI_3_2 0x7f
#define MIDI_4_0 0xb0
#define MIDI_4_1 0x05
#define MIDI_4_2 0x7f
#define MIDI_5_0 0xb0
#define MIDI_5_1 0x06
#define MIDI_5_2 0x7f
#define MIDI_AD0_0 0xb0
#define MIDI_AD0_1 0x07
const unsigned int mapping[3*6] =
{
MIDI_0_0, MIDI_0_1, MIDI_0_2,
MIDI_1_0, MIDI_1_1, MIDI_1_2,
MIDI_2_0, MIDI_2_1, MIDI_2_2,
MIDI_3_0, MIDI_3_1, MIDI_3_2,
MIDI_4_0, MIDI_4_1, MIDI_4_2,
MIDI_5_0, MIDI_5_1, MIDI_5_2,
};
#endif
How Arduino signal converted to MIDI signal?
Simply thinking “how can I read MIDI signal from external device?”, here would be two typical solutions, use USB MIDI or use MIDI signal and connect it to Mac through USB MIDI Converter.
However… for Arduino, it is possible to write USB MIDI Driver on Arduino micro controller but usually it needs ISP(In System Programmer) tools. It’s not comfortable for happy, easy DIY life!
Generating MIDI signal and put converter before Mac… it’s messy.
Finally I chose to connect USB Serial signal(default) to Mac. And then, it’s translated to CoreMIDI signal by Python code.
Here is Python code working on Mac.
Before execute this code, please install “simplecoremidi” and pyserial.
sudo pip install simplecoremidi
sudo pip install pyserial
F.Y.I. From line 6 to 24, it’s detecting USB Port automatically.
from simplecoremidi import send_midi
import time
import serial
import os
class Command(object):
"""Run a command and capture it's output string, error string and exit status"""
def __init__(self, command):
self.command = command
def run(self, shell=True):
import subprocess as sp
process = sp.Popen(self.command, shell = shell, stdout = sp.PIPE, stderr = sp.PIPE)
self.pid = process.pid
self.output, self.error = process.communicate()
self.failed = process.returncode
return self
@property
def returncode(self):
return self.failed
com = Command("ls /dev |grep tty |grep usb").run()
print com.output
usbport = '/dev/' + com.output.rstrip('\n')
ser = serial.Serial(usbport, 38400, timeout=1)
while (1):
result=ser.read(ser.inWaiting())
while(result.find("$") < 0):
result=ser.read(ser.inWaiting())
temp = result.find("$")
while(result.rfind('$') == temp):
result=ser.read(ser.inWaiting())
data = result.split("$")[1].split(",")
if len(data) >= 3:
for i in range(len(data)):
data[i] = int(data[i])
print data
send_midi((data))
ser.close()
I confirmed these codes on Yosemite.
Maker Faire version
These codes above are simplified for ease of understand.
Actually I’m using over 10 switches and 5 analogs, 2 USB devices and 1 BLE devices.
The final version for Maker Faire demo,
github link
https://github.com/kuzlab/midi_controller_pj
If you did not visit “kuz lab” boose at Maker Faire yet, please check #50521 in ZONE2 EXPO hall!

