So I've been working on how to digitally implement a static reference frame PLL (SRF-PLL), which is a quite popular PLL used for extracting three-phase grid angle.
This PLL works by using the DQ0 transform as a phase detector. Using the estimated grid angle $\hat{\theta}(t)$ as the rotation angle $\theta_r(t)$ of the DQ0 transform, a signal $v_q(t)$ is obtained. This signal is proportional to the phase difference between $\hat{\theta}(t)$\ $\theta_r(t)$ and the true grid angle. A PI controller drives $v_q(t)$ to zero by adjusting $\Delta\omega(t)$, which is the difference between the expected grid frequency $\omega_g$ and the true grid frequency. This is then fed to a sawtooth generator/VCO (i.e. resettable integrator), which generates the estimated grid angle $\hat{\theta}(t)$.
Since the PLL I'm actually implementing is a little bit more complex, I basically need to discretize the individual blocks and not the whole thing in one go (is that even possible? Even if so, it wouldn't help my case - see additional info below).
Discretizing the PI and VCO is trivial enough, just use backwards euler or tustin/bilinear, easy - with the caveat that the integrator can't just be reset at any given timestep, it has to either "overflow" at $2\pi$ or have its output be the remainder of a division by $2\pi$ in order to avoid weird phase jumps.
That's all fine, the problem stems from the fact that a delay is obviously needed. My first approach was to place a unit delay between $\hat{\theta}(t)$ and $\theta_r(t)$, so my pseudo-code at each time-step would look like:
At each timestep compute:
vq = DQ0(v_abc, theta_r)
delta_omega = PI(vq)
omega_i = omega_g + delta_omega
theta_estimated = VCO(omega_i)
//Prepare theta_r for next timestep
theta_r = theta_estimated
Note that:
- The DQ0 transform only outputs
vq=0
if its input equals the grid angle $\theta[n]$. - Its input is
theta_r
, i.e. $\hat{\theta}[n-1]$. - The PI will drive
vq
to zero.
The only logical conclusion is that $\hat{\theta}[n-1]$ will equal $\theta[n]$. Thus it makes no sense to have $\hat{\theta}[n]$ be the actual output of the SRF-PLL, the output must be $\hat{\theta}[n-1]$ in order to achieve zero-error steady state.
But this is just weird. So if in a given timestep $n$ I find that my estimation was a little bit off, my PI corrects, a new angle is calculated... but I'll still be outputting $\hat{\theta}[n-1]$, which I know must be wrong because that's what I just used to compute the DQ0 transform!!
So yeah, basically I really don't know where to place the unit delay. I thought about it, like placing after the PI or after the DQ0 transform, but none really seem to make sense to me.
One super weird solution that I came up with (which would alter the system architecture) would be to add to theta_r
what I "predict" $\theta[n]$ would be at the beginning of each timestep. Hence, the input to the DQ0 would be this "predicted" angle $\hat{\theta}[n-1] + \omega_i[n-1]\cdot sample\_rate$. I really don't like this solution because it is no longer a direct 1:1 discretization, but I'm curious to hear your opinions about it.
Additional info:
1) The DQ0 transform, whatever variant it might be (power invariant, amplitude invariant, A-aligned, 90deg before A, etc), is non-linear, involving different sine and cosine functions. Understanding how it works isn't really important to answer this question other than the fact that it provides a signal proportional to the phase difference between its rotation angle $\theta_r(t)$ and the grid angle of the three-phase voltages $v_a(t)$, $v_b(t)$ and $v_c(t)$.
2) Discretizing the whole thing in one go is not an option because my implementation requires other non-linear components. Hence, discretizing blocks one-by-one is my only choice.
EDIT: As was pointed out, placing a unit delay at any of the locations I mentioned makes no difference as LTI systems are commutative.
I guess the answer I'm searching for is more of a confirmation that yes - I just need to place a unit delay somewhere and live with the fact that the PLL takes 1 extra time-step to respond to disturbances - or that no - there is a way to make the PLL react to a disturbance in the same time-step where said disturbance appeared.