Arduino kullanarak MIDI sıralayıcı zamanlama doğruluğu


11

Bu müzik dizilerini oluşturuyorum .

resim açıklamasını buraya girin

Sadece tam bir sıralayıcı değil, sıralayıcı için fiziksel bir arayüz. Sıralayıcı, sıralayıcının bağlandığı bir dizüstü bilgisayarda çalışan bir uygulamadır, bu şey kullanıcının anında davul döngüleri yapmasına izin verir. Oldukça eğlenceli, ancak bir dizüstü bilgisayar gerektiriyor çünkü sıralayıcı 'yerleşik' değil.

Seveceğim şey sıralamayı cihazımda yapmaktır.

Şimdi USB MIDI bağlantısı için sınıf uyumluluğunu nasıl çözeceğimizi bildiğimi varsayalım ve ayrıca 5 pinli DIN bağlantı noktasından MIDI notları göndermek için bir arduinoyu nasıl bağlayacağımı da varsayalım. En çok endişelendiğim şey, olay döngüsünün her çalışması sırasında dakika miktarlarındaki tutarsız zamanlama nedeniyle zamanla tempo kayması.

Bildiğim bazı şeyler:

  1. delay()Tempo döngüsünü kontrol etmeye güvenmemelisiniz . Gecikme, bellenimin tüm çalışmasını durdurur ve bu işlem yapılamaz çünkü sıra çalışırken fiziksel kullanıcı arabirimini değişiklikler için yoklamam gerekir.

  2. Baz alınan hesaplamalar millis()daha iyidir çünkü bellenim belirli bir sayı geçtiğinde çalışmaya devam edebilir.

  3. Fiziksel kontrollerimin hiçbiri kesme rutinlerini tetiklemese de, bazı işlemler ana ünitenin çalışmasını geciktirebilir loop(). Kullanıcı girdisini bekleyen bir işlev tasarlarsam, bu millis()sayım çoktan sona erdiğinde harekete geçmek için bir "son teslim tarihi" eksikliğine neden olabilir . Bu sorunun kendi tasarımım olduğunu biliyorum ...

Sorular:

A. AVR tabanlı arduino, bir kullanıcı arabirimini yoklamak ve kritik bir zamanlama döngüsü çalıştırmak için uygun bir mikrodenetleyici midir? ARM tabanlı bir Arduino olduğunu biliyorum, bu çok daha hızlı. Teensy 3.0 daha iyi bir alternatif olabilir mi? Her ikisi de 3.3V panoları, bu yüzden çalışmak için başka bir sorun kümesi ... ama şimdilik bunu görmezden geleceğim.

B. Görevi iki mikroişlemciye ayırmalı mıyım? Biri yoklama ve kullanıcı arayüzünü güncellemek için ve diğeri kritik görev zamanlama döngüsü için.

c. Başka bir şey?

Asıl amacım hiç bilgisayar kullanmak zorunda kalmak değil. Ayrıca salıncak için hesaplamak istiyorum, ancak bu durumda, kilitli ve zamanlama doğru bir tempo yoksa, salıncak bir şey ifade etmiyor. Tavsiyeniz için teşekkürler!


1
Arduino her zaman bazı kesme rutinleri kurarak titremeye neden olur. Çoğu durumda bu bir sorun değildir, ancak bunun farkında olmak iyidir. noInterrupts();titremeyi durdurur, ancak istenen tüm kesintileri de durdurur.
jippie

1
"Gemide sıralama" dediğinizde, bu, bar, BPM ve gemide bir kene izi başına vuruşların ayarlanması anlamına mı geliyor? Sonra muhtemelen "beynin" dizüstü bilgisayarınıza midi notları besleyebilirsiniz böylece çubuk içinde meydana gelen düğmeye basmak hatırlamak istiyor musunuz? O zaman, daha önce kaydedilmiş notanın üzerine tekrar vurursanız, belirli perküsyon seslerini kaldırmak ister misiniz? Vb .. ne kadar gitmek istiyorsun? Ritimlerinizin saklanması? Tam bir parçaya karşılık gelen bir dizi çubuk oluşturuyor musunuz? Belirli çubuklar düzenleniyor mu? Belirli çubukların geçici olarak değiştirilmesi? Hepsi CPU yiyor, bu yüzden en iyi CPU'ya gidin.
Andy aka

Evet, hepsi.
Steve Cooley

2
Bu tatlı görünümlü bir durum!
shuckc

3
Başkalarının söylediklerine ek olarak, bu belki de üretmeyi ve satmayı düşündüğünüz bir düşünmeye benziyor. Bir Arduino'nun maliyeti 20 dolar, AVR'nin maliyeti ise 2 dolar. Sadece uygulamanızın ihtiyaç duyduğu donanım üzerinde kontrol sahibi olmakla kalmaz, aynı zamanda çok tasarruf edersiniz.
Phil Frost

Yanıtlar:


5

Kesintiler, hassas görevleri zamanlamak için arkadaşınızdır, ancak yalnızca zamanlama kritik yönlerini kesintiye sokarsanız ve daha yüksek önceliğe sahip başka kesintiler olmazsa. "AVR tabanlı" Arduino (örn. ATmega328P) üzerindeki mikrodenetleyiciler, veri sayfasının 58. sayfasında ayrıntıları verilen sabit kesme önceliklerine sahiptir . Bu nedenle, kritik zamanlama kesintiniz olarak TIMER2 COMPA kullandıysanız ve başka hiçbir kesinti yoksa, en iyi önceliğe sahip olmalısınız (en yüksek önceliğe sahip olduğu için). Daha düşük öncelikli kesintileri de kullanmak istiyorsanız, kesme hizmet yordamlarına girerken hepsinin genel kesintileri yeniden etkinleştirdiğinden emin olmanız gerekir:

Bir kesme oluştuğunda, Global Kesme Etkinleştirme I biti temizlenir ve tüm kesintiler devre dışı bırakılır. Kullanıcı yazılımı iç içe kesmeleri etkinleştirmek için I-bit'e mantıksal bir yazabilir. Etkinleştirilen tüm kesmeler daha sonra geçerli kesme yordamını kesebilir.

( veri sayfasının s.14 )

Bu, ARM tabanlı Arduinos'ta biraz farklıdır, çünkü Cortex-M3 çekirdeği, önceliklerin sabit olmadığı (yazılımda ayarlanabilir) ve iç içe kesme işleme normdur. Kritik uygulamaları zamanlamak için ARM tabanlı Arduino size daha fazla esneklik sağlayacaktır. Ancak, bunun başvurunuz için gerçekten gerekli olduğunu düşünmüyorum.

Daha büyük soru, bunların Arduino kütüphaneleri ile ne kadar kolay uygulanabileceğidir. En iyi performansı elde etmek için muhtemelen en azından zamanlama kritik bitleri için kütüphanelerin dışında bir dereceye kadar kod yazmanız gerekir, yani delay () veya millis () gibi şeylerden tamamen kaçınmalısınız.

Bölmeniz gerekip gerekmediği, ne kadar işlem yapmak istediğinize bağlıdır. Yine, kütüphanelerin dışına çıkmak size daha iyi performans verebilir.


3

Bu, uygun programlama ile, kesinlikle bir ATmega328P üzerinde yapılabilir (biraz drum-loop'un karmaşıklığına bağlı olarak. ~ <50 drum olayını döngüde varsayıyorum. Bu makul mi?).

ATmega328P dedim , mutlaka bir Arduino değil .

Arduino ortamının arka planda devam eden çok fazla varsayılan özelliği vardır, bu da son derece belirleyici programlama yapar (zamanlama açısından kritik bir şeye ihtiyacınız olacak gibi) zorlaştırır.

Burada sormanız gereken asıl soru programlama ile ne kadar ilgilisiniz, vs bir enstrüman geliştirmekle ne kadar ilgilisiniz?

Oldukça eminim iken bu kadar mümkün Asıl soru ne kadar iş o her şeyi sıkmak olacak, sen tek ATMEGA üzerinde istediğiniz her şeyi (davul döngü, çoklu analog giriş LCD, düğmeler, MIDI arayüzü) yapmalı? Tekrar, gömülü MCU kodunu optimize etmeyi mi yoksa enstrümanlar oluşturmayı mı öğrenmek istiyorsunuz? Bu sadece gerekirse MCU daha hızlı gitmek, ama sen gerekmez MCU performansını belirlemek gerekir oldukça kolaydır şimdi , sen olamaz farkında değilsiniz de, işin bu yüzden altı ay oldukça sizin kadar hızlı işe her şeyi elde ihtiyaç.


Ben olsaydım, yapacağım ilk şey, arduino olmadan çalışmasını sağlamaktı (temel olarak, ham bir ATmega gibi davranın ve AVR stüdyosu veya benzeri kullanın). Ardından, ne tür bir performansa ihtiyacınız olduğunu ve ATmega'nın bunu yönetip yönetemeyeceğini çok daha etkili bir şekilde analiz edebilirsiniz.

Arduino malzemelerinden kurtulduktan sonra, farklı MCU'ları kullanmak için çok daha özgürsünüz (genellikle farklı olanlardan daha benzerler. Birini belgelerinden anlayabilirseniz, muhtemelen başkaları için de yapabilirsiniz).

ATxmega cihazlarıyla son zamanlarda ÇOK çalışıyorum ve gerçekten çok iyi. Zaman açısından kritik olan şeyleri yönetmeyi kolaylaştıran üç kesme önceliği elde edersiniz. Ayrıca çalışmak çok güzel (Sane çevre tasarımları! Uygun liman yapıları! Vb ...).

Ayrıca NXP'den ARM tabanlı LPC cihazları ve Atmel'in bazı ARM cihazları (Arduino Due'da kullanıldığı gibi) veya ST'den STM32 MCU'lar da vardır. Bunlardan herhangi biri bir ATmega'dan, hatta bir ATxmega'dan çok daha fazla performans gösterecektir.

Daha büyük, daha güçlü bir işlemcinin birincil dezavantajı fiyattır, ancak bu birimleri binlerce yapmazsanız, birim başına montaj ve üretim maliyetleri maliyet farkını çok fazla aşacaktır (bu sadece birkaç dolar olacaktır) ) temelde alakasız olduğunu gösterir.


Güzel bir şekilde söylemek gerekirse - ticari bir ürün için Arduino basitçe gitmenin yolu değildir - güce aç, yavaştır ve IDE optimal (hızlı / küçük) kod için değil, kolaylık ve kolay öğrenme için tasarlanmamıştır. Daha az maliyetle, bir aşırıya kaçma olsa da, bir STM32 F4 (32 bit Cortex M4> 100MHz) veya benzeri bir ürününüz bile olabilir. Daha küçük PIC32'lerden, Cortex M3'lerden veya AVR32'den biri gibi bir şeyin muhtemelen bahsettiğiniz gibi olduğunu düşünüyorum. Çok sayıda kesme önceliği, DMA, gelişmiş çevre birimleri, hızlı / düşük güç ve bol miktarda RAM, Arduino'ya kıyasla kolay bir seçim olmasını sağlar.
Oli Glaser

@OliGlaser - Sanırım bir Arduino ve ATmega arasında net bir şekilde tanımlamanız gerekiyor . Bir ATmega üzerinde küçük, hızlı kodlar yapabilirsiniz ve ATmega bir Arduino kartında bile olabilir. Arduino "IDE" ise şimdiye kadar kullandığım en boktan kod editörlerinden biri. Öte yandan, OptiBoot önyükleyici çok güzel. Bazı parçaların saçmalık olması, her şeyi atmanız gerektiği anlamına gelmez.
Connor Wolf

Kesinlikle - Arduino'ya bir bütün olarak atıfta bulunuyordum, tahta ve IDE dahil - ATmega değil, karşılaştırılabilir başka bir uC (PIC16 / 18F, vb.) 8-bit ve 16/32-bit arasındaki fiyatın bugünlerde çok yakın olmasıyla, muhtemelen ekstra 1 $ harcamak ve yedekleyecek işlemci gücünüz olduğunu bilmek iyi bir fikirdir (bahsettiğiniz gibi, çok sayıda konuşuyoruz ve mutlak en düşük fiyata inşa edildi, ama sonra bir Arduino düşünüleceğini düşündüm :-))
Oli Glaser

1

Zamanlama doğruluğunu düşünmeye başlamadan önce zamanlayıcıları okumam gerekiyordu (ayrıca bir arduino ile bir midi adım sıralayıcısı inşa etmeliyim, ancak bunlardan daha az serin görünmesi garanti ediliyor ^^). Bu makale dizisi en bilgilendirici oldu:

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

Şu anda kesin zamanlama için benim çözümüm olacağını düşünüyorum.

AVR arduino kullanın

B. Görevi bir mikroişlemcide tutun

C. Gerekli hassasiyeti elde etmek için ön ölçekleyicileri, zamanlayıcıları ve kesintileri akıllıca kullanın.

GÜNCELLEME

Arduino için temel midi öğretici kullanarak ve zamanlayıcılar ve prescalers hakkında bu makaleye baktıktan sonra , aşağıdaki kod ile geldi. Kod, her çeyrek saniyede bir midi notası ve her çeyrek saniyede bir nota çalmak için timer1 ve CTC modunu kullanır (tam olarak 120 bpm olmalıdır). Ne yazık ki, bu hala 120bpm'den daha yavaş geliyor, ancak bu en yakın aldığım ...

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

GÜNCELLEME

~ 24 saattir bununla mücadele ediyorum ve sonunda forumdan bazı cevaplar aldım. Ben yukarıda kullanılan ^ ^ kod oldukça iyi olduğunu düşünüyorum. Uzanarak sonra CTC modunu ve prescalers vb kullanarak, ISR kullanarak foruma I (benim synthesizer ve işlenme) aynı bağladım çözüm daha az midi dizicisinde hassasiyet elde ama benim bütün donanım kurulumuyla ilgili olduğunu düşünüyorum midi saat, saat Arduino'dan geliyor olsun olmasın.


0

Bağlı bir bilgisayardan µC tabanlı bir sisteme ne kadar yavaş geçiş yapmak istediğinize bağlı olarak, Raspberry Pi'yi bu kutunun içine koymayı düşünebilirsiniz (25-35 $ perakende ). Bu şekilde, USB bağlantı noktaları ve GPIO pinlerine sahip tam (düşük güçlü de olsa) linux tabanlı bir bilgisayara sahip olabilirsiniz.


Eminim genişletme kalkanları ya da Pi için her ne diyorlarsa da, stok panosunda 17 GPIO pimi var. Arduino mega üzerindeki her iğneyi kullanıyorum. 31 yazı + 30 LED, 10 analog giriş. 70+ G / Ç.
Steve Cooley

Oh, demek istediğim, acil hedef harici bilgisayarı kaldırmaksa, "sequencer [that] bir dizüstü bilgisayarda çalışan bir uygulamadır" ve Pi'de çalıştırabilir, mevcut sisteminize dahili olarak aynı şekilde bağlayabilirsiniz şimdi bağlı.
Rob Starling

@SteveCooley - IO çoğullama / düğme matrislerine bakmanız gerektiği anlaşılıyor. Düğme başına tam bir IO hattına ihtiyacınız olmamalıdır.
Connor Wolf

@SteveCooley - Cehennem, gerçekten bir düğmeye daha ihtiyacın yok. TÜM dijital IO'nuzu yalnızca 4 rPi pin kullanarak yapabilirsiniz. Tüm düğmeleri ve LED'leri bazı kaydırma kayıtlarından asın (düğmeler için paralel seri, LED'ler için seri paralel) ve kaydırma kayıtlarını rPi'nin SPI bağlantı noktasından sürün. SPI donanımı yardımıyla tüm matris için> 1 Khz güncelleme oranlarını kolayca almalısınız.
Connor Wolf

Arduino Mega kullanmanın tek nedeni IO ise, birkaç harici cihazla kolayca yapılabilecek bir şeye çok fazla para harcıyorsunuz, <3 $.
Connor Wolf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.