Step 7Programming
First things first, we need to program the Arduino board. If this is your first encounter with an Arduino board, you'll need to setup the Arduino IDE on your PC so it can talk to the Arduino and you can load programs on to it. To do this simply follow the Getting Started guide on the Arduino homepage. You will also need to install the Timer1 library . Download it and unzip it to /hardware/libraries/Timer1/
Edit: As of MIDI_Controller_2011-03-21.zip, Timer1 is no longer needed.
Once your Arduino is up and running, we'll need to load a sketch on it that reads all of the digital and analogue channels and converts that info into MIDI messages. Those MIDI messages are then sent serially over the USB cable to the PC.
Download the attached sketch and upload it to your Arduino. The code has been documented so you can see what is going on. In a nutshell the code continually polls all of the digital and analogue inputs checking for changes. If a change is detected (a button was pressed or a slider was moved), a MIDI message corresponding to the input is sent to the PC.
One thing to note is that the logic for when a button is pressed and released may seem a bit backwards. When a button is pressed the digital input goes 'low', and when it's released it goes 'high'. This is to do with the internal pull up resistor and the buttons being wired to ground in the previous step.
When there is no input to the digital pin (no button is being pressed), the input is being pulled up, or high, hence the name. So the default state of the digital pin is high. Each button was wired to ground so that when a button is pressed, the pin will read low.
Code revision history:
2012-01-20
- Updated to support Arduino 1.0 (updated Serial.print to Serial.write)
2011-10-23
- Added default #defines for Teensy 2.0 and Teensy++ 2.0 digital pins
- Removed #defines for Teensy 1.0 as usbMIDI is not supported
2011-04-11
- Teensy USB code added (thanks to Tim Crawford).
- Updated with #defines for Arduino Mega and Teensy USB for easy compilation
2011-03-21
- Removed TimerOne library. Each analogue pin now maintains its own time since it was last moved, rather than one timer for all pins. This stops sending jittery movements on analogue inputs which haven't been touched.
2011-03-14
- Modified analogue input logic so only pins moved within the timer period are updated, not all of them.
- Experimental code added for higher speed (but less accurate) analogue reads
- Reduced analogue timer length from 1000ms to 250ms
2011-03-01
- Updated MIDI output to send same MIDI signals as official MIDI Fighter
- Reduced debounce length from 5ms to 2ms
2011-02-22
- Initial Release
| « Previous Step | Download PDFView All Steps | Next Step » |































![Beatfly : Make an illuminating blimp and control it with your voice, Keyboard, MIDI Controller, Garageband file, iPhone, Flash, and more! [Mac OSX]](http://img.instructables.com/files/deriv/F1M/MOZ0/G56ZPYN9/F1MMOZ0G56ZPYN9.SQUARE.jpg)
















Thanks a lot for this instructable, I'm just having 1 issue.
I have an Arduino Uno and I've connected/wired everything correctly. I uploaded the Jan 2012 version of the code, which was fine, but whenever I run the device the TX and RX serials aren't operating. I have not altered any of the parts or changed any of the code, i'm just not getting any serial reads from my arduino. Do you have any idea why this would be? I've tried a bunch of Arduino's official troubleshooting guides and nothings working.
Thanks for any help,
Cheers.
Whenever I press a button or use the faders/knobs the TX Serial light comes on the Arduino and in the Midi Serial Converter the RX Serial light lights up. I thought this might have been a solution but when I go to map the controller to Ableton Live it doesn't respond to any of my input.
I have just one question i'm total a newbie on electronic sorry.
the resistor is a 4.7 kohm but what watt i need ?
thank you
It should just be a matter of modifying the code so an analogue input sends a note on message (with velocity) rather than a control change. You may also need to have some sort of rising edge/falling edge logic (similar to the buttons) to send a single note on or off message, rather than a stream of CC messages as the analogue reading increases and decreases.
Also, I want a 16 key pad matrix, but I want to do it with 8 digital pins so I have room for more pots. Is there a way to plex the buttons like a 16 key pad similar to what you'd find on a security system, where all the rows are connected on one leg of the switches, and all the columns connected... so essentially you read 2 pins to get the right location.
The bad thing I forsee with a multiplex like that, is that if 2 buttons are held down simultaneously, are 2 midi controls being sent?
Cool project!!!
The MIDI data is sent as serial messages via the on board Serial-USB adapter. If you wanted to use the 5 pin DIN connectors, you'd simply wire them to pins 0 and 1. The serial baud rate in the sketch would also need to change to 31250.
In terms of the button matrix, that should work. You'd obviously need to store the state of each button (in a 2D array for example), then check for rising and falling edges for each button and update the states accordingly. If two buttons were pressed, two messages would be sent.
If this was a problem for the software/hardware receiving the MIDI messages, you could have a software filter setup so that if two or more buttons were simultaneously pressed, sent out a completely different MIDI message.
Hope that helps!
I only have one issue. The arcade buttons function as momentary switches so a keypress will result in one midi signal being sent to the host computer. If a button is held down, the signal should repeat until the button is released. This is not the case.
This has caused problems with mapping for me while using Traktor Pro 2 and their modifiers, considering that you have to hold one button and press another for the modifier to work.
Is there a line of code that can be added to the arduino sketch that will enable each button to continue sending midi messages while the button is pressed? I've done multiple searches on how to put this into practice, but I am not a programmer and the coding of the arduino is a bit intimidating.
I don't think the controller needs to send a continuous stream of messages saying a button is pressed. The software (Traktor) should see the note on message, and know that the button is being held until the note off message is received. I've been able to configure modifiers in Traktor so the lower right button on the controller acts as a shift key. I can't image Traktor 2 would be too different.
You could fairly easily modify the sketch to send a stream of messages whenever a button is pressed, but I suspect this will cause other problems. For example if you pressed a button to play a track, Traktor would receive multiple note on messages. This could cause a jittery sounding start to the playback, or play/pause very rapidly.
If you're still running in to problems with modifiers in Traktor, I can post up my config. Otherwise if you're certain a key repeat would help, I'll write up an explanation of what lines of code to change and post the sketch too.
I don't understand, truthfully. Perhaps it's a fault with my Serial to MIDI software (S2Midi, I couldn't get MIDIyoke or Serial To MIDI Converter to configure on my Win 7 box) or maybe my own stupidity, but I built everything as you stated and the controller works just fine otherwise. I've tried 3 different computers all running TP2 and I get the same result with each comp.
To setup a button as a modifier, add a new input set to Modifier #1. Hit Learn and grab the button's MIDI channel. Now set Type of Controller to Button, and Interaction Mode to Hold. Set Assignment to Global, and Set to value to 1.
For other buttons ensure the Modifier Conditions are set so M1 is either 0 or 1 so it only executes if the modifier button is/isn't being held. That should be it!
"error: 'A0' was not declared in this scope"
why?
I haven't noticed any latency or delays when using the controller, even going via the serial->MIDI software step. To verify the time delay of a single iteration of loop(), I added in a few calls to micros() and came out with about 850 microseconds (under 1ms) per iteration. It changes by about 4us when buttons/knobs are being moved.
The most time consuming part of the code is the analogRead() call, which take about 100us per pin. I did find on the arduino forum ways of speeding up the analogue reads, but at the cost of the accuracy of the value.
I'll upload the code with the micros timing and the above analogue read speed improvements. Each one can be enabled/disabled through a #define.
MIDI_Controller.cpp.o: In function `analogueInputStopped()':
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:354: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:354: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:354: undefined reference to `TimerOne::stop()'
MIDI_Controller.cpp.o: In function `loop':
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:268: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:268: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:268: undefined reference to `TimerOne::start()'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:274: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:274: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:274: undefined reference to `TimerOne::restart()'
MIDI_Controller.cpp.o: In function `setup':
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:164: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:164: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:164: undefined reference to `TimerOne::initialize(long)'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:166: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:166: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:166: undefined reference to `TimerOne::attachInterrupt(void (*)(), long)'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:168: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:168: undefined reference to `Timer1'
C:\Users\matthew\AppData\Local\Temp\build6227156280145822065.tmp/MIDI_Controller.cpp:168: undefined reference to `TimerOne::start()'