micros() の解説と実装リファレンス

記事内には広告が含まれています。

micros() の解説と実装リファレンス

【概要】

micros() は、Arduino環境において、ボードの電源投入(またはリセット)から現在までの経過時間をマイクロ秒(μs)単位で取得する関数です。
この関数は、内部のハードウェアタイマーのカウント値を読み取ることで動作します。delay() 関数とは異なり、プログラムの実行を停止させずに経過時間を取得できるため、ノンブロッキングな処理や、高速な時間制御を必要とする処理の実装において極めて重要な役割を果たします。

【仕様】

  • 戻り値: unsigned long(符号なし長整数)
  • 単位: マイクロ秒
  • 初期状態: ボードの起動時(電源ONまたはリセット)に 0 からカウントを開始。
  • データ型: 32ビットの符号なし整数として処理されます。

【技術的特徴】

  • 高分解能: millis() 関数(ミリ秒単位)よりも細かな時間スケールの管理を可能にします。
  • ハードウェアレベルの挙動:
    Arduinoの種類(AVR, ESP32, SAMD等)によって、背後のタイマー実装は異なります。しかし、基本的にはシステムクロックをベースとしたカウンタを読み取ります。
  • 比較(millis() との差異):
  • millis(): 比較的大きな時間間隔(秒単位以上)の管理に適しており、1ミリ秒単位の精度で十分なケースで使用します。
  • micros(): 高速な信号の計測、PWMのソフトウェア制御、またはミリ秒未満の精度を要する精密なタイミング制御に適します。

【注意点】

  • オーバーフロー(重要):
    32ビットの unsigned long を使用しているため、カウントは 約71.5分で最大値に達し、その後 0 に戻ります。このため、非常に長時間の経過時間を計算する場合は、オーバーフローを考慮した差分計算を行う必要があります。
  • 精度とジッタ:
    内部RC発振器を使用しているマイコンでは、温度変化によってクロック精度が変動する可能性があります。極めて高い時間精度を求める場合は、外部クリスタルを使用したボードの使用が推奨されます。
  • 割り込みの影響:
    micros() 自体はタイマーの現在の値を返すだけですが、割り込み処理が頻繁に発生する環境では、関数を呼び出した瞬間と実際のタイマーカウントの間に微小なジッタが生じる可能性があります。

【サンプルコード】

// micros() を使用したノンブロッキングのLED点滅と
// 経過時間の計測例
const int LED_PIN = 13;
unsigned long previousMicros = 0;
const unsigned long interval = 500000; // 500ms (500,000マイクロ秒)

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMicros = micros();

  // 前回の実行から指定した時間が経過したか判定
  if (currentMicros - previousMicros >= interval) {
    previousMicros = currentMicros;

    // LEDの状態を反転
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));

    // 実行タイミングをシリアル出力
    Serial.print("Toggle at: ");
    Serial.print(currentMicros);
    Serial.println(" us");
  }

  // ここに他の処理を記述することで、delay()を使わずに並行処理が可能
}

【活用例】

  • パルス幅の計測: 超音波センサーの反射波や、特定の通信プロトコルのビット長をマイクロ秒単位で正確に測定する。
  • PID制御のサンプリング周期管理: 高速な制御ループにおいて、一定のサンプリング周期を維持するための時間管理。
  • ソフトウェアPWM: ハードウェアPWMピンが不足している場合、micros() を利用して特定の周期で出力をON/OFFする処理の実装。
  • 非同期な状態マシン: delay() を排除し、特定のマイクロ秒間隔でイベントを発生させる状態遷移の実装。

コメント

タイトルとURLをコピーしました