Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live

Компоненты и материалы

Компонент Количество Примечание
Arduino UNO 1
Кнопки APEM A01 серии (с подсветкой) 9
Перемычки 1 комплект

Необходимые инструменты

Приложения и онлайн-сервисы

О проекте

Краткое описание

Большинство уроков по MIDI-контроллерам охватывают только сторону Arduino, но не работу в DAW. Я хотел собрать всё в одном месте. Этот проект поможет новичкам понять процесс создания и использования контроллера.

Давно хотел сделать MIDI-контроллер и наконец сделал. Arduino Uno не умеет слать MIDI по USB, поэтому нужны дополнительные программы (объясню ниже).

Далее: электрическая схема, код Arduino, подключение к компьютеру и DAW (Ableton).

Схема

Очень простая. 9 кнопок, не в матрице, а по отдельному пину — чтобы можно было нажимать несколько одновременно (проще и свободных пинов хватает: 9 вместо 6 в матрице).

Кнопка 3 → D2
Кнопка 2 → D3
Кнопка 1 → D4
Кнопка 6 → D5
Кнопка 5 → D6
Кнопка 4 → D7
Кнопка 9 → D8
Кнопка 8 → D9
Кнопка 7 → D10

MIDI-маппинг

Определены 9 MIDI-нот (36–44) и команды NOTE_ON / NOTE_OFF.

#define NOTE_ONE 36
#define NOTE_TWO 37
// ... до NOTE_NINE 44
#define NOTE_ON_CMD 0x90
#define NOTE_OFF_CMD 0x80
#define MAX_MIDI_VELOCITY 127

Этот MIDI-учебник поможет понять, как использовать MIDI для управления любым устройством.

MIDI через USB

Arduino Uno не отправляет MIDI в DAW напрямую. Нужны две программы: LoopMIDI (создаёт виртуальный MIDI-порт) и Hairless MIDI<->Serial Bridge (соединяет Serial-порт 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.

Никаких внешних резисторов — кнопка между пином и землей. Используем INPUT_PULLUP вместо INPUT.

// Buttons.cpp
pinMode(_pin, INPUT_PULLUP);

Трюк: при нажатии кнопка даёт LOW (0), а не HIGH. Начальное состояние — 1.

// Button is pressed
if (state == 0) { midiNoteOn(Buttons[i]->Note,127); }
// Button is not pressed
if (state == 1) { midiNoteOff(Buttons[i]->Note,0); }
// Buttons.cpp
_state = 1;

Каждому NOTE_ON должен соответствовать NOTE_OFF. При нажатии — NOTE_ON, при отпускании — NOTE_OFF. Храним последнее состояние.

// Buttons.cpp
_lastState = 1;

MIDI-сообщения шлём только при смене состояния.

// Buttons.cpp
if(state != _lastState) { // ... }

Функции отправки MIDI (параметры: нота, 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);
}

Логика в функции 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);
  }
}

Вызывается в loop():

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
}

Использование контроллера в DAW (Ableton Live)

Как новичок в DAW, не знал, как подключить самодельный контроллер. Korg Nanokey Ableton определил сам, а Arduino — нет, ПК видит в нём просто Arduino.

Пошагово для Ableton Live 10:

Подключение к Ableton

  1. Открыть loopMIDI, создать виртуальный MIDI-порт (скриншоты в оригинале).
  2. Открыть Hairless MIDISerial, назначить: Serial port — порт Arduino, MIDI In/Out — созданный виртуальный порт.
  3. Установить baudrate такой же, как в скетче Arduino (Файл → Preferences).
  4. Если всё верно, в Hairless будут видны MIDI-сообщения при нажатии кнопок.
  5. Не закрывать Hairless!
  6. В Ableton: Options → Preferences → Link MIDI. Настроить как на примере (скриншот).
  7. Проверить: в правом верхнем углу Ableton верхний квадратик должен мигать при нажатии кнопок (GIF).

Контроллер готов!

Использование как Drum Rack или клавиатура

Выбрать MIDI-трек. В секции Monitor выбрать In вместо Auto, в MIDI to — выход на колонки. Должен звучать. То же для Drum Rack (GIF).

Мой готовый проект

Корпус — старый динамик, пластик дома. Вырезал пластины под корпус, просверлил отверстия под кнопки и один светодиод (добавлю позже). Ещё один такой же динамик оставлю для следующего контроллера с энкодерами и джойстиками.

Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Готовый Unopad в корпусе от динамика
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live
Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live

Планы (To Do)

Код

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: https://github.com/sadreactonly/MidiDrumpad

Схемы

Unopad: Бесшовный Arduino MIDI-контроллер для Ableton Live

Производственный процесс

  1. Управление яркостью LED с ШИМ через кнопку на Arduino Mega
  2. Создание игры в реальном времени на Arduino Nano с гироскопом MPU-6050 и OLED-дисплеем
  3. Проект с датчиком DHT11: индикация температуры светодиодами и пьезо-динамиком на Arduino
  4. Строим Iron Man на Arduino: компоненты, сенсоры и пошаговый гайд
  5. Простой ИК-датчик препятствий на Arduino: ИК-светодиод и фотодиод
  6. Find Me: Умный поисковик вещей на Arduino и Bluetooth
  7. DIY-контроллер увлажнителя на Arduino с реле: безопасная работа с высоким напряжением
  8. Создание интерактивного 4x4x4 светодиодного куба на Arduino Uno и 1Sheeld
  9. Своё рулевое управление (джойстик) для игр на Arduino
  10. Arduino 101: Пedometer с датчиком DHT11 и LCD-дисплеем