2

PID フィードバックとポジショニングの両方を同時に実行するのに苦労しています。

RPMを計算する私の考えは次のとおりです。

  1. タイマーを開始し、割り込みを使用してエンコーダー パルスをカウントします。
  2. 簡単な計算を使用して RPM に変換します。
  3. 使用した変数をリセットして最初からやり直してください。

RPM を計算することはできますが、計算後にしか PID コントローラーを呼び出すことができません (ただし、適切な解像度が得られるまで待ちたいと思います)。これにより、非常に厄介なコードが作成されます。より簡単な方法または私が見逃しているものはありますか?

私のアプリケーションに関する情報: DC モーター/1 回転あたり ~600 パルス (ギアヘッド後) のデュアル磁気エンコーダーを備えた Atmel ATmega328P にプログラミングしています。GoToTarget(#) を呼び出して、PID パラメータを更新しながらモーターをその位置に移動させたいと考えています。さらに、双方向である必要があります。

4

1 に答える 1

7

速度計算タイマーと PID ループ タイマーは、別々ではなく、同じものにする必要があります。

パルス数を RPM の速度に変換する時間と分解能を無駄にしないでください。タイマーが正確に周期的であり、安定した PID である必要がある場合、パルス数は速度に正比例し、PID は単位を気にしません。係数の値によって調整できます。セットポイント速度を実際の単位にしたい場合は、その逆ではなく、PID 周期あたりのパルス数に変換してください。

ループは次のようになります。

for(;;)
{
    WaitTimer() ;
    pulses = pulse_count - previous_pulse_count ;
    previous_pulse_count = pulse_count ;
    control = pid( pulses ) ;
    motor( control ) ;
}

次に、パルスをカウントするための割り込みのみが必要です。計算を実行する必要はなく、カウンターをインクリメントするだけです。WaitTimer() の実装とこれがマルチスレッドかどうかによっては、おそらくタイマーの割り込みが必要です。

また、共有変数 pulse_count がアトミックでない場合は、読み取り中は割り込みを無効にする必要があり (関数でラップするのが最適です)、宣言する必要があることにも注意してvolatileください。

于 2013-06-22T06:25:29.783 に答える