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.タスクを2つのマイクロプロセッサに分割する必要がありますか?1つはユーザーインターフェイスのポーリングと更新を処理し、もう1つはミッションクリティカルなタイミングループ用です。

c。他に何か?

私の主な目標は、コンピュータをまったく使用する必要がないことです。スイングについても計算したいのですが、この場合、スイングは、ロックされたタイミングの正確なテンポが得られなければ意味がありません。助言ありがとう!


1
Arduinoは常にいくつかの割り込みルーチンをセットアップし、ジッターを引き起こします。多くの場合、これは問題ではありませんが、認識しておくことをお勧めします。noInterrupts();ジッターを停止しますが、必要なすべての割り込みも停止します。
ジッピー2013年

1
「オンボードでシーケンスを行う」と言う場合、それはバーごとのビート、BPM、およびティックトラックをオンボードで設定することを意味しますか?次に、デバイスの「頭脳」がラップトップにミディノートを送ることができるように、バー内で発生したボタンの押下を覚えておきたいと思いますか?次に、特定のパーカッションサウンドを、以前に録音されたノートの上でもう一度叩いた場合に削除しますか?など、どこまで行きたいですか?ビートの保存?フルトラックに対応するバーのシーケンスを作成しますか?特定のバーを編集しますか?特定の小節のテンポ変更?すべてがCPUを消費するので、最高のCPUを探します。
アンディaka

うん、それはすべて。
スティーブクーリー

2
それはあなたが作ったスイートなケースです!
shuckc 2013

3
他の人が言ったことに加えて、これはおそらくあなたが生産し、販売するつもりであると考えているようです。Arduinoの価格は$ 20、AVRの価格は$ 2です。アプリケーションに必要なハードウェアを制御できるだけでなく、多くのコストを節約できます。
Phil Frost

回答:


5

割り込みは、タイミングに敏感なタスクの友ですが、タイミングの重要な側面を割り込みに入れ、優先度の高い他の割り込みが発生していない場合のみです。「AVRベース」のArduino(ATmega328Pなど)のマイクロコントローラーには、データシートの 58ページ以降に記載されているように、割り込み優先順位が固定されています。したがって、重要なタイミング割り込みとしてTIMER2 COMPAを使用し、他の割り込みがない場合は、問題ありません(優先度が最も高いため)。優先度の低い割り込みも使用する場合は、割り込みサービスルーチンに入るときに、すべての割り込みがグローバル割り込みを再度有効にするようにする必要があります。

割り込みが発生すると、グローバル割り込みイネーブルIビットがクリアされ、すべての割り込みが無効になります。ユーザーソフトウェアは、ロジック1をIビットに書き込んで、ネストされた割り込みを有効にすることができます。有効になっているすべての割り込みは、現在の割り込みルーチンに割り込むことができます。

データシートの 14ページ)

ARMベースのArduinoでは、Cortex-M3コアに「ネストされたベクター割り込みコントローラー」があり、優先度が固定されておらず(ソフトウェアで設定可能)、ネストされた割り込み処理が標準であるため、これは少し異なります。したがって、タイミングが重要なアプリケーションの場合、ARMベースのArduinoを使用すると柔軟性が向上します。しかし、私はそれがあなたのアプリケーションにとって本当に必要であるとは思いません。

より大きな問題は、これらのものがArduinoライブラリを使用してどれほど簡単に実装できるかです。最高のパフォーマンスを得るには、少なくともタイミングクリティカルなビットについては、おそらくライブラリの外部である程度コーディングする必要があります。つまり、delay()やmillis()などを完全に回避します。

分割する必要があるかどうかは、実行する処理の量によって異なります。繰り返しになりますが、ライブラリの外に出ると、パフォーマンスが向上する場合があります。


3

これは、適切なプログラミングを使用して、ATmega328Pで確実に実行できます(ドラムループの複雑さに多少依存します。ループ内のドラムイベントは〜<50であると想定しています。それは妥当ですか?)。

ATmega328Pと言ったことに注意してください。必ずしもArduinoではありません。

Arduino環境では、バックグラウンドで多くのデフォルトの処理が行われているため、非常に確定的なプログラミング(タイミングが重要なものに必要なプログラミング)が困難になります。

ここで尋ねる必要がある本当の質問は、プログラミングにどの程度関心があるか、それとも計測器の開発にどの程度関心があるかです。

1 つのATmega(ドラムループ、複数のアナログ入力、LCD、ボタン、MIDIインターフェイス)で必要なすべてを実行できると確信していますが、実際の問題は、すべてを絞り込むのにどれだけの作業が必要かということです。繰り返しますが、組み込みMCUコードの最適化を学びたいですか、それとも計測器を構築したいですか?これは単に、必要に応じてより速くMCUに行く、しかし、あなたが必要なMCU性能を決定する必要があるのは非常に簡単です、今のあなたがすることはできません気付いていない、で、仕事のように半年はかなりあなたの速としての仕事にすべてを取得します必要。


もし私があなただったら、最初にやってみたいことはarduinoを使わずにそれを機能させることです(基本的には生のATmegaとして扱い、AVRスタジオなどを使います)。次に、必要なパフォーマンスの種類と、ATmegaがそれを管理できるかどうかをより効果的に分析できます。

arduinoがなくなると、さまざまなMCUを自由に使用できるようになります(通常、MCUは似ていますが、異なります。ドキュメントから1つを理解できれば、他のMCUでも同じことができるでしょう)。

私は最近ATxmegaデバイスをLOTで使っていて、本当に素晴らしいです。割り込みの優先順位が3つあるので、タイムクリティカルなものの管理が簡単になります。彼らはまた、一緒に作業するのが本当に素晴らしいです(正気な周辺機器の設計!便利なポート構造!など...)。

ARMベースのNXPのLPCデバイス、Atmelの一部のARMデバイス(Arduino Dueで使用されている)、またはSTのSTM32 MCUもあります。これらのいずれも、ATmega、またはATxmegaよりも大幅に高いパフォーマンスを発揮します。

より大きく、より強力なプロセッサの主な欠点は価格ですが、これらのユニットを何千個も製造しない限り、ユニットごとの組み立ておよび製造コストは、コストの差(おそらく数ドルのみ)を大幅に超えることになります。 )それは基本的に無関係です。


うまく言えば-商用製品の場合、Arduinoは単に進むべき道ではありません-それらは電力を消費し、遅く、IDEは最適(高速/小型)コード用に設計されておらず、むしろ便利で簡単に学習できます。コストを抑えるには、STM32 F4(32ビットCortex M4> 100MHz)または同等のものを使用することもできますが、これはやり過ぎです。小さいPIC32、Cortex M3、またはAVR32のようなものがおそらくお勧めの方法です。多数の割り込み優先度、DMA、洗練された周辺機器、高速/低消費電力、および大量のRAMにより、Arduinoに比べて簡単に選択できます。
Oli Glaser 2013

@OliGlaser -私はあなたがはっきりとの間で線引きする必要があると思うのArduinoATMEGA。ATmegaで小さくて高速なコードを実行でき、そのATmegaをArduinoボード上に置くこともできます。一方、Arduinoの「IDE」は、私が今まで使った中で最も洗練されたコードエディターの1つです。一方、OptiBootブートローダーは非常に優れています。一部の部品ががらくたになっているからといって、すべてを捨てる必要があるわけではありません。
コナーウルフ

絶対に-私は全体としてArduinoを参照しており、ボードとIDEが含まれていました-ATmegaではなく、他の同等のuC(PIC16 / 18Fなど)と同じくらい優れていると思いますが、リストに含めましたが、私は8ビットと16/32ビットの間の価格が最近非常に近いと思うので、おそらく余分な$ 1を費やして、プロセッサの能力に余裕があることを知っておくとよいでしょう(あなたが言及している場合を除き、そして絶対最低価格に建てられましたが、Arduinoが検討されたとは思えません:
Oli Glaser 2013

1

タイミングの正確さを考える前に、タイマーを確認する必要がありました(Arduinoを使用してMIDIステップシーケンサーを構築していますが、それよりも見た目が悪くなることが保証されています^^)。この一連の記事は最も有益でした。

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

正確なタイミングを得るための私の解決策は今だと思います。

A. AVR arduinoを使用する

B.タスクを1つのマイクロプロセッサーで実行する

C.必要な精度を得るために、プリスケーラー、タイマー、割り込みを賢く使用する。

更新

Arduinoの基本的なmidiチュートリアルを使用して、タイマーとプリスケーラーに関するこの記事を読んだ後、次のコードが私が思いついたものです。このコードは、timer1およびCTCモードを使用して、1/4秒ごとにMIDIノートを再生し、1/4秒ごとにノートオフを再生します(正確には120 bpmです)。悲しいことに、これはまだ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モードやプリスケーラーの使用など。フォーラムに到達した後の解決策は、MIDIシーケンサーの精度を上げることではなく、ハードウェアセットアップ全体(シンセサイザーとサンプラー)を同じものに接続することだと思います。 midiクロック、クロックがArduinoからのものかどうか。


0

テザリングされたコンピュータからµCベースのシステムに徐々に移行したい場合に応じて、Raspberry Piをその箱の中に入れることを検討してください(小売価格25〜35ドル)。そうすることで、USBポートとGPIOピンを備えた完全な(低電力ではありますが)Linuxベースのコンピューターを使用できます。


拡張シールドまたはPiと呼ばれるものがあると思いますが、ストックボードには17個のGPIOピンがあります。私はarduino megaのすべてのピンを使用しています。31タクト+ 30 LED、10アナログ入力。70+I / O。
Steve Cooley 2013

ああ、つまり、当面の目的が外部コンピューターを削除することだった場合、「シーケンサーはラップトップで実行されるアプリケーション」を維持し、Piで実行することができます。これは、既存のシステムに内部的に接続されている方法と同じです。接続されました。
Rob Starling 2013

@SteveCooley-IO多重化/ボタンマトリックスを調べる必要があるようです。ボタンごとに専用のIOライン全体を必要とするべきではありません。
コナーウルフ2013

@SteveCooley-地獄、あなたは本当にボタンマトリックスを必要としません。4つのrPiピンのみを使用して、すべてのデジタルIOを実行できます。すべてのボタンとLEDを一部のシフトレジスタ(ボタンの場合はパラレルシリアル、LEDの場合はシリアルパラレル)に掛け、rPiのSPIポートからシフトレジスタを駆動します。SPIハードウェアの助けを借りて、マトリックス全体で1Khzを超える更新レートを簡単に取得できます。
Connor Wolf

Arduino Megaを使用している唯一の理由がIOである場合、いくつかの外付けデバイスで非常に簡単に実行できる何かに多額の費用を費やしています。
コナーウルフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.