サンプリング周波数を知るにはどうすればよいですか?


16

私はサンプリングレートやボーレートなどについて少し混乱し始めています。このArduinoコードがあります:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;


byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

遅延割り込みがないので、サンプリングレート/周波数はいくらですか?Arduino ADCの速度に基づいていますか?ボーレートを上げると、サンプリング周波数が上がりますか、それともシリアルポートを介してデータを送信する速度だけが上がりますか?

回答:


21

Arduino ADCのクロック速度は..arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.cで設定されます

ここに関連部分があります

#if defined(ADCSRA)
    // Set A/D prescale factor to 128
    // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
    // XXX: this will not work properly for other clock speeds, and
    // this code should use F_CPU to determine the prescale factor.
    sbi(ADCSRA, ADPS2);
    sbi(ADCSRA, ADPS1);
    sbi(ADCSRA, ADPS0);

    // Enable A/D conversions
    sbi(ADCSRA, ADEN);
#endif

16 MHz Arduinoの場合、ADCクロックは16 MHz / 128 = 125 KHzに設定されます。AVRの各変換には13個のADCクロックがかかるため、125 KHz / 13 = 9615 Hzです。

これは可能な最大サンプリングレートですが、アプリケーションの実際のサンプリングレートは、連続する変換呼び出しの間隔に依存します。
結果を読み取ってシリアルポート経由で送信するため、ボーレートが低下するにつれて遅延が増加します。ボーレートが低いほど、同じ長さのデータを送信するのに時間がかかり、次のADC変換を呼び出すのに時間がかかります。

アプリケーションの実際のサンプリングレートは、デバッガーまたはシミュレーターを使用して決定できますが、より簡単な解決策は、変換を実行するたびにデジタルピンを切り替えて、デジタルピンが切り替える周波数を測定することです。


また、タイムスタンプ間の時間は、最大で1300から最大で16400まで増加します。確かに同じままである必要がありますか?それは9600で、115200で、多くの時間を経て約1500までしか増加しません。
user3284376 14年

あなたのタイムスタンプコードに関する@ user3284376、私はそれが常に機能することはできないと思います(間違った時間にいくつかの割り込みによって偏ることができます)。Arduinoで高精度のタイミングを取得する方法に関する特定の質問を投稿し、そこにコードの関連部分を配置することをお勧めします。
jfpoilpret 14年

7

また、プロジェクトの高いサンプリングレートを取得したかったのです。ADCSRAレジスタのADPS2、ADPS1、ADPS0ビットは、サンプリングレートが76923 s / sまたは76.8 ks / sになるように設定できることがわかりました。しかし、私はarduinoのADCをフリーランニングモードで実行していることに注意してください、次の行が私のために働きました。

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup() {
// Set the Prescaler to 16 (16000KHz/16 = 1MHz)
// WARNING: Above 200KHz 10-bit results are not reliable.
//ADCSRA |= B00000100;
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);

// Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt.
// Without this, the internal interrupt will not trigger.
//ADCSRA |= B00001000;
sbi(ADCSRA,ADIE)
}

この頻度では、通常の10ビットの結果は信頼できません。つまり、サンプルレートを上げると、結果の精度が低下します。したがって、このプリスカラーでは上位8ビットが信頼できるため、上位8ビットのみを使用します。このページで詳細を見ることができます、この男はロックします!彼はUNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/を使用して高サンプルレートのオシロスコープを作成しました


3

9600bpsシリアルリンクで8文字を印刷する各ループ。各文字は10ビット(1スタート、8ビット、1ストップ)かかります。つまり、このループは1秒あたり約120回しか実行できません。

analogRead()関数は、現実的に、それはおよそ8600回/秒で、理論的にはおよそ9600回/秒でサンプリングすることができます。

シリアル通信に縛られています。


115200に増加すると、1440回/秒になりますが、それはサンプルレートですか?
user3284376 14年

はい、与えてください。シリアルでは相手側が応答する必要があるため、PCの応答に依存していることに留意する必要があります。これは確定的ではないため、ジッタが発生します。
サイバーギボン14年

あなたはArduinoの端に正しい、それはすべてうまく見えますが、Pythonでは物事がはるかに遅いです、物事のコンピュータ端のパフォーマンスを向上させるためにどんな種類のことをする必要がありますか?
user3284376 14年

これをPCのシリアルパフォーマンスの問題と見なす必要はありませんが、サンプリングをデータの送信から切り離すにはどうすればよいですか。
サイバーギボン

1
@Cyber​​gibbons-いいえ、これはUSBとシリアルが分離されているUnoで実行されているため、「S」文字を発行して「F」文字を発行する以外にPCに依存しません。ここに掲載されているスケッチとそれが動作するプラットフォームは、USBシリアルコンパニオンマイクロにシリアルデータを喜んで投げます。
クリスストラットン14

3

9600のボーでシリアル経由で11ビットを送信しますが、サンプリングのために、できるだけ遅延のない配列に格納し、それが完了したら、シリアルポートを介して送信してPythonスクリプトで読み取ります。matplotlibを使用してFFTに対してこれを行っています。0〜5Vの信号を聞いてから、delay()関数を使用せずに、analogRead()値をその配列に格納します。一瞬で読み取りが行われ、シリアルデータダンプが開始されます。接続された別のArduinoからのtone()を使用して入力周波数をキャリブレーションすると、0.1 Hz以内の精度を得るために8915でインデックスを除算する必要があることに気付きました。適切なインデックス間隔を得るためにサンプリングの周波数で除算する必要があるため、私の推測では、Arduinoのサンプリング周波数(少なくとも私のコードでは私のもの)は8915Hzです。


1

サンプルレートとボーレートの違いに関する部分を参照すると、それらは異なる測定値です。

サンプルレートは、デバイス(arduino)が着信アナログ値のデジタル表現を再作成できる周波数です。

ボーレートは、情報が通信チャネルで転送される速度です。これは、マイクロコントローラーと外の世界(コンピューター)との間の通信速度を表します。

このelectronics_stack_exchangeリンクをお勧めします。 /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915Hz-125000/14に非常に近い〜= 8928.6隣接する変換の間に正確に1つのギャップが必要であるという私の最初の推測サンプリング用の1つのADCクロックと変換自体用の13つのADCクロック。小さなエラーは、Arduinoの完全なクロックソースではない可能性があります。まだ確かではありません。サンプリングされたデータはデジタルフィルターに入力する必要があるため、このトピックは今私にとって現実的です。


1
「サンプリングされたデータはデジタルフィルターに入力する必要があるため、このトピックは今や私にとって実際のものです」と言うときの意味がわかりません。同様の問題がありますか?
VE7JRO

各変換はADCクロックの立ち上がりエッジで開始され、コードの実行中に少なくとも 1つのADCクロックサイクルが失われます。そのためanalogRead()、フリーランニングモードでは非常に一貫性のある9615.4 Hzに対して、8928.6 Hzはタイトループで呼び出すことで得られる最速です。
エドガーボネット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.