The circuit files for this case are in these two links:
If you are here to know how to use control functions in the simulator, read this post and run the simulator
with the circuit files in the above links. To start, as usual, run the file circuit_solver.py and enter the file
standalone_inv as the circuit file. No need to add the .csv extension. The file standalone_inv.csv is in the links above.
The parameter file standalone_inv_params.csv can also be found in the links above.
Now comes the part about controls. There are two control files in this simulation - one is the phase angle generator
angle_gen.py and the other is the current controller currcont_3ph.py. The simulator asks for the control files and these
two are entered as shown above. As before without the .py extension. A simulation can contain a single control file or
multiple. The purpose of this example is to show how to use multiple control files and more importantly how to exchange
signals between control files. This way, you can design cascaded control or embedded control functions.
The next part - the descriptor files. Every control file used in the simulation will have a descriptor file. In this case -
angle_gen_desc.csv and currcont_3ph_desc.csv. The purpose of a descriptor file is to define the interface of the control
file - the inputs, outputs, static variables, time events and storage variables. More on this:
- Inputs: The inputs to a control file are from meters - ammeters and voltmeters.
- Outputs: The outputs of a control file are to components that have controls.
- Static variables: Typically any variable used within a function exists only within the
function. Similarly, all variables that you use within a function will have a value only in a particular iteration of
the function. If you want to access the variable in the next simulation run, you can't. To solve this problem, declare
the variable in the descriptor file of the control function as a static variable. Now the value of the variable will
be stored and will be available in the next simulation run.
- Time events: A control function can run at a frequency different from the simulator. It
can be slower or even faster. For this reason, you can define variables as time events and update them in your control
code to choose when to run the control code. The simulator will arrange all the time events generated by all the
control code in ascending order along with the user defined simulation time step and will choose the next simulation
time to be the first in the list. So if a control code is slower than the simulation time, the simulator will run more
or less at the simulation time steps. However, if the control code is faster or asynchronous to the simulation time
step, the simulator could run at any time step the control function causes a change in its outputs.
- Variable storage: There are two purposes of these. The first is if you want to debug a
control code and want to check what are intermediate signals in the control code, you could use this to plot these
variables. The other purpose is to link control functions together. The special property of the these are that a variable
defined as VariableStorage can occur only once in all the control functions in a simulator. However, if defined in any
of the control functions, they are available in all control functions. So, a variable defined as VariableStorage could
be defined in one descriptor file and be accessed in another control function and also plotted at the same time. This
way control signals can be passed between control code.
With the above background, time to go into details with actual code. First the angle_gen.py code.
dt_sample = 100.0e-6
omega = 2*3.141*60.0
ph_angle += omega*dt_sample
if (ph_angle > 2*math.pi):
ph_angle = 0.0
t1 = t1 + dt_sample
control_ph_angle = ph_angle
The above code can be described in the following way:
- dt_sample=100.0e-6 implies that this control code should run every 100 microseconds.
- The frequency of the signal is 60 Hz or 377 rad/s.
- t_clock is a reserved variable in the simulator. It is available in every control function and provides
the simulation time instant. When t_clock is greater than a defined time event t1, the block is executed.
- The phase angle is generated as a sawtooth waveform with frequency of 60Hz. The phase angle is limited
to 0 to 2pi.
- At the end of the block, the time event t1 is incremented by dt_sample which is 100 microseconds. This way
the block executes every 100 microseconds.
- control_ph_angle is the "output" of the control function. Typically an output of a control function
is fed to a controllable element. In this case, all that is done is a phase angle of a frequency is generated. Therefore,
the phase angle is a signal that needs to be available to another control function and that is the current controller
The screenshot below shows the descriptor for angle_gen_desc.csv.
The control function does not have any inputs because there is no need for any. There are no outputs either as the function
does not directly affect any controllable component. ph_angle is defined a static variable. This is because of the
ph_angle += omega*dt_sample
This implies ph_angle uses its previous value to compute its current value. Therefore, the value of ph_angle has to
be stored for future use and so it is defined as a static variable.
The next row is the definition of the time event t1. From the control code above, t1 is progressed by steps of 100
microseconds so that the control code runs every 100 microseconds when compared the simulation time instant. This could
have been a static variable also. Except that time event has a special significance for the simulator. When t1 is updated
in the control code, it generates a time event. There could be multiple time events generated in a control code. And there
could be several control codes that generate several time events. What the simulator does is to arrange all these time events
so that it knows the closest time event from the present instant of time. This is then combined with the next intended
simulation time instant generated with the constant simulation time step. The simulator will choose the next simulation time
instant to be closes time event or the next simulation time instant whichever is nearer. So time events are a way to
control the run frequency of the simulator besides also deciding how often the control code is run.
The last row is the tricky part. The angle generator produces a phase angle that will be used by the current controller.
Therefore the phase angle is not an Output. So to make the ph_angle available to the current controller or for that matter
any other controller, it is defined as VariableStorage. This means the control variable is stored in a "global" space
where it is available for all control functions. Since, this is similar to a global variable, a variable defined as
VariableStorage cannot be defined in another control function. However, it can be used and also modified in another
function. Since, it is a global variable, care should be taken while using this variable in control functions. To show
how this is used, the current controller will be described next.
- There are two sample rates in this control code. One block runs every 100 microseconds
(dt_sample). The other runs every 1 microsecond (dt_carr).
- The ph_angle is obtained from VariableStorage control_ph_angle in line 14. As said before,
any variable defined as VariableStorage can be accessed and changed in any control code. In this case it is merely accessed.
To know more about the interface of the control code, the screenshot of the descriptor file is:
For every control code that you specify, the simulator generates a template descriptor file for you to be able to edit.
So you use that as a starting point or use the files provided in the link. The input can be any meter and there can be
multiple inputs limited by as many meters there are in the circuit. The name of the input is as it appears in the circuit
file. The next column asks you how you want to access the input in the control function. The variable specified is the
variable by which the meter output will be made available to you. Lines 19 and 20 use the variables curr_a, curr_b and
curr_c that are the meter outputs.
As for the outputs, there can be multiple outputs and these are also accessed by variable names linked with each control
tag. Here it is essential that you get both the element name and the name of the control tag matched. Or else you will
have an error when the simulator tries to access a control tag in an element that does not exist.
The definition of static variables is quite similar to the previous case. Try to read the control code and figure out how
the control works. The current controller works at 100 microseconds while the pulse width modulator works at 1 microseconds.
Try changing some of the control parameters or implement you own control along the same lines as above.
The results are:
From the control code, it can be seen that the current reference for the d axis has been set at 10Amps and q axis at
0Amps. The tracking can be seen from the figure.