ScilabのTIPS


  1. シミュレーションの設定
  2. 制御系の設計に役に立つ
    1. 伝達関数の定義
    2. 極,ゼロを求める.
    3. 極をs平面上に表示させる.
    4. ボード線図を書く,位相,ゲイン余裕を求める
  3. 状態フィードバック・オブザーバーの設計
  4. FFTしてみる
  5. XcosでC言語関数を定義


    

シミュレーションの設定

シミュレーション ー 設定 で,積分絶対許容誤差に気をつける.
例)High-Qの共振のシミュレーション
f = 10 kHzのシミュレーションで,
積分終了時間 0.1
実時間スケール 0
積分絶対許容誤差 1e-11
積分相対誤差 1e-7
時間の誤差 1e-10
最大積分時間間隔 2e-6
ソルバー Sundials/CVODE - BDF -NEWTON
とした場合,得られた振幅は,



のようになる. この場合は,共振のQが大きい場合をシミュレートしているので,振幅は時間と共に増大する.

積分絶対許容誤差を 1e-10にしてみると,



ほとんど同じ.(=許容誤差は結果に影響を与えないレベル)

積分絶対許容誤差を 1e-9にしてみると,

となり,振幅が小さくなる.
このくらいだと,誤差が結果に影響してしまう.

積分絶対許容誤差を 1e-8にしてみると,

もはや,振動の様子は大きく違ってくる.
原点付近を拡大すると,


となり,振動はしているが,ある振幅で落ち着いてしまっている.
(本来なら,振幅は増大しなければおかしい)

このように,一見何らかの結果は出てくるが,物理的にはおかしいので,注意が必要.


どのくらいの許容誤差にすればよいかは,今後考察する必要あり.

scilab/scicos ふぁいる




制御系の設計に役に立つ

伝達関数の定義

s = %s
とすることで,変数sを宣言する. (s1=%sとかでも良い)

g = 100
f1 = 100
f2 = 200

G =  1 / (1 + s * 10)
H =  g / ( (1 + s /f1) * (1 + s/f2) )

などとする.
上の例の場合,g, f1, f2などの値を変更した場合は,
H =  g / ( (1 + s /f1) * (1 + s/f2) )
をもう一度実行する必要がある.


極,ゼロを求める.

poles = roots( denom( G / (1 + G*H) ))
zeros = roots( numer( G / (1 + G*H) ))

などとする.

極をs平面上に表示させる.

function s_plot(G, win_num)
  zelos=roots(numer(G));
  poles=roots(denom(G));
 
  xset("window",win_num); clf();
  plot2d(real(poles), imag(poles), -2*ones(1,20),...
        axesflag=6,rect=[-300,-300,300,300],strf="011");
 
endfunction

のように,functionを定義して,

s_plot( G / (1 + G*H), 100)
などと呼び出す.

functionの中の, >>> axesflag=6,rect=[-300,-300,300,300],strf="011" <<<のあたりをいじると,プロット範囲などを変更できる.


ボード線図を書く,位相,ゲイン余裕を求める

xset("window", 100);
として,windowを定義する.

sys1 = syslin("c", G*H/(1+G*H))
として,系を定義する.

clf()
で画面を消去する.

bode(sys1,  0.1,  10e3)
として,ボード線図を書く.(第2,3引数は周波数範囲)

gm=g_margin(sys1)ControlTheory/%E5%88%B6%E5%BE%A1%E7%B3%BB%E3%81%AE%E8%A8%AD%E8%A8%88.odp
でゲイン余裕(-位相が180回るときの,ゲイン(db) )

pm=p_margin(sys1)
で移送余裕(180 - ゲインが1になる時の位相)

が求まる.


状態フィードバック・オブザーバーの設計

メモ



FFTしてみる

Xcos上ではFFTを直接実行するモジュールはなさそう.
なので,実行結果をScilabに持って行ってFFTする.

FFTしたい信号に "ToWorkspace"モジュールを接続する.
Size of bufferに保存する時刻数,variable nameに変数名を指定する.

Xcosでシミュレーションを実行する.

次に,Scilabで以下の関数を定義する.

function MyFFT(Variable)

val=Variable.values;
time=Variable.time;
dt=time(2)-time(1);
val_t=val';
N=size(val,'r');
freqs=1/dt*(0:N/2)/N;
n=size(freqs,"*");

scf(1);
clf(1);
plot(time, val);

scf(2);
clf(2);
fft_res=fft(val_t);
plot2d(freqs, abs(fft_res(1:n)));

endfunction

Scilabのコマンドで MyFFT( 変数名 )とすると,FFTの結果がWindowに表示される.
表示されるWindow番号は,Functionのscf(1), clf(1)あたりを変更することで変えられる.

XcosでC言語関数を定義

C block 2などを使う.

入力は block->inptr[i][j] などでえられる. iが入力ポート番号,jが(ベクトルなどの)要素のインデックス.
同様に出力は block->outptr[k][l]など.
イベント入力(赤い線のやつ)は,イベントがトリガーされるとblock->nevprtに何番目のイベント入力がトリガーされたかセットされる.
なので,toto_block_outputs()の中で,switchかifでblock->nevprtの値で場合分けすれば,各イベントによってトリガされる動作を記述できる.