====== MIDI (Troyka-модуль) ====== {{ :hq:rnd:articles-proto:troyka-midi:troyka_midi_all.jpg |}} [[amp>collection/new-2017-06-07?utm_source=man&utm_campaign=midi&utm_medium=wiki|Troyka-MIDI]] (Musical Instrument Digital Interface — цифровой интерфейс музыкальных инструментов) — это модули, которые позволяют подключиться к профессиональным музыкальным инструментам. ===== Видеообзор ===== {{youtube>qIx2DA6j914?large}} ===== Подключение и настройка ===== {{ :продукты:troyka:midi:troyka-midi.png? |}} Стандарт MIDI подразумевает общение устройств между собой по асинхронному протоколу, аналогичному [[видеоуроки:6-serial-и-processing|UART]]. Отличие в том, что данные передаются не уровнем напряжения, а током. Поэтому мы будем подключать модули к Serial-порту управляющей платы. ==== MIDI IN ==== Простой MIDI-сниффер можно сделать, используя Troyka Slot Shield и Troyka-модуль [[amp>product/troyka-midi-in?utm_source=man&utm_campaign=midi&utm_medium=wiki|MIDI IN]]. * Подключите Troyka-модуль MIDI IN к пину ''RX'' микроконтроллера; * Загрузите скетч в Iskra Neo, откройте монитор порта; * Подключите выход MIDI-клавиатуры к Troyka MIDI IN; * Нажмите любую клавишу на MIDI-клавиатуре. В мониторе порта вы увидите MIDI-сообщения. {{ :продукты:troyka:midi:midi-in-conn-slot-box.png? |}} === Arduino Leonardo === //Мы используем плату с двумя Serial-портами. Это //Arduino Leonardo или Iskra Neo void setup() { //Настройка виртуального Serial-порта для подключения к компьютеру Serial.begin(115200); // Настройка Serial-порта для подключения к MIDI-клавиатуре Serial1.begin(31250); } void loop() { // Отправляем все сообщения c MIDI IN в монитор порта if (Serial1.available()) { Serial.println(Serial1.read()); } } === Iskra JS === Тот же пример можно выполнить и на Iskra JS. Добавим расшифровку MIDI-сообщений: номер ноты, номер MIDI-канала и сила нажатия клавиши. var midi = require('Midi').setup(Serial3, 31250); midi.on('noteOn', function(i) { console.log('Note: ' + i.note + ' on channel: ' + i.chan + ' with velocity: ' + i.velocity); }); === Arduino Uno === В Arduino Uno подключение к компьютеру происходит по единственному Serial-соединению. Чтобы иметь возможность наблюдать MIDI-команды в мониторе порта, изменим схему и создадим программный последовательный порт.{{ :продукты:troyka:midi:midiuno.png?nolink |}} //Мы используем с единственным Serial-портом. //MIDI-вход находится на 10-м пине, на котором мы запустим SoftwareSerial SoftwareSerial mySerial(10, 11); // RX, TX void setup() { //Настройка виртуального Serial-порта для подключения к компьютеру Serial.begin(115200); // Настройка SoftwareSerial-порта для подключения к MIDI-клавиатуре mySerial(31250); } void loop() { // Отправляем все сообщения c MIDI IN в монитор порта if (mySerial.available()) { Serial.println(mySerial.read()); } } ==== MIDI OUT ==== Troyka-модуль [[amp>product/troyka-midi-in?utm_source=man&utm_campaign=midi&utm_medium=wiki|MIDI OUT]] подключается к пину ''TX'' микроконтроллера. Есть особенность при использовании модуля вместе с Troyka Slot Shield. В этом случае придётся подать питание на модуль через ножки микроконтроллера. {{ :продукты:troyka:midi:midi-out-connect.png? |}} Мы используем Arduino Uno, поэтому в коде используется объект ''Serial''. Если вы используете Arduino Leonardo или Iskra Neo, используйте ''Serial1''. // Ножки микроконтроллера, которые мы используем для питания модуля: #define VCC 5 #define GND 4 void setup() { // Устанавливаем скорость обмена Serial.begin(31250); // Организуем питание модуля через ножки микроконтроллера: pinMode(VCC, OUTPUT); pinMode(GND, OUTPUT); digitalWrite(VCC, HIGH); digitalWrite(GND, LOW); } void loop() { // Играем ноты от F#-0 (0x1E) до F#-5 (0x5A): for (int note = 0x1E; note < 0x5A; note ++) { //Отправляем нажатие ноты на канале 1 (0x90), номер ноты (note), средняя сила нажатия (0x45): noteOn(0x90, note, 0x45); delay(100); // Стандарт допускает отключение ноты (аналог отпускания клавиши синтезатора) // при помощи отправки сообщения noteOn (0x90), // с номером той же ноты (note), и силой нажатия, равной нулю (0x00): noteOn(0x90, note, 0x00); // Пауза между нажатиями клавишь delay(100); } } // Отправка MIDI-ноты. // Здесь отсутствует проверка валидности данных. // MIDI-команда должна быть больше 127, а номер ноты и сила нажатия - меньше, либо равна 127 void noteOn(int cmd, int pitch, int velocity) { Serial.write(cmd); Serial.write(pitch); Serial.write(velocity); } ===== Проекты ===== ==== MIDI-тройник ==== Некоторые синтезаторы обладают только одним или двумя MIDI-разъёмами, без MIDI THRU. Поэтому их не удаётся подключить классическим способом. Подключить же MIDI-входы параллельно друг другу не получится. В этом случае ток в токовой петле будет распределяться между входами непредсказуемым образом. Но проблему подключения таких синтезаторов можно решить, используя Troyka MIDI IN и горсть Troyka MIDI OUT. Для подключения модулей удобно использовать несколько [[amp>product/troyka-pad-1x2?utm_source=man&utm_campaign=midi&utm_medium=wiki|Troyka Pad 1×2]] и [[amp>product/power-bank-li-ion?utm_source=man&utm_campaign=midi&utm_medium=wiki|Power Bank]]. {{ :продукты:troyka:midi:midi-splitter.png? |}} ==== Индикатор нажатия клавиш ==== Используем цветную светодиодную ленту для индикации номера и силы нажатия клавиши синтезатора. Понадобится: * [[amp>product/ws2811-led-strip-sealed?utm_source=man&utm_campaign=midi&utm_medium=wiki|Цветная адресуемая светодиодная лента]] * [[amp>product/iskra-neo?utm_source=man&utm_campaign=midi&utm_medium=wiki|Iskra Neo]] * [[amp>/product/arduino-troyka-slot-shield?utm_source=man&utm_campaign=midi&utm_medium=wiki|Troyka Slot Shield]] * [[amp>/product/troyka-midi-in?utm_source=man&utm_campaign=midi&utm_medium=wiki|MIDI IN (Troyka-модуль)]] * [[amp>/product/troyka-potentiometer?utm_source=man&utm_campaign=midi&utm_medium=wiki|Потенциометр (Troyka-модуль)]] * [[amp>/product/wall-plug-1a?utm_source=man&utm_campaign=midi&utm_medium=wiki|Блок питания на 12 В]] {{ :продукты:troyka:midi:midi-ledstrip.png?direct&|}} #include #include #ifdef __AVR__ #include #endif // Светодиодная лента подключена к пину 11 #define PIN 11 // Она состоит из 50 светодиодов #define NUMPIXELS 50 // Создаём объект для управления лентой Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); // Создаём объект для связи по MIDI через Serial1 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, myMidi); // Вспомогательные переменные int r, g, b, pitchPot; // Функция, пересчитывающая оттенок в RGB. // Подробности: http://wiki.amperka.ru/projects:christmastree void f_HSV_to_RGB(int hue, int sat, int val) { int base; if (sat == 0) { r = val; g = val; b = val; } else { base = ((255 - sat) * val) >> 8; switch (hue / 60) { case 0: { r = val; g = (((val - base) * hue) / 60) + base; b = base; break; } case 1: { r = (((val - base) * (60 - (hue % 60))) / 60) + base; g = val; b = base; break; } case 2: { r = base; g = val; b = (((val - base) * (hue % 60)) / 60) + base; break; } case 3: { r = base; g = (((val - base) * (60 - (hue % 60))) / 60) + base; b = val; break; } case 4: { r = (((val - base) * (hue % 60)) / 60) + base; g = base; b = val; break; } case 5: { r = val; g = base; b = (((val - base) * (60 - (hue % 60))) / 60) + base; break; } case 6: { r = val; g = 0; b = base; break; } } } } // Обработчик события NoteOn. Эта функция будет вызвана автоматически при // при приёме сообщения NoteOn по MIDI-входу. // Подробнее: http://arduinomidilib.fortyseveneffects.com/a00022.html void handleNoteOn(byte channel, byte pitch, byte velocity) { // Velocity имеет значение от 0 до 127 // Чтобы не снижать диапазон значений оттенка цвета (0-255), // мы сдвигом влево умножаем силу нажатия на 2. byte doubleVelocity = velocity << 1; // Переводим оттенок в RGB f_HSV_to_RGB(doubleVelocity, 255, 255); // Номер ноты имеет значение от 0 до 127, // а светодиодов всего 50. Чтобы лента отображала ноты // в нужном интервале, подкрутим ленту под нужные ноты потенциометром. // Чтение значения с потенциометра происходит в loop(); int activePitch = pitch - pitchPot; // Устанавливаем цвет светодиода в нужную позицию... pixels.setPixelColor(activePitch, pixels.Color(r, g, b)); // ... и зажигаем ленту. pixels.show(); } // Обработчик события NoteOff. Эта функция будет вызвана автоматически при // при приёме сообщения NoteOff по MIDI-входу. // Подробнее: http://arduinomidilib.fortyseveneffects.com/a00022.html void handleNoteOff(byte channel, byte pitch, byte velocity) { // Гасим светодиод, который был зажжён от NoteOn int activePitch = pitch - pitchPot; pixels.setPixelColor(activePitch, pixels.Color(0, 0, 0)); pixels.show(); } void setup() { // Инициализируем светодиодную ленту... pixels.begin(); // ... и гасим все светодиоды pixels.show(); // Присоединяем обработчик события NoteOn myMidi.setHandleNoteOn(handleNoteOn); // Присоединяем обработчик события NoteOff myMidi.setHandleNoteOff(handleNoteOff); // Инициализируем MIDI-интерфейс на прослушку всех // MIDI-каналов. myMidi.begin(MIDI_CHANNEL_OMNI); } void loop() { // Здесь мы просто вызываем MIDI.read, // остальное библиотека сделает сама myMidi.read(); // Считаем значение с потенциометра. // Нам нужно значение в диапазоне (0-127), // его можно получить из диапазона (0-1024) сдвигом на 3 бита вправо pitchPot = analogRead(A4) >> 3; } ===== Библиотеки ===== * [[https://github.com/FortySevenEffects/arduino_midi_library|Библиотека для Arduino]] * [[https://www.espruino.com/Midi|библиотека для IskraJS и Espruino]] ===== Принципиальная и монтажная схемы ===== {{:продукты:troyka:midi:module-m37-midi-a4-schematic.png?direct&350 |}} {{ :продукты:troyka:midi:module-m37-midi-a4-layout-nv-bottom.png?direct&300|}} ===== Характеристики ===== * Напряжение питания: 3,3–5 В * Габариты: 25,4×25,4 мм