Homemade MIDI Controller!

Since I have been home over winter break, I felt like doing a little bit of fun hacking. As a few of my posts have shown, I am fairly interested in hardware oriented projects, so I thought I would try another. I have several AVR chips and support supplies laying around, so I thought I would use them. Recently, I have also been playing around with DJing. It is fairly common to use a controller to control a DJing setup, but they are all fairly expensive. Since they are just a collection of buttons, knows, and faders, I decided it would be interesting to try to make my own.

My inspiration for this project

This post will cover what I did for the various parts as well as some of the interesting bits of code, so that you can make your own!

The majority of DJing software and controller use what is called MIDI (Musical Instrument Digital Interface) to control interact with each other. In fact, most digital instruments also use this standard when plugged into a computer. Rather than transmitting analog sound data, the instrument will transmit MIDI commands, which could be of the types ‘note on’, ‘note off’, ‘pitch bend’, or one of many others. This greatly simplifies processing the signals as well as reduces the sheer amount of data that needs to be sent; MIDI messages are typically three bytes, as compared to how large an audio stream would be.

The first step to the project was to make sure that my computer could talk through a MIDI interface to my circuit. MIDI is a fairly uncommon peripheral on computers, so I had to go to Sam Ash to buy a 1×1 MidiSport, which provides 1 MIDI In/Out port and plugs into a USB port. Easy enough. I also purchased the MIDI Breakout Board from Sparkfun, which allows my ATtiny2313 AVR chip to connect to the MIDI cables.

This was a really handy board to have

MIDI is actually just a fancy serial port connection that runs at 31250 baud, and I already had some code for doing that type of communication (as shown below), so the step of transmitting data wasn’t all that complicated. I DID run into a gotcha in that I needed to apply voltage to the MIDI breakout board as well as a data line. That took me about a day to figure out. Anyways, here is the code:

void init_uart()
{
	/* Initialize the UART */
   UBRRH = (unsigned char)(15 >> 8);//(unsigned char)((unsigned int)((F_CPU / 16.0 / MIDI_BAUD)-1) >> 8);
   UBRRL = (unsigned char)(15);//(unsigned char)((F_CPU / 16.0 / MIDI_BAUD)-1);

   UCSRB = (1 << RXEN) | (1 << TXEN);

   UCSRC = (0 << USBS) | (0 << UCSZ2) | (1 << UCSZ1) | (1 << UCSZ0);
}

void usart_send_byte(uint8_t u8Data)
{
	// Wait if a byte is being transmitted
	 while (!(UCSRA & (1 << UDRE)));

	// Transmit data
	UDR = u8Data;
}

uint8_t usart_receive_byte()
{
	// Wait until a byte has been received
	while (!(UCSRA & (1 << RXC)));

	// Return received data
	return UDR;
}

After I had the micro controller talking over the MIDI port, I thought it would be exciting to actually have some buttons, rather than just hard coding sequences of notes. So, I got on DigiKey and bought a 4×4 keypad. I had never used a ‘matrix keypad’ before, but thought it couldn’t be too complicated. Boy was I wrong. The way a (4×4) matrix keypad works is that there are 8 I/O lines. 4 correspond to a row each and the other 4 correspond to a column each. When a button is pressed, a circuit is completed between the appropriate row and column pins. By detecting which pins are connected, the micro controller can deduce which specific button is pushed.

A basic 4x4 matrix keypad

There are other sites on the internet that explain a little bit more of the theory behind matrix keypads, so I won’t repeat them here. However, I could not get any of the sample code I found to work, so I had to end up writing my own. Before providing the code, I will explain the setup I was using. I was using PORTB on the ATtiny2313 to handle all 8 pins of the keypad, PB0-PB3 were the columns (H,G,F, and E, respectively) while PB4-PB7 were the rows (J, K, L, and M, respectively). I did not use any external resistors, despite some sites suggesting I do so.

/************************************************************************/
/* Returns which button is pressed. Indexed, 0-15. 0xFE if none is pressed*/
/************************************************************************/
uint8_t button_pressed()
{
	/*
		// outputs (columns) low 4 bits
		E - PB0
		F - PB1
		G - PB2
		H - PB3

		// inputs (rows) high 4 bits
		J - PB4
		K - PB5
		L - PB6
		M - PB7
	*/

	/* Everything is an input */
	DDRB = 0x0;

	/* Columns are Hi-Z */
	PORTB = 0x0;

	/* Rows are pulled high */
	PORTB = PORTB | 0xF0;

	/* For each column */
	uint8_t c;
	for(c = 0; c < 4; c++)
	{
		/* Turn this column into an output. It will be a low output. */
		DDRB = DDRB | (1 << c);

		/* For each row */
		uint8_t r;
		for(r = 0; r < 4; r++)
		{
			uint8_t pins = PINB;

			/* Is this row low? (binary left shift by the row count + 4 to get into high nibble */
			if(! (pins & (1 << (r+4) ) ) )
			{
				/* If yes, */

				/* Return this button */
				return 15 - (r*4 + c); // Subtracting the value from 15 flips it so that the upper left is 0 and bottom right is 15
			}
			else
			{
				/* If no, */
				/* Continue */
			}
		}

		/* Turn this column back to Hi-Z */
		DDRB = 0;
	}

	return 0xFE;
}

After I was able to figure out how to interface with the 4×4 matrix keypad, I was able to configure each button to send a unique message to the computer. Currently, I am using Traktor for my DJ software and I have  it set up so each button causes a different function in Traktor; one button loops 8 bars, another performs a pitch bend, others fire off samples, and I haven’t figured out what to do with the rest!

The final results of the MIDI controller project.

The final result of my project looks like the picture to the left. It was a lot of fun to build and work on this project. For an extension, I might try to make a PCB, rather than a breadboard for all the components. I would also like to put a USB to MIDI chip directly on the board, rather than using an external one. That would be more convenient and I’m sure cheaper. Also, it would be fun to make a nice enclosure of some kind or to have fancier buttons than what I am currently using.

Leave me a comment and let me know what you think!

About samkerr

I'm an eclectic person. I like to dabble in a multitude of things. I'm sure you'll find my blog reflects that.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *