precisión del tiempo del secuenciador MIDI utilizando el Arduino

11

Construyo estos secuenciadores de música .

Soloquenoesexactamenteunsecuenciador,esunainterfazfísicaparaunsecuenciador.Elsecuenciadoresunaaplicaciónqueseejecutaenunacomputadoraportátilalaqueseconectaelsecuenciador,estopermitealusuariohacerbuclesdebateríasobrelamarcha.Esbastantedivertido,perorequiereunacomputadoraportátilporqueelsecuenciadornoestá"a bordo".

Lo que me encantaría es hacer la secuenciación en mi dispositivo.

Ahora supongamos que sé cómo resolver el cumplimiento de clase para la conectividad MIDI USB, y también supongamos que puedo averiguar cómo cablear un arduino para enviar notas MIDI desde un puerto DIN de 5 pin. Lo que más me preocupa es la variación del tempo a lo largo del tiempo debido a un tiempo inconsistente en cantidades de minutos en cada ejecución del bucle de eventos.

Algunas cosas que sé:

  1. No debes confiar en delay() para controlar el ciclo de tempo. La demora detiene todas las operaciones del firmware, y eso no puede funcionar porque necesito sondear la interfaz de usuario física para detectar cambios mientras se ejecuta la secuencia.

  2. Los cálculos basados en millis() son mejores porque el firmware puede continuar funcionando y actuar cuando ha transcurrido un cierto conteo.

  3. Aunque ninguno de mis controles físicos está activando rutinas de interrupción, algunas operaciones pueden retrasar la ejecución de loop() principal. Si diseño una función que espera la entrada del usuario, eso obviamente puede causar un problema de falta de una "fecha límite" para actuar si el recuento de millis() está por encima. Sé que este problema es de mi propio diseño ...

Preguntas:

A. ¿Es el arduino basado en AVR un microcontrolador apropiado para sondear una interfaz de usuario y ejecutar un ciclo de tiempo crítico? Sé que hay un Arduino basado en ARM ahora que es mucho más rápido. ¿Sería un Teensy 3.0 una mejor alternativa? Ambos son tableros de 3.3 V, por lo que es otro conjunto de problemas con los que trabajar ... pero lo ignoraré por ahora.

B. ¿Debo dividir la tarea en dos microprocesadores? Uno para manejar el sondeo y la actualización de la interfaz de usuario y otro para el ciclo de tiempo de misión crítica.

c. ¿Algo más?

Mi objetivo principal es no tener que usar una computadora en absoluto. También quiero calcular el swing, pero en este caso, swing no significa nada si no tengo un tempo preciso bloqueado y sincronizado. Gracias por tu consejo!

    
pregunta Steve Cooley

4 respuestas

5

Las interrupciones son su amigo para sincronizar las tareas sensibles, pero solo si coloca los aspectos críticos de la sincronización en la interrupción, y no hay otras interrupciones que tengan una prioridad más alta. Los microcontroladores en el Arduino "basado en AVR" (por ejemplo, el ATmega328P) tienen prioridades de interrupción fijas como se detalla en la página 58ff de hoja de datos . Entonces, si usó TIMER2 COMPA como su interrupción de temporización crítica y ninguna otra interrupción debería estar bien (ya que tiene la máxima prioridad). Si también desea utilizar interrupciones de prioridad más baja, debe asegurarse de que todas ellas vuelvan a habilitar las interrupciones globales al ingresar a su rutina de servicio de interrupción:

  

Cuando se produce una interrupción, el bit de habilitación de interrupción global se borra   y todas las interrupciones están deshabilitadas. El software del usuario puede escribir una lógica   al bit I para habilitar interrupciones anidadas. Todas las interrupciones habilitadas pueden   luego interrumpe la rutina de interrupción actual.

(pág. 14 de hoja de datos )

Esto es ligeramente diferente en los Arduinos basados en ARM, ya que su núcleo Cortex-M3 tiene un "Controlador de interrupción de vector anidado", donde las prioridades no son fijas (se pueden configurar en el software), y el manejo de interrupciones anidadas es la norma. Así que para cronometrar aplicaciones críticas, el Arduino basado en ARM le dará más flexibilidad. Sin embargo, no creo que sea realmente necesario para su aplicación.

La pregunta más importante es realmente qué tan fáciles pueden implementarse estas cosas con las bibliotecas Arduino. Para obtener el mejor rendimiento, probablemente tendrá que codificar fuera de las bibliotecas hasta cierto punto, al menos para los bits críticos de tiempo, es decir, evitar cosas como el retraso () o los milis () en conjunto.

El hecho de que deba o no dividirse depende de la cantidad de procesamiento que pretende hacer. Una vez más, salir de las bibliotecas puede ofrecerte un mejor rendimiento.

    
respondido por el fm_andreas
3

Esto puede, con la programación apropiada, definitivamente realizarse en un ATmega328P (dependiendo de la complejidad del bucle de batería. Estoy asumiendo ~ < 50 eventos de batería en el bucle. ¿Es razonable?). p>

Tenga en cuenta que dije ATmega328P , no necesariamente un Arduino .

El entorno de Arduino tiene muchas cosas predeterminadas en segundo plano, lo que hace que la programación extremadamente determinista (ya que será necesaria para algo crítico para el tiempo) sea un desafío.

La verdadera pregunta que debe hacer aquí es ¿qué tan interesado está en la programación, en comparación con qué interés tiene usted en desarrollar un instrumento?

Aunque estoy bastante seguro de que es posible hacer todo lo que quieras en un solo ATmega (loop de batería, múltiples entradas analógicas, LCD, botones, interfaz MIDI), la verdadera pregunta es cuánto trabajo. ¿Será apretar todo? De nuevo, ¿quieres aprender a optimizar el código MCU incorporado o construir instrumentos? Es bastante fácil simplemente ir a una MCU más rápida si es necesario, pero necesita determinar el rendimiento de la MCU que necesita ahora , por lo que seis meses de trabajo no se da cuenta de que no puede bastante haga que todo funcione tan rápido como lo necesite.

Si fuera tú, lo primero que haría sería que funcionara sin cosas de arduino (básicamente, trátalo como un ATmega en bruto y utiliza AVR studio o similar). Luego, puede analizar mucho más efectivamente qué tipo de rendimiento necesita y si ATmega puede administrarlo.

Una vez que esté libre de las cosas arduino, es mucho más libre para usar diferentes MCU (generalmente son más similares que diferentes. Si puede descubrir uno a partir de su documentación, probablemente pueda hacer lo mismo para otros).

He estado trabajando mucho con los dispositivos ATxmega recientemente, y son realmente agradables. Obtiene tres prioridades de interrupción, lo que hace que la gestión de cosas críticas con el tiempo sea más fácil. También son muy agradables para trabajar con ellos (¡diseños periféricos Sane! ¡Estructuras de puertos convenientes! Etc ...).

También existen los dispositivos LPC de NXP, que están basados en ARM, así como algunos de los dispositivos ARM de Atmel (como se usan en Arduino Due), o las MCU STM32 de ST. Cualquiera de estos tendrá significativamente más rendimiento que un ATmega, o incluso un ATxmega.

El principal inconveniente de un procesador más grande y más poderoso es el precio, pero a menos que esté obteniendo miles de esas unidades, los costos de ensamblaje y fabricación por unidad superarán en gran medida la diferencia de costos (lo que probablemente será solamente unos pocos dólares) que es básicamente irrelevante.

    
respondido por el Connor Wolf
1

Necesitaba leer los cronómetros antes de comenzar a pensar en la precisión de la sincronización (también construí un secuenciador de pasos midi con un arduino, aunque está garantizado que se verá menos genial que esos ^^). Esta serie de artículos ha sido la más informativa:

enlace

En este momento creo que mi solución para obtener el tiempo preciso será.

A. Usa el arduino AVR

B. Mantener la tarea en un microprocesador

C. Use sabiamente los precalificadores, temporizadores e interrupciones para obtener la precisión que se necesita.

ACTUALIZAR

Utilizando el tutorial básico de midi para Arduino y luego de consultar este artículo en los temporizadores y preescaladores, el código siguiente es el que se me ocurrió. El código utiliza el modo timer1 y CTC para reproducir una nota de midi cada cuarto de segundo y una nota de apagado cada cuarto de segundo (que debe ser exactamente 120 bpm). Lamentablemente, esto sigue llegando solo a 120 bpm, aunque es lo más cerca que he estado ...

// 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);
}

ACTUALIZAR

He estado luchando con esto por ~ 24 horas y finalmente obtuve algunas respuestas del foro. Creo que el código que usé arriba ^^ es bastante bueno. Usar el ISR, usar el modo CTC y preescaladores, etc. Después de llegar al foro , creo que La solución no consiste en lograr precisión en el secuenciador midi, sino que la configuración de mi hardware completo (mis sintetizadores y samplers) se conecta al mismo reloj midi, ya sea que el reloj provenga del Arduino o no.

    
respondido por el crunkchitis
0

Dependiendo de la manera gradual en que desee realizar la transición de una computadora conectada a un sistema basado en µC, podría considerar colocar una Raspberry Pi dentro de esa caja ($ 25-35 retail ). De esa manera, puede tener una computadora completa basada en Linux (aunque de baja potencia) con puertos USB y pines GPIO.

    
respondido por el Rob Starling

Lea otras preguntas en las etiquetas