Unopad - 带有 Ableton 的 Arduino MIDI 控制器
组件和用品
![]() |
| × | 1 | |||
![]() |
| × | 9 | |||
![]() |
| × | 1 |
必要的工具和机器
![]() |
|
应用和在线服务
| ||||
| ||||
|
关于这个项目
总结
Midi 控制器的大多数教程和项目仅基于对 Arduino 工作的解释,而不是在 DAW 本身中使用它。我想在一个地方创建一个包含所有必要内容的教程。通过这个项目,我想帮助初学者更好地理解创建和使用控制器的过程,希望对某人有用。
我想做一个midi控制器很久了,我终于做到了,现在我将这个项目与大家分享。我使用了一个 Arduino Uno,它不能通过 USB 发送 MIDI 消息,因此必须使用特殊程序(稍后将在文本中解释)。
以下部分将描述电路、Arduino 代码以及如何连接到计算机和 DAW,在本例中为 Ableton。
电路
这是一个非常简单的电路。我使用了 9 个按钮,但不是在矩阵中,因为我想要按下多个按钮的能力(这更容易,而且我有未使用的数字引脚 - 我使用 9,矩阵中是 6)。
Button 3 ==> D2 Button 2 ==> D3 Button 1 ==> D4 Button 6 ==> D5 Button 5 ==> D6 Button 4 ==> D7Button 9 ==> D8 Button 8 ==> D9 按钮 7 ==> D10
MIDI 映射
我定义了 9 个 MIDI 音符,从 36 到 45,以及 NOTE_ON 和 NOTE_OFF。
本 MIDI 教程将帮助您了解如何使用 MIDI 语言来控制使用 MIDI 协议的任何设备。
#define NOTE_ONE 36#define NOTE_TWO 37 // 在这里定义所有音符。#define NOTE_ON_CMD 0x90#define NOTE_OFF_CMD 0x80#define MAX_MIDI_VELOCITY 127
USB 上的 MIDI
因为 Arduino Uno 不能自己将 MIDI 音符发送到 DAW,我们必须使用两个额外的程序 - LoopMidi 和 Hairless MIDI<->Serial Bridge。
使用 LoopMidi,我们创建了一个虚拟 MIDI 端口,我们可以在 Hairless Midi 中使用它来连接 Arduino 端口。
代码说明
我创建了 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。
因为我们不使用任何电阻器而只将按钮连接到数字引脚和地,所以我们使用 INPUT_PULLUP 而不是 INPUT。
//Buttons.cpppinMode(_pin, INPUT_PULLUP);
唯一棘手的部分是您不是在寻找 HIGH
就像你想象的那样——你的按钮会发出 LOW
(0)
按下时。
// 按钮被按下 if (state ==0) { midiNoteOn(Buttons[i]->Note,127); } // 按钮没有被按下 if (state ==1) { }
这也意味着初始按钮状态是 1,而不是 0。
//Buttons.cpp _state =1;
每个 NOTE ON 消息都需要其相应的 NOTE OFF 消息。当按钮被按下时,它会发送 NOTE_ON 消息。当按钮被释放时,它会发送NOTE_OFF消息,所以除了初始状态之外,我在代码中添加了最后记住的状态。
//Buttons.cpp _lastState =1;
如果当前状态与上一状态不同,我们只发送 MIDI 消息。
//Buttons.cppif(state!=_lastState){//....}
使用这两个函数发送 MIDI 信息。函数参数注意 和 midiVelocity (我使用了最大速度)。
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 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 时,Ableton 自己认出了它,我可以立即使用控制器。这(当然)不是 Arduino 控制器的情况,因为它不是 HID 设备,PC 仍将其识别为 Arduino。
我将在这里向您展示如何在 Ableton Live 10 中连接和使用您的 Arduino MIDI 控制器。
- 与 Ableton 联系
打开loopMIDI 并像下一张图片一样创建新的虚拟 MIDI 端口。


打开 hairless-midiserial 并在下一个图像上分配串行端口、MIDI 输出和 MIDI 输入。对于串口,我们选择Arduino Uno端口,对于MIDI输入和输出,我们使用我们在上一步创建的虚拟MIDI端口。
在您的 Arduino 草图中将波特率设置为相同的速率。转到 File>Preferences ,然后您应该设置波特率。
如果一切正常,您可以调试控制器发送的 MIDI 消息。按下控制器上的按钮并检查无毛 MIDI 中传入的 MIDI 消息。


不要关闭无毛MIDI!
打开 Ableton Live,然后转到选项选项卡,然后是首选项。链接 MIDI 选项卡在本例中应如下所示。

要检查一切是否连接良好以及 Ableton 是否正在读取 MIDI 消息,我们将查看 Ableton 的右上角。当按下控制器上的按钮时,顶部框应闪烁,如下例所示。

控制器已准备就绪!
- 将控制器用作鼓架 或 键盘
选择 MIDI 轨道。在监视器 部分选择In , 而不是 自动 , 并在 MIDI 到 选择您的扬声器输出。你现在应该听到你的键盘了。鼓架也是如此。

我完成的项目
我在这个项目中使用了旧音箱和我在家里找到的一些塑料。我将两个塑料板切割成外壳的尺寸,并为按钮和一个 LED 钻孔,我稍后会添加。
我还有另一个旧扬声器,外壳相同,我将用于另一个 MIDI 控制器,这次带有旋钮和操纵杆。P>
图>
图>
图>
图>
图>
图>
图>



要做
- 按钮长按更改为 CC 模式。
代码
- MidiDrumPad.ino
- 按钮.cpp
- 按钮.h
MidiDrumPad.inoArduino
#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; igetButtonState(); // 按钮被按下 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);模拟写入(green_light_pin,green_light_value); analogWrite(blue_light_pin, blue_light_value);}// 发送 MIDI 音符 ONvoid midiNoteOn(byte note, byte midiVelocity){ Serial.write(NOTE_ON_CMD); Serial.write(note); Serial.write(midiVelocity);}//发送MIDI音符OFFvoid midiNoteOff(byte note, byte midiVelocity){ Serial.write(NOTE_OFF_CMD); Serial.write(note); Serial.write(midiVelocity);}
Buttons.cppArduino
#include "Buttons.h"Button::Button(int pin, short note){ _pin =pin; pinMode(_pin, INPUT_PULLUP); _状态=1; _lastState =1; Note =note;}int Button::getButtonState(){ int returnValue =-1; int state =digitalRead(_pin); if(state ==_lastState) 返回 5; if(state!=_lastState) { if(state ==0) { returnValue =0; } else { 返回值 =1; } } _lastState =状态;返回返回值;}
Buttons.hArduino
#ifndef Buttons_h#define Buttons_h#include//Button (Pin Number, Note Number)class Button{ public:Button(int pin, short note); int getButtonState(); int 注意;私人:int _pin;短_note; int_state; int _lastState;};#endif
你可以从我的 Github 下载代码
https://github.com/sadreactonly/MidiDrumpad示意图

制造工艺