大規模で予測不可能な異常を伴うPID制御ループ


10

短い質問
他の点では均一な制御領域内で非常に大きな異常(桁)を処理する一般的な方法はありますか?

背景
一般に均一な制御領域にわたってモーターを駆動する制御アルゴリズムに取り組んでいます。負荷がゼロまたは最小限の場合、PIDコントロールは適切に機能します(高速応答、オーバーシュートがほとんどない、またはまったくない)。私が遭遇している問題は、通常、少なくとも1つの高負荷の場所があることです。位置はインストール中にユーザーによって決定されるため、いつ/どこでそれを期待するかを知るための合理的な方法はありません。

高負荷の場所を処理するようにPIDを調整すると、非負荷領域に大きなオーバーシュートが発生します(これは完全に予想されていました)。移動途中でオーバーシュートしても問題ありませんが、エンクロージャーには機械的なハードストップはありません。ハードストップがないことは、大幅なオーバーシュートが発生すると、コントロールアームがモーターから切り離される可能性があることを意味します(デッドユニットが発生します)。

私がプロトタイピングしているもの

  • ネストされたPID(ターゲットから遠く離れている場合は非常にアグレッシブ、近くにある場合は控えめ)
  • 遠くはゲインを固定、近距離はPID
  • 保守的なPID(負荷なしで機能)+目標が達成されるか、または急速な変化率が検出されるまで(つまり、高負荷領域を離れるまで)、PIDを探して失速させ、追加のエネルギーを適用する外部制御

制限事項

  • 完全な旅行の定義
  • ハードストップは追加できません(現時点では)
  • エラーはおそらくゼロになりません
  • 高負荷は、10%未満の移動から得られた可能性があります(「実行開始」がないことを意味します)

回答:


2

微分項を使用する場合、誤差計算は誤差を累積しないようであり、微分項のみがプロセスの速い変化に反応できるため、これを変更することができます。

私がそれを正しく理解していれば、あなたのコード

// Determine the error delta
dE = abs(last_error - new_error);
last_error = new_error;

は常に現在のエラーに基づいて制御項を計算します。これは、PIDが実装された従来の方法です。とにかく蓄積されたエラーをI項で処理することになっているので問題ありません。

しかし、私はあなたが試してみたいかもしれない次のアイデアを思い付いた顧客がいました。より積極的な変更が必要なプロセス曲線の一部があるので、D部分のエラーでさえも累積させることができます。

if(TD)                                                 // Calculate D term
{  
   Last_C += (Error - Last_C) / TD;                    // D term simulates
   Dterm = (Error - Last_C) * KD;                      // capacitor discharging
}
else    
   Dterm = 0;                                          // D term is OFF (TD is 0)

ここで注目すべき2つの興味深い点があります。

  • TD値は微分ゲイン(KD)ではなく、微分時間であり、誤差が蓄積する時間を制御するユーザー定数です。ゼロに設定されている場合、PIDのD部分は、設定されたKDゲイン値に関係なく無効になります。

  • Dパーツの計算に引き継ぐ前に、Last_C値を「チャージ」するために現在のエラーがどのように使用されたかに注意してください。Last_C変数はコンデンサーのように機能し、エラーが大きいときに蓄積されるため、派生部分はエラーの最近の「履歴」に基づいて動作し、その後(エラーが小さい場合)この「履歴」 'コンデンサのように放電します。

もちろん、あなたがおそらくすでに行っている方法で総出力を制限する必要があります(アンチワインドアップリセット、バンプレス自動から手動転送、およびその他の通常のもの)。

私のPIDアルゴリズムの他の用語について、それが役立つとわかった場合は詳細を投稿できますが、これを試して何が起こるかを確認したい場合があります。それは何年もの間私の顧客によく役立ちました。


入力いただきありがとうございます。私はこれを試さなければならないでしょう。一見するとそれは理にかなっているようです。
アダムルイス

わかりましたので、「メイン」PID内にD項の寄与があり、ストール検出が計算にもたらすものは何でもあります。
Drazen Cika

1
そのとおりです。PIDのDtermが使用されますが、あまり積極的ではありませんが、チューニング中に使用されます。この問題をさらに困難にするのは、負荷が非常に短い時間で解放される可能性があることです。IEのリンクが解除されました。この力の突然の除去は、失速力に適用された平滑化関数(合計)がある場合に大きなオーバーシュートを引き起こします。
アダムルイス

邪悪な問題、いくつかのファジーロジックアルゴリズムがこれをどれだけうまく処理できるかを知ることは興味深いでしょう。少なくとも、標準的なソリューションの範囲内にとどまるのではなく、問題に関連する経験をアルゴリズムに組み込むことができます。とにかく、これで頑張ってください:-)
Drazen Cika

1

最初の解決策

stalled_pwm_output = PWM / | ΔE|

PWM =最大PWM値
ΔE= last_error-new_error

最初の関係は、モーターの変化ないことに基づいてPWM出力を正常にランプアップします。出力例については、下のグラフを参照してください。

このアプローチは、非アグレッシブなPIDが機能しなくなった状況に対応します。ただし、非アグレッシブなPIDがセットポイントを達成でき、速度を下げようとすると、stalled_pwm_outputが上昇するという不幸な(そして明らかな)問題があります。この上昇により、非負荷位置に移動するときに大きなオーバーシュートが発生します。

1 /ΔE対ΔE

現在のソリューション

理論

stalled_pwm_output =(kE * PID_PWM)/ | ΔE|

kE =スケーリング定数
PID_PWM =非
アグレッシブPIDからの現在のPWMリクエストΔE= last_error-new_error

現在の関係では1 /ΔEの概念を使用していますが、非積極的なPID PWM出力を使用してstall_pwm_outputを決定しています。これにより、PIDが目標設定点に近づき始めたときにPIDがstall_pwm_outputをスロットルバックできるようになりますが、ストールした場合は100%PWM出力が可能になります。スケーリング定数kEは、PWMが飽和点(下のグラフでは10,000以上)に入るようにするために必要です。

疑似コード

cal_stall_pwmからの結果が電流制御ロジックのPID PWM出力に追加されることに注意してください。

int calc_stall_pwm(int pid_pwm, int new_error)
{
    int ret = 0;
    int dE = 0;
    static int last_error = 0;
    const int kE = 1;

    // Allow the stall_control until the setpoint is achived
    if( FALSE == motor_has_reached_target())
    {
        // Determine the error delta
        dE = abs(last_error - new_error);
        last_error = new_error;

        // Protect from divide by zeros
        dE = (dE == 0) ? 1 : dE;

        // Determine the stall_pwm_output
        ret = (kE * pid_pwm) / dE;
    }

    return ret;
}

出力データ

ストールしたPWM出力 ストールしたPWM出力

停止したPWM出力のグラフでは、モーターが所定の時間内に位置に到達できなかったため、約3400での突然のPWM低下は、組み込まれた安全機能がアクティブになっていることに注意してください。

無負荷PWM出力 無負荷PWM出力


1

何を制御しているのかわからない...モーター速度?ポジション?まあそれが何であれ、最初のステップは許容できるエラーが何であるかを定義することです。たとえば、制御が速度用である場合、ターゲットの1%以内の最大誤差を設定できます。許容可能なエラーを定義しないと、ADCまたはPWMカウントに必要な分解能を決定できません。それがなければ、PID補償は完全である可能性がありますが、それでも制限サイクル振動があります。

次に、開ループシステムのダイナミクスを知る必要があります。これがないと、ループの比例(P)、積分(I)、微分(D)部分に必要なゲインを知ることができません。入力ステップ(ドライブレベルまたはPWMのステップ変化)、または負荷のステップ変化(これはあなたに関係しているようです)でダイナミックを測定できます。

制御アルゴリズムの分母にあるサイクル間エラーの変化を使用してPWM値を変更すると、ループが解決しないことが保証されます。これにより、制御のリミットサイクル発振が保証されます。ほとんどの顧客はそれに耐えません。

ループのP部分は、即時エラーを処理します(エラーに迅速に応答します)。ただし、有限のゲインがあるため、多少の誤差が残ります。ループのI部分は、時間の経過とともにゆっくりと反応して無限ゲイン(無限ゲインの無限時間)を適用し、Pパーツによって残されたエラーを修正します。

I部分は遅いので、適切なゲインを設定していても、エラーの最小化に必要な修正によって位相がずれることがあります。そのため、回復するのに長い時間がかかります。または、P部に対抗させておく。

ワインドアップを処理する最良の方法は、インテグレータに保存される最大値を、最悪の場合に比例誤差を補正するために必要な値よりも少しだけ多く制限することです。積分器の位相がずれ、Pの反対側にある場合は、積分器の値をゼロに設定するのが最善の方法です。アルゴはこれを検知し、必要に応じて積分器をリセットするように設計できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.