Точность синхронизации MIDI-секвенсора с использованием Arduino


11

Я создаю эти музыкальные секвенсоры .

введите описание изображения здесь

Только это не совсем секвенсор, это физический интерфейс для секвенсора. Секвенсор - это приложение, которое работает на ноутбуке, к которому подключается секвенсор, и позволяет пользователю создавать барабанные петли на лету. Это довольно весело, но для этого нужен ноутбук, потому что секвенсор не «встроен».

То, что я хотел бы, чтобы сделать последовательность на борту моего устройства.

Теперь давайте предположим, что я знаю, как найти соответствие классу для подключения USB MIDI, и давайте также предположим, что я могу выяснить, как подключить arduino для отправки MIDI-нот через 5-контактный порт DIN. Больше всего меня беспокоит сдвиг темпа во времени из-за непоследовательной синхронизации минутных значений во время каждого цикла цикла событий.

Некоторые вещи, которые я знаю:

  1. Вы не должны полагаться на delay()контроль петли темпа. Задержка останавливает все операции прошивки, и это не может работать, потому что мне нужно опросить физический интерфейс пользователя на предмет изменений во время выполнения последовательности.

  2. Расчеты на основе millis()лучше, потому что прошивка может продолжать работать и действовать после истечения определенного количества.

  3. Даже при том, что ни один из моих физических элементов управления не вызывает подпрограммы прерывания, некоторые операции могут задержать loop()запуск основного . Если я спроектирую функцию, которая ожидает пользовательского ввода, то это, очевидно, может вызвать проблему пропуска «крайнего срока», чтобы действовать, если millis()счет окончен. Я знаю, что это проблема моего собственного дизайна ...

Вопросы:

A. Является ли основанный на AVR arduino подходящим микроконтроллером для опроса пользовательского интерфейса и запуска критически важного цикла синхронизации? Я знаю, что теперь есть Arduino на базе ARM, который работает намного быстрее. Будет ли Teensy 3.0 лучшей альтернативой? Обе эти платы имеют напряжение 3,3 В, так что это еще один набор проблем для работы ... но я пока проигнорирую это.

B. Должен ли я разделить задачу на два микропроцессора? Один для обработки опроса и обновления пользовательского интерфейса и один для критически важного цикла синхронизации.

с. Что-то другое?

Моя главная цель - вообще не использовать компьютер. Я также хочу рассчитывать на свинг, но в этом случае свинг ничего не значит, если у меня нет фиксированного и синхронизированного с точным темпом темпа. Спасибо за ваш совет!


1
Ардуино всегда устанавливает некоторые процедуры прерывания, вызывающие дрожание. Во многих случаях это не проблема, но хорошо знать об этом. noInterrupts();останавливает дрожание, но также останавливает все нужные прерывания.
Джиппи

1
Когда вы говорите «выполнить секвенирование на плате», означает ли это, что вы должны настроить такты на такт, BPM и тик-трек на борту? Тогда, вероятно, вы хотите вспомнить нажатия кнопок, которые происходили внутри панели, чтобы «мозги» устройства могли подавать миди-ноты на ваш ноутбук? Тогда хотите ли вы удалить некоторые звуки перкуссии, если вы снова нажмете их на ноте, которая была ранее записана? И т.д .. как далеко вы хотите пойти? Хранение ваших ударов? Создание последовательности тактов, соответствующих полному треку? Редактирование конкретных баров? Темп изменения конкретных баров? Все это ест процессор, так что выбирайте лучший процессор.
Энди ака

Да, все это.
Стив Кули,

2
Это прекрасный случай, который вы сделали!
Shuckc

3
В дополнение к тому, что говорили другие, это похоже на мысль, что, возможно, вы намереваетесь производить и продавать. Arduino стоит 20 долларов, а AVR - 2 доллара. Вы не только получите контроль над оборудованием, которое требуется вашему приложению, но и сэкономите много денег.
Фил Фрост

Ответы:


5

Прерывания - ваш друг для выполнения чувствительных к времени задач, но только в том случае, если вы добавляете критические аспекты синхронизации к прерыванию, и не происходит никаких других прерываний с более высоким приоритетом. Микроконтроллеры на Arduino «на базе AVR» (например, ATmega328P) имеют фиксированные приоритеты прерываний, как подробно описано на странице 58ff таблицы данных . Поэтому, если вы использовали TIMER2 COMPA в качестве критического прерывания по времени, и никаких других прерываний у вас не должно быть проблем (так как он имеет самый высокий приоритет). Если вы также хотите использовать прерывания с более низким приоритетом, вам необходимо убедиться, что все они повторно включают глобальные прерывания при входе в свою подпрограмму обработки прерываний:

При возникновении прерывания I-бит разрешения глобального прерывания очищается, и все прерывания отключаются. Программное обеспечение пользователя может записать логическую единицу в бит I, чтобы разрешить вложенные прерывания. Все разрешенные прерывания могут прервать текущую процедуру прерывания.

(стр. 14 таблицы )

В Arduinos на основе ARM это немного отличается, так как их ядро ​​Cortex-M3 имеет «Nested Vector Interrupt Controller», где приоритеты не фиксированы (могут быть установлены в программном обеспечении), а обработка вложенных прерываний является нормой. Таким образом, для приложений, критичных по времени, Arduino на базе ARM обеспечит вам большую гибкость. Однако я не думаю, что это действительно необходимо для вашего приложения.

Главный вопрос заключается в том, насколько легко эти вещи можно реализовать с помощью библиотек Arduino. Чтобы добиться максимальной производительности, вам, вероятно, придется до некоторой степени кодировать за пределами библиотек, по крайней мере, для битов, критичных по времени, то есть избегать таких вещей, как delay () или millis () в целом.

Требуется ли разделение, зависит от того, сколько обработки вы намереваетесь выполнить. Опять же, выход за пределы библиотек потенциально может повысить производительность.


3

Это может, при соответствующем программировании, определенно быть сделано на ATmega328P (в некоторой степени зависящей от сложности барабанной петли. Я предполагаю, что <<50 событий барабана в петле. Это разумно?).

Обратите внимание, что я сказал ATmega328P , не обязательно Arduino .

В среде Arduino в фоновом режиме происходит множество вещей по умолчанию, что делает чрезвычайно детерминированное программирование (так как вам нужно что-то критичное по времени) сложным.

Реальный вопрос, который вам нужно здесь задать, заключается в том, насколько вы заинтересованы в программировании, и насколько вы заинтересованы в разработке инструмента?

Хотя я совершенно уверен, что на одном ATmega можно делать все, что вы хотите (петлевая петля, несколько аналоговых входов, ЖК-дисплей, кнопки, интерфейс MIDI), но на самом деле вопрос в том, во сколько все это уложится? Опять же, вы хотите научиться оптимизировать встроенный код MCU или создавать инструменты? Это довольно легко , если нужно просто перейти на более быстрый MCU, но вы должны определить производительность MCU вам нужно прямо сейчас , так что шесть месяцев работы, вы не понимаете , что вы не можете вполне получить все для работы так же быстро , как вы нужно.


Если бы я был на вашем месте, первое, что я сделал бы, это заставило бы его работать без Arduino (в основном, относиться к нему как к сырому ATmega и использовать AVR studio или подобное). Затем вы сможете намного более эффективно проанализировать, какая производительность вам нужна, и сможет ли ATmega управлять ею.

Как только вы освободитесь от Arduino, вы сможете использовать разные микроконтроллеры (они, как правило, больше похожи, чем разные. Если вы можете найти один из его документации, вы, вероятно, можете сделать то же самое для других).

Я недавно много работал с устройствами ATxmega, и они действительно хороши. Вы получаете три приоритета прерываний, которые упрощают управление критичными по времени вещами. С ними также очень приятно работать (Sane периферийные конструкции! Удобные портовые конструкции! И т.д ...).

Есть также устройства LPC от NXP, основанные на ARM, а также некоторые устройства Atmel ARM (используемые в Arduino Due) или микроконтроллеры STM32 от ST. Любой из них будет иметь значительно большую производительность, чем ATmega или даже ATxmega.

Основным недостатком более крупного и более мощного процессора является цена, но если вы не будете производить тысячи таких устройств, затраты на сборку и изготовление на единицу будут значительно превышать разницу в стоимости (которая, вероятно, составит всего несколько долларов). ) что это в принципе не имеет значения.


Мягко говоря, для коммерческого продукта Arduino просто не подходит - они потребляют много энергии, работают медленно, а среда IDE не предназначена для оптимального (быстрого / маленького) кода, скорее для удобства и простоты обучения. За меньшие деньги вы могли бы даже иметь STM32 F4 (32-битный Cortex M4> 100 МГц) или аналогичный, хотя это было бы излишним. Я думаю, что что-то вроде меньшего PIC32, Cortex M3 или AVR32, вероятно, является подходящим вариантом, как вы упоминаете. Многочисленные приоритеты прерываний, DMA, сложные периферийные устройства, быстрая / низкая мощность и большое количество оперативной памяти делают его легким выбором по сравнению с Arduino.
Оли Глейзер

@OliGlaser - я думаю, вам нужно четко разграничить Arduino и ATmega . Вы можете сделать небольшой, быстрый код на ATmega, и этот ATmega может даже быть на плате Arduino. Arduino "IDE", с другой стороны, является одним из самых дерьмовых редакторов кода, которые я когда-либо использовал. С другой стороны, загрузчик OptiBoot очень хорош. Только то, что некоторые части - дерьмо, не означает, что вы должны выбросить все это.
Коннор Вольф

Абсолютно - я имел в виду Arduino в целом, включая плату и IDE - не ATmega, который, я уверен, так же хорош, как любой другой сопоставимый uC (PIC16 / 18F и т. Д.), Я бы включил его в свой список, но Я думаю, что в настоящее время цена между 8-битными и 16/32-битными очень близка, поэтому, вероятно, стоит потратить лишние 1 доллар и знать, что у вас есть запасная мощность процессора (если, как вы упомянули, мы говорим об огромных цифрах и построен по абсолютно низкой цене, но тогда я сомневаюсь, что Arduino был бы рассмотрен :-))
Оли Глейзер

1

Мне нужно было почитать о таймерах, прежде чем я начал думать о точности синхронизации (также создавал миди-шаговый секвенсор с Arduino, хотя он гарантированно будет выглядеть не так круто, как эти ^^). Эта серия статей была наиболее информативной:

http://maxembedded.com/category/microcontrollers-2/atmel-avr/avr-timers-atmel-avr/

Прямо сейчас я думаю, что мое решение для получения точного времени будет.

А. Используйте AVR Arduino

Б. Держите задачу на одном микропроцессоре

C. Мудро используйте прескалеры, таймеры и прерывания, чтобы получить необходимую точность.

ОБНОВИТЬ

Использование базового миди учебника для Arduino и после просмотра этой статьи о таймерах и прескалерах, я пришел к следующему коду. Код использует таймер 1 и режим CTC для воспроизведения миди-ноты каждую четверть секунды и ноты каждую четверть секунды (что должно быть ровно 120 ударов в минуту). К сожалению, это все еще идет медленнее, чем 120 ударов в минуту, хотя это самое близкое, что я получил ...

// Includes
#include <avr/io.h>
#include <avr/interrupt.h>

int last_action=0;

void setup()
{
    //  Set MIDI baud rate:
    Serial.begin(31250);

    // initialize Timer1
    cli();          // disable global interrupts
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // same for TCCR1B

    // set compare match register to desired timer count:
    OCR1A = 15624;
    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);
    // Set CS12 bits for 256 prescaler:
    TCCR1B |= (1 << CS12);
    // enable timer compare interrupt:
    TIMSK1 |= (1 << OCIE1A);
    // enable global interrupts:
    sei();
}

void loop()
{
    // do some crazy stuff while my midi notes are playing
}

ISR(TIMER1_COMPA_vect)
{
  // Turn notes on
  if (last_action == 0) {
    send_note(0x90, 60, 0x45);
    last_action = 1;

  // Turn notes off
  } else {
    send_note(0x90, 60, 0x00);
    last_action = 0;
  }
}

//  plays a MIDI note
void send_note(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}

ОБНОВИТЬ

Я боролся с этим в течение ~ 24 часов и наконец получил ответы на форуме. Я думаю, что код, который я использовал выше ^^, довольно хорош. Использование ISR, использование режима CTC, прескалеров и т. Д. После обращения к форуму я думаю, что решение заключается не столько в достижении точности на миди-секвенсоре, сколько в том, чтобы все мои аппаратные настройки (мои синтезаторы и сэмплеры) были подключены к одному и тому же. Миди-часы, будь или нет часы от Arduino.


0

В зависимости от того, насколько постепенно вы хотите перейти от привязанного компьютера к системе на основе микроконтроллера, вы можете рассмотреть возможность размещения Raspberry Pi внутри этой коробки ( розничная цена 25-35 долларов ). Таким образом, у вас может быть полноценный (хотя и маломощный) компьютер на базе Linux с портами USB и выводами GPIO.


Я уверен, что есть щиты расширения или как они называют их для Pi, но на стандартной плате есть 17 контактов GPIO. Я использую каждый пин-код на Arduino Mega. 31 такт + 30 светодиодов, 10 аналоговых входов. 70+ входов / выходов.
Стив Кули

О, я имел в виду, что если непосредственной целью было удалить внешний компьютер, вы можете оставить «секвенсор [это] приложение, работающее на ноутбуке» и запустить его на Pi, внутренне подключенный к вашей существующей системе так же, как подключен сейчас.
Роб Старлинг

@SteveCooley - Похоже, вам нужно посмотреть на IO мультиплексирование / кнопки-матрицы. Вам не нужна целая выделенная строка ввода-вывода для каждой кнопки.
Коннор Вольф

@ SteveCooley - Черт, тебе даже не нужна кнопка Matrice. Вы можете сделать ВСЕ свой цифровой ввод-вывод, используя только 4 контакта RPI. Просто повесьте все кнопки и светодиоды на некоторых регистрах сдвига (параллельно-последовательный для кнопок, последовательно-параллельный для светодиодов) и подключите сдвиговые регистры от порта SPI контроллера RPI. Вы должны легко получить частоту обновления> 1 кГц для всей матрицы с помощью оборудования SPI.
Коннор Вольф

Если единственной причиной, по которой вы используете Arduino Mega, является IO, вы тратите много денег на что-то, что можно сделать очень легко с помощью нескольких внешних устройств, за <3 доллара.
Коннор Вольф
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.