Arduino를 사용한 MIDI 시퀀서 타이밍 정확도


11

나는이 음악 시퀀서를 구축 한다 .

여기에 이미지 설명을 입력하십시오

시퀀서가 아니라 시퀀서의 실제 인터페이스입니다. 시퀀서는 시퀀서가 연결된 랩톱에서 실행되는 응용 프로그램으로, 사용자는 드럼 루프를 즉석에서 만들 수 있습니다. 꽤 재미 있지만 시퀀서는 '온보드'가 아니기 때문에 랩톱이 필요합니다.

내가 좋아하는 것은 장치 내에서 시퀀싱을 수행하는 것입니다.

이제 USB MIDI 연결을위한 클래스 컴플라이언스를 해결하는 방법을 알고 있다고 가정하고, 5 핀 DIN 포트에서 MIDI 노트를 전송하기 위해 arduino를 연결하는 방법을 알아낼 수 있다고 가정하겠습니다. 내가 가장 걱정하는 것은 이벤트 루프가 실행될 때마다 일정하지 않은 타이밍으로 인해 시간에 따른 템포 드리프트입니다.

내가 아는 것 :

  1. delay()템포 루프를 제어하는 ​​데 의존해서는 안됩니다 . 지연은 펌웨어의 모든 작동을 중지하며 시퀀스가 ​​실행되는 동안 물리적 사용자 인터페이스를 변경하여 변경해야하므로 작동하지 않습니다.

  2. millis()특정 카운트가 경과하면 펌웨어가 계속 작동하고 작동 할 수 있기 때문에 기반으로 계산하는 것이 좋습니다.

  3. 물리적 컨트롤 중 어느 것도 인터럽트 루틴을 트리거하지는 않지만 일부 작업은 메인 loop()실행을 지연시킬 수 있습니다 . 사용자 입력을 기다리는 함수를 디자인하면 millis()카운트가 끝나면 "마감"이 누락되는 문제가 발생할 수 있습니다 . 나는이 문제가 내 자신의 디자인이라는 것을 알고있다 ...

질문 :

A. AVR 기반 arduino는 사용자 인터페이스를 폴링하고 미션 크리티컬 타이밍 루프를 실행하기에 적합한 마이크로 컨트롤러입니까? ARM 기반 Arduino가 훨씬 빠르다는 것을 알고 있습니다. Teensy 3.0이 더 나은 대안일까요? 이 두 가지 모두 3.3V 보드이므로 작동해야 할 또 다른 문제입니다 ...하지만 지금은 무시하겠습니다.

B. 작업을 두 개의 마이크로 프로세서로 분할해야합니까? 하나는 사용자 인터페이스 폴링 및 업데이트를 처리하고 하나는 미션 크리티컬 타이밍 루프를위한 것입니다.

씨. 다른 것?

나의 주요 목표는 컴퓨터를 전혀 사용할 필요가 없다는 것입니다. 나는 또한 스윙을 계산하고 싶지만,이 경우 스윙은 정확한 타이밍과 템포를 가지고 있지 않다면 아무 의미가 없습니다. 조언 해 주셔서 감사합니다!


1
Arduino는 항상 몇 가지 인터럽트 루틴을 설정하여 지터를 발생시킵니다. 많은 경우에 이것은 문제가되지 않지만, 알고있는 것이 좋습니다. noInterrupts();지터를 중지하고 원하는 모든 인터럽트를 중지합니다.
jippie

1
"온보드 시퀀싱"이라고 말하면 바당 비트 수, BPM 및 틱 트랙을 온보드로 설정한다는 의미입니까? 그런 다음 장치의 "두뇌"가 노트북에 미디 노트를 공급할 수 있도록 막대 내에서 발생한 버튼 누름을 기억하고 싶습니까? 그런 다음 이전에 녹음 된 음표를 다시 타악하면 특정 타악기 소리를 제거 하시겠습니까? 등등. 얼마나 멀리 가고 싶어? 비트 저장? 전체 트랙에 해당하는 일련의 막대를 생성합니까? 특정 바를 편집 하시겠습니까? 특정 바의 템포 변경? 그것은 모두 CPU를 먹으므로 최고의 CPU를 찾으십시오.
Andy 일명 12

그렇습니다.
Steve Cooley 16:11에

2
그것은 당신이 만든 달콤한 사건입니다!
shuckc

3
다른 사람들이 말한 것 외에도, 이것은 당신이 생산하고 판매하려는 생각처럼 보입니다. Arduino는 20 달러, AVR은 2 달러입니다. 응용 프로그램에 필요한 하드웨어를 제어 할 수있을뿐만 아니라 많은 비용을 절약 할 수 있습니다.
Phil Frost

답변:


5

인터럽트는 민감한 작업 타이밍을 정하는 친구이지만 타이밍 결정적인 측면을 인터럽트에 넣고 우선 순위가 높은 다른 인터럽트가없는 경우에만 가능합니다. "AVR 기반"Arduino의 마이크로 컨트롤러 (예 : ATmega328P)는 데이터 시트 58ff 페이지에 자세히 설명 된대로 고정 된 인터럽트 우선 순위를 갖습니다 . 따라서 TIMER2 COMPA를 중요 타이밍 인터럽트로 사용하고 다른 인터럽트가없는 경우에는 우선 순위가 가장 높으므로 괜찮습니다. 우선 순위가 낮은 인터럽트를 사용하려면 인터럽트 서비스 루틴에 들어갈 때 모든 인터럽트를 다시 활성화해야합니다.

인터럽트가 발생하면 Global Interrupt Enable I-bit가 지워지고 모든 인터럽트가 비활성화됩니다. 사용자 소프트웨어는 로직 1을 I 비트에 기록하여 중첩 된 인터럽트를 활성화 할 수 있습니다. 활성화 된 모든 인터럽트는 현재 인터럽트 루틴을 인터럽트 할 수 있습니다.

( 데이터 시트 14 페이지 )

Cortex-M3 코어에는 "Nested Vector Interrupt Controller"가있어 우선 순위가 고정되어 있지 않고 (소프트웨어에서 설정할 수 있음) 중첩 된 인터럽트 처리가 표준이기 때문에 ARM 기반 Arduino의 경우 약간 다릅니다. 따라서 타이밍이 중요한 애플리케이션의 경우 ARM 기반 Arduino는 더 많은 유연성을 제공합니다. 그러나 이것이 실제로 응용 프로그램에 필요한 것은 아니라고 생각합니다.

더 큰 문제는 Arduino 라이브러리를 사용하여 이러한 것들을 얼마나 쉽게 구현할 수 있는지입니다. 최상의 성능을 얻으려면 최소한 타이밍 임계 비트에 대해 라이브러리 외부에서 어느 정도 코드를 작성해야합니다. 즉, delay () 또는 millis ()와 같은 것을 피하십시오.

분할해야하는지 여부는 처리하려는 처리량에 따라 다릅니다. 다시 말하지만, 라이브러리 외부로 나가면 잠재적으로 더 나은 성능을 제공 할 수 있습니다.


3

이것은 적절한 프로그래밍으로 ATmega328P에서 가장 확실하게 수행 될 수 있습니다 (드럼 루프의 복잡성에 따라 다소 다릅니다. 루프에서 ~ <50 드럼 이벤트를 가정하고 있습니다. 합리적입니까?).

내가 Arduino가 아니라 ATmega328P 라고 말했다 .

Arduino 환경은 백그라운드에서 진행되는 많은 기본 작업을 수행하므로 결정적인 프로그래밍이 필요합니다 (타이밍에 중요한 요소가 필요할 수 있음).

여기서 물어봐야 할 실제 질문 은 프로그래밍에 관심이있는 것과 악기 개발에 얼마나 관심이 있는가입니다.

나는 꽤 확신하지만 그건 가능 진짜 문제는 얼마나 많은 일이 모든 것을 집어 넣은 것입니다, 당신은 하나의 ATMEGA에 원하는 모든 것을 (드럼 루프, 여러 개의 아날로그 입력, LCD, 버튼, MIDI 인터페이스)를 어떻게? 다시 말하지만 임베디드 MCU 코드를 최적화하거나 계측기를 구축하는 방법을 배우고 싶습니까? 그것은 단순히 필요한 경우 MCU 빠른 이동,하지만 당신은 당신이 필요로하는 MCU의 성능을 결정하기 위해 필요에 아주 쉽게 지금 , 당신은 당신이 할 수없는 모르고에서, 일이 너무 육개월을 확실히 당신이 최대한 빨리 작업에 모든 것을 얻을 필요한 것.


내가 당신이라면, 내가 할 첫 번째 일은 arduino 작업없이 작동시키는 것입니다 (기본적으로 원시 ATmega로 취급하고 AVR 스튜디오 또는 이와 유사한 것을 사용하십시오). 그러면 어떤 종류의 성능이 필요한지, ATmega가이를 관리 할 수 ​​있는지 훨씬 더 효과적으로 분석 할 수 있습니다.

아두 이노가 없어지면 다른 MCU를 사용하는 것이 훨씬 더 자유 롭습니다 (일반적으로 다른 MCU와 비슷합니다. 문서에서 하나를 알아낼 수 있다면 다른 사람들도 똑같이 할 수 있습니다).

나는 최근에 ATxmega 장치와 많은 작업을 해왔으며 정말 훌륭합니다. 세 가지 인터럽트 우선 순위가 있으므로 시간이 중요한 항목을보다 쉽게 ​​관리 할 수 ​​있습니다. 그들은 또한 (Sane 주변 장치 디자인! 편리한 포트 구조! 등) 작업하기가 정말 좋습니다.

ARM 기반의 NXP의 LPC 장치와 Arduino Due에서 사용되는 Atmel의 ARM 장치 또는 ST의 STM32 MCU도 있습니다. 이들 중 어느 것도 ATmega 또는 심지어 ATxmega보다 성능 이 훨씬 뛰어납니다.

더 크고 강력한 프로세서의 주요 단점은 가격이지만, 수천 대를 생산하지 않는 한, 단위당 조립 및 제조 비용은 비용 차이를 크게 초과 할 것입니다. ) 기본적으로 관련이 없습니다.


상업용 제품의 경우 Arduino는 단순히 갈 길이 아닙니다. 전력이 고갈되고 느리고 IDE는 최적의 (빠른 / 작은) 코드, 편의성 및 쉬운 학습을 위해 설계되지 않았습니다. 더 적은 비용으로 STM32 F4 (32 비트 Cortex M4> 100MHz) 또는 이와 유사한 것을 가질 수도 있지만 이는 너무 과도합니다. 작은 PIC32, Cortex M3 또는 AVR32와 같은 것이 아마도 당신이 언급 한 것처럼 갈 것이라고 생각합니다. 수많은 인터럽트 우선 순위, DMA, 정교한 주변 장치, 고속 / 저전력 및 많은 RAM이 Arduino에 비해 손쉬운 선택입니다.
Oli Glaser

@OliGlaser- ArduinoATmega 사이를 명확하게 설명해야한다고 생각합니다 . ATmega에서 작고 빠른 코드를 수행 할 수 있으며 ATmega는 Arduino 보드에도있을 수 있습니다. 반면에 Arduino "IDE"는 내가 사용해 본 가장 현명한 코드 편집기 중 하나입니다. 반면에 OptiBoot 부트 로더는 매우 훌륭합니다. 일부 부품이 쓰레기라고해서 모든 것을 버려야한다는 것은 아닙니다.
코너 울프

절대적으로-나는 Arduino를 전체적으로, 보드와 IDE가 포함 된 것으로 언급하고있었습니다 .ATmega는 아닙니다. 다른 다른 uC (PIC16 / 18F 등)만큼 좋았습니다. 내 목록에 포함 시켰지만 나는 8 비트와 16/32 비트 사이의 가격이 요즘 너무 가깝다고 생각합니다. 아마도 1 달러를 더 지불하고 프로세서 전력을 아끼지 않는 것이 좋습니다 (언급하지 않는 한, 우리는 많은 수의 이야기를하고 있습니다) 등) 절대 최저 가격에 내장,하지만 난 :-) 아두 이노 간주되었을 것이다 의심
OLI 글레이저에게

1

타이밍 정확도에 대해 생각하기 전에 타이머를 읽어야했습니다 (또한 arduino로 미디 스텝 시퀀서를 구축하는 것이 좋습니다.하지만 그보다 시원하지는 않습니다.). 이 기사 시리즈는 가장 유익한 정보입니다.

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

지금은 정확한 타이밍을 얻는 솔루션이 될 것이라고 생각합니다.

A. Arduino 사용

B. 하나의 마이크로 프로세서에 작업을 유지

C. 필요한 정밀도를 얻기 위해 프리스케일러, 타이머 및 인터럽트를 현명하게 사용하십시오.

최신 정보

Arduino의 기본 미디 튜토리얼을 사용하고 타이머 및 프리스케일러에 대한 이 기사 를 살펴본 후 다음 코드를 생각해 보았습니다. 이 코드는 timer1 및 CTC 모드를 사용하여 매 1/4 초마다 미디 노트를 연주하고 매 분기 초마다 노트를 연주합니다 (정확히 120bpm이어야 함). 슬프게도, 이것은 여전히 ​​120bpm보다 느리게 진행되지만 이것이 내가 얻은 가장 가까운 것입니다 ...

// 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 모드와 프리스케일러 등을 사용합니다. 포럼 에 연락 한 후 해결책은 미디 시퀀서의 정밀도를 얻는 것이 아니라 전체 하드웨어 설정 (신디사이저 및 샘플러)을 동일하게 연결하는 것입니다. 시계는 아두 이노에서 온 것인지 아닌지


0

테 더링 된 컴퓨터에서 µC 기반 시스템으로 점차적으로 전환하려는 경우에 따라 라즈베리 파이를 상자 안에 넣는 것을 고려할 수 있습니다 ($ 25-35 소매 ). 이렇게하면 USB 포트와 GPIO 핀이있는 완전한 (저전력이지만) Linux 기반 컴퓨터를 가질 수 있습니다.


확장 쉴드 또는 Pi라고 부르는 것이 있지만 스톡 보드에는 17 개의 GPIO 핀이 있습니다. arduino mega의 모든 단일 핀을 사용하고 있습니다. 31 택트 + 30 LED, 10 아날로그 입력 70+ I / O.
Steve Cooley

외부 컴퓨터를 제거하는 것이 바로 목표라면 "노트북에서 실행되는 응용 프로그램 인 시퀀서"를 유지하고 기존 시스템과 동일한 방식으로 내부 시스템에 연결된 Pi에서 실행할 수 있습니다. 지금 연결되었습니다.
Rob Starling

@SteveCooley-IO 멀티플렉싱 / 버튼 매트릭스를 살펴 봐야 할 것 같습니다. 버튼 당 전체 전용 IO 라인이 필요하지 않습니다.
코너 울프

@SteveCooley-지옥, 실제로 버튼 행렬이 필요하지 않습니다. 4 개의 rPi 핀만 사용하여 모든 디지털 IO를 수행 할 수 있습니다. 모든 버튼과 LED를 일부 시프트 레지스터 (버튼의 경우 직렬 직렬, LED의 직렬 병렬)에서 중단하고 rPi의 SPI 포트에서 시프트 레지스터를 구동하십시오. SPI 하드웨어를 사용하면 전체 매트릭스에 대해 1Khz 이상의 업데이트 속도를 쉽게 얻을 수 있습니다.
코너 울프

Arduino Mega를 사용하는 유일한 이유가 IO 인 경우, 외부 장치 몇 개를 사용하여 <$ 3에 매우 쉽게 할 수있는 일에 많은 돈을 쓰고 있습니다.
코너 울프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.