我发现的最适合初学者的版本之一是MIDI控制器。MIDI控制器是将MIDI数据(乐器数字接口)发送到设备以触发声音并制作音乐的任何硬件。

我发现许多实现都很复杂,即使是初学者也是如此。发现我需要使用数百行不可读的代码感到非常沮丧。或者在某些情况下,我需要焊接电阻器。

该项目

通过构建自己的Arduino MIDI控制器,我的目的是创建一个令人愉悦的项目,同时将噪音降至最低。任何初学者都可以跟随。为此,我使用MIDI Fighter 3D作为基本灵感,并删除了所有不必要的功能

项目总成本不到30美元,而且材料清单确实很短:

  • Arduino Leonardo:10美元至20美元之间。淘宝更便宜
  • 16个24毫米Sanwa纽扣:每个纽扣在1到2.50美元之间。
  • 烙铁
  • 22 AWG电线

Arduino开发板

当我开始这个项目时,我发现有一堆新的Arduino模型(不包括数百个兼容板)。它们提供的功能略有不同。

我需要将MIDI信号发送到计算机,而最简单的方法是通过USB。任何基于ATmega32u4微控制器的Arduino板都有内置USB通信。

具有本地USB支持的正式Arduino板是Arduino Due,Arduino Zero,Arduino Leonardo,Arduino Micro。这些开发板具有集成的USB支持,这意味着它们可以充当USB MIDI设备。

我决定选择Arduino Leonardo的克隆。它具有用于该项目的足够输入,并且还包含插头,可以更轻松地插入/拔出电线。

第一步

尽管我将逐步解释如何实现该项目的代码,但是您可以下载最终版本

要将代码上传到板上,您需要使用Arduino IDE。他们还有一个非常有用的Web编辑器,但是每天可以编译代码的配额有限。

步骤1.闪烁内置LED

有趣的是,硬件世界中的“ Hello World”如何使LED闪烁。

令我惊讶的是,我发现Arduino Leonardo内置了一个LED,您可以通过闪烁来测试代码。这样,您无需在带有LED和电阻的面包板上构建外部电路。

// The setup function runs once when you press reset or power the board
void setup() {
  // Initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// The loop function runs over and over again forever
void loop() {
  // Turn the LED on (HIGH is the voltage level)
  digitalWrite(LED_BUILTIN, HIGH);
  // Wait for a second
  delay(1000);
  // Turn the LED off by making the voltage LOW
  digitalWrite(LED_BUILTIN, LOW);
  // Wait for a second
  delay(1000);
}

步骤2.LED闪烁手动输入

下一步的逻辑步骤是,每当我发送一些信号时,同一LED就会闪烁。我卸下了2根杜邦线一端的塑料盖,并将另一端连接到板上:

  • 引脚号2数字输入之一(正)。它可以是任何数字引脚。
  • 引脚GND任何接地引脚(负极)。

现在,每次连接导线的裸露末端时,我都会闭合电路,因此可以安全地执行代码。

Leonardo的20个数字引脚中的每一个都有一个内部电阻器(默认情况下已断开),可使用来启用该电阻器INPUT_PULLUP。请记住,上拉输入表示按钮状态为反转

  • HIGH 当电路断开(未按下按钮)时。
  • LOW 当电路闭合(按下按钮)时。
const int BUTTON_PIN = 2;

// The setup function runs once when you press reset or power the board
void setup() {
  // Initialize button pin as a pull-up input.
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  // Initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// The loop function runs over and over again forever
void loop() {
  // Get the digital state from the button pin
  // In pull-up inputs the button logic is inverted (HIGH is not pressed, LOW is pressed)
  int buttonState = digitalRead(BUTTON_PIN);
  // Turn on/off the LED depending on the button state
  if (buttonState == LOW) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

步骤3:安装MIDIUSB库

该库允许具有USB功能的Arduino板充当USB上的MIDI乐器。查看官方文档以获取更多信息。

使用Arduino IDE,您可以使用库管理器安装额外的Arduino库

  1. 打开IDE,然后单击“草图”菜单,然后单击“包含库”,然后单击“管理库”
  2. 搜索MIDIUSB,然后单击“安装”
  3. 完成后,已安装标签应出现在MIDIUSB库的旁边。
  4. 关闭库管理器。

现在,莱昂纳多可以通过USB发送MIDI信息!但是首先,需要对MIDI如何工作有一些了解。

MIDI如何运作

“ MIDI(乐器数字接口)是连接电子乐器,计算机和相关音频设备以播放音乐的标准通信协议。” —维基百科

它可以处理事件消息,其中包括演奏音符的音高和力度数据以及其他指令。

在此特定项目中,来自16个按钮的输入通过USB发送不同的消息。您可以使用GarageBand或Ableton Live等任何合适的软件在计算机上将这些消息转换为声音

MIDI消息剖析

要发送MIDI消息,我使用了sendMIDI()步骤3中安装的MIDIUSB库中的方法。

此方法可以接收4个参数:

  • 事件类型:可以0x09用于音符开(播放音符)或0x08音符关(停止播放音符)。
  • 注On / Off:事件类型与MIDI通道(1-16)组合。我只使用通道1,所以它0x90用于音符开或0x80音符关。
  • 音符编号:每个音符都有一个关联的数字音高(频率刻度)。
  • 速度:0(无速度)到127(最快)。

步骤4:传送MIDI讯息

我包含了MIDIUSB库,而是发送了一条便条,而不是闪烁内置LED。

#include "MIDIUSB.h"

const int BUTTON_PIN = 2;
// Note "C2"! See https://github.com/arduino/tutorials/blob/master/ArduinoZeroMidi/PitchToNote.h
const int BUTTON_PITCH = 36;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  byte buttonState = digitalRead(BUTTON_PIN);
  if (buttonState == LOW) {
    noteOn(BUTTON_PITCH);
  } else {
    noteOff(BUTTON_PITCH);
  }
}

void noteOn(int pitch) {
  MidiUSB.sendMIDI({0x09, 0x90, pitch, 127});
  MidiUSB.flush();
}

void noteOff(int pitch) {
  MidiUSB.sendMIDI({0x08, 0x80, pitch, 0});
  MidiUSB.flush();
}

⚠重要:

从这一步开始,Arduino变成了MIDI USB控制器,并且它停止通过USB接收代码。

当您陷入无法再编程Arduino的位置时,请执行以下步骤:

  1. 按住Arduino板上的圆形复位按钮。
  2. 单击Arduino IDE上的Upload。
  3. 释放复位按钮。
  4. 更新的代码将被上传到开发板上。

步骤5:从每个按钮发送MIDI消息

最后一步是将每个音高映射到一个按钮。对于这16个按钮,我定义了从C 2到E 3 b的比例,即从下到上以及从左到右的顺序从36到51的音高。看看从Arduino的教程文件,看看有什么间距对应于每一个音符。

我用从数字引脚212(使用它们作为七段)从和模拟引脚A0A4

3个MIDI控制器的图表,带有音符,音高和大头针,从下到上和从左到右分配给16个按钮

这就是最终代码的样子:

#include "MIDIUSB.h"

const byte TOTAL_BUTTONS = 16;
// All the Arduino pins used for buttons, in order.
const byte BUTTONS_PIN[TOTAL_BUTTONS] = {2,3,4,5,6,7,8,9,10,11,12,A0,A1,A2,A3,A4};
// Every pitch corresponding to every Arduino pin. Each note has an associated numeric pitch (frequency scale).
// See https://github.com/arduino/tutorials/blob/master/ArduinoZeroMidi/PitchToNote.h
const byte BUTTONS_PITCH[TOTAL_BUTTONS] = {36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
// Current state of the pressed buttons.
byte currentRead[TOTAL_BUTTONS];
// Temporary input reads to check against current state.
byte tempRead;

// The setup function runs once when you press reset or power the board
void setup() {
  // Initialize all the pins as a pull-up input.
  for (byte i = 0; i < TOTAL_BUTTONS; i++) {
    pinMode(BUTTONS_PIN[i], INPUT_PULLUP);
  }
}

// The loop function runs over and over again forever
void loop() {
  for (byte i = 0; i < TOTAL_BUTTONS; i++) {
    // Get the digital state from the button pin.
    // In pull-up inputs the button logic is inverted (HIGH is not pressed, LOW is pressed).
    byte buttonState = digitalRead(BUTTONS_PIN[i]);
    // Temporarily store the digital state.
    tempRead = buttonState;
    // Continue only if the last state is different to the current state.
    if (currentRead[i] != tempRead) {
      // See https://www.arduino.cc/en/pmwiki.php?n=Tutorial/Debounce
      delay(2);
      // Get the pitch mapped to the pressed button.
      byte pitch = BUTTONS_PITCH[i];
      // Save the new input state.
      currentRead[i] = tempRead;
      // Execute note on or noted off depending on the button state.
      if (buttonState == LOW) {
        noteOn(pitch);
      } else {
        noteOff(pitch);
      }
    }
  }
}

void noteOn(byte pitch) {
  MidiUSB.sendMIDI({0x09, 0x90, pitch, 127});
  MidiUSB.flush();
}

void noteOff(byte pitch) {
  MidiUSB.sendMIDI({0x08, 0x80, pitch, 0});
  MidiUSB.flush();
}

案子

为了使这个项目简单,我非常挑剔地选择了哪些功能。

  • 仅按钮: 4个4×4网格中的16个类似于sanwa的街机按钮。没有旋钮,滑块,推子或任何其他模拟输入。
  • 单身机壳:请勿在外壳上使用任何螺钉,螺母,螺栓或胶水或固定Arduino板。
  • 日常工具:例如,我焊接电线,而不是为街机按钮购买特定的电线钳。

一体式设计

我面临的挑战之一是设计一个足够简单的机壳,使其无需组装,并可以一次进行3D打印

为避免使用螺钉或胶水,我需要设计一种外壳,以使对电子设备的访问最少。机箱的最大灵感来自Mac Mini,它的底部有一个圆形的孔。我也想为此设计一个可拧盖,但是我决定让它打开以露出电子设备。

我的MIDI控制器的底面

下载3d可打印盒(322 KB)。推荐设置:PLA,0.15mm层,20%填充,至少对圆形底部孔,Arduino支架和micro USB支持执行器。

这些是3d打印盒的尺寸(以毫米为单位):

带有外壳尺寸的图表

拿不带螺丝的Arduino

莱昂纳多(Leonardo)有4个孔,可将板子拧入任何合适的盒子中,但我的想法是使从盒子中添加和拆卸板子变得容易

在Thingiverse上找到Arduino的固定很容易,我花了5次迭代将该固定夹集成到一体式设计中。最困难的部分是使其腿部避免按钮上的孔,并使Micro USB对准外壳的中心

MIDI控制器盒内的3条腿,用于固定Arduino板

接线

这是MIDI控制器的接线图:

MIDI控制器的接线图

将所有按钮插入到位后,我焊接了黑色的导线,将它们之间的所有负极脚连接在一起

黑线焊接到按钮负极

然后,我从每个正极脚上焊接了很长的红色电线,以直接连接到板上

红色和黑色导线焊接到按钮上

为了将电线连接到Arduino,我切割并焊接了一些杜邦端,并用热缩管覆盖它们。

带有杜邦端和热缩管的红线

我按照与MIDI Fighter中相同的顺序将电线连接到板上。从下到上,从左到右。

底部的MIDI控制器,全部连接到Arduino板

使用MIDI控制器

任何音乐软件(或适当的硬件)均可用于接收MIDI并制作一些音乐。最受欢迎的是Garage Band,Ableton live,我知道有很多应用程序可以在手机上安装

所有这些工具都可用于加载预定义的声音以进行手鼓演奏,但它们是为更大的目的而制作的。这些工具对于初学者来说很难设置。

Web浏览器中的MIDI

为了使该项目及其简单性更加协调一致,我构建了一个完全专注于MIDI控制器的Web工具

Punchy:用于MIDI控制器的WebMIDI和WebAudio实现。

它可以在任何支持WebMIDI JavaScript API的浏览器上读取MIDI消息。然后,它在合成器(使用WebAudio API)或采样器中播放声音,从任何声音包中加载自定义声音。

设置Ableton Live

要使MIDI控制器与Ableton Live一起使用,请遵循官方文档中的以下简单步骤

转到“首选项”→“链接MIDI”,并确保“输入”的“音轨”和“远程”为ON,并且输出的“ Remote”为ON,如指南中所述:

Ableton Live屏幕快照,其中包含前面提到的选项。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。