PIDコントローラの基本とチュートリアル: ArduinoでのPID実装
工業制御に携わる人にとって、比例・積分・微分(PID)理論はおそらく馴染みのある概念でしょう。大多数の人にとってはまったくの未知の用語ですが、実はあなたは思っている以上にそれを理解しているかもしれません。車のアクセルを押すとき、理想の速度からどれだけ離れているかを考えるだけでなく、車の加速特性や丘のような条件も考慮に入れます。
工業制御に携わる人にとって、比例・積分・微分(PID)理論はおそらく馴染みのある概念でしょう。大多数の人にとってはまったくの未知の用語ですが、実はあなたは思っている以上にそれを理解しているかもしれません。車のアクセルを押すとき、理想の速度からどれだけ離れているかを考えるだけでなく、車の加速特性や丘のような条件も考慮に入れます。
これらのより微妙な効果が、IとDの項が数学的に考慮するものです。この例では、車の速度が上限と下限の間で変動するのを防ぎ、同じ概念をさまざまな制御状況に適用することができます。制限ベースの制御は大雑把にはうまくいくかもしれませんが、システムはやや不規則に動作する傾向があります。
PID方程式
PID制御は、次の方程式で数学的に表現できます。P、I、およびDは、ここで一緒に加算される3つの項で表されます。Kp、Ki、およびKdは、システムが各要因にどのように反応するかを調整する定数です:
また、KiとKdをそれぞれ1/TiとTdに置き換えることもできます。この変更により、方程式はその物理的意味との関係をより良くし、単位が適切に無次元数として機能するようになります。
また、方程式を変形してKp値を抽出し、標準形として知られる形式で全体の方程式に適用することもできます。この形式の利点の一つは、全体のKp定数を一度に調整できることです:
これは少し怖いかもしれません、エンジニアリングの学位を持っている人にとってさえ。良いニュースは、ここで何が起こっているのかを理解するために、動的システムのモデリングと分析の教科書を引っ張り出す必要がないということです。そして、決して悪いことではありませんが、微積分をすることができなくてもかまいません。
最初の方程式を分解すると、左側にある無次元のコントローラー出力u(t)を、等号の右側にある3つの数学的要素P、I、およびDを加算することで生成します。それぞれの要素の前には定数K値(Kp、Ki、Kd)があり、u(t)または特定の時点での制御出力を形成する際の各要素の重みを示しています。システムの性能を向上させるために、各K値を個別に調整することができ、以下で詳しく説明します:
比例(P—Kp)
この方程式で最初で最も重要な項はe(t)です。それに続くKpの値は、通常、他のK値よりも大きくなっています。ここで、e(t)は単にある時点での瞬間的な誤差であり、制御されたデバイスの実際の値から目標値を引いたものです。これをKpで掛けることで、全体のコントローラー出力に対する寄与が得られます。
積分(I—Ki)
この方程式の第2の項は、時間を通じた誤差の合計に関係しています。それは、デバイス上で経験したすべての誤差の合計です:
コントローラーが毎回u(t)を計算するとき、瞬間的な誤差を走らせている合計に加算します。
この値にKiを掛け、u(t)に加えます。
モーターの指定位置に戻ることを妨げる力がかかり、通常の条件下では戻れない状況を考えてみてください。仕様外にある時間が長くなるにつれ、I項は増加し続け、最終的にはこの力を克服するか、モーターの能力の限界に達します。
微分(D—Kd)
この方程式の第3の項は、誤差の変化速度に関係しています:
理論的には、この方程式にD項のみがあり、プロセスが誤った値を持続的に維持している場合、この項はゼロのまま適切な出力に寄与しません。一方、他の2つの項のいずれかがデバイスの出力をすばやく元に戻そうとすると、微分がその効果を抑制するのに役立つことがあります。
微積分に基づくこの概念の表現は役に立つかもしれませんが、現実のPID制御は一見ほど魔法のようではありません。実際には、誤差と読み取り間の時間を考慮に入れて、加算、減算、乗算のみを使用して出力を計算します。実際、PID制御の初期形態を実装するために、各「項」を入力するための機械的手段を使って空気力学のシステムを使用しました。
- コントローラーは瞬間的な誤差を読み取ります。
- 前の瞬間的な読み取り値をそれから引きます。
- その結果の値にKdを掛けて、u(t)への寄与を計算します。
Arduino PID コントローラー チュートリアル
多くの場合、専用のPIDコントローラをプロセスに接続するのが手軽ですが、Arduinoや類似の開発ボードを使って自作することも可能です。さらに、独自のPIDルーチンを作成することもできます。コード内では、各項を次のように表現できます:
- P:instanteneousError = setpoint – input;
- I:cumulativeError = += error * elapsedTime;
- D:rateOfError = (error – errorLastCalculation)/elapsedTime
必要な出力を得るには、これら各項に対応するK値を掛け合わせ、それらを合計します。一方で、車輪の再発明を避けたい場合は、Brett BeuregardのPIDライブラリを利用することもできます。このライブラリは細かな処理を代わりに行ってくれるため、P、I、Dの各定数の調整に集中することができます。
PID理論を実践するために、ツールボックスからArduino Nano Everyを取り出し、以下のものを用意しました:
- モータードライバーボード
- 赤外線センサー
- Hubsan H107Cドローンから取り出したモーター
私はモーター用のブレッドボードマウントと、光を50%の時間遮る「ファン」を印刷し、スピン中にパルスを逃さないようにしました。モータードライバーは(他には制御されていない)モーターへの入力であり、フィードバックはパルス間の時間に基づいています。
最終的に コードを完成 させ、3Dプリントした部品を手に入れた時には、モーターを定常的なPWM(パルス幅変調)出力で電源ボタンを操作するよりも洗練された方法で制御できるようになりました。
コードの注目すべき点には、遮断デバイスが回転する際に各パルスを登録するための割り込みルーチンを使用し、millis() を使用してパルス間の時間を計算することが含まれます。コードの最初の部分で関数外に PID を設定しました:
PID myPID (&difference, &driverOut, &setPoint,Kp,Ki,Kd, DIRECT)
Kp、Ki、Kd はコード内のこの行の前に定義されており、&difference は &driverOut を制御し、&setPoint はシリアルモニタによって変更されます。この数式を操作してこの時間差を RPM に変換することができますが、この特定のドライバは入力が低に引かれるとオンになるため、PID 設定は DIRECT 出力として機能します。アナログ出力が高くなると(モーターがオフ)、パルス間の遅延も増加します。
PIDルーチンの以前のバージョンです。CH1は入力パルスを読み取り、CH2はPIDルーチンを使用して計算された出力で、低いパルスはモーターへの入力です。
このシンプルなPIDコントローラーの例は、手持ちの部品(新しいArduino Nano Everyを含む)と、少しだけ知っているモーターで実行されました。しかし、私はPID制御を多様な状況で適用する方法を示すことができました。たとえすべての事実が揃っていなくても、モーター制御、オーブンの温度制御、またはロボットのバランスなど、少しのPID設定と調整で無限の実験オプションが得られます。
記事タグ