前書き
この記事では永久磁石同期モータ(Permanent Magnet Synchronous Motor; PMSM)の電流制御シミュレーションを対象としたPMSMモータの制御系の設計を検討する。
PMSM駆動システムモデル
検討する永久磁石同期モータ(Permanent Magnet Synchronous Motor; PMSM)の制御は空間ベクトル理論を用いて、 PMSM をインバータによって駆動するシステムである。モータの負荷は定速度負荷とする。インバータは PWM Controller から受け取ったゲート信号にしたがって、必要な電圧を出力するように動作する。モータコントローラは、検出した$i_{u}$、$i_{v}$、$i_{w}$と$\theta_{m}$を用いて、電流フィードバック制御により PMSM を指令値に追従させるために必要なインバータ出力電圧指令値を出力する。PWMコントローラはこれらの指令値を実現するインバータのゲート信号を三角波比較法を用いて生成する。
PMSMの制御システム
ここでは古典的な比例積分(PI)制御を適用する。PMSMの電流フィードバック制御では、 dq 軸電流の干渉項と永久磁石による誘起電圧項をフィードフォワードすることによって補償する。上図は制御ブロック図であり、$i_{d}^{\ast}$、$i_{q}^{\ast}$、$v_{d}^{\ast}$、$v_{q}^{\ast}$は$i_{d}$、$i_{q}$、$v_{d}$、$v_{q}$の司令値である。上図の$i_{d}$、$i_{q}$、$\omega_{e}$はセンサなどにより検出する。司令値$v_{d}^{\ast}$、$v_{q}^{\ast}$は逆dq変換と逆クラーク変換により、$v_{u}^{\ast}$、$v_{v}^{\ast}$、$v_{w}^{\ast}$に変換して PWM Controller に転送する。
PMSM駆動システムのブロック線図
PMSMの数理モデルは前回の記事で示した。干渉項と誘起電圧項はフィードフォワードによって補償されるため、ブロック線図上では相殺されて無くなる。これらの項を無視して巻き線抵抗を$R$とすると、PMSMの入出力伝達関数は次式となる。
\begin{align} G_{dm} &= \frac{I_{d}}{V_{d}} = \frac{1}{R + s L_{d}} \\ G_{qm} &= \frac{I_{q}}{V_{q}} = \frac{1}{R + s L_{q}} \end{align}
dq 軸の伝達関数はどちらも1次遅れ系であるため、それぞれ同じ解析となる。したがって、ここではPMSMの伝達関数を次式として解析する。
\begin{equation} G_{m} = \frac{I_{dq}}{V_{dq}} = \frac{K_{m}}{1 + \tau_{m} s} \end{equation}
dq 軸の伝達関数に置き換えるときには下式を用いる。
\begin{equation} \begin{split} I_{dq} &= I_{d} \;\mathrm{or}\; I_{q} \\ V_{dq} &= V_{d} \;\mathrm{or}\; V_{q} \\ \tau_{m} &= \frac{L_{d}}{R} \;\mathrm{or}\; \frac{L_{q}}{R} \\ K_{m} &= \frac{1}{R} \end{split} \end{equation}
PI制御器の伝達関数$G_{c}$はゲイン$K_{c}$と時定数$\tau_{c}$を用いて次式で表される。$K_{c}$と$\tau_{c}$が設計変数である。
\begin{equation} G_{c} = K_{c} \left( 1 + \frac{1}{\tau_{c} s} \right) \end{equation}
よってシステムの閉ループ伝達関数$G$は次式で得られる。
\begin{equation} G = \frac{G_{c} G_{m}}{1 + G_{c} G_{m}} = \frac{K_{c} K_{m} \left(\tau_{c} s + 1\right)}{K_{c} K_{m} \left(\tau_{c} s + 1 \right) + \tau_{c} s \left(\tau_{m} s + 1 \right)} \label{eq:system_transfer_func} \end{equation}
ボード線図を用いた PI 制御系の設計
電流フィードバック制御による補償では、アプリケーションにもよるが、一般に応答速度が速く、電流の振動がないほうがよい。一方でインバータの出力電圧にはスイッチング周波数成分が重畳して電流波形をひずませるため、この周波数成分を減衰させるシステムとすることが求められる。
2次遅れと1次進み伝達関数による設計
\eqref{eq:system_transfer_func}を展開して整理することで次式を得る。
\begin{equation} G = \left( \tau_{c} s + 1 \right) \left( \frac{K_{c} K_{m} / \left( \tau_{c} \tau_{m}\right) }{s^{2} + \left( K_{c} K_{m} + 1 \right) / \tau_{m} s + K_{c} K_{m} / \left( \tau_{c} \tau_{m} \right) } \right) \end{equation}
上式は伝達関数$G$が1次進み系と2次遅れ系の伝達関数の積であることを示す。これらの1次進み系と2次遅れ系の伝達関数をそれぞれ$G_{1\_lead}$、$G_{2\_lag}$とする。
\begin{align} G_{1\_lead} &= \tau_{c} s + 1 \\ G_{2\_lag} &= \frac{K_{c} K_{m} / \left( \tau_{c} \tau_{m}\right) }{s^{2} + \left( K_{c} K_{m} + 1 \right) / \tau_{m} s + K_{c} K_{m} / \left( \tau_{c} \tau_{m} \right) } \end{align}
$G_{1\_lead}$はPI制御器の時定数$\tau_{c}$だけでシンプルに設計される。一方で$G_{2\_lag}$は下式のように減衰係数$\zeta_{2\_lag}$と共振周波数$\omega_{c2\_lag}$に置き換えて設計される。つまり、$K_{c}$と$\tau_{c}$の2変数を適切に設定して、必要な$G_{1\_lead}$の時定数と$G_{2\_lag}$の$\zeta_{2\_lag}$、$\omega_{2\_lag}$とする必要がある。
\begin{align} G_{2\_lag} &= \frac{\omega^{2}_{2\_lag}}{s^{2} + 2 \zeta_{2\_lag} \omega_{2\_lag} s + \omega^{2}_{2\_lag}} \\ 2 \zeta_{2\_lag} \omega_{2\_lag} &= \frac{K_{c} K_{m} + 1}{\tau_{m}} \\ \omega^{2}_{2\_lag} &= \frac{K_{c} K_{m}}{\tau_{c} \tau_{m}} \end{align}
伝達関数$G$、$G_{1\_lead}$、$G_{2\_lag}$のボード線図の概形を下記に示す。これらのボード線図の詳細については制御理論を参照していただき、ここでは簡単な特徴のみ記述する。伝達関数$G$の大きさ$|G|$は、dBで考えると、$G_{1\_lead}$の大きさ$|G_{1\_lead}|$と$G_{2\_lag}$の大きさ$|G_{2\_lag}|$の和である。$|G_{1\_lead}|$は$\omega = \omega_{1\_lead}$以上で20dB/dec. で変化する。一方で、$|G_{2\_lag}|$は$\omega = \omega_{2\_lag}$以上で-40dB/dec. で変化する。低周波領域で$|G_{1\_lead}|$による増幅を避けるためには$\omega_{2\_lag} < \omega_{1\_lead}$とする必要がある。このとき$|G|$は-40dB/dec. と-20dB/dec. で変化する区間を持ち、それぞれの領域をPI制御器のパラメータ$K_{c}$と$\tau_{c}$によって調節する。
零極相殺による設計方法
この制御系は零極相殺により、より簡単に設計することが可能である。\eqref{eq:system_transfer_func}より、$\tau_{c} = \tau_{m}$となるように設計すると、$G$は明らかに$s = - 1 / \tau_{m} < 0$の安定な極とゼロ点をもち、これらが約分されて、1次のシステムとなる。よって、このときのシステムの伝達関数$G_{1\_lag}$は次式となる。
\begin{equation} G_{1\_lag} = \frac{1}{1 + \frac{1}{K_{c}} \frac{\tau_{m}}{K_{m}} s } \label{eq:system_1st_transfer_func} \end{equation}
\eqref{eq:system_transfer_func}と\eqref{eq:system_1st_transfer_func}を比較すると、零極相殺により、伝達関数が1次遅れ系となるとともに、設計変数が$K_{c}$だけとなり、システムの設計が簡単になる。\eqref{eq:system_1st_transfer_func}の1次遅れ系のカットオフ角周波数$\omega_{1\_lag}$は次式で表される。
\begin{equation} \omega_{1\_lag} = \frac{K_{c} K_{m}}{\tau_{m}} \end{equation}
このとき\eqref{eq:system_1st_transfer_func}のボード線図の概形は下図となる。
さて、インバータの出力電圧にはスイッチング周波数成分が重畳して電流波形をひずませるため、この周波数成分を減衰させるシステムとする必要がある。よって、スイッチング角周波数$\omega_{sw}$をどれくらい減衰させるかによって$\omega_{1\_lag}$を決定することができる。例えば$\omega_{sw}$を-20dBとするためには$\omega_{1\_lag} = \omega_{sw} / 10$とすればよい。ただし低い$\omega_{1\_lag}$ほど、システムの応答は遅くなる。シミュレーション
OpenModelica を用いた PMSM のシミュレーションにより、制御系の設計による効果を確認する。シミュレーションに用いたModelicaモデルを下記に示す。シミュレーションではスイッチング周波数$f_{sw} = 10 \mathrm{ kHz}$であり、三角波比較では、搬送波をこの2倍の周波数でゼロ次ホールドした波形と三角波を比較する。
model PMSM_model_20230907 parameter Modelica.Electrical.Machines.Utilities.ParameterRecords.SM_PermanentMagnetData smpmData(useDamperCage = true) annotation( Placement(visible = true, transformation(origin = {0, 0}, extent = {{240, 10}, {260, 30}}, rotation = 0))); Modelica.Blocks.Math.Gain gain_Phi(k = sqrt(3)*smpmData.VsOpenCircuit/(2*Modelica.Constants.pi*smpmData.fsNominal)) annotation( Placement(visible = true, transformation(origin = {150, -340}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.MathBoolean.Not not_w annotation( Placement(visible = true, transformation(origin = {40, 16}, extent = {{4, -4}, {-4, 4}}, rotation = -90))); Modelica.Blocks.Math.Gain gain_half(k = 0.5) annotation( Placement(visible = true, transformation(origin = {-70, -350}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Continuous.PI pi_q(T = (smpmData.Lmq)/(smpmData.Rs), k = 2*Modelica.Constants.pi*5e2*(smpmData.Lmq)) annotation( Placement(visible = true, transformation(origin = {150, -280}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Math.Add add_d(k2 = -1) annotation( Placement(visible = true, transformation(origin = {50, -266}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Math.Add add_q2 annotation( Placement(visible = true, transformation(origin = {90, -316}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_pw annotation( Placement(visible = true, transformation(origin = {0, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_nu annotation( Placement(visible = true, transformation(origin = {-120, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Blocks.Continuous.Der der_theta annotation( Placement(visible = true, transformation(origin = {210, -320}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Machines.BasicMachines.SynchronousMachines.SM_PermanentMagnet smpm(Jr = smpmData.Jr, Js = smpmData.Js, Lmd = smpmData.Lmd, Lmq = smpmData.Lmq, Lrsigmad = smpmData.Lrsigmad, Lrsigmaq = smpmData.Lrsigmaq, Lssigma = smpmData.Lssigma, Lszero = smpmData.Lszero, Rrd = smpmData.Rrd, Rrq = smpmData.Rrq, Rs = smpmData.Rs, TrOperational = 293.15, TrRef = smpmData.TrRef, TsOperational = 293.15, TsRef = smpmData.TsRef, VsOpenCircuit = smpmData.VsOpenCircuit, alpha20r = smpmData.alpha20r, alpha20s = smpmData.alpha20s, frictionParameters = smpmData.frictionParameters, fsNominal = smpmData.fsNominal, p = smpmData.p, permanentMagnetLossParameters = smpmData.permanentMagnetLossParameters, phiMechanical(displayUnit = "rad", fixed = true), statorCoreParameters = smpmData.statorCoreParameters, strayLoadParameters = smpmData.strayLoadParameters, useDamperCage = smpmData.useDamperCage, wMechanical(displayUnit = "rad/s", fixed = false)) annotation( Placement(visible = true, transformation(origin = {0, 0}, extent = {{200, -50}, {220, -30}}, rotation = 0))); Modelica.Blocks.Sources.Constant zero_voltage_ref(k = 0) annotation( Placement(visible = true, transformation(origin = {-30, -240}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_pv annotation( Placement(visible = true, transformation(origin = {-60, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Blocks.Logical.Greater greater_u annotation( Placement(visible = true, transformation(origin = {-80, -90}, extent = {{-10, 10}, {10, -10}}, rotation = 90))); Modelica.Blocks.Sources.Trapezoid triangle(amplitude = 2, falling(displayUnit = "us") = 5.000000000000003e-05, offset = -1, period(displayUnit = "us") = 0.0001000000000000001, rising(displayUnit = "us") = 5.000000000000003e-05, width(displayUnit = "us") = 0) annotation( Placement(visible = true, transformation(origin = {-130, -140}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Math.MatrixGain InvParkConvGain(K = [sqrt(2/3), 0, 0; 0, sqrt(2/3), 0; 0, 0, sqrt(2/3)]) annotation( Placement(visible = true, transformation(origin = {-90, -250}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); Modelica.Electrical.Polyphase.Basic.PlugToPin_p plugToPin(k = 1) annotation( Placement(visible = true, transformation(origin = {70, 30}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Blocks.Math.Division div_Vdc_d annotation( Placement(visible = true, transformation(origin = {10, -272}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Math.Add add_q annotation( Placement(visible = true, transformation(origin = {50, -310}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.MathBoolean.Not not_u annotation( Placement(visible = true, transformation(origin = {-80, 16}, extent = {{4, -4}, {-4, 4}}, rotation = -90))); Modelica.Blocks.Math.Feedback feedback_q annotation( Placement(visible = true, transformation(origin = {210, -280}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Blocks.Math.Product product_id_omega annotation( Placement(visible = true, transformation(origin = {150, -310}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Mechanics.Rotational.Sensors.AngleSensor angleSensor annotation( Placement(visible = true, transformation(origin = {226, -70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Machines.SpacePhasors.Blocks.ToSpacePhasor toSpacePhasor annotation( Placement(visible = true, transformation(origin = {130, -30}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Blocks.Math.Gain gain_Ld(k = smpmData.Lmd) annotation( Placement(visible = true, transformation(origin = {122, -310}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Sources.Constant const_ref_d_current(k = 0) annotation( Placement(visible = true, transformation(origin = {250, -260}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_nw annotation( Placement(visible = true, transformation(origin = {0, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Mechanics.Rotational.Sources.ConstantSpeed constantSpeed(w_fixed = 2*Modelica.Constants.pi*20) annotation( Placement(visible = true, transformation(origin = {270, -40}, extent = {{-10, 10}, {10, -10}}, rotation = 180))); Modelica.Blocks.MathBoolean.Not not_v annotation( Placement(visible = true, transformation(origin = {-20, 16}, extent = {{4, -4}, {-4, 4}}, rotation = -90))); Modelica.Blocks.Sources.Constant const_ref_q_current(k = 30) annotation( Placement(visible = true, transformation(origin = {290, -280}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Logical.Greater greater_v annotation( Placement(visible = true, transformation(origin = {-20, -90}, extent = {{-10, 10}, {10, -10}}, rotation = 90))); Modelica.Blocks.Math.Feedback feedback_d annotation( Placement(visible = true, transformation(origin = {190, -260}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Electrical.Polyphase.Basic.PlugToPin_p plugToPin_p(k = 2) annotation( Placement(visible = true, transformation(origin = {70, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Electrical.Polyphase.Basic.Star star annotation( Placement(visible = true, transformation(origin = {170, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Blocks.Math.Division div_Vdc_q annotation( Placement(visible = true, transformation(origin = {10, -316}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Polyphase.Sensors.CurrentSensor currentSensor annotation( Placement(visible = true, transformation(origin = {130, 0}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Logical.Greater greater_w annotation( Placement(visible = true, transformation(origin = {40, -90}, extent = {{-10, 10}, {10, -10}}, rotation = 90))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_nv annotation( Placement(visible = true, transformation(origin = {-60, -50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Analog.Ideal.IdealOpeningSwitch idealOpenSW_pu annotation( Placement(visible = true, transformation(origin = {-120, 50}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Machines.SpacePhasors.Blocks.Rotator inv_rotator annotation( Placement(visible = true, transformation(origin = {-30, -280}, extent = {{-10, 10}, {10, -10}}, rotation = 180))); Modelica.Electrical.Machines.SpacePhasors.Blocks.FromSpacePhasor fromSpacePhasor annotation( Placement(visible = true, transformation(origin = {-70, -280}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Electrical.Analog.Basic.Ground ground annotation( Placement(visible = true, transformation(origin = {-60, -76}, extent = {{-10, -10}, {10, 10}}, rotation = 0))); Modelica.Blocks.Math.Gain gain_minus1(k = -1) annotation( Placement(visible = true, transformation(origin = {50, -390}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Electrical.Analog.Sensors.VoltageSensor voltageSensor annotation( Placement(visible = true, transformation(origin = {-150, 0}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); Modelica.Electrical.Machines.SpacePhasors.Blocks.Rotator rotator annotation( Placement(visible = true, transformation(origin = {130, -210}, extent = {{-10, 10}, {10, -10}}, rotation = -90))); Modelica.Blocks.Math.Product product_iq_omega annotation( Placement(visible = true, transformation(origin = {150, -370}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Math.MatrixGain ParkConvGain(K = [sqrt(3/2), 0; 0, sqrt(3/2)]) annotation( Placement(visible = true, transformation(origin = {130, -70}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Analog.Sources.ConstantVoltage constantVoltage(V = 282) annotation( Placement(visible = true, transformation(origin = {-180, 0}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Electrical.Polyphase.Basic.PlugToPin_p plugToPin_p1(k = 3) annotation( Placement(visible = true, transformation(origin = {70, -30}, extent = {{-10, -10}, {10, 10}}, rotation = 180))); Modelica.Blocks.Math.Gain gain_pole_pair(k = smpmData.p) annotation( Placement(visible = true, transformation(origin = {226, -208}, extent = {{-10, -10}, {10, 10}}, rotation = -90))); Modelica.Blocks.Math.Gain gain_Lq(k = smpmData.Lmq) annotation( Placement(visible = true, transformation(origin = {90, -370}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Continuous.PI pi_d(T = (smpmData.Lmd)/(smpmData.Rs), k = 2*Modelica.Constants.pi*5e2*(smpmData.Lmd)) annotation( Placement(visible = true, transformation(origin = {110, -260}, extent = {{10, -10}, {-10, 10}}, rotation = 0))); Modelica.Blocks.Discrete.ZeroOrderHold zeroOrderHold(samplePeriod = triangle.period) annotation( Placement(visible = true, transformation(origin = {-80, -170}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); Modelica.Blocks.Discrete.ZeroOrderHold zeroOrderHold1(samplePeriod = triangle.period) annotation( Placement(visible = true, transformation(origin = {-20, -170}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); Modelica.Blocks.Discrete.ZeroOrderHold zeroOrderHold2(samplePeriod = triangle.period) annotation( Placement(visible = true, transformation(origin = {40, -170}, extent = {{-10, -10}, {10, 10}}, rotation = 90))); equation connect(der_theta.y, gain_Phi.u) annotation( Line(points = {{199, -320}, {180, -320}, {180, -340}, {162, -340}}, color = {0, 0, 127})); connect(plugToPin_p1.plug_p, currentSensor.plug_p) annotation( Line(points = {{72, -30}, {80, -30}, {80, 0}, {120, 0}}, color = {0, 0, 255})); connect(idealOpenSW_nu.n, idealOpenSW_nv.n) annotation( Line(points = {{-120, -60}, {-60, -60}}, color = {0, 0, 255})); connect(greater_w.y, idealOpenSW_nw.control) annotation( Line(points = {{40, -78}, {40, -50}, {12, -50}}, color = {255, 0, 255})); connect(plugToPin.plug_p, currentSensor.plug_p) annotation( Line(points = {{72, 30}, {80, 30}, {80, 0}, {120, 0}}, color = {0, 0, 255})); connect(idealOpenSW_pu.p, idealOpenSW_pv.p) annotation( Line(points = {{-120, 60}, {-60, 60}}, color = {0, 0, 255})); connect(constantVoltage.p, idealOpenSW_pu.p) annotation( Line(points = {{-180, 10}, {-180, 60}, {-120, 60}}, color = {0, 0, 255})); connect(add_q.y, div_Vdc_q.u1) annotation( Line(points = {{39, -310}, {22, -310}}, color = {0, 0, 127})); connect(plugToPin_p.pin_p, idealOpenSW_pv.n) annotation( Line(points = {{68, 0}, {-60, 0}, {-60, 40}}, color = {0, 0, 255})); connect(der_theta.y, product_id_omega.u2) annotation( Line(points = {{199, -320}, {180, -320}, {180, -316}, {162, -316}}, color = {0, 0, 127})); connect(gain_minus1.y, inv_rotator.angle) annotation( Line(points = {{39, -390}, {-30, -390}, {-30, -292}}, color = {0, 0, 127})); connect(der_theta.y, product_iq_omega.u2) annotation( Line(points = {{199, -320}, {180, -320}, {180, -376}, {162, -376}}, color = {0, 0, 127})); connect(smpm.flange, angleSensor.flange) annotation( Line(points = {{220, -40}, {226, -40}, {226, -60}})); connect(gain_half.y, div_Vdc_d.u2) annotation( Line(points = {{-59, -350}, {32, -350}, {32, -278}, {22, -278}}, color = {0, 0, 127})); connect(idealOpenSW_pw.n, idealOpenSW_nw.p) annotation( Line(points = {{0, 40}, {0, -40}}, color = {0, 0, 255})); connect(plugToPin_p.plug_p, currentSensor.plug_p) annotation( Line(points = {{72, 0}, {120, 0}}, color = {0, 0, 255})); connect(smpm.flange, constantSpeed.flange) annotation( Line(points = {{220, -40}, {260, -40}})); connect(greater_u.y, idealOpenSW_nu.control) annotation( Line(points = {{-80, -78}, {-80, -50}, {-108, -50}}, color = {255, 0, 255})); connect(div_Vdc_q.y, inv_rotator.u[2]) annotation( Line(points = {{-1, -316}, {-8, -316}, {-8, -280}, {-18, -280}}, color = {0, 0, 127})); connect(plugToPin.pin_p, idealOpenSW_pu.n) annotation( Line(points = {{68, 30}, {-120, 30}, {-120, 40}}, color = {0, 0, 255})); connect(not_w.y, idealOpenSW_pw.control) annotation( Line(points = {{40, 20}, {40, 50}, {12, 50}}, color = {255, 0, 255})); connect(gain_Phi.y, add_q2.u2) annotation( Line(points = {{139, -340}, {110, -340}, {110, -322}, {102, -322}}, color = {0, 0, 127})); connect(rotator.y[2], feedback_q.u2) annotation( Line(points = {{130, -221}, {130, -241}, {210, -241}, {210, -273}}, color = {0, 0, 127})); connect(greater_v.y, idealOpenSW_nv.control) annotation( Line(points = {{-20, -78}, {-20, -50}, {-48, -50}}, color = {255, 0, 255})); connect(product_iq_omega.y, gain_Lq.u) annotation( Line(points = {{139, -370}, {102, -370}}, color = {0, 0, 127})); connect(pi_q.y, add_q.u1) annotation( Line(points = {{139, -280}, {76, -280}, {76, -304}, {62, -304}}, color = {0, 0, 127})); connect(ParkConvGain.y, rotator.u) annotation( Line(points = {{130, -81}, {130, -198}}, color = {0, 0, 127}, thickness = 0.5)); connect(const_ref_q_current.y, feedback_q.u1) annotation( Line(points = {{279, -280}, {218, -280}}, color = {0, 0, 127})); connect(star.plug_p, smpm.plug_sn) annotation( Line(points = {{180, -30}, {204, -30}}, color = {0, 0, 255})); connect(rotator.y[1], product_iq_omega.u1) annotation( Line(points = {{130, -221}, {130, -241}, {170, -241}, {170, -365}, {162, -365}}, color = {0, 0, 127})); connect(feedback_d.y, pi_d.u) annotation( Line(points = {{181, -260}, {122, -260}}, color = {0, 0, 127})); connect(currentSensor.plug_n, smpm.plug_sp) annotation( Line(points = {{140, 0}, {216, 0}, {216, -30}}, color = {0, 0, 255})); connect(gain_pole_pair.y, der_theta.u) annotation( Line(points = {{226, -219}, {226, -320}, {222, -320}}, color = {0, 0, 127})); connect(not_u.y, idealOpenSW_pu.control) annotation( Line(points = {{-80, 20}, {-80, 50}, {-108, 50}}, color = {255, 0, 255})); connect(rotator.y[1], feedback_d.u2) annotation( Line(points = {{130, -221}, {130, -241}, {190, -241}, {190, -253}}, color = {0, 0, 127})); connect(inv_rotator.y, fromSpacePhasor.u) annotation( Line(points = {{-41, -280}, {-58, -280}}, color = {0, 0, 127}, thickness = 0.5)); connect(greater_u.y, not_u.u) annotation( Line(points = {{-80, -78}, {-80, 10}}, color = {255, 0, 255})); connect(idealOpenSW_pv.p, idealOpenSW_pw.p) annotation( Line(points = {{-60, 60}, {0, 60}}, color = {0, 0, 255})); connect(gain_Ld.y, add_q2.u1) annotation( Line(points = {{111, -310}, {102, -310}}, color = {0, 0, 127})); connect(plugToPin_p1.pin_p, idealOpenSW_nw.p) annotation( Line(points = {{68, -30}, {0, -30}, {0, -40}}, color = {0, 0, 255})); connect(rotator.y[2], product_id_omega.u1) annotation( Line(points = {{130, -221}, {130, -241}, {170, -241}, {170, -305}, {162, -305}}, color = {0, 0, 127})); connect(fromSpacePhasor.y, InvParkConvGain.u) annotation( Line(points = {{-81, -280}, {-90, -280}, {-90, -262}}, color = {0, 0, 127}, thickness = 0.5)); connect(feedback_q.y, pi_q.u) annotation( Line(points = {{201, -280}, {162, -280}}, color = {0, 0, 127})); connect(gain_half.y, div_Vdc_q.u2) annotation( Line(points = {{-59, -350}, {32, -350}, {32, -322}, {22, -322}}, color = {0, 0, 127})); connect(add_q2.y, add_q.u2) annotation( Line(points = {{79, -316}, {62, -316}}, color = {0, 0, 127})); connect(gain_Lq.y, add_d.u2) annotation( Line(points = {{79, -370}, {70, -370}, {70, -272.063}, {62, -272.063}, {62, -272}}, color = {0, 0, 127})); connect(div_Vdc_d.y, inv_rotator.u[1]) annotation( Line(points = {{-1, -272}, {-8, -272}, {-8, -280}, {-18, -280}}, color = {0, 0, 127})); connect(constantVoltage.n, idealOpenSW_nu.n) annotation( Line(points = {{-180, -10}, {-180, -60}, {-120, -60}}, color = {0, 0, 255})); connect(greater_v.y, not_v.u) annotation( Line(points = {{-20, -78}, {-20, 10}}, color = {255, 0, 255})); connect(greater_w.y, not_w.u) annotation( Line(points = {{40, -78}, {40, 10}}, color = {255, 0, 255})); connect(idealOpenSW_pu.n, idealOpenSW_nu.p) annotation( Line(points = {{-120, 40}, {-120, -40}}, color = {0, 0, 255})); connect(voltageSensor.n, constantVoltage.n) annotation( Line(points = {{-150, -10}, {-150, -20}, {-180, -20}, {-180, -10}}, color = {0, 0, 255})); connect(angleSensor.phi, gain_pole_pair.u) annotation( Line(points = {{226, -80}, {226, -196}}, color = {0, 0, 127})); connect(voltageSensor.p, constantVoltage.p) annotation( Line(points = {{-150, 10}, {-150, 20}, {-180, 20}, {-180, 10}}, color = {0, 0, 255})); connect(const_ref_d_current.y, feedback_d.u1) annotation( Line(points = {{239, -260}, {198, -260}}, color = {0, 0, 127})); connect(gain_pole_pair.y, gain_minus1.u) annotation( Line(points = {{226, -219}, {226, -390}, {62, -390}}, color = {0, 0, 127})); connect(pi_d.y, add_d.u1) annotation( Line(points = {{99, -260}, {62, -260}}, color = {0, 0, 127})); connect(idealOpenSW_nw.n, idealOpenSW_nv.n) annotation( Line(points = {{0, -60}, {-60, -60}}, color = {0, 0, 255})); connect(product_id_omega.y, gain_Ld.u) annotation( Line(points = {{139, -310}, {134, -310}}, color = {0, 0, 127})); connect(gain_pole_pair.y, rotator.angle) annotation( Line(points = {{226, -219}, {226, -233}, {200, -233}, {200, -211}, {142, -211}}, color = {0, 0, 127})); connect(idealOpenSW_pv.n, idealOpenSW_nv.p) annotation( Line(points = {{-60, 40}, {-60, -40}}, color = {0, 0, 255})); connect(currentSensor.i, toSpacePhasor.u) annotation( Line(points = {{130, -10}, {130, -18}}, color = {0, 0, 127}, thickness = 0.5)); connect(add_d.y, div_Vdc_d.u1) annotation( Line(points = {{39, -266}, {22, -266}}, color = {0, 0, 127})); connect(zero_voltage_ref.y, fromSpacePhasor.zero) annotation( Line(points = {{-41, -240}, {-51, -240}, {-51, -272}, {-58, -272}}, color = {0, 0, 127})); connect(voltageSensor.v, gain_half.u) annotation( Line(points = {{-138, 0}, {-130, 0}, {-130, -40}, {-160, -40}, {-160, -350}, {-82, -350}}, color = {0, 0, 127})); connect(toSpacePhasor.y, ParkConvGain.u) annotation( Line(points = {{130, -40}, {130, -58}}, color = {0, 0, 127}, thickness = 0.5)); connect(not_v.y, idealOpenSW_pv.control) annotation( Line(points = {{-20, 20}, {-20, 50}, {-48, 50}}, color = {255, 0, 255})); connect(ground.p, idealOpenSW_nv.n) annotation( Line(points = {{-60, -66}, {-60, -60}}, color = {0, 0, 255})); connect(triangle.y, greater_u.u2) annotation( Line(points = {{-118, -140}, {-88, -140}, {-88, -102}}, color = {0, 0, 127})); connect(triangle.y, greater_v.u2) annotation( Line(points = {{-118, -140}, {-28, -140}, {-28, -102}}, color = {0, 0, 127})); connect(triangle.y, greater_w.u2) annotation( Line(points = {{-118, -140}, {32, -140}, {32, -102}}, color = {0, 0, 127})); connect(InvParkConvGain.y[1], zeroOrderHold.u) annotation( Line(points = {{-90, -238}, {-90, -200}, {-80, -200}, {-80, -182}}, color = {0, 0, 127})); connect(InvParkConvGain.y[2], zeroOrderHold1.u) annotation( Line(points = {{-90, -238}, {-90, -200}, {-20, -200}, {-20, -182}}, color = {0, 0, 127})); connect(InvParkConvGain.y[3], zeroOrderHold2.u) annotation( Line(points = {{-90, -238}, {-90, -200}, {40, -200}, {40, -182}}, color = {0, 0, 127})); connect(zeroOrderHold.y, greater_u.u1) annotation( Line(points = {{-80, -158}, {-80, -102}}, color = {0, 0, 127})); connect(zeroOrderHold1.y, greater_v.u1) annotation( Line(points = {{-20, -158}, {-20, -102}}, color = {0, 0, 127})); connect(zeroOrderHold2.y, greater_w.u1) annotation( Line(points = {{40, -158}, {40, -102}}, color = {0, 0, 127})); annotation( uses(Modelica(version = "4.0.0")), Diagram(coordinateSystem(extent = {{-200, 60}, {320, -400}})), version = "", Documentation(revisions = "
")); end PMSM_model_20230907;
零極相殺による設計方法で、$\omega_{1\_lag} / 2 \pi = f_{sw},\; f_{sw}/10,\; f_{sw}/20$とした三通りのシミュレーションを行った。シミュレーション結果を示す。
上図は、搬送波をゼロ次ホールドする前後の波形であり、赤色がホールド前、黒色がホールド後の波形である。カットオフ周波数$\omega_{1\_lag} / 2 \pi =f_{sw}/10,\; f_{sw}/20$の場合には、スイッチング周波数成分が十分に減衰されるため、搬送波に重畳するスイッチング周波数成分は小さく、ゼロ次ホールド後の波形はゼロ次ホールド前の波形の平均値に近い値となっている。一方で$\omega_{1\_lag} / 2 \pi =f_{sw}$では、搬送波のスイッチング周波数成分が支配的であり、ゼロ次ホールド後の波形が搬送波を正しくサンプリングできない。このため、誤った信号が三角波比較され、システムが不安定となる。
上図はdq電流の司令値(点線)と測定値(実線)を示しており、これらが一致するようにフィードバック制御を適用している。$\omega_{1\_lag} / 2 \pi =f_{sw}/10,\; f_{sw}/20$では、測定値は司令値に追従している。$\omega_{1\_lag} / 2 \pi =f_{sw}/10$の方が$\omega_{1\_lag} / 2 \pi =f_{sw}/20$よりも少し早く収束しているため、大きい$\omega_{1\_lag}$の方が応答速度が速い。$\omega_{1\_lag} = f_{sw}$ではフィードバック制御が不安定となることがわかる。したがって、$\omega_{1\_lag} \ll f_{sw}$とする必要がある。
まとめ
。
0 件のコメント:
コメントを投稿