Arduinoを使用して電動フェーダー(リニアスライドポテンショメーター)を制御しようとしています。
PID制御は、特定のターゲット位置への「ジャンプ」に対して良い結果をもたらしますが、ランプの追跡は問題であり、まったくスムーズではありません。何をしようとしても、動きはとてもぎくしゃくしています。
ランプを追跡するときの基準位置、測定位置、モーター出力のプロットは次のとおりです。
そして、同じテストのビデオがあります。
商用システムでは、はるかにスムーズに見えます。これを参照してください。
詳細:
モーターフェーダーは、アルプスRSA0N11M9A0Kです。それを駆動するために、安定化された10 V DC電源(XL6009)から電力を供給されるST L293D Hブリッジを使用しています。
Arduino UNO(ATmega328P)では、ピン9と10を使用して、PWM周波数31.372 kHzで聞こえないようにします(プリスケーラが1のTimer1 )。
ポテンショメータはグランドと5Vの間に配線され、ワイパーは通常どおりADC0に接続されます。TCCR1B = (TCCR1B & 0b11111000) | 0b001
コントローラー:
アンチワインドアップ機能を備えたシンプルなPIDコントローラーを使用しています。これは、1 kHzのレート(Ts = 1e-3 s)で更新します。
float update(int16_t input) {
int16_t error = setpoint - input;
int16_t newIntegral = integral + error;
float output = k_p * error
+ k_i * newIntegral * Ts
+ k_d * (input - previousInput) / Ts;
if (output > maxOutput)
output = maxOutput;
else if (output < -maxOutput)
output = -maxOutput;
else
integral = newIntegral;
previousInput = input;
return output;
}
コントローラーの出力は-127〜127の値です。PWM出力は次のように生成されます。
const int8_t knee = 48;
uint8_t activation(int8_t val) {
if (val == 0)
return 0;
else {
return map(val, 0, 127, 2 * knee, 255);
}
}
void writeMotor(int8_t val) {
if (val >= 0) {
analogWrite(forward, activation(val));
digitalWrite(backward, 0);
} else {
analogWrite(backward, activation(-val));
digitalWrite(forward, 0);
}
}
モーターが31 kHzで動き始めるので、7ビットPWM信号に48を追加し、それを8ビット数にスケールアップします(analogWrite
関数が期待するものだからです):
試したこと:
入力、制御信号、PIDコントローラーの派生コンポーネントにEMAフィルターを追加しようとしましたが、役に立ちませんでした。また、ヒステリシスを使用して、静止時に2つの値の間で反転しないようにアナログ入力の解像度を下げてみました。これは何にも影響しないようです。タイムステップを10ミリ秒に増やしても効果はありません。
また、MATLABでシステム識別を試み、Simulinkでそれを調整しようとしました(このビデオシリーズに従って)。91%の適合のモデルを得ましたが、MATLABモデルの入力および出力の非線形性を処理する方法、それらがPIDチューニングにどのように影響するか、Arduinoに実装する方法がわかりませんでした。
私が最後に試したのは、2つの異なるコントローラーを作成することです。1つは基準位置での大きなジャンプ用で、もう1つはランプの追跡時の小さなエラー用です。これは少し助けになるようです。なぜなら、ジャンプするときにオーバーシュートを増やすことなく、追跡するときに積分係数を増やすことができるからです。
ただし、積分(および比例)ゲインを増加させることで、モーターは静止している必要があり、基準が変化しない場合でも、常に何かを実行しています。(実際には移動しませんが、振動を感じることができます。)
1e-4よりも高くすると、さらにジャーキーになるように見えるため、実質的に微分ゲインはありません。 1e-4。
私の推測では、静止摩擦を克服するにはより多くの力が必要であり、動的摩擦は小さいためオーバーシュートするため、モーターを後方に駆動して再び停止し、再び静止摩擦を克服しなければならず、再び前方に撃ちますなど
商用コントローラーはこの問題をどのように克服しますか?
私の経歴:
電気工学の3年生で、制御理論、デジタル信号処理、LQR制御などのコースを受講しているため、理論的な背景はありますが、これらすべての理論を適用するのに苦労していますこの現実のシステム。
編集:
laptop2dが推奨するように、開ループセンサー測定をテストしましたが、その結果に非常に驚いています:高PWM周波数では、読み取り値に不快なピークがあります。490 Hzでは、何もありません。
これは一定のデューティサイクルであるため、モーターが非常に高速で方向を反転しているときにどのようなノイズが発生するか想像できません。
そのため、コントローラーでの作業を再開する前に、そのノイズを除去する方法を見つける必要があります。
編集2:
指数移動平均フィルターを使用しても、ノイズを除去するのに十分ではありませんでした。
0.25、0.50、0.75でポールを試しました。小さなポールはあまり効果がなく、大きなポールはレイテンシーを追加しすぎたため、ゲインを下げて安定性を維持する必要があり、全体的なパフォーマンスが低下しました。
ポテンショメータ(ワイパーとグランドの間)に0.1 µFのコンデンサを追加しましたが、これできれいになったようです。
今のところ、それは十分に機能します。それまでは、ティムウェスコットが投稿した論文を読んでいます。
ご協力ありがとうございます。
This device is suitable for use in switching applications at frequencies up to 5 kHz.
しかし、3ページの電気的特性は、すべての遅延を加算した場合、690kHzの絶対最大値を示しています。(下の4行は)個人的に、私は遅くそれよりも多くのことをいいと思うが、私は31kHzが適切でなければならないこと...それは1ページのノートがなかった場合に思うだろう