naokichiのブログ

しがないロボコニストの雑多なブログ

DCモータを回してみたい(制御編)

まえがき

ブラシ付きDCモータを回してみた(制御編)。とりあえず簡単な速度制御を行ってみました。制御器設計にはMATLAB/Simulinkを活用しました。

システム同定

ブラシ付きDCモータにおける、端子電圧から回転子の角速度への伝達関数は2次遅れ系。 モータのインダクタンスが非常に小さいとすると、1次遅れ系に近似できる。 今回はこの仮定の下に、ステップ応答を測定し曲線フィッティングにより1次遅れ系の時定数 Tとゲイン Kを求めました。

[システム同定の様子]

曲線フィッティングの様子。Excelのソルバーを使えばいい話ですが、イキリなのでPythonでやっている()。
脳筋システム同定()ですが、上手くいってしまうのでいつもこれでやってます()。

不感帯の測定

モータが起動する電圧を測定し、それ以下の電圧を不感帯としました。

シミュレーション(とゲインのチューニング)

Simulinkで遊んでいる瞬間が一番制を実感する!

Simulinkモデル

  • PID制御を用いました(今回は速度制御なので内部モデル原理によりPI制御)。
  • setMotorっていうのはデューティ比を千分率で表したものだと思ってください。
  • 左下のRampは入力をランプ状に変化させて台形加速させようとしたときのものです。
  • 上側の伝達関数は電流どれくらい流れるかな~と概算しようとしたものです。

(恐らく、多くの人を苦しめる)ゲインのチューニングですが、Control System Toolboxに入っているPID Tunerを使って行いました。

PID Tunerを使ってチューニングしている様子
判断基準:位相余裕85°近くあるしヨシ!(適当)
制御器の各種パラメータ

出来上がったSimulinkモデルの実行結果を以下に示します。

実行結果(ステップ入力のとき)
実行結果(ランプ入力のとき)

マイコンへ実装

上記の制御系をマイコンに実装します。今回はz領域で設計したのでオイラー法を用いました。以下はmain.cから抜粋。

/**
 * @brief PID制御器
 * @param input 入力値
 * @param target 目標値
 * @return 操作量
 */
float PID(float input, float target)
{
    const float K_p = 1.08717133443287f;
    const float K_i = 0.05749282f;
    const float K_d = 0.0f;

    static float error;
    static float ierror;
    static float derror;
    static float output;

    error = target - input;
    derror = error - derror;

    output = K_p * error + K_i * ierror + K_d * derror;

    ierror += error;
    derror = error;

    return output;
}

補足

マイコンで行っていることは、

  • ロータリーエンコーダの角度を読む
  • PID制御の計算
  • モータの駆動
  • メインの計算機(今回はマイPC)との通信

です。今回は全てLL APIを用いてみたのですが、ナイーブな実装でも1ステップあたり5usくらいで終わるようでした(コンパイラによる最適化は入れてるけどね)。以下に今回使用したSTM32CubeIDE用プロジェクトのリポジトリを載せました。 github.com

結果

[モータが回っている様子]

まぁ回りますよね()。本当はシミュレーションの結果と実際の応答とを比較検討するべきですが…メンドクサイのでやってない

あとがき

現代制御もやってみたい。最適レギュレータの設計とか面白そうだし。 www.mathworks.com ↑を見ると、LQRのほうが外乱特性が良いみたい。