(Beginning is extra information, my question related to the PID part)
Dear forum member,
I am designing a closed loop system using SigmaDSP and external hardware. Basically, we take the input signal from the photodetector, demodulate(multiply with reference signal) and pass it through LPF and obtain an in-phase signal(also mentioned as an error signal).
There are coils and we apply a signal with constant amplitude and changing frequency. The in-phase signals amplitude changes(between 1 and -1) with respect to the frequency applied to the coils. We have to apply the frequency which will make the in-phase(error) signal zero. We have to constantly track the error signal and change the frequency if the error signal becomes nonzero. Basically, at 8500Hz, the error signal is +1 and decreases linearly. At 8610Hz it becomes 0V and at 8720Hz the error signal becomes -1V. My purpose is to adjust the frequency in a way to keep the error signal at 0V. (add freq on a positive error and subtract on negative)
First, the approximate resonance frequency(is a frequency which will make the error signal close to zero) is found, then the PID closed loop is applied to fine-tune the error signal and make the error signal exactly zero. With changing the magnetic field, changes the resonance frequency, so the PID must track the error signal and change the frequency accordingly.
I have designed a PID system, but the output(error signal) never becoming stable. It keeps oscillating around zero. I presume the problem might be in the derivative part.
The code is as follows, I tried to design a similar system in Sigma Studio. /*The proportional value of the PID is just a proportional constantmultiplied by the error*/
pid_p = kp*error;
/*To integrate we just sum the previous integral value with theerror multiplied by the integral constant. This will integrate (increase)the value each loop till we reach the 0 point*/ pid_i = pid_i+(ki*error);
/*The last part is the derivate. The derivate acts upon the speed of the error.As we know the speed is the amount of error produced in a certain amount oftime divided by that time. For that, we will use a variable called previous_error.We subtract that value from the actual error and divide all by the elapsed time. Finaly we multiply the result by the derivate constant*/
pid_d = kd*((error - previous_error)/elapsedTime);
/*The final PID values is the sum of each of this 3 parts*/PID = pid_p + pid_i + pid_d;
More is given in the sigma studio material with the comments.
Question: Am I implementing PID control correctly, derivative, integral? I am in need of help.
SigmaPID - working.rar
(very detailed answer)
Hi Bob, thanks for your fast response. I replaced the 2Hz second-order LPF with 1st order LPF and I still see the oscillation of the error signal. I was thinking, maybe the problem might be with the design of the feedback system.
Brief info on DC2_5(bottom right): DC value is adjusted so that the signal's frequency, generated from VCO1_3(bottom right) makes the error signal close to zero. (error signal directly depends linearly[negative slope] on the frequency generated from VCO1_3, at 8500Hz error=+1, at 8610Hz its close to zero[not exactly zero], at 8720Hz error = -1).
As shown on the picture attached, instead of adding the PID total to ADD1_5, I think I should add it to the DC value. (better seen on the picture)
I think here is the problem with an old design:
For ex: let's say in the beginning DC=0.3588(initial value), freq is 8610Hz(initial value) and error = 0.1V(initial value).
1) A 0.1V error signal is read and appropriate PID value is generated, let's say PIDtotal=0.005V. PID total will be added to DC source using Add1_5 and 0.3588+0.005=0.3638V(new value) and this sum will generate 8615Hz(new value), which will make the error=0(new value).
2) A 0.0V error signal is read and appropriate PID value is generated, it will be PIDtotal=0V. PID total will be added to DC source using Add1_5 and 0.3588+0=0.3588V(back to initial dc level) and this sum will generate 8610Hz(initial value), which will make the error=0.1V(initial value).
So the loop continues with error signal oscillating between 0.1V and 0V, frequency changing between 8610Hz and 8615Hz.
Question: How can I add the PID total value to the DC2_5(I have to increase the level of the DC2_5, PID total is added to 0.3588), so that in the next loop the DC2_5 value will be the previousPIDtotal+previousDC2_5voltage.
1) A 0.1V error signal is read and appropriate PID value is generated, let's say PIDtotal=0.005V. PID total will be added to DC source(I don't know how) and 0.3588+0.005=0.3638V(the new value of DC source) and this sum will generate 8615Hz(new value), which will make the error=0(new value).
2) A 0.0V error signal is read and appropriate PID value is generated, it will be PIDtotal=0V. PID total will be added to DC source (I don't know how) and 0.3638V+0=0.3638V and this sum will generate 8615Hz, which will make the error=0V.
This way we can always keep the error signal at zero.
The integrator portion of your PID loop implements something like what you're wishing to do -- since it accumulates the error and adds this to the final output. Remember that your project executes 48000 times per second, so any additions accumulate rapidly. The idea is to adjust the error towards zero over time. However, there may be a larger issue here.
If I understand correctly, adjusting the PID parameters and replacing the 2 Hz filter doesn't significantly affect the circuit's operation. Another way of saying this is that the system isn't responding to classical control theory. In turn this suggests that the PLL consisting of the phase detector (multiplier), VCO, and the system dynamics simply isn't locking. Control theory only applies when the PLL is locked. Getting the PLL to lock can prove quite frustrating, especially with a system as involved as this one. PLLs can be quite temperamental -- they work great when they want to..
Perhaps the frequency detector shown below would work more reliably than the multiplier phase detector. Based upon the ratio detector found in most FM radios, it compares the outputs of two peaking filters to provide a frequency-dependent output. The top portion of this schematic provides a test signal, the bottom half is the ratio detector itself (for some reason the pictures aren't showing, click on the icons to see them):
As the test signal sweeps from 8220 Hz to 9000 Hz, the detector's output follows a negative slope which could be used to adjust your output frequency. Its wide bandwidth of 200 Hz allows you to place a dominant pole elsewhere in this loop to achieve stability.
This circuit as it stands assumes that your reference frequency is a steady 8610 Hz -- however your original circuit shows the reference external to the ADAU1701, thus it may vary either over time or with different sets of coils (etc). Here's several ways you might handle this:
Manual calibration (only if the whole system is very stable to begin with)
Automatic power-on calibration (if the system is reasonably stable during use) -- For an example of power-on calibration, see this post
Using a simple PLL, measure the incoming reference frequency (convert the frequency to a DC voltage), then use this to adjust the frequency detector's offset. This PLL should be much easier to implement compared to the original system PLL since it's self-contained without any of the system dynamics. An example of such a PLL is here
Thank you, I will try this schematic on setup and get back to you.