Я пытаюсь исследовать пример Modelica Modelica.Electrical.Machines.Examples.SynchronousInductionMachines.SMPM_VoltageSource
, но я заменил signalVoltage
на инвертор и ШИМ-блок signalPWM
, основанный на Modelica.Electrical.PowerConverters.DCDC.Control.SignalPWM
. Поэтому вместо синусоидальных напряжений я хочу исследовать модулированные по ШИМ напряжения. Проблема состоит в том, что контроллер продолжает линейно увеличивать свою выходную мощность из-за интегрирующей части контроллера, поскольку он никогда не достигает эталонного значения требуемого добротности. Кроме того, он выводит странные значения для voltageController.y[1]
в диапазоне [24E3, ..., 150E3], что, вероятно, является проблемой.
Выход контроллера:
и токовый выход:
К сожалению, нетпонять, почему контроллер работает нормально с синусоидальными напряжениями, а не с широтно-импульсными.
Ниже приведена моя основная модель:
model SMPM_INV_SineLoad "Test example: PermanentMagnetSynchronousInductionMachine fed by FOC"
extends Modelica.Icons.Example;
import Modelica.Constants.pi;
constant Integer m = 3 "Number of phases";
parameter Modelica.SIunits.Frequency f = 8000 "Switching frequency";
parameter Modelica.SIunits.AngularVelocity wRef = 30 "Desired speed of the PMSM";
parameter Modelica.SIunits.Current Idq[2] = {0, 10} "Desired d- and q-current";
parameter Modelica.SIunits.AngularVelocity wNominal = 2 * pi * smpmData.fsNominal / smpmData.p "Nominal speed";
parameter Modelica.SIunits.Torque TLoad = 5 "Nominal load torque";
parameter Modelica.SIunits.Inertia JLoad = 0.29 "Load's moment of inertia";
parameter Modelica.SIunits.Voltage VBat_2 = 100 "Half Battery Voltage";
Modelica.Electrical.Machines.BasicMachines.SynchronousInductionMachines.SM_PermanentMagnet smpm(phiMechanical(start = 0, fixed = true), wMechanical(start = 0, fixed = true), useSupport = false, useThermalPort = false, p = smpmData.p, fsNominal = smpmData.fsNominal, Rs = smpmData.Rs, TsRef = smpmData.TsRef, Lszero = smpmData.Lszero, Lssigma = smpmData.Lssigma, Jr = smpmData.Jr, Js = smpmData.Js, frictionParameters = smpmData.frictionParameters, statorCoreParameters = smpmData.statorCoreParameters, strayLoadParameters = smpmData.strayLoadParameters, VsOpenCircuit = smpmData.VsOpenCircuit, Lmd = smpmData.Lmd, Lmq = smpmData.Lmq, useDamperCage = smpmData.useDamperCage, Lrsigmad = smpmData.Lrsigmad, Lrsigmaq = smpmData.Lrsigmaq, Rrd = smpmData.Rrd, Rrq = smpmData.Rrq, TrRef = smpmData.TrRef, permanentMagnetLossParameters = smpmData.permanentMagnetLossParameters, TsOperational = 293.15, alpha20s = smpmData.alpha20s, TrOperational = 293.15, alpha20r = smpmData.alpha20r) annotation(Placement(transformation(extent = {{-20, -50}, {0, -30}}, origin = {-0, -10}, rotation = 0), visible = true));
Modelica.Electrical.Machines.Utilities.TerminalBox terminalBox(terminalConnection = "Y") annotation(Placement(transformation(extent = {{-20, -34}, {0, -14}}, origin = {-0, -10}, rotation = 0), visible = true));
Modelica.Mechanics.Rotational.Sensors.AngleSensor angleSensor annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 90, origin = {20, -10}), visible = true));
Modelica.Mechanics.Rotational.Components.Inertia inertiaLoad(J = JLoad) annotation(Placement(transformation(extent = {{50, -50}, {70, -30}}, origin = {-0, -10}, rotation = 0), visible = true));
Modelica.Electrical.MultiPhase.Sensors.CurrentSensor currentSensor(m = m) annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 270, origin = {-10, -10}), visible = true));
Modelica.Electrical.Machines.Utilities.VoltageController voltageController(p = smpm.p, Ld = smpm.Lssigma + smpm.Lmd, Lq = smpm.Lssigma + smpm.Lmq, Rs = Modelica.Electrical.Machines.Thermal.convertResistance(smpm.Rs, smpm.TsRef, smpm.alpha20s, smpm.TsOperational), fsNominal = smpm.fsNominal, VsOpenCircuit = smpm.VsOpenCircuit) annotation(Placement(transformation(extent = {{-50, 40}, {-30, 60}}, origin = {-0, -10}, rotation = 0), visible = true));
Modelica.Mechanics.Rotational.Sensors.TorqueSensor torqueSensor annotation(Placement(transformation(extent = {{10, 10}, {-10, -10}}, rotation = 180, origin = {40, -70}), visible = true));
Modelica.Mechanics.Rotational.Sensors.SpeedSensor speedSensor annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 90, origin = {50, -10}), visible = true));
Modelica.Electrical.Machines.Sensors.RotorDisplacementAngle rotorDisplacementAngle(p = smpm.p) annotation(Placement(transformation(origin = {20, -50}, extent = {{-10, 10}, {10, -10}}, rotation = 270), visible = true));
Modelica.Electrical.Analog.Basic.Ground groundM annotation(Placement(transformation(origin = {-80, -38}, extent = {{-10, -10}, {10, 10}}, rotation = 270), visible = true));
Modelica.Electrical.MultiPhase.Basic.Star starM(final m = m) annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 180, origin = {-60, -20}), visible = true));
Modelica.Electrical.Machines.Sensors.VoltageQuasiRMSSensor voltageQuasiRMSSensor annotation(Placement(transformation(extent = {{-10, 10}, {10, -10}}, rotation = 180, origin = {-30, -20}), visible = true));
parameter Modelica.Electrical.Machines.Utilities.ParameterRecords.SM_PermanentMagnetData smpmData(useDamperCage = false) annotation(Placement(transformation(extent = {{-20, -80}, {0, -60}}, origin = {-0, -10}, rotation = 0), visible = true));
Modelica.Electrical.Machines.Sensors.CurrentQuasiRMSSensor currentQuasiRMSSensor annotation(Placement(transformation(origin = {-10, 10}, extent = {{-10, -10}, {10, 10}}, rotation = 270), visible = true));
Modelica.Mechanics.Rotational.Sources.SignTorque signTorque1(tau_constant = -TLoad, w0 = wNominal) annotation(Placement(visible = true, transformation(origin = {90, -50}, extent = {{10, -10}, {-10, 10}}, rotation = 0)));
Modelica.Blocks.Sources.Constant id(k = Idq[1]) annotation(Placement(transformation(extent = {{-90, 60}, {-70, 80}}, origin = {-0, -10}, rotation = 0), visible = true));
SignalPWM signalPWM1[m](useConstantDutyCycle = false, f = f) annotation(Placement(visible = true, transformation(origin = {22.087, 64.88}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Electrical.PowerConverters.DCAC.MultiPhase2Level multiPhase2Level1 annotation(Placement(visible = true, transformation(origin = {22.083, 116.565}, extent = {{-10, -10}, {10, 10}}, rotation = 0)));
Modelica.Electrical.Analog.Sources.ConstantVoltage U_n(V = VBat_2) annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 270, origin = {-30, 97.365}), visible = true));
Modelica.Electrical.Analog.Basic.Ground ground annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 180, origin = {-50, 127.365}), visible = true));
Modelica.Electrical.Analog.Sources.ConstantVoltage U_p(V = VBat_2) annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 270, origin = {-30, 137.365}), visible = true));
Modelica.Blocks.Sources.Constant iq(k = Idq[2]) annotation(Placement(transformation(extent = {{-90, 20}, {-70, 40}}, origin = {0, -10}, rotation = 0), visible = true));
initial equation
smpm.is[1:2] = zeros(2);
equation
connect(terminalBox.plug_sn, smpm.plug_sn) annotation(Line(points = {{0, 0}, {0, 0}, {0, 0}}, color = {0, 0, 255}, visible = true, origin = {-16, -40}));
connect(terminalBox.plug_sp, smpm.plug_sp) annotation(Line(points = {{0, 0}, {0, 0}, {0, 0}}, color = {0, 0, 255}, visible = true, origin = {-4, -40}));
connect(smpm.flange, angleSensor.flange) annotation(Line(points = {{-6.667, -10}, {3.333, -10}, {3.333, 20}, {13.333, 20}}, visible = true, origin = {6.667, -40}, color = {64, 64, 64}));
connect(currentSensor.plug_n, terminalBox.plugSupply) annotation(Line(points = {{-10, -10}, {-10, -28}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(angleSensor.phi, voltageController.phi) annotation(Line(points = {{20, 11}, {20, 34}, {-34, 34}, {-34, 38}}, color = {1, 37, 163}, visible = true, origin = {0, -10}));
connect(currentSensor.i, voltageController.iActual) annotation(Line(points = {{-21, 0}, {-46, 0}, {-46, 38}}, color = {1, 37, 163}, visible = true, origin = {-0, -10}));
connect(inertiaLoad.flange_a, torqueSensor.flange_b) annotation(Line(points = {{50, -40}, {50, -60}}, visible = true, origin = {-0, -10}, color = {64, 64, 64}));
connect(torqueSensor.flange_a, smpm.flange) annotation(Line(points = {{30, -60}, {30, -40}, {0, -40}}, visible = true, origin = {-0, -10}, color = {64, 64, 64}));
connect(speedSensor.flange, smpm.flange) annotation(Line(points = {{23.333, 20}, {13.333, 20}, {13.333, -10}, {-26.667, -10}}, visible = true, origin = {26.667, -40}, color = {64, 64, 64}));
connect(rotorDisplacementAngle.flange, smpm.flange) annotation(Line(points = {{10, -40}, {0, -40}}, visible = true, origin = {-0, -10}, color = {64, 64, 64}));
connect(rotorDisplacementAngle.plug_p, smpm.plug_sp) annotation(Line(points = {{14, -30}, {-4, -30}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(rotorDisplacementAngle.plug_n, smpm.plug_sn) annotation(Line(points = {{26, -30}, {26, -20}, {-16, -20}, {-16, -30}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(voltageQuasiRMSSensor.plug_p, currentSensor.plug_n) annotation(Line(points = {{-20, -10}, {-10, -10}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(starM.plug_p, voltageQuasiRMSSensor.plug_n) annotation(Line(points = {{-50, -10}, {-40, -10}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(groundM.p, starM.pin_n) annotation(Line(points = {{-70, -28}, {-70, -10}}, color = {10, 90, 224}, visible = true, origin = {-0, -10}));
connect(currentQuasiRMSSensor.plug_n, currentSensor.plug_p) annotation(Line(points = {{0, 0}, {0, 0}, {0, 0}}, color = {0, 0, 255}, visible = true, origin = {-10, 0}));
connect(inertiaLoad.flange_b, signTorque1.flange) annotation(Line(visible = true, origin = {75, -50}, points = {{-5, 0}, {5, 0}}, color = {64, 64, 64}));
connect(id.y, voltageController.id_rms) annotation(Line(points = {{-69, 70}, {-60, 70}, {-60, 56}, {-52, 56}}, color = {1, 37, 163}, visible = true, origin = {-0, -10}));
connect(voltageController.y[1:3], signalPWM1[1:3].dutyCycle) annotation(Line(visible = true, origin = {-16.728, 52.44}, points = {{-12.272, -12.44}, {-7.272, -12.44}, {-7.272, 12.44}, {26.815, 12.44}}, color = {1, 37, 163}));
connect(ground.p, U_n.p) annotation(Line(visible = true, origin = {-40, 112.78}, points = {{-10, 4.585}, {-10, 4.557}, {10, 4.557}, {10, -5.415}}, color = {10, 90, 224}));
connect(U_p.n, U_n.p) annotation(Line(visible = true, origin = {-30, 117.365}, points = {{0, 10}, {0, -10}}, color = {10, 90, 224}));
connect(U_n.n, multiPhase2Level1.dc_n) annotation(Line(visible = true, origin = {-15.583, 93.045}, points = {{-14.417, -5.68}, {-14.417, -10.68}, {0.583, -10.68}, {0.583, 13.52}, {27.666, 13.52}}, color = {10, 90, 224}));
connect(U_p.p, multiPhase2Level1.dc_p) annotation(Line(visible = true, origin = {-15.583, 141.045}, points = {{-14.417, 6.32}, {-14.417, 11.32}, {0.583, 11.32}, {0.583, -14.48}, {27.666, -14.48}}, color = {10, 90, 224}));
connect(signalPWM1[1:3].fire, multiPhase2Level1.fire_p[1:3]) annotation(Line(visible = true, origin = {16.085, 85.551}, points = {{0.002, -9.671}, {0.002, -4.671}, {-0.002, -4.671}, {-0.002, 19.014}}, color = {190, 52, 178}));
connect(signalPWM1[1:3].notFire, multiPhase2Level1.fire_n[1:3]) annotation(Line(visible = true, origin = {28.085, 85.551}, points = {{0.002, -9.671}, {0.002, -4.671}, {-0.002, -4.671}, {-0.002, 19.014}}, color = {190, 52, 178}));
connect(multiPhase2Level1.ac, currentQuasiRMSSensor.plug_p) annotation(Line(visible = true, origin = {22.417, 66.626}, points = {{9.666, 49.939}, {27.583, 49.939}, {27.583, -26.626}, {-32.417, -26.626}, {-32.417, -46.626}}, color = {10, 90, 224}));
connect(iq.y, voltageController.iq_rms) annotation(Line(visible = true, origin = {-62.25, 27}, points = {{-6.75, -7}, {-1.75, -7}, {-1.75, 7}, {10.25, 7}}, color = {1, 37, 163}));
annotation(experiment(StopTime = 2.0, Interval = 0.1), Diagram(coordinateSystem(extent = {{-200, -200}, {200, 200}}, preserveAspectRatio = true, initialScale = 0.1, grid = {10, 10})), Icon(coordinateSystem(extent = {{-100, -100}, {100, 100}}, preserveAspectRatio = false, initialScale = 0.1, grid = {10, 10})), Documentation(info = "<html>
<p>
A synchronous induction machine with permanent magnets accelerates a quadratic speed dependent load from standstill.
The rms values of d- and q-current in rotor fixed coordinate system are controlled by the voltageController,
and the output voltages fed to the machine. The result shows that the torque is influenced by the q-current,
whereas the stator voltage is influenced by the d-current.</p>
<p>
Default machine parameters of model <a href=\"modelica://Modelica.Electrical.Machines.BasicMachines.SynchronousInductionMachines.SM_PermanentMagnet\">SM_PermanentMagnet</a> are used.
</p>
</html>"));
end SMPM_INV_SineLoad;
И модель сигнала ШИМ:
model SignalPWM "Generates a pulse width modulated (PWM) boolean fire signal"
extends Modelica.Electrical.PowerConverters.Icons.Control;
parameter Boolean useConstantDutyCycle = true "Enables constant duty cycle";
parameter Real constantDutyCycle = 0 "Constant duty cycle" annotation(Dialog(enable = useConstantDutyCycle));
parameter Modelica.SIunits.Frequency f = 1000 "Switching frequency";
parameter Modelica.SIunits.Time startTime = 0 "Start time";
Modelica.Blocks.Interfaces.RealInput dutyCycle if not useConstantDutyCycle "Duty cycle" annotation(Placement(transformation(extent = {{-140, -20}, {-100, 20}})));
Modelica.Blocks.Interfaces.BooleanOutput fire "Firing PWM signal" annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 90, origin = {-60, 110})));
Modelica.Blocks.Interfaces.BooleanOutput notFire "Firing PWM signal" annotation(Placement(transformation(extent = {{-10, -10}, {10, 10}}, rotation = 90, origin = {60, 110})));
Modelica.Blocks.Sources.Constant const(final k = constantDutyCycle) if useConstantDutyCycle annotation(Placement(transformation(extent = {{-100, -60}, {-80, -40}})));
Modelica.Blocks.Nonlinear.Limiter limiter(uMax = 500000, uMin = -500000) annotation(Placement(transformation(extent = {{-60, -10}, {-40, 10}})));
Modelica.Blocks.Logical.Less greaterEqual annotation(Placement(transformation(extent = {{-10, 10}, {10, -10}}, origin = {22, -8})));
Modelica.Blocks.Discrete.ZeroOrderHold zeroOrderHold(final startTime = startTime, final samplePeriod = 1 / f) annotation(Placement(transformation(extent = {{-30, -10}, {-10, 10}})));
Modelica.Blocks.Sources.SawTooth sawtooth(final period = 1 / f, final amplitude = 1000000, final nperiod = -1, final offset = -500000, final startTime = startTime) annotation(Placement(transformation(origin = {-50, -50}, extent = {{-10, -10}, {10, 10}})));
Modelica.Blocks.Logical.Not inverse annotation(Placement(transformation(extent = {{-10, 10}, {10, -10}}, rotation = 90, origin = {52, 20})));
equation
connect(const.y, limiter.u) annotation(Line(points = {{-79, -50}, {-70, -50}, {-70, 0}, {-62, 0}}, color = {0, 0, 127}));
connect(dutyCycle, limiter.u) annotation(Line(points = {{-120, 0}, {-62, 0}}, color = {0, 0, 127}));
connect(limiter.y, zeroOrderHold.u) annotation(Line(points = {{-39, 0}, {-32, 0}}, color = {0, 0, 127}));
connect(zeroOrderHold.y, greaterEqual.u2) annotation(Line(points = {{-9, 0}, {10, 0}}, color = {0, 0, 127}));
connect(sawtooth.y, greaterEqual.u1) annotation(Line(points = {{-39, -50}, {0, -50}, {0, -8}, {10, -8}}, color = {0, 0, 127}));
connect(greaterEqual.y, inverse.u) annotation(Line(points = {{33, -8}, {52, -8}, {52, 8}}, color = {255, 0, 255}));
connect(greaterEqual.y, fire) annotation(Line(points = {{33, -8}, {36, -8}, {36, 80}, {-60, 80}, {-60, 110}}, color = {255, 0, 255}));
connect(inverse.y, notFire) annotation(Line(points = {{52, 31}, {52, 80}, {60, 80}, {60, 110}}, color = {255, 0, 255}));
annotation(Icon(coordinateSystem(preserveAspectRatio = false, extent = {{-100, -100}, {100, 100}}, initialScale = 0.1, grid = {10, 10}), graphics = {Line(visible = true, points = {{-100, 0}, {-98, 0}, {12, 0}}, color = {64, 64, 64}), Line(visible = true, points = {{-60, -22}, {-60, -64}, {44, -64}, {44, -36}}, color = {64, 64, 64}), Line(visible = true, points = {{-80, -16}, {-80, -20}, {-40, 20}, {-40, -20}, {-36, -16}}, color = {64, 64, 64}), Line(visible = true, points = {{-62, 0}, {-76, 4}, {-76, -4}, {-62, 0}}, color = {64, 64, 64}), Line(visible = true, points = {{44, -36}, {44, -36}, {40, -50}, {44, -50}, {48, -50}, {44, -36}}, color = {64, 64, 64}), Line(visible = true, points = {{20, -20}, {22, -20}, {24, -20}, {24, 20}, {44, 20}, {44, -20}, {64, -20}, {64, -16}}, color = {190, 53, 179}), Line(visible = true, points = {{-40, -16}, {-40, -20}, {0, 20}, {0, -20}, {4, -16}}, color = {64, 64, 64}), Line(visible = true, points = {{60, -20}, {62, -20}, {64, -20}, {64, 20}, {84, 20}, {84, -20}, {84, -20}, {88, -20}}, color = {190, 53, 179})}), Documentation(info = "<html>
<p>
This controller can be used both for DC/DC and AC/DC converters.
The signal input of the PWM controller is the duty cycle; the duty cycle is the ratio of the on time
to the switching period. The output firing signal is strictly determined by the actual duty cycle, indicated as <code>d</code> in Fig. 1.
</p>
<table border=\"0\" cellspacing=\"0\" cellpadding=\"2\">
<caption align=\"bottom\"><b>Fig. 1:</b> Firing (<code>fire</code>) and inverse firing (<code>notFire</code>) signal of PWM control; <code>d</code> = duty cycle; <code>f</code> = switching frequency </caption>
<tr>
<td>
<img src=\"modelica://Modelica/Resources/Images/Electrical/PowerConverters/dutyCycle.png\">
</td>
</tr>
</table>
<p>
The firing signal is generated by comparing the sampled duty cycle input with a periodic saw tooth signal [<a href=\"modelica://Modelica.Electrical.PowerConverters.UsersGuide.References\">Williams2006</a>].
</p>
</html>"));
end SignalPWM;
Редактировать: Я уже снизил требуемый q-ток с Idq={0,84} A
до Idq={0,10} A
и нагрузку с TLoad = 120 Nm
до TLoad = 5 Nm
и все еще получаю эти безумно высокие сигналы напряжения от voltageController
.
- У кого-нибудь может быть идея, как решить проблему с контроллером, чтобы получить правильные результаты для симуляции?
- Почему он не может достичь контрольного значения, как в примере MSL? Является ли ШИМ-блок большой проблемой?
- Такое поведение симулятора сбивает меня с толку, потому что я работаю с реальным двигателем и ШИМ-управлением, и он прекрасно работает с аналогичной конфигурацией.
Любая помощь будет высоко оценена!