Unopad: Naadloze Arduino MIDI-controller voor Ableton Live
Onderdelen en benodigdheden
| Arduino UNO | × | 1 |
| Schakelaar actuator, APEM A01 serie verlichte drukknoppen | × | 9 |
| Draadbruggen (algemeen) | × | 1 |
Nodige gereedschappen en machines
- Solderbout (algemeen) - Optioneel
Apps en online diensten
- loopMidi
- Hairless MIDI<->Serial Bridge
- Ableton Live 10 Proefversie
Over dit project
Samenvatting
De meeste tutorials en projecten voor MIDI-controllers richten zich alleen op de Arduino-kant, maar niet zoveel op het gebruik ervan in de DAW zelf. Ik wilde een tutorial maken met alle benodigde stappen op één plek. Met dit project wil ik beginners helpen het proces van het maken en gebruiken van een controller beter te begrijpen, en hoop dat het iemand van nut is.
Ik wilde al lang een MIDI-controller maken en heb het nu eindelijk gedaan. Ik gebruikte een Arduino Uno die niet zelf MIDI-berichten via USB kan sturen, dus speciale programma's waren nodig (wordt later uitgelegd).
De volgende secties beschrijven het elektrisch schema, de Arduino-code, en hoe je verbindt met een computer en DAW, in dit geval Ableton.
Schakeling
Het is een heel simpele schakeling. Ik gebruikte 9 drukknoppen, maar niet in een matrix, omdat ik de mogelijkheid wilde om meerdere knoppen tegelijk in te drukken (het is makkelijker en ik had ongebruikte digitale pinnen - ik gebruik 9, in een matrix zouden het 6 zijn).
Knop 3 ==> D2 Knop 2 ==> D3 Knop 1 ==> D4
Knop 6 ==> D5 Knop 5 ==> D6 Knop 4 ==> D7
Knop 9 ==> D8 Knop 8 ==> D9 Knop 7 ==> D10
MIDI-toewijzingen
Ik definieerde 9 MIDI-noten, van 36 tot 45, en NOTE_ON en NOTE_OFF.
Deze MIDI-tutorial helpt je begrijpen hoe je de MIDI-taal kunt gebruiken om elk apparaat dat het MIDI-protocol gebruikt te besturen.
#define NOTE_ONE 36
#define NOTE_TWO 37
// Definieer alle noten hier.
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127
MIDI over USB
Omdat de Arduino Uno niet zelf MIDI-noten naar de DAW kan sturen, moeten we twee extra programma's gebruiken: LoopMidi en Hairless MIDI<->Serial Bridge.
Met LoopMidi maken we een virtuele MIDI-poort die we in Hairless Midi kunnen gebruiken om verbinding te maken met de Arduino-poort.
Code-uitleg
Ik maakte een Button-klasse en gebruik die als volgt:
int NUMBER_BUTTONS = 9;
Button Button1(4, NOTE_ONE);
Button Button2(3, NOTE_TWO);
Button Button3(2, NOTE_THREE);
Button Button4(7, NOTE_FOUR);
Button Button5(6, NOTE_FIVE);
Button Button6(5, NOTE_SIX);
Button Button7(10, NOTE_SEVEN);
Button Button8(9, NOTE_EIGHT);
Button Button9(8, NOTE_NINE);
Button *Buttons[] {&Button1,&Button2,&Button3,&Button4,&Button5,&Button6,&Button7,&Button8,&Button9};
Voor meer over de knop-implementatie, zie Buttons.cpp.
Omdat we geen weerstanden gebruiken maar de knop alleen met de digitale pin en massa verbinden, gebruiken we INPUT_PULLUP in plaats van INPUT.
//Buttons.cpp
pinMode(_pin, INPUT_PULLUP);
Het tricky deel is dat je niet naar een HIGH signaal zoekt zoals je misschien denkt – je knop geeft LOW (0) wanneer hij ingedrukt is.
// Knop is ingedrukt
if (state == 0) {
midiNoteOn(Buttons[i]->Note,127);
}
// Knop is niet ingedrukt
if (state == 1) {
}
Dit betekent ook dat de initiële knopstaat 1 is, niet 0.
//Buttons.cpp
_state = 1;
Elk NOTE ON bericht vereist het bijbehorende NOTE OFF bericht. Wanneer de knop ingedrukt wordt, stuurt hij een NOTE_ON bericht. Wanneer de knop losgelaten wordt, stuurt hij een NOTE_OFF bericht, dus naast de initiële staat voegde ik de laatste onthouden staat toe aan de code.
//Buttons.cpp
_lastState = 1;
We sturen alleen MIDI-berichten als de huidige staat anders is dan de laatste staat.
//Buttons.cpp
if(state!= _lastState) {
//....
}
Gebruik deze twee functies om MIDI-berichten te sturen. Functieparameters zijn note en midiVelocity (ik gebruikte max velocity).
void midiNoteOn(byte note, byte midiVelocity) {
Serial.write(NOTE_ON_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
void midiNoteOff(byte note, byte midiVelocity) {
Serial.write(NOTE_OFF_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
Ik stopte de programmalogica in de functie updateButtons.
void updateButtons() {
for (int i = 0; i < NUMBER_BUTTONS; i++) {
int state = Buttons[i]->getButtonState();
// Knop is ingedrukt
if (state == 0) {
midiNoteOn(Buttons[i]->Note,127);
}
// Knop is niet ingedrukt
if (state == 1)
midiNoteOff(Buttons[i]->Note,0);
}
}
Functie wordt aangeroepen binnen de loop-methode.
void loop() {
if (NUMBER_BUTTONS != 0)
updateButtons();
}
Je controller gebruiken met DAW (Ableton Live)
Als beginner in DAW's wist ik niet hoe ik dingen moest verbinden. Toen ik mijn Korg Nanokey aansloot, herkende Ableton het zelf en kon ik direct gebruiken. Dit was natuurlijk niet het geval met de Arduino-controller, omdat het geen HID-apparaat is en de PC het nog steeds als een Arduino herkent.
Ik laat je hier zien hoe je je Arduino MIDI-controller in Ableton Live 10 kunt verbinden en gebruiken.
Verbinden met Ableton
Open loopMIDI en maak een nieuwe virtuele MIDI-poort zoals op de volgende afbeeldingen.
Open hairless-midiserial en wijs de seriële poort, MIDI Out en MIDI In toe zoals op de volgende afbeeldingen. Voor de seriële poort kiezen we de Arduino Uno poort, en voor MIDI in en out gebruiken we de virtuele MIDI-poort die we in de vorige stap maakten.
Zet de baudrate op dezelfde waarde als in je Arduino-sketch. Ga naar Bestand>Voorkeuren, en daar stel je de baudrate in.
Als alles goed is, kun je MIDI-berichten die door de controller worden gestuurde debuggen. Druk op een knop op de controller en check voor inkomende MIDI-berichten in Hairless MIDI.
Sluit Hairless MIDI niet!
Open Ableton Live, ga naar het tabblad Opties, dan Voorkeuren. Het tabblad Link MIDI moet eruitzien als in dit voorbeeld.
Om te checken dat alles goed verbonden is en dat Ableton MIDI-berichten leest, kijken we in de rechterbovenhoek van Ableton. Het bovenste vakje moet knipperen wanneer een knop op de controller ingedrukt wordt, zoals in het volgende voorbeeld.
Controller is klaar voor gebruik!
Controller als Drum Rack of Toetsenbord gebruiken
Selecteer een MIDI-track. In de Monitor sectie kies In in plaats van Auto, en in MIDI to kies je je luidsprekeruitgang. Je zou nu je toetsenbord moeten horen. Hetzelfde moet gedaan worden voor Drum Rack.
Mijn afgeronde project
Ik gebruikte een oude luidsprekerdoos voor dit project en wat plastic dat ik thuis vond. Ik zaagde beide plastic platen op de afmetingen van de doos en boorde gaten voor de knoppen en één LED die ik later toevoeg.
Ik heb nog een andere oude luidspreker met dezelfde behuizing die ik voor een andere MIDI-controller ga gebruiken, deze keer met knoppen en joysticks.
To do
- Knop lang-inhouden voor wisselen naar CC-modus.
Code
- MidiDrumPad.ino
- Buttons.cpp
- Buttons.h
MidiDrumPad.ino Arduino
#include "Buttons.h"
//------Noten-------------
#define NOTE_ONE 36
#define NOTE_TWO 37
#define NOTE_THREE 38
#define NOTE_FOUR 39
#define NOTE_FIVE 40
#define NOTE_SIX 41
#define NOTE_SEVEN 42
#define NOTE_EIGHT 43
#define NOTE_NINE 44
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127
//------------------------
int NUMBER_BUTTONS = 9;
Button Button1(4, NOTE_ONE);
Button Button2(3, NOTE_TWO);
Button Button3(2, NOTE_THREE);
Button Button4(7, NOTE_FOUR);
Button Button5(6, NOTE_FIVE);
Button Button6(5, NOTE_SIX);
Button Button7(10, NOTE_SEVEN);
Button Button8(9, NOTE_EIGHT);
Button Button9(8, NOTE_NINE);
Button *Buttons[] {&Button1,&Button2,&Button3,&Button4,&Button5,&Button6,&Button7,&Button8,&Button9};
int red_light_pin= 11;
int green_light_pin = 12;
int blue_light_pin = 13;
void setup() {
Serial.begin(9600);
}
void loop() {
if (NUMBER_BUTTONS != 0)
updateButtons();
}
void updateButtons() {
for (int i = 0; i < NUMBER_BUTTONS; i++) {
int state = Buttons[i]->getButtonState();
// Knop is ingedrukt
if (state == 0) {
midiNoteOn(Buttons[i]->Note,127);
}
// Knop is niet ingedrukt
if (state == 1) {
midiNoteOff(Buttons[i]->Note,0);
}
}
}
void RGB_color(int red_light_value, int green_light_value, int blue_light_value) {
analogWrite(red_light_pin, red_light_value);
analogWrite(green_light_pin, green_light_value);
analogWrite(blue_light_pin, blue_light_value);
}
// Stuur MIDI note ON
void midiNoteOn(byte note, byte midiVelocity) {
Serial.write(NOTE_ON_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
// Stuur MIDI note OFF
void midiNoteOff(byte note, byte midiVelocity) {
Serial.write(NOTE_OFF_CMD);
Serial.write(note);
Serial.write(midiVelocity);
}
Buttons.cpp Arduino
#include "Buttons.h"
Button::Button(int pin, short note) {
_pin = pin;
pinMode(_pin, INPUT_PULLUP);
_state = 1;
_lastState = 1;
Note = note;
}
int Button::getButtonState() {
int returnValue = -1;
int state = digitalRead(_pin);
if(state == _lastState)
return 5;
if(state!= _lastState) {
if(state == 0) {
returnValue = 0;
} else {
returnValue = 1;
}
}
_lastState = state;
return returnValue;
}
Buttons.h Arduino
#ifndef Buttons_h
#define Buttons_h
#include <Arduino.h>
//Button (Pin Nummer, Noot Nummer)
class Button {
public:
Button(int pin, short note);
int getButtonState();
int Note;
private:
int _pin;
short _note;
int _state;
int _lastState;
};
#endif
Je kunt de code downloaden van mijn Github
https://github.com/sadreactonly/MidiDrumpad
Schema's
Productieproces
- LED helderheid regelen met PWM via drukknop op Arduino Mega
- Bouw een real-time gyroscoop-spel met Arduino Nano & MPU-6050 sensor
- DHT11 Temperatuur- & Vochtigheidsensor Project met LED-indicatoren en Piezo-luidspreker
- Een Arduino Iron Man bouwen: onderdelen, sensoren en stapsgewijze handleiding
- Een eenvoudige obstakelsensor bouwen met Arduino – IR LED & Fotodiodo Tutorial
- Find Me: Slimme Item Locator met Arduino en Bluetooth
- DIY Arduino Luchtbevochtiger Controller met Relais – Veilige Hoogspanningsopstelling
- Bouw een 4x4x4 LED-kubus met Arduino Uno & 1Sheeld – Interactief LED-project
- Bouw een Aangepaste Arduino Joystick Stuurwiel voor Gaming
- Arduino 101: Bouw een teller met DHT11 sensor & LCD display
- Bouw een Arduino RGB Kleur Mixer – Stap-voor-stap Handleiding