4コマ(6時間)で制御工学を履修していない学生さんに倒立振子を制御してもらうという大変責任重大な学生実験の担当を拝命しました.
引き継いだ実験装置もあったのですが,20年前のPC-9801で動いており,たまにエラーが出る状況だったので,学生実験に最適化したシステムに入れ替えようと思い立ち,マイコンは Arduino,機械部分はレゴというちょっと変わった構成で倒立振子を製作しました.
実験装置の外観 |
予備機製作の際のマニュアルも必要ですし,製作に必要な情報を徐々にブログにまとめていこうかと思います.第一回はこの実験装置の設計で特徴的なところをまとめ,大雑把な設計意図について説明します.
モータは電流入力
小型の実験機だとモータはPWMな電圧を印加することで駆動されている場合が多いと思います.ただ制御するだけならPWMのデューティー比を制御入力としておけば概ね問題ありません.しかし,学生実験の前半ではモータの位置決め制御の実験を通して制御理論の基礎を学んでもらわなければならないので,理論的な扱いが簡単になるようにモータに電流が印加できる状態にしておきます.
簡単になる理由は大きく2つあって
- 入力が電流,角度が出力であれば2次系のモデルが使えるのに対して,電圧を入力とすると3次系になってしまう.
- モータ(とギア)には無視できない非線形摩擦があり,電流入力の方が対処が簡単になる.
といったことです.
2について補足すると,非線形摩擦はトルクに静的に加わる外乱としてそこそこモデル化できます.電流を入力とした場合,電流と発生トルクが線形の関係を持つので,モータを含んだシステムのモデルは
のようになります.これは Hammerstein モデルと呼ばれるもので,小難しい理論を使うまでもなく入力を $\fbox{非線形静的システム}$の逆特性で補正することで非線形性をかなり相殺できます.
(学生実験で相殺する過程を実習してもらうか,相殺する処理を予め組み込んでしまうかは悩ましいですが・・・)
一方,電圧を入力とした場合モデルの構造は
のようになり,非線形システムを線形システムでサンドイッチした構造になっています.この場合入力と出力のデータから具体的なモデルを構築することは大変難しく,非線形性を打ち消すことも容易ではありません.そういうわけで,モータを電流入力にすることにしました.
$\mbox{入力}\rightarrow\fbox{非線形静的システム}\rightarrow\fbox{線形動的システム}\rightarrow\mbox{出力}$
(学生実験で相殺する過程を実習してもらうか,相殺する処理を予め組み込んでしまうかは悩ましいですが・・・)
一方,電圧を入力とした場合モデルの構造は
$\mbox{入力} \rightarrow\fbox{線形動的システム}\rightarrow\fbox{非線形静的システム}\rightarrow\fbox{線形動的システム}\rightarrow\mbox{出力}$
のようになり,非線形システムを線形システムでサンドイッチした構造になっています.この場合入力と出力のデータから具体的なモデルを構築することは大変難しく,非線形性を打ち消すことも容易ではありません.そういうわけで,モータを電流入力にすることにしました.
機体はLEGO
実験機の機械部分はLEGOで作っています.理由はいくつかありますが
- 故障が少なく(机から落としてもバラバラになるだけで済むことが多い),交換による修理が容易.
- MINDSTORMS NXT に含まれるモータは簡易ながらもエンコーダを備えている.
といったところが大きいです.
コントローラはArduino
順当に行けばコントローラもMINDSTORMSのブロックですが,Arduinoにしました.主な理由は
- 電流センサを追加する必要がある.
- Arduinoの方が軽量.
- MINDSTORMSを使うと電池の用意が面倒.
- Arduino の方が安い.
- Arduino の開発環境のほうが初心者向け.
ちなみに学生のバックグラウンドは機械系で,プログラミングに不慣れなので,
#include "Pendulum.h" void setup() { initializePendulum(controlModeAccel); } void loop() { double theta,phi,dtheta,dphi,u; theta = getMotorAngle(); dtheta = getMotorVelocity(); phi = getBodyAngle(); dphi = getBodyAngularVelocity(); u = 8.193654e-01*theta + 1.010551e+00*dtheta + 2.556476e+02*phi + 3.504656e+01*dphi; setMotorAccel(u); }
という程度のプログラムで倒立を実現できるようにし,学生に見えている範囲は初心者でも理解できるようにしています.ArduinoのIDEは低機能にも程がある感じですが,理解できないコマンドが羅列されたメニューを見ながら作業するのも苦手意識に繋がりそうですし,いくら遊んでも壊れないおもちゃのような雰囲気があって丁度良いと思っています.
GUIでゲインだけ入力させたり,ブロックの組み合わせでプログラミングさせたりするパターンもありますが,計算機による制御器実装の本質を隠し過ぎている感がありますし,プログラム部分を完全に隠蔽してしまうことで苦手意識を定着させてしまいそうなので,このような形式にしました.ただ,
- 計算機の並列化がすすんでいる.
- プログラマブルロジックデバイス(FPGA等)によってハードウェアとソフトウェアの境界が曖昧になっている.
- プログラマブルロジックデバイスに対しても SystemC で設計したりする.
といった混沌とした現状を考えると,大学の制御の授業では実装形態に依存しない数学に徹するべきかなとも思います.
電源はUSBバスパワー
地味なようですが電源は重要です.今回の実験機ではかなり機能を割りきってUSBバスパワーで動く範囲で構成することにしました.その理由は
- PCで電源装置を兼ねることができる.
- 5Vに安定化されており,実験の再現性が高い
- スタンドアロンで動作させるときは入手性が良いモバイル機器用のUSB電源を使うことが出来る.
ちなみに上の写真では
を搭載していますが,3時間連続で倒立させても電池残量70%以上という十分な性能で,ラジコン用のリチウム電池等を流用するよりも安全面での配慮が優れているように思います.
モータは1つ
左右の車輪を独立に駆動することができれば前後左右に移動できて遊びとしては断然楽しくなるのですが,割りきって左右の車輪を同一のモータで駆動しています.理由は
- 電源が Max 1.5A なのでLEGOのモータを2つ駆動するのはキツそう.
- 徒に運動方程式の導出を複雑にしたくない.(運動方程式の導出は学生さんの課題になっているので,本質的でない複雑さで消耗して欲しくない)
- Arduino の Peripheral 的にエンコーダとモータを二個にするのが危うい.
といったことです.
まとめ
とりあえず,設計する時に気をつけた点を忘れないうちにまとめておきました.
設計のかなりの部分は電源をUSBに依存することと Arduino Due (cortex-M3を搭載した高性能Arduino) のリリースが間に合わないことが確定した時点でほぼ決まってしまったので,これらの前提が崩れれば大幅に設計を修正するべきかもしれません.
設計のかなりの部分は電源をUSBに依存することと Arduino Due (cortex-M3を搭載した高性能Arduino) のリリースが間に合わないことが確定した時点でほぼ決まってしまったので,これらの前提が崩れれば大幅に設計を修正するべきかもしれません.
以前超音波距離計による倒立振子を作ったが、
返信削除このレゴで倒立振子を見て再度挑戦してみようと考えているが。
スケッチの中で使われている"Pendulum.h"が
Webで拾えないのですが。どこにあるか教えていただけませんか。それとも丸田さんの自作ですか。
返事が遅くなってすみません.
返信削除Pendulum.h は自作のものです.
今のところ Arduino 開発環境本体に手を加えないと利用できないものになっているので,いずれ整理ができましたら公開するかも知れません.
期待して待っております。よろしく!!
返信削除こんにちは!
返信削除倒立振子を勉強し始めたものです。
Arduinoのコードで、モータへの電圧は theta, dtheta, phi, dphiに係数をかけて求められています。
これらの係数は、各種の物理パラメータから状態方程式を求め、極をおいて得たフィードバックゲインでしょうか。
差し支えなければ、計算に用いられた各種 物理パラメータと極を教えていただけないでしょうか。
よろしくお願いいたします。