Первый MIDI-контроллер я собрал вслепую: кнопка, потенциометр и скетч, который шлёт ноты через Serial.begin(9600). Монитор порта показывал аккуратные строки — по-моему, всё работало. Синтезатор молчал. Вечер ушёл на проверку кабеля, разъёма и перечитывание форумов, пока я не наткнулся на цифру, которая всё объяснила: MIDI — это UART, но не 9600, а 31250 бод. Плата честно вещала ноты в эфир — просто синтезатор слушал на другой скорости. Ровно та же история, что в уроке про первое знакомство с монитором порта: данные идут, но стороны не договорились о темпе.
Разберём, чем MIDI-линия отличается от привычного порта: скорость 31250 и кадр 8N1, сообщение из трёх байт со статусом, нотой и силой нажатия, разъём DIN-5 с парой резисторов по 220 Ом на выходе и обязательной оптопарой на входе. В симуляторе покрутим то же самое: кнопка станет клавишей, потенциометр — силой нажатия, а байты сообщения будут печататься в HEX — потому что DIN-разъёма в браузере нет, и это честная замена, а не упрощение.
Ставка урока — не на библиотеку, а на понимание: MIDI-выход — это три Serial.write в правильном порядке, и когда вы увидите байты 90 3C 64 в дампе, любой миди-синт, от старой клавиатуры до компьютера с виртуальным инструментом, станет просто приёмником UART. Библиотеки оборачивают те же вызовы удобствами — колбэками на приход нот и классами каналов — но байты в линии от этого не меняются, и отлаживать всё равно придётся дампом. Поэтому сначала голый протокол, потом — любые обёртки сверху.
Тот же UART, другая скорость
Формат кадра у MIDI тот же, что в любом UART: стартовый бит, восемь бит данных, стоповый, без бита чётности — 8N1. Меняется только темп: 31250 бод означают, что каждый бит стоит ровно 32 микросекунды, а кадр из десяти битов — 320 мкс. Сообщение из трёх байт укладывается примерно в миллисекунду, и даже аккорд из пяти нот с полной скоростью нажатия занимает пятнадцать байтов — на канале, который держит около 3125 байтов в секунду, это капля. Именно поэтому MIDI десятилетиями живёт на паре проводов без всяких протоколов поверх.
Само сообщение — три байта подряд. Первый — статус: 0x90 означает Note On на первом канале, 0x80 — Note Off; в десятичной записи это 144 и 128, и обе цифры всплывут в отладке. Второй байт — номер ноты от 0 до 127: middle C, до первой октавы, — это 60, а в HEX — 0x3C. Третий — скорость нажатия от 1 до 127: насколько сильно ударили по клавише, и от неё зависит громкость — на пищалке через tone громкость задаётся скважностью, здесь же она кодируется числом внутри пакета. Нюанс, который я узнал позже, чем хотелось бы: Note On со скоростью 0 многие устройства трактуют как Note Off — так экономят один тип сообщения.
Статус хранит и канал: младшие четыре бита статуса — номер канала от 0 до 15, поэтому Note On занимает диапазон 0x90-0x9F. Мой скетч шлёт 0x90 — нулевой канал; если синтезатор слушает четвёртый, 0x94 он примет, а 0x90 проигнорирует, и вы будете искать кабель там, где виноват один бит. Плата Uno держит в запасе один аппаратный UART, и MIDI занимает его целиком: после Serial.begin(31250) монитор порта на той же линии мёртв, поэтому параллельную отладку я веду либо светодиодом, либо через SoftwareSerial, о чём скажу ниже.
| Поле пакета | Диапазон | Что несёт |
|---|---|---|
| Статус 0x90 / 0x80 | Note On и Note Off, канал в младших битах | нажали клавишу или отпустили |
| Номер ноты | 0-127, middle C = 60 (0x3C) | какая клавиша задета |
| Скорость (velocity) | 1-127, ноль трактуется как Note Off | громкость: 1 — шёпот, 127 — форте |
| Канал (в статусе) | 0-15: Note On занимает 0x90-0x9F | кто играет: синтезатор слушает свой номер |
| Темп канала | 31250 бод, байт 320 мкс | аккорд из 5 нот — около 5 мс эфира |
Разъём DIN-5: два резистора и оптопара
Выход собирается на разъёме DIN-5 с углом 180 градусов, и схема там аскетичная: пин 4 разъёма через резистор 220 Ом питается от 5 вольт, пин 5 через такой же 220 Ом приходит на TX платы, экран пина 2 прижимается к земле приёмника. Ток в петле выходит около 5 миллиампер: два резистора и излучатель оптопары на другом конце съедают большую часть пяти вольт. Никаких чипов на выходе не нужно — TX уже даёт правильный формат, скорость задаётся одной строкой Serial.begin(31250).
Вход — другое дело: стандарт требует оптопару, и это не перестраховка. Синтезатор и плата питаются от разных розеток, их земли могут гулять на единицы вольт; без развязки первый же концерт заканчивается выгоревшим входом. Классический выбор — 6N138: быстрый оптодарлингтон, успевающий за битом в 32 мкс. Медленные оптопары вроде PC817 или 4N38 на MIDI-входе дают битые ноты: фронт расплывается, и приёмник читает мусор — картина та же, что в уроке про глючную линию, только виновата не длина провода, а скорость оптопары. Петля тока в 5 мА — это гальваническая развязка: земли устройств не соединяются вообще.
Кабель по стандарту тянется до пятнадцати метров — экранированный, с экраном на пине 2; у меня доживал и длиннее, но на репетиционной сцене лучше не спорить со спецификацией. И грабля, на которой спотыкается каждый второй: пины 4 и 5 перепутаны местами. Снаружи разъём выглядит симметрично, а байты «на слух» из монитора не проверить — в нём печатаются непечатаемые коды. Поэтому я всегда проверяю распайку дампом байтов и держу под рукой перемычку: переставил два провода — синтезатор ожил после часа поисков несуществующей поломки в коде.
// TX (пин 1) -> 220 Ом -> пин 5 DIN-5; 5В -> 220 Ом -> пин 4; пин 2 — экран.// Кнопка на D2 (INPUT_PULLUP: нажато = LOW), светодиод L — индикатор ноты.int nota = 60; // middle Cint knopkaByla = HIGH; void setup() { Serial.begin(31250); // скорость MIDI, кадр 8N1 pinMode(2, INPUT_PULLUP); pinMode(13, OUTPUT);} void loop() { int knopka = digitalRead(2); if (knopka == LOW && knopkaByla == HIGH) { int skor = map(analogRead(A0), 0, 1023, 1, 127); Serial.write(0x90); // Note On, канал 0 Serial.write(nota); // нота 0-127 Serial.write(skor); // сила нажатия 1-127 digitalWrite(13, HIGH); } if (knopka == HIGH && knopkaByla == LOW) { Serial.write(0x80); // Note Off Serial.write(nota); Serial.write(0); digitalWrite(13, LOW); } knopkaByla = knopka;}В симуляторе DIN-разъёма и синтезатора нет, и движок не гоняет сырые байты в отдельную линию — вместо этого скетч печатает байты MIDI-сообщения в HEX прямо в Serial Monitor: то, что на реальной плате уехало бы в разъём, здесь видно глазами. Формат тот же: статус, нота, скорость, числа с ведущим нулём, чтобы байты читались парами; перевод чисел между системами мы поднимали в уроке про BIN, HEX и DEC.
Кнопка на пине 2 работает клавишей: нажали — в журнале уходит Note On, отпустили — Note Off. Потенциометр на A0 задаёт силу нажатия 1-127 на момент нажатия. Команда nota меняет ноту от 0 до 127 с защитой от выхода за диапазон — попробуйте nota 60 против nota 72: в дампе поменяется второй байт, 3C против 48, а на настоящем синтезаторе разница слышна как до первой октавы против до второй. Ноты в массивах и их раскладку по октавам я разбирал в уроке про мелодии на массивах нот — оттуда удобно брать последовательности для автоигры.
Команды скетч читает через readStringUntil, как в уроке про чтение входа Serial: строка режется по пробелу, аргумент проходит через toInt с ограничением. На реальной плате этот же приём позволит собрать переключатель октав с матричной клавиатуры — жмёшь ноту, держишь аккорд из трёх Note On подряд. И практическая мелочь вдогонку: на слух держите скорость нажатия от 20 — единица и двойка тонут даже в тихой комнате, я потратил вечер, прежде чем понял, что ноты звучат, просто слишком тихо.
- MIDI — UART на 31250 бод 8N1: бит стоит 32 мкс, сообщение из трёх байт укладывается в миллисекунду
- Note On — 0x90 плюс нота плюс скорость; middle C = 60; скорость 1-127, ноль многие трактуют как Note Off
- Выход — два резистора 220 Ом и DIN-5: TX на пин 5, 5 вольт на пин 4, ток петли около 5 мА
- Вход без оптопары — сломанный вход: 6N138 успевает за битом, PC817 и 4N38 на 31250 бод дают битые ноты
- Монитор порта MIDI не читает: отладка — второй UART с печатью байтов в HEX или светодиод на статусе ноты
- 1. Синтезатор молчит, контроллер шлёт ноты через Serial.begin(9600). В чём причина?
- 2. Сколько байтов занимает сообщение Note On и что внутри?
- 3. Какой номер у ноты middle C — до первой октавы?
- 4. Почему на MIDI-входе нужна оптопара, причём быстрая?
- 5. Что вы увидите в Serial Monitor, подключённом к MIDI-линии на 31250 бод?
Частые вопросы по теме урока
- Синтезатор молчит, контроллер шлёт ноты через Serial.begin(9600). В чём причина?
- MIDI использует тот же кадр UART, но на 31250 бод: бит — 32 мкс. На 9600 приёмник заглядывает в линию в чужие моменты и не собирает сообщения. Скорость не та: MIDI живёт на 31250 бод 8N1
- Сколько байтов занимает сообщение Note On и что внутри?
- Статус 0x90, номер ноты 0-127, скорость 1-127. Note Off — та же тройка со статусом 0x80. Три байта: статус, нота, скорость нажатия
- Какой номер у ноты middle C — до первой октавы?
- Middle C — это 60, в HEX 0x3C. 69 — ля первой октавы, камертонная A4. 60
- Почему на MIDI-входе нужна оптопара, причём быстрая?
- Стандарт требует гальванической развязки: приборы питаются от разных розеток. 6N138 успевает, а PC817 и 4N38 на 31250 бод расплывают фронт и дают битые ноты. Она развязывает земли устройств, а медленная оптопара не успевает за битом в 32 мкс
- Что вы увидите в Serial Monitor, подключённом к MIDI-линии на 31250 бод?
- Монитор печатает символы, а MIDI-байты — коды вроде 144. Отладку в HEX вешают на второй UART через SoftwareSerial. Ничего или мусор: байты непечатаемые, а скорость нестандартная