Unopad: Ableton Live連携シームレスなArduino MIDIコントローラー
必要な部品と材料
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino UNO | 1 | |
| APEM A01シリーズ 照光式プッシュボタンスイッチ | 9 | |
| ジャンパーワイヤー | 1式 |
必要な工具と機器
- はんだごて(任意、ブレッドボードのみでも可)
使用するアプリとオンラインサービス
- loopMIDI(仮想MIDIポート作成)
- Hairless MIDI⇔Serial Bridge(シリアル⇔MIDI変換)
- Ableton Live 10 Trial
プロジェクト概要
概要
MIDIコントローラー自作のチュートリアルは数多くありますが、Arduino側の実装に終始し、DAW側での実際の使い方まで解説しているものは少ないです。このプロジェクトでは、コントローラーの作成からDAWでの活用まで、必要なすべてを一か所にまとめました。初心者がコントローラーの作成・使用プロセスをより深く理解できるよう支援することを目的としています。
長らくMIDIコントローラーを自作したいと考えていましたが、今回ようやく実現できたので共有します。使用したArduino UnoはUSB経由でMIDIメッセージを直接送信できないため、専用ソフトウェア(後述)を併用します。
以下のセクションで、電気回路、Arduinoコード、PCおよびDAW(ここではAbleton)との接続手順を順に説明します。
回路図
非常にシンプルな回路です。9個のプッシュボタンを使用しますが、マトリックス配線にはしません。理由は、複数ボタンの同時押しを容易にするためと、未使用のデジタルピンが十分あるためです(マトリックスなら6ピンで済みますが、直結で9ピン使用)。
Button 3 → D2
Button 2 → D3
Button 1 → D4
Button 6 → D5
Button 5 → D6
Button 4 → D7
Button 9 → D8
Button 8 → D9
Button 7 → D10
MIDIマッピング
MIDIノート番号36〜45の9音を割り当て、NOTE_ON / NOTE_OFF で制御します。MIDIプロトコルの基礎を理解するにはこのチュートリアルが参考になります。
#define NOTE_ONE 36
#define NOTE_TWO 37
// ... NOTE_NINE まで定義
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127
USB経由のMIDI通信
Arduino Uno単体ではDAWへMIDIノートを送れないため、2つの追加プログラムを使用します。
- loopMIDI で仮想MIDIポートを作成
- Hairless MIDI⇔Serial Bridge で、Arduinoのシリアルポートと仮想MIDIポートを接続
コード解説
ボタン管理用の Button クラスを作成し、以下のようにインスタンス化しています。
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};
ボタン実装の詳細は Buttons.cpp を参照してください。
外部抵抗を使わず、ボタンをデジタルピンとGNDに直結しているため、INPUT_PULLUP モードを使用します。
// Buttons.cpp
pinMode(_pin, INPUT_PULLUP);
このモードでは、ボタン押下時に LOW (0)、非押下時に HIGH (1) が読み取られます。一般的な HIGH 検知とは逆なので注意が必要です。
// ボタン押下時
if (state == 0) { midiNoteOn(Buttons[i]->Note, 127); }
// ボタン非押下時
if (state == 1) { midiNoteOff(Buttons[i]->Note, 0); }
初期状態は 1(非押下)です。
// Buttons.cpp
_state = 1;
_lastState = 1;
NOTE_ON には必ず対応する NOTE_OFF が必要です。押下で NOTE_ON、離すで NOTE_OFF を送信するため、現在状態と前回状態を比較し、変化があったときのみメッセージを送信します。
// Buttons.cpp
if (state != _lastState) {
// MIDIメッセージ送信処理
}
MIDIメッセージ送信関数(引数:ノート番号、ベロシティ)。ベロシティは最大値127を使用。
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);
}
メインループから呼ばれる updateButtons() で全ボタンをポーリングします。
void updateButtons() {
for (int i = 0; i < NUMBER_BUTTONS; i++) {
int state = Buttons[i]->getButtonState();
if (state == 0) {
midiNoteOn(Buttons[i]->Note, 127);
}
if (state == 1) {
midiNoteOff(Buttons[i]->Note, 0);
}
}
}
void loop() {
if (NUMBER_BUTTONS != 0) updateButtons();
}
DAW(Ableton Live)での使用方法
DAW初心者の私は、Korg NanoKeyを繋いだときは自動認識されてすぐ使えましたが、ArduinoコントローラーはHIDデバイスではないため、PCからは単なるArduinoとして認識されます。以下にAbleton Live 10での接続・使用手順を示します。
Abletonとの接続
- loopMIDI を起動し、新規仮想MIDIポートを作成(画像参照)
- Hairless MIDI⇔Serial Bridge を起動し、以下を設定:
- Serial port:Arduino Unoのポート
- MIDI In / MIDI Out:loopMIDIで作成した仮想ポート
- ボーレート:Arduinoスケッチと同じ値(
File > Preferencesで設定)
- 正しく設定できていれば、コントローラーのボタンを押した際にHairlessのログにMIDIメッセージが表示されます
- Hairlessを閉じずに、Ableton Liveを起動
- Abletonで
Options > Preferences > Link MIDIを開き、入力ポートとして作成した仮想MIDIポートを有効化(画像参照) - 画面右上のMIDIインジケーター(四角いボックス)がボタン押下で点滅すれば接続成功
ドラムラック / キーボードとして使用
- MIDIトラックを選択
- Monitor を In に設定(Autoから変更)
- MIDI To でスピーカー出力を選択
- これでキーボード/ドラムラックとして演奏可能
完成作品
古いスピーカーボックスと家にあったプラスチック板を再利用し、ボタン穴と後で追加予定のLED用穴を開けました。同じケースのスピーカーがもう1台あるので、次回はノブとジョイスティック搭載のMIDIコントローラーを作る予定です。
今後の拡張予定
- ボタン長押しでCC(Control Change)モードへ切替
ソースコード
MidiDrumPad.ino (Arduino)
#include "Buttons.h"
//------Notes-------------
#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();
if (state == 0) {
midiNoteOn(Buttons[i]->Note,127);
}
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);
}
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);
}
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 Number, Note Number)
class Button {
public:
Button(int pin, short note);
int getButtonState();
int Note;
private:
int _pin;
short _note;
int _state;
int _lastState;
};
#endif
コード一式は GitHub からもダウンロード可能です。
回路図
製造プロセス
- Arduino MegaでPWM制御:プッシュボタン付きLEDフェード制御チュートリアル
- Arduino NanoとMPU-6050で作るリアルタイムジャイロスコープゲーム
- DHT11温湿度センサーで作る温度アラート – LEDとピエゾブザーで視覚/聴覚通知
- Arduinoでアイアンマンを自作:部品・センサー・手順ガイド
- Arduinoでシンプルな障害物センサーを自作 – IR LEDとフォトダイオード入門
- ArduinoとBluetoothで作るスマート紛失防止タグ「Find Me」
- DIY Arduino加湿器コントローラー:リレーを用いた安全な高電圧制御
- Arduino Unoと1Sheeldで作る4x4x4 LEDキューブ – インタラクティブLEDプロジェクト
- ゲーム用カスタムArduinoジョイスティックハンドルの製作
- Arduino 101で作る万歩計:DHT11温湿度センサー&LCD表示付き
- Arduino RGBカラーミキサーの製作 - ステップバイステップチュートリアル