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近く遅延します。しかし、それを測定しようとする試みには誤りがあります。
また、割り込みが発生すると、間隔が少し長くなります。正確な遅延が必要な場合は、割り込みをオフにする必要があります。