I use Ableton live a lot to jam and to DJ, and using the mouse to
control all the parameters got in the way quite often. You can’t
select a scene and turn a knob at the same time, switching between
views was tiresome. I first thought about building a midibox, but then decided to build my own midi system
using an AVR microcontroller, which I’m more used to. Blueloop helped me a lot
with the schematics, showing me a nice trick to control LEDs using the
same matrix as for the switches (this is not integrated yet,
though).
The midi controller is quite simple. It features 33 switches and 56
potentiometers. The switches and potentiometers are laid out in a
matrix. You can select a horizontal row by pulling down a port to 0 V,
and then reading the switch values on another port, or by going
through the ADCs in the case of the potentiometers. The actual circuit
for the microcontroller is really really simple. There is an
oscillator and a resistor for the MIDI output. The rest of the I/O
pins go to a pinhead which connects the front panel to the circuit
board.
There is a second circuit board in the midi controller that
converts the MIDI output of the first circuit to USB. It was an old
USB programmer board I built 2 years ago that was lying around. I
directly connected the power of the first circuit board to the USB
connector, and connected the MIDI output to the RX pin of the USB
programmer. I had no 12 Mhz oscillator (the one which I normally use),
so I used a 20 Mhz quartz out of an old network card. The board is
really simple too, and consists of a PDIUSBD11 chip by Phillips, which
gets commands over I2C and outputs USB, and an ATMEGA8
microcontroller. Sadly, the PDIUSBD11 is not manufactured any more,
which is kind of sad, as it is the only USB controller I am aware of
that uses I2C, which spared pins on the microcontroller side. I
implemented the USB MIDI
specification out of the specification, and the controller seems
to work under Linux and Windows (there is a problem with MacOSX, but I
last checked two years ago and haven’t tried/debugged it since
then). I can’t publish the whole code for the usb-midi adapter though,
as most of it (including the USB stack) was written by Till Harbaum.
The matrices are soldered on the front panel, which I made out of a
plexiglas sheet through which I drilled holes for the switches and
pots. I had no real problems with the plexiglas, except that you have
to drill quite slowly through it in order not to split it, and that I
had to remove the melt plastic around the holes using a rasp. Each
switch has a diode at one of its outputs, so that two knobs pressed at
the same time can be distinguished on the controller side. The
potentiometers are connected to VCC one one side, to the select port
on the other side, and the variable output is connected to the ADC
using a diode. When selecting a switch or a pot, the select pin is
set to GND, all the other pins are set to VCC. Because of the diodes,
the pressed switches or the pots which are not selected are always
high, and the diode won’t allow them to influence the signal.
The code on the microcontroller is almost as simple as the circuit
board. A simple ring-buffer interrupt-based UART handling is used to
handle outgoing MIDI data (the midi controller can’t receive MIDI
events).
#define RB_SIZE 16
#define MIDI_BAUD 31250UL /* 31.25 kbps */
volatile char tx_buf[RB_SIZE];
volatile char tx_wr = 0, tx_rd = 0;
#define TX_INCR(a, b) (((a) + (b)) & (RB_SIZE - 1))
#define UART_TX_OK (UCSRA & _BV(UDRE))
#define TX_FREE (!(TX_INCR(tx_wr, 1) == tx_rd))
SIGNAL(SIG_UART_TRANS) {
if (tx_rd != tx_wr) {
UDR = tx_buf[tx_rd];
tx_rd = TX_INCR(tx_rd, 1);
}
}
void uart_putc(char c) {
if (UART_TX_OK && (tx_wr == tx_rd)) {
UDR = c;
} else {
while (TX_INCR(tx_wr, 1) == tx_rd) ;
tx_buf[tx_wr] = c;
tx_wr = TX_INCR(tx_wr, 1);
}
}
void uart_init(void) {
tx_wr = tx_rd = 0;
/* set baudrate */
UBRRL = (((F_CPU) / (16 * MIDI_BAUD)) - 1);
/* enable TX, interrupts */
UCSRB = _BV(TXEN) | _BV(TXCIE);
sei();
}
The static buffer “tx_buf” is used to buffer outgoing serial
data. “tx_wr” and “tx_rd” are used as indices into the ring
buffer. “TX_INCR” handles the indices when a character is added to the
ring buffer. “TX_FREE” checks if there is free space in the ring
buffer. “UART_TX_OK” checks if the serial interface is ready to send
another character. “SIGNAL(SIG_UART_TRANS)” is the interrupt routine
that is called when a character has successfully been sent. It checks
if the ring buffer is empty, and sends the next character if it is
not. “uart_putc” is the API to the UART code, and directly sends the
character if the serial interface is ready and the ring buffer is
empty. If not, it waits until there is space in the ring buffer, and
adds the new character to the ring buffer. “uart_init” handles the
initialization of the serial interface, sets the correctly baudrate,
and enables TX and the TX_TRANS interrupt. Finally, interrupts on the
AVR are enabled.
void io_init(void) {
/* disable watchdog */
WDTCR = 0;
/* DD = 1, output */
/* PORT = 1 wenn DD = 0, dann pull-up */
/* portd = output */
DDRD = 0XFF;
/* enable ADC */
DDRA = 0;
PORTA = 0xFF;
ADMUX = _BV(ADLAR);
ADCSRA = _BV(ADEN)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);
// ADCSRA = _BV(ADEN);
uart_init();
}
The routine “io_init” initializes the Atmel, first disabling the
watchdog, then setting PORTD to output (which is not really necessary,
as the status of the port is set by the switch polling routine). The
ADC is enabled by setting the PORTA to input, enabling pullup
resistors, and enabling the ADC in a 10 bit mode, and using AVCC as
reference voltage. Finally the UART is initialized.
/*** MIDI zeugs ***/#define MIDI_NOTE_ON 0x9
#define MIDI_NOTE_OFF 0x8
#define MIDI_AFTERTOUCH 0xA
#define MIDI_CC 0xB
#define MIDI_PROG_CHANGE 0xC
#define MIDI_CHAN_PRESS 0xD
#define MIDI_PITCH_WHEEL 0xE#define MIDI_STATUS_TYPE(c) (((c) & 0xF0) >> 4)
#define MIDI_STATUS_CHAN(c) ((c) & 0xF)static inline midi_is_status(char c) {
return (c & 0x80);
}void midi_send_note_on(unsigned char channel, unsigned char note, unsigned char velocity) {
uart_putc((MIDI_NOTE_ONThe midi controller sends three types of midi messages. When a switch
is pressed, it sends a note on message, when a switch is release, it
sends a note off message, and when a pot is modified it sends a
control channel message. All three messages are three bytes long and
sent directly to the uart using "uart_putc".#define LED_BUTTON_PORT D
#define PORTLED_BUTTON_PORT PORTD
#define DDRLED_BUTTON_PORT DDRD
#define PINLED_BUTTON_PORT PIND#define SET_PIN_OUTPUT(port, pin) { DDR ## port |= _BV(pin); }
#define SET_PIN_INPUT(port, pin) { DDR ## port &= ~(_BV(pin)); }
#define SET_PIN_INPUT_PULLUP(port, pin) { SET_PIN_INPUT(port, pin); PORT ## port |= _BV(pin); }
#define SET_PIN_LOW(port, pin) { PORT ## port &= ~(_BV(pin)); }
#define SET_PIN_HIGH(port, pin) { PORT ## port |= _BV(pin); }
#define PIN_VALUE(port, pin) ((PIN ## port & _BV(pin)) ? 1 : 0)#define NUM_BUTTONS 30
#define BUTTON_STATUS(i) (button_status[(i)] & 0xF)
#define SET_BUTTON_STATUS(i, val) { button_status[(i)] = button_status[(i)] & 0xF0 | (val); }
#define LED_STATUS(i) ((button_status[(i)] >> 4) & 0xF)
#define SET_LED_STATUS(i, val) { button_status[(i)] = button_status[(i)] & 0xF | ((val) 1 (bounce?) -> 2
wenn knopf auf 1 dann nachricht senden (note on), wieder auf 0 (note off)
*/#define BUTTON_ROWS 5
unsigned char button_status[BUTTON_ROWS * 8];void init_buttons(void) {
int i, j;
for (i = 0; iThe button polling routines are a bit longer. The routine
"ask_buttons" polls through all the buttons, and calls the routine
"ask_button" to get the status of a single switch. The result of the
polling is stored in the array button_status. A simple state machine
is used to handle press/release status. "ask_button" sets the
corresponding select pin low, enables the input pin and enables the
internal pullup resistor. The value is then read and handled. After
all buttons have been read, midi_buttons is called, which reads the
switch status in the "button_status" array, and sends the
corresponding midi message.#define POTI_SEL_PORT B
#define PORTPOTI_SEL_PORT PORTB
#define DDRPOTI_SEL_PORT DDRB#define NUM_POTIS 64
unsigned char poti_status[NUM_POTIS];void init_potis(void) {
int i, j;
for (i = 0; i MAX_THRESHOLD) return 0x7F;
uint32_t bla = (uint32_t)((uint32_t)adc - (uint32_t)MIN_THRESHOLD);
bla *= 0x7F;
bla /= 0xDFF0;
return bla;
}void ask_poti(unsigned char sel_pin, unsigned char adc) {
SET_PIN_LOW(POTI_SEL_PORT, sel_pin);
_delay_us(50);
ADMUX = _BV(ADLAR) | adc;
ADCSRA |= _BV(ADSC);
loop_until_bit_is_set(ADCSRA, ADIF);
loop_until_bit_is_clear(ADCSRA, ADSC);
last_adc = ADC;
SET_PIN_HIGH(POTI_SEL_PORT, sel_pin);
unsigned char val = convert_to_cc(last_adc);
unsigned char poti = sel_pin + 8 * adc;
unsigned char old = poti_status[poti] & 0x7f;
if ((val != old) && ((val == 00) || (val == 0x7F) || (abs(val - old) > 1)))
poti_status[poti] = 0x80 | val;
}void ask_potis(void) {
int i, j;DDRPOTI_SEL_PORT = 0xFF;
PORTPOTI_SEL_PORT = 0xFF;for (i = 0; i
The code to read the potentiometers is pretty similar, except that the
routine "ask_poti" reads the value using the ADC. The diodes on the
variable pins of the potentiometers have a voltage drop of 0.6V, which
we account for by subtracting MIN_THRESHOLD from the read ADC
value. The value is then scaled to 0-127, and sent if it differs more
than one from the previous value. The value is stored into the array
"poti_status". Finally, the routine "midi_potis" sends the value of
the potis which have changed (signalled by the flag 0x80)./*** Main ***/int main(void) {
io_init();init_buttons();
init_potis();DDRPOTI_SEL_PORT = 0xFF;
PORTPOTI_SEL_PORT = 0xFF;
DDRA = 0x00;
PORTA = 0xFF;
ADMUX = 0;int i;
for (i =0 ; iThe main routine initializes the buttons, potis, I/O, waits for 100
iterations of the main loop to let the pots and switch bounce around,
and then loops asking for switch and pot status, and sending the
corresponding MIDI messages. You can find the code for the project
hereThe main problem with the midi controller is that I used "cheap"
pots (though it was quite expensive to buy 56), and some of them have
short circuits or jump around or don't work at all. Another problem is
that I probably will have to convert the linear output of the pots to
something more approaching logarithmic scale because the resolution in
the high-end is too bad. Finally, another problem with the pots is
that the value sometimes oscillate due to environment noise or so, and
that using live in record mode tends to overwrite some parameter
automation envelopes. The next version will probably use less pots,
maybe some rotary encoders, though I have to find somewhere were I can
get them without being too expensive.All in all, it was a lot of work to build the midi controller, and
you can buy the same stuff for around 120 EUR from Behringer. The next
version will have some features that are not easily found. I
absolutely want to be able to record "automation macros" directly on
the hardware. Press "record pattern A", then move some pots and knobs
for a few bars, stop the recording, and then be able to play in back
"in sync". The next midi controller I am building will be a bad-ass
step sequencer with those macros features and other mad stuff. I'll
post about it when it's ready and working.




geil
mehr krach!
+++ neingeist
Comment by neingeist — November 4, 2005 @ 3:18 am
Das Ding ist ja echt kühl geworden und tolle Dokumentation!
Comment by Blueloop — November 4, 2005 @ 8:00 am
hallo
ich bastel auch gerade an nem midi controller, hab allerdings ziemliche probleme mim uart des ATMEGA 16. Bekomme einfach nix rauß geschrieben.
das liegt bestimmt an der krummen baudrate der midi spezifikation. hast du den internen oszilator des avr`s genutz zur uart taktung oder nen quarz ?
Comment by gast — December 14, 2006 @ 9:42 pm
Mit 8 Mhz als Quartz kriegst du saubere 31250 bps hin. Muesste eigentlich kein problem sein. Vielleicht reicht der Pin output nicht fuer den receiver? Hast du einen Transistor eingebaut?
Comment by manuel — December 14, 2006 @ 11:26 pm
really cool ,any ideas on implementing an lcd?
how are the revisions and new features coming along?? vey keen to hear your progress.
Comment by manyworldsproductions — January 7, 2007 @ 6:55 pm
Hallo,
könnte ich die unterlagen vom AVR-Midi-USB Adapter bekommen?
Gruß Raphael
Comment by Raphael — February 6, 2007 @ 7:59 am
Hallo Raphael,
leider nicht, die oben dokumentierte Version ist eh mit einem Chip gebaut, den es nicht mehr gibt, und der Code ist leider zum Teil nicht meiner. Allerdings habe ich eine neue Version mit dem AT90USB1286, setz dich bitte mit mir in Verbindung manuel@bl0rg.net
Comment by netzstaub — February 6, 2007 @ 11:34 am
I need to repeat your device but with different number of buttons and pots. Can you compile a firmware for atmega644? With 8 pots (each one on 1 ADC line) and 8×8 buttons matrix. I’m asking because you said that you will not give a full source. Thank you.
Comment by MonZon — February 11, 2007 @ 5:54 am
I need to repeat your device but with different number of buttons and pots. Can you compile a firmware for atmega644? With 8 pots (each one on 1 ADC line) and 8×8 buttons matrix. I’m asking because you said that you will not give a full source. Thank you. Mail it here slamlmd (doggy) yandex.ru
Comment by MonZon — February 11, 2007 @ 5:54 am
Well the code for the MIDI application itself is completely available in the posting on top (yeah that’s all the firmware), so just modify it for your need. What I’m not posting is the USB MIDI code which is obsolete anyway. Cheers, manuel
Comment by netzstaub — February 11, 2007 @ 1:45 pm
some forums says that it’s not possible to make USB MIDI HID device on atmega because MIDI requres bulky endpoints. I don’t know what does it mean. Can you give me any hints how to do that?
Comment by MonZon — February 11, 2007 @ 5:54 pm
Hi well done! … Today I finished the firmware for my own device and it passed all usb9 tests and windows knows it as audio device. So far so good … now I have a working USB midi device. I want to connect it to Traktor 3, but i can’t. It is not available inside. It is no prob of tracktor. I just can’t interact with the midipart of the device. I thought the device is mapped by a standard driver of windows so I can connect it to Traktor. What did you do to connect your device under windows to ableton live? … is there a special software required?
Alex
Comment by alibabashack — May 9, 2007 @ 12:37 pm
Hi alibabashack,
I just used the standard windows driver. Maybe there is something wrong with your usb midi descriptors? It is quite tricky… Maybe if you send me a copy of them I could go over them. Did you define only one midi output? I guess windows needs to have a port with both in and out, else it won’t be recognized correctly.
Comment by manuel — May 9, 2007 @ 12:46 pm
thank you for quickly answering…
my descriptors are ok … they passed the usb9 test, but your last idea is right maybe … i just defined a midi IN port because I just want to controll tracktor and need no respond from pc .. I’ll send you a dump of my descriptors and try to define an out endpoint in addition. hope it will work then… thank you very much!
Comment by alibabashack — May 9, 2007 @ 2:43 pm
hmmm doesn’t work also with out pipe …
Comment by alibabashack — May 9, 2007 @ 3:25 pm
Hi I am currently starting my own project similar to yours and was scouring the web for resources. Your controller looks awesome btw! Just one thing, I can’t grasp why you have the output of 2 pots connected to one terminal, i.e. I think the schematic shows there are 16 pots connected to an 8-bit A/D port, have you used a multiplexer and just not shown it or do your rotary pots interact as pairs?
Comment by haydos — December 14, 2007 @ 3:57 am
ahh i just read over it, and the penny dropped. Would you advise not to use mux’s because of propogation delays?
Comment by haydos — December 14, 2007 @ 4:22 am
this still blows my mind everytime i bring this page up. hopefully i can get started on my knob-box soon!
Comment by slvmchn — December 15, 2007 @ 4:49 am
I will soon start my own midi project too.
Comment by usb — March 7, 2008 @ 10:57 pm
Vielen Dank für all die sehr nutzvollen Informationen…. Webdesign Agentur Düsseldorf
Comment by Webdesign Agentur — March 16, 2008 @ 11:55 pm
It is no prob of tracktor. I just can’t interact with the midipart of the device. I thought the device is mapped by a standard driver of windows so I can connect it to Traktor.
Comment by 普通話課程 — May 19, 2008 @ 11:35 am
We sell cheap rechargeable laptop battery for most every notebook computer on the market. Since 1996, we have worked with leading laptop battery manufacturers around the world to design, specify, and build high quality laptop batteries. All our laptop batteries must pass stringent quality control tests that ensure they will work with your laptop computer.
Comment by laptop batteries — September 10, 2008 @ 6:37 am
Use the laptops power management system. This application will help optimize power usage.
Comment by computer battery — October 15, 2008 @ 3:21 am
http://www.tool-battery.com/ is specialize in replacement power tools batteries for most brands such as black&decker, dewalt, makita, hitachi, bosch and many more.Our products are new and 12 months warranty!
Comment by power tool battery — October 15, 2008 @ 3:23 am
If you need a new laptop battery, I suggest you could purchase one from http://www.bestebuy.co.uk/ , which would shipping to yu fast and the quality is satisfy satisfied.:)
Comment by laptop battery battery — October 15, 2008 @ 3:25 am
We supply a large range of rechargeable Laptop Battery packs for your Laptop , All Laptop Battery in our website are made with high quality cells. Shipping with us is 100% secure guaranteed.
http://www.inbattery.com/
Comment by ACER battery — October 15, 2008 @ 3:26 am
http://www.batteryfast.com/laptop-ac-adapter/toshiba/toshiba-19V-4.74A-90w-6.3mm-3.0mm.php toshiba 19V 4.74A 90w 6.3mm*3.0mm adapter PA3201U-1ACA SEB100P2-15.0
http://www.batteryfast.com/laptop-ac-adapter/toshiba/toshiba-19V-6.3A-120w-5.5mm-2.5mm.php toshiba 19V 6.3A 120w 5.5mm*2.5mm adapter PA3290U-2ACA PA-1121-08
Comment by baterry — November 15, 2008 @ 6:31 am
http://www.batteryfast.com/acer/squ-519.htm acer squ-519 battery,
Comment by baterry — November 18, 2008 @ 12:22 pm
http://www.batteryfast.co.uk/asus/a32-f3.htm asus a32-f3 battery,
http://www.batteryfast.co.uk/compaq/n400.htm compaq n400 battery,
Comment by baterry — November 23, 2008 @ 3:13 pm
http://www.batteryfast.co.uk/dell/latitude-d810.htm dell latitude d810 battery,
Comment by baterry — November 24, 2008 @ 11:35 am
http://www.batteryfast.co.uk/toshiba/pa3420u.htm toshiba pa3420u battery,
http://www.batteryfast.co.uk/sony/vgp-bps2.htm sony vgp-bps2 battery,
Comment by baterry — November 28, 2008 @ 10:20 am
We here at batteryeshop.com strive to make you battery purchases easy. Since we understand that finding the right batteries for your needs can be overwhelming and confusing at times we developed a battery finder to help find the right size for the make and model of your equipment. We also offer educational articles and tips to help you conserve your rechargeable batteries and choose the proper battery chargers and some of the common functions of different power supplies. By us providing education you are able to make the right purchasing decisions as well as provide proper care for all of your electronics.
Comment by laptop battery — December 9, 2008 @ 6:39 am
wholesale jewelry
handmade jewelry
Comment by wholesale jewelry — January 8, 2009 @ 9:23 am
Lots of the files from the Megaupload system at the global web are available for downloading at http://megauploadfiles.com/ without registration!
Comment by hilla — January 23, 2009 @ 11:59 pm
Fashion jewelry Pandora jewelry
Comment by fashion jewelry — February 20, 2009 @ 2:25 pm
thank you
Comment by beyonce — March 3, 2009 @ 11:58 am