delayMicrosecondsをより正確にすることはできますか?



Can I Make Delaymicroseconds More Accurate



解決:

前の回答で説明したように、あなたの実際の 問題 の精度ではありませんdelayMicroseconds()ではなく、マイクロ()。

しかし、あなたの実際に答えるために 質問 、より正確な代替手段がありますdelayMicroseconds():関数AVR-libcの_delay_us()はサイクル精度が高く、たとえば



_delay_us(1.125);

それが言うことを正確に行います。主な注意点は、引数はコンパイル時定数でなければならないということです。必ずこの関数にアクセスするには、#includeを使用してください。

正確な遅延が必要な場合は、割り込みをブロックする必要があることにも注意してください。



編集 :例として、PD2(メガのピン19)で4 µsのパルスを生成する場合、次のように進めます。まず、次のコードに注意してください

noInterrupts(); PORTD | = _BV(PD2); // PD2 HIGH PORTD&= 〜_BV(PD2); // PD2 LOW割り込み();

ポートを設定する命令の実行にかかる時間であるため、0.125 µsの長いパルス(2 CPUサイクル)を生成します。低い。次に、不足している時間を遅延で追加します。

noInterrupts(); PORTD | = _BV(PD2); // PD2 HIGH _delay_us(3.875); PORTD&= 〜_BV(PD2); // PD2 LOW割り込み();

サイクル精度のパルス幅があります。これはで達成できないことに注意する価値がありますdigitalWrite()は、この関数の呼び出しに約5 µsかかります。




あなたのテスト結果は誤解を招くものです。delayMicroseconds()は、実際にはかなり正確に遅延します(2または3マイクロ秒を超える遅延の場合)。そのソースコードは、ファイル/usr/share/arduino/hardware/arduino/cores/arduino/wiring.c(Linuxシステムの場合、または他のシステムの同様のパス上)で調べることができます。

ただし、micros()は4マイクロ秒です。 (たとえば、garretlabのページを参照してください。micros()。)したがって、読み取り値は表示されません。 の間に 4マイクロ秒と8マイクロ秒。実際の遅延は4マイクロ秒で数サイクルである可能性がありますが、コードはそれを8として報告します。

10または20を試してみてくださいdelayMicroseconds(4); (ループを使用するのではなく、コードを複製することによって)連続して呼び出し、次に次の結果を報告します。マイクロ()。


Arduinoの遅延がどれほど優れているかを確認しています...かなりひどいようです。

micros()の分解能は、十分に文書化されており、4 µsです。

タイマー0のプリスケーラーを変更することで、解像度を向上させることができます(もちろん、数値は破棄されますが、それを補正することはできます)。

または、プリスケーラが1のタイマー1またはタイマー2を使用すると、62.5nsの分解能が得られます。


Serial.begin(9600);

とにかくそれは遅くなるでしょう。


8 4 8 4 4 4 4 4 8 8 8 8 4 8 8 4 4 8 4 4 4 8 8 8 4 8 4

出力は、4 µsの分解能と正確に一致しています。micros()は、タイミングを開始した正確な時期に応じて、2つの「ティック」を取得することもあれば1つの「ティック」を取得することもあるという事実と相まって。


あなたのコードは、測定誤差の興味深い例です。delayMicroseconds(4); 4 µs近く遅延します。しかし、それを測定しようとする試みには誤りがあります。

また、割り込みが発生すると、間隔が少し長くなります。正確な遅延が必要な場合は、割り込みをオフにする必要があります。