![見出し画像](https://assets.st-note.com/production/uploads/images/131440556/rectangle_large_type_2_1e25d45d9ab198c873dd0f357ff19646.png?width=1200)
PLECS C-Script離散時間制御方法
パワーエレクトロニクス回路のシミュレーションでは、一周期の間に複雑なパルスを生成する場合などにおいて、Variable-stepによる連続時間シミュレーション中に離散時間制御が要求されるケースがあります。本記事では最も基本的なゲート信号生成を例に、離散時間に基づく波形生成についてその方法を説明します。
生成するモジュールは以下の通りです。離散時間を定めるメインクロックの周波数はユーザー変数で定義します。また、キャリア周波数、デューティサイクル、デッドタイムはユーザー変数で定義したのち、ConstantブロックからC-Scriptに入力変数として入力します。出力はキャリア、ハイサイド信号、ローサイド信号です。したがって、C-Scriptの入力引数は3,出力引数も3になります。
![](https://assets.st-note.com/img/1708364982083-c73k9MP9Uc.png?width=1200)
はじめに、次のようにユーザー変数を定義します。それぞれ上からメインクロック周波数、キャリア周波数、デューティレシオ、デッドタイムです。
![](https://assets.st-note.com/img/1708365465752-lyYFol8Eux.png)
C-Script初期設定
![](https://assets.st-note.com/img/1708366235260-LqGcku4rhb.png?width=1200)
離散時間で制御を行う場合、Sample Timeの設定に注意が必要です。Sample Timeが0あるいは[0, 0]の場合、C-Scriptは連続時間関数としてすべてのマイナータイムステップでその出力が評価されます。[-2, 0]の場合、離散時間変数基づくサンプル時間でスクリプトがコールされます。また、[$${T_\mathrm{p}, T_\mathrm{o}}$$]とした場合は離散時間$${nT_\mathrm{p}+T_\mathrm{o}}$$で周期的にスクリプトがコールされます。これらは組み合わせることが可能で、例えば$${[T_\mathrm{p}, 0 ; -2, 0]}$$とするとメインステップ$${T_\mathrm{p}}$$で周期的にコールしつつ、離散時間変数に基づくコールが追加で実行できます。これは例えば、PFCのTCMやCRMのような、セクターによってスイッチング周波数が変化するような対象に対して、Mains Periodを$${T_\mathrm{p}}$$に、スイッチングタイミングを離散時間変数で管理する場合に有効です。
今回は離散時間変数のみでの制御になるので、Sample Timeは[-2, 0]とします。また、離散時間変数をひとつ用いるのでNumber of disc. statesを1とします。ユーザー変数で定義したクロック周波数を、時間ステップとして読み込むためにparametersに1/fcを記述します。インプットおよびアウトプットは3信号ずつ定義します。
Code declarations
#include <float.h>
//#include <math.h>
//#include <stdio.h>
//#include <string.h>
#define TS ParamRealData(0,0)
#define freq InputSignal(0,0)
#define duty InputSignal(1,0)
#define deadtime InputSignal(2,0)
#define Carrier OutputSignal(0,0)
#define GateSignalH OutputSignal(1,0)
#define GateSignalL OutputSignal(2,0)
#define STATE DiscState(0)
#define T_EPS DBL_EPSILON
#define NEVER DBL_MAX
static int NEXT_STATE;
static int INC_FLAG;
まずは変数定義を行います。ユーザー変数で定義したfcは、C-Scriptのparameters領域に1/fcとして読み込まれています。この変数領域にアクセスするにはParamRealData()マクロが必要です。続いて入力、および出力変数を定義します。今回はすべて1要素のベクトルなので、個別にその要素を指定します。複数の要素を持つベクトルに対してOut(X) = OutputSignal(0,X)のような記述も可能です。
次に、離散時間変数STATEを定義します。この値は連続時間では変化せず、離散時間制御によってのみ変化するパラメータになります。T_EPS、NEVERはシミュレーションの最小時間および最大時間を表しており、float.hからインクルードされています。
最後に状態遷移のための変数NEXT_STATEと、キャリアの増加フラッグを表すINC_FLAGを定義してこのフィールドは終了です。
Start Function Code
STATE = 0;
NextSampleHit = T_EPS;
INC_FLAG = 1;
このフィールドは、シミュレーション開始時に一度だけコールされます。離散時間変数の初期化はこのフィールドで行う必要があります。また、NextSampleHitは次にスクリプトがコールされる時間を指定する変数です。Sample Timeを[-2, 0]として設定した場合、NextSampleHitをこのフィールドで有限の値に設定しないと、一度もスクリプトがコールされることなくシミュレーションが終了します。一度NextSampleHit時間後にコールされた後は、続くスクリプトの内容に従って順次コールされます。
Output Function Code
NextSampleHit = CurrentTime + TS; // Set Next Script Call Time
// Increment or Decrement according to INC_FLAG
if(INC_FLAG == 1){
if(NEXT_STATE == (int) 1/(2*freq*TS) - 1){
NEXT_STATE = (int)(STATE - 1);
INC_FLAG = 0;
}
NEXT_STATE = (int)(STATE + 1);
}else{
if(NEXT_STATE == 0 + 1){
NEXT_STATE = (int)(STATE - 1);
INC_FLAG = 1;
}
NEXT_STATE = (int)(STATE - 1);
}
// Output Carrier
Carrier = (int) STATE ;
// Output Gate Signal
if(STATE > (int) (duty*1/(2*freq*TS)) - deadtime/(2*TS)){
GateSignalH = 0;
}else{
GateSignalH = 1;
}
if(STATE > (int) (duty*1/(2*freq*TS)) + deadtime/(2*TS)){
GateSignalL = 1;
}else{
GateSignalL = 0;
}
Output FunctionはNextSampleHitに設定された時間に達するたびにコールされるので、ここで設定した値に基づいて次のコールタイミングが決定されます。CurrentTimeは現在時刻にアクセスするマクロで、上のコードでは常にTS秒毎にこの関数がコールされます。残りのコードでは三角波生成とデューティ指令値に基づくゲート信号生成が行われています。ここで離散変数であるSTATEの次の値をインクリメントorデクリメントに応じてNEXT_STATEに格納します。STATE自身の更新はここでは行われていないことに注意してください。
Update Function Code
STATE = NEXT_STATE;
Update FunctionはOutput Functionの評価がすべて終わったのちにコールされる関数で、離散時間変数の更新はこのフィールドで行います。したがって、先ほどセットした次の離散状態変数を、離散変数へ代入します。
シミュレーション実行結果
上で作成したC-Scriptを使って、適当にBuck動作をさせます。
![](https://assets.st-note.com/img/1708370430886-IHX8lHlWf9.png?width=1200)
![](https://assets.st-note.com/img/1708370571861-9Vls9BG9ni.png?width=1200)
![](https://assets.st-note.com/img/1708370607442-uUol84Bn2Y.png?width=1200)
シミュレーション結果より、適切にゲート信号の生成ができていることが分かります。また、スイッチング時の波形を拡大すると、離散時間に基づいてキャリアが生成されていることが分かります。
まとめ
PLCESのC-Scriptにおいて、離散時間変数の使い方を説明しました。今回の例はPWM+Delayブロックで容易に実装できるので有難みがあまりありませんが、ある周期内で時間ベースで計算されたスイッチングを行いたいときにこの離散時間制御は有用です。