C-script block in Frequency Response Analysis (FRA)

Hello all,

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?

@Bryan_Lieblick , this is coming from the previous post:

discreteFunctionFrequencySweep_R02.plecs (30.3 KB)

Many thanks in advance,

Omar

Hi Omar,

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.

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.

Regards,
Bryan

discreteFunctionFrequencySweep_R02_BL.plecs (30.7 KB)

Dear @Bryan_Lieblick ,

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):

What are your insights on that? given that I have discretized the TF using MMPZ and pre-warped Tustin at Ts=1/200e3.

Many thanks again for all your help and support.

Omar

Hi Omar,

You may find this article helpful in your investigation: Discretization Done Right: From Continuous Design to Digital Control

1 Like

Hello @Munadir_Ahmed ,

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:

Atatched PLECS model for your reference

discreteFunctionFrequencySweep_R05.plecs (23.2 KB)

I believe I’m missing something in my C model, can you please advise?

Kind regards,

Omar

Hello @Bryan_Lieblick and @Munadir_Ahmed ,

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..

Kind regards,

Omar

Hi Omar,

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.

See: discreteFunctionFrequencySweep_R05_BL.plecs (17.7 KB)

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).

Regards,
Bryan

1 Like

Dear @Bryan_Lieblick ,

Many thanks for the clear and thorough explanation, it has been truly helpful in grasping the various concepts of the C-block.

Kind regards,

Omar

1 Like