In the attached model, I’m trying to compare the frequency response of an analogue 3P3Z (type-III) controller to it’s discrete counter-parts (two versions: MMPZ and Tustin), but the discrete versions seems way off around the crossover frequency (8 kHz), I suspect I didn’t set up the C block correctly, any chance it has to do with the discreteStates(0,0)?
Also why would frequency response generate a smooth bode plot, while the AC sweep produces a pretty jittery one?
Your diagnosis is correct. The methods below rely on accurate accounting of the system states. When you do not explicitly define states as such in the C-Script, then the PLECS solver doesn’t know they are states.
AC Sweep uses states for steady-state convergence.
Fixing the state issue, the Frequency Response Analysis (FRA) and Multitone both return consistent results. There also was an issue in your FRA setup where the settling time span was set to 0. This parameter is the “Time needed by the system to reach steady state after the sinusoidal perturbation is applied, in seconds (s).” and should be non-zero. It’s based on your system dynamics, but I chose 0.01 sec and it looked fine. Also note that multitone would have worked fine from the start because it doesn’t rely on the stored system state, but rather two transient runs.
The AC Sweep has some issues converging because it has a pure integrator, as alluded to in this previous forum post, so it isn’t a great method for this application. If you set the AC Sweep’s “Operating Point” to “non-periodic (DC)” then the analog TF extraction works, but the digital ones don’t. Generally, AC Sweep is superceded by FRA since it side-steps many of the steady-state convergences issues that limit that method.
I really appreciate the detailed explanation and the revised model, they are really helpful resources and allows better understanding of the different applications of analysis tools.
I have ran the provided model, and I still see that there is a big difference in the phase magnitude between the analogue TF and it’s C-implemented variants, specifically at 8kHz (frequency of interest):
Many thanks for sharing this article, I came across it earlier and it was a valuable reference in modelling discrete TFs in PLECS environment.
However, I’m still not clear on the difference in the Phase magnitude between the discrete version, and it’s C counterpart. Please see the attached example, where I use the C script provided earlier by @Bryan_Lieblick in the same thread:
And I added the analogue, and discrete versions, and still see a big difference in the phase magnitude at 8 kHz:
Did you have a chance to check this? my specific inquiry is about justifying the phase difference between the discrete controller and it’s C implementaion..
The C-Script as you have implemented it introduces an artificial delay of 2/fsw.
1. Input delay of one sample (UpdateFcn). Inside UpdateFcn at step k, error is e[k]. But unew is computed from e(0)…e(3), and e(0) is only set to error after unew is computed. So b[0] multiplies e[k-1], not e[k]. The whole numerator is shifted by one sample. 2. Output delay of one sample (OutputFcn).unew is computed in UpdateFcn and stored in u(0). OutputFcn only returns Command = u(0). PLECS runs the output function, then the update function, at each sample. The value computed at step k therefore only appears at the output at step k+1.
Together, Command at step k+1 is built from e[k-1]…, which is two samples late compared with the discrete transfer function. The OutputFcn never reads InputSignal, so there is no direct feedthrough path.
The fix is to compute the filter in OutputFcn with the current error input, and then perform the shift in UpdateFcn. The results then match.
You can review the PLECS: Using the C-Script Block tutorial which in section 5.3 describes the sequence a bit more clearly and how the ordering of output/update calls can introduce the delay.
I also removed the triggered subsystem setup to see if it introduced any additional delay (it didn’t) but I find the bare C-Script to be more straightforward (and in more complicated models the pulse delay introduces another solver step at the falling edge of the pulse generator, which can slow things down).