リアルタイム制御

ジッタ

周期処理のばらつき。

概要

ジッタ(Jitter)は、周期的に実行されるべき処理(タスク・割り込み・信号等)の実際の実行タイミングが、理想的なタイミングからずれるばらつきのことです。「タイミングのゆらぎ」とも表現されます。

レイテンシが「要求から応答までの遅延時間」の絶対値であるのに対し、ジッタはその遅延時間の「ばらつき(変動)」を表します。制御工学の観点では、レイテンシが一定(ジッタがゼロ)であれば、その遅延分を制御モデルに組み込むことができます。しかしジッタが大きいと、制御系の安定性が低下します。

ジッタの定量的な表現:

  • ピーク・ツー・ピークジッタ: 最大値と最小値の差
  • RMSジッタ: 二乗平均平方根(統計的な標準偏差に相当)
  • 決定論的ジッタ: 繰り返しパターンを持つジッタ(EMIや電源ノイズ等に起因)
  • ランダムジッタ: 予測不能なジッタ

ハードリアルタイムシステムでは、最悪ケースのジッタを含めてデッドラインを満たすことが必要です。

歴史・背景

ジッタという概念はもともと電気通信分野で使われていました。ITU-T G.810(1996年)でジッタの定義が標準化されており、デジタル通信回線の品質指標として普及していました。

組み込み・リアルタイム分野でのジッタへの注目は、1990年代のモーション制御・サーボ制御の精度向上とともに高まりました。サーボモーターのPID制御において、制御周期のばらつきが位置誤差に直結することが認識されたためです。

2000年代のフィールドバス(EtherCAT、PROFINET IRT等)では、μs単位のジッタ管理が産業標準として求められるようになりました。EtherCATの分散クロック(DC)機能は、ネットワーク上の複数デバイスの同期精度を1μs以内に抑える仕組みです。

技術仕様

ジッタの発生原因

原因ジッタ量の目安対策
RTOSのTick割り込みタイミング0〜Tick周期(最悪1ms)vTaskDelayUntil()使用
高優先度タスク/ISRによる横取り数μs〜数十μs優先度設計・WCET管理
割り込み禁止区間数μs〜数十μsクリティカルセクション最小化
キャッシュミス数クロック〜数十クロックコード/データをRAMに配置
DMAバス競合数クロック〜DMAバースト制限
電源ノイズ・クロックジッタppm〜数ns低ノイズ電源・水晶発振器
Linuxスケジューラ(非RT)数ms〜数十msPREEMPT_RT適用

許容ジッタの目安

用途許容ジッタ(ピーク・ツー・ピーク)
産業サーボ制御(高精度)±1μs以内
EtherCAT分散クロック±1μs
CNCマシン制御±10μs以内
一般的な組み込みリアルタイム制御±100μs以内
モーター制御(一般産業用)±1ms以内
音声処理バッファ周期±1ms程度
IoTセンサ送信周期数ms〜数秒(許容範囲が広い)

クロックジッタ(発振器の精度)

マイコンのクロック源によるジッタ:

クロック源精度周波数精度
内部RC発振器(HSI)±1〜2%(温度依存)低(数十kHz程度のジッタ)
外部水晶発振器(HSE)±20〜100ppm高(数Hzレベルのジッタ)
TCXO(温度補償)±0.5〜2ppm非常に高
OCXO(恒温槽付き)±0.01〜0.1ppm最高(通信機器・計測器)

タイマーの周期精度はクロック精度に直結します。精密な制御タイミングが必要な場合は外部水晶発振器(HSE)を使用します。

動作原理

ジッタの発生メカニズム

vTaskDelay()を使った周期処理でジッタが発生する例:

/* ジッタが発生する(悪い)例 */
void periodicTask(void *pvParam) {
    for (;;) {
        uint32_t start = xTaskGetTickCount();
        do_processing(); /* 処理時間: 0.5〜3ms(変動あり) */

        /* 処理時間の分だけ次の開始が遅れる */
        vTaskDelay(pdMS_TO_TICKS(10)); /* 10ms後に起床 */
        /* 実際の周期 = 処理時間 + 10ms = 10.5〜13ms(最大3msのジッタ) */
    }
}
/* ジッタを抑制する(良い)例 */
void periodicTask(void *pvParam) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    const TickType_t xPeriod = pdMS_TO_TICKS(10);

    for (;;) {
        do_processing(); /* 処理時間: 0.5〜3ms(変動あり) */

        /* 処理時間に関わらず、前回起床から10ms後に起床 */
        vTaskDelayUntil(&xLastWakeTime, xPeriod);
        /* 実際の周期 ≈ 10ms(Tickジッタ分のみ残る) */
    }
}

vTaskDelayUntil()でのジッタ

vTaskDelayUntil()を使っても、RTOSのTick割り込みタイミングにより最大Tick周期分のジッタが残ります。Tick周波数1kHz(1ms Tick)の場合、最悪1msのジッタが生じます。

より低いジッタが必要な場合:

  1. Tick周波数を上げる: 10kHz Tick → 最悪0.1msジッタ(ただしオーバーヘッド増大)
  2. ハードウェアタイマで直接実行: ISRで処理または高優先度タスクを即座に起床
  3. ハードウェアタイマ + DMA: CPUを介さない定周期転送でジッタを最小化
/* ハードウェアタイマ割り込みによる高精度周期処理 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {
        /* タイマ割り込みで直接処理(ジッタ: 数百ns以内) */
        adc_raw = HAL_ADC_GetValue(&hadc1);
        pid_output = pid_update(adc_raw);
        set_pwm(pid_output);
        /* 処理時間がTick周期を超えてはならない点に注意 */
    }
}

ジッタの計測

/* タスク周期のジッタを計測するコード(FreeRTOS) */
TickType_t prev_tick = 0;
uint32_t max_jitter_us = 0;
const uint32_t PERIOD_US = 10000; /* 10ms */

void periodicTask(void *pvParam) {
    TickType_t xLastWakeTime = xTaskGetTickCount();
    const TickType_t xPeriod = pdMS_TO_TICKS(10);

    for (;;) {
        /* DWTカウンタで高精度時刻を取得 */
        uint32_t now_cycles = DWT->CYCCNT;
        uint32_t elapsed_us = (now_cycles - prev_cycles) / (SystemCoreClock / 1000000);
        prev_cycles = now_cycles;

        /* ジッタ = 実際の周期 - 理想周期 */
        int32_t jitter = (int32_t)elapsed_us - PERIOD_US;
        if (abs(jitter) > max_jitter_us) {
            max_jitter_us = abs(jitter);
        }

        do_processing();
        vTaskDelayUntil(&xLastWakeTime, xPeriod);
    }
}

用途・ユースケース

精密モーション制御

サーボドライバのPID制御で制御周期にジッタがあると、速度推定・位置補間の精度が低下します。

位置誤差 = 速度 × ジッタ
例:モーター速度 = 1000rpm = 100mm/s
   制御周期ジッタ ±100μs
   位置誤差 = 100mm/s × 0.1ms = 0.01mm(10μm)

高精度CNCマシン(加工精度1μm要求)では、ジッタを±1μs以内に抑える必要があります。

デジタル通信

  • UART: ボーレートのタイミングジッタが過大だと通信エラーが増加(スタートビット検出ずれ)
  • I2S(オーディオ): クロックジッタがオーディオのTHD+N(高調波歪み)に影響。プロ用途では100ps以下のジッタが求められる
  • SPI: マスタークロックのジッタはスレーブデバイスのサンプリングタイミングに影響

ネットワーク時刻同期

  • NTP: インターネット経由では数ms〜数十msのジッタが生じる
  • PTP(IEEE 1588): ハードウェアタイムスタンプを使い、サブμsのジッタで時刻同期
  • gPTP(IEEE 802.1AS): 車載・産業Ethernetでの高精度時刻同期(ジッタ数百ns以内)

実装・開発のポイント

ジッタ低減の設計原則

  1. vTaskDelayUntil()の使用: vTaskDelay()の代わりに使用してジッタを抑制
  2. 高優先度タスクのWCET管理: 制御タスクより高優先度のタスクがないことを確認、あるいはWCETが小さいことを保証
  3. 割り込み禁止時間の最小化: 長い割り込み禁止はジッタの主要原因
  4. Tick周波数の適切な設定: 要求ジッタよりTick周期を十分短くする
  5. タイマ直接駆動(最高精度要求時): RTOSのTick依存をなくしてハードウェアタイマで直接処理

ジッタ計測ツール

  • ロジックアナライザ: GPIOをトグルしてタスク実行タイミングを外部から計測
  • cyclictest(Linux): RTスレッドのウェイクアップレイテンシのヒストグラムを取得
  • オシロスコープ: クロック・PWM信号のジッタをジッタ計測モードで表示(統計的解析)
  • FreeRTOS Run-time Statistics: タスクごとのCPU使用時間の統計
# Linux: cyclictest でジッタを計測してヒストグラム生成
cyclictest -l 1000000 -m -n -p 90 -i 1000 -h 1000 --histofall > hist.txt
# gnuplot でヒストグラムを可視化

他技術との比較

観点ベアメタル(タイマISR)FreeRTOS(vTaskDelayUntil)標準LinuxPREEMPT_RT Linux
典型的なジッタ数百ns〜数μs数μs〜Tick周期(最悪1ms)数ms〜数十ms数十μs〜数百μs
ジッタの原因ISRレイテンシ・DMA競合Tick精度・高優先タスクカーネルスケジューラRTスレッド競合
対策難易度低(ハードウェア直接制御)中(優先度設計)難(カーネルパッチ必要)

レイテンシとジッタはリアルタイム制御の双璧です。デッドライン設計ではWCET(最悪実行時間)に最悪ジッタを加えたものが最悪レスポンスタイムとなります。この値がデッドライン以内に収まることをスケジューラビリティ解析で事前に検証することが、信頼性の高いリアルタイムシステム設計の基本です。

関連用語

参考リンク