Continuing the Ball and Beam Part 1 project now we require to control the Motor output angle this will be done with the use of a recursive 2DOF PID controller.
I will not go into detail on how to get the recursive algorithm it involves a lot of math and equation solving. What you need to know about the controller is how it works:
- R - Reference Signal (Setpoint/Desired output)
- Beta - Proportional reference weight (Range 0-1)
- Gamma - Derivative reference weight (Range 0-1)
- I - Integral Control (Cumulative error)
- P - Proportional Control (Error Magnitude)
- D - Derivative Control (Slope of the error or error rate of change )
- U - Controller output/Control signal
- D - Disturbance (external influences that cannot be measured)
- Gp - Plant (the actual system to be controlled, in this case is the motor and gearbox)
- Y - Output
Since the algorithm is in recursive form we only need to store the last three values of each reference signal, control signal, and output:
First we initialize the required variables the whole first line will be used for the equation constants calculations, the second line has all the variables that will be constantly updated.
double aA,aB,aC,aD,aE,aF,aG,aH,aI,aJ,aTd,apP,apI,apD,aWD,aWK,apN,aTf;
float uX,uXold1,uXold2,uXold3,rX,rXold1,rXold2,rXold3,X,Xold1,Xold2,Xold3,SPX;
Now the initialization of the PID algorithm the first line contains all the modifiable parameters apP
, apI,
apD
, apN
, aWK
, aWD
, aTf
.
apP=7;apI=125;apD=0;apN=2000;aWK=0.6;aWD=0,aTf=0.00003;
initpidang();
SPX=1;
uX=0; uXold1=0;uXold2=0;uXold3=0;
X=0; Xold1=0; Xold2=0; Xold3=0;
rX=0; rXold1=0;rXold2=0;rXold3=0;
In order to give the processor less tasks or math operations I simplified the equation and separated each coefficient, so after initializing the variables the full equation only uses constant coefficients.
void initpidang (void){ //2dofPID
aA=1/(apN*Ts);
aB=aA*(apN*Ts-1);
aC=aA*(apP*apN*Ts*aWK+apI*Ts*Ts*apN);
aD=aA*(aWK*apP-aWK*apP*apN*Ts+apI*Ts+apD*apN*aWD);
aE=aA*(-2*apP*aWK-apI*Ts-2*apD*apN*aWD);
aF=aA*(apP*aWK+apD*apN*aWD);
aG=aA*(-apP*apN*Ts-apI*Ts*Ts*apN);
aH=aA*(-apP+apP*apN*Ts-apI*Ts-apD*apN);
aI=aA*(2*apP+apI*Ts+2*apD*apN);
aJ=aA*(-apP-apD*apN);
}
And finally the actual control loop first line is the controller equation. Second and third lines limit the maximum and minimum output. Fourth line is just motor command update and the last ones are the values updating to the current set.
uX=uXold1*aB-2*uXold2*aA-uXold3*aA+aC*rX+aD*rXold1+aE*rXold2+aF*rXold3+aG*X+aH*Xold1
+aI*Xold2+aJ*Xold3;
if(fabs(uX)>(PWMmaxper-1)){mot=(PWMmaxper-1)*fabs(uX)/uX;}
else{mot=uX;}
motoroutput();
uXold3=uXold2; uXold2=uYold1; uXold1=motspd;
Xold3=Xold2; Xold2=Xold1; Xold1=X; X=ang;
rXold3=rXold2; rXold2=rXold1; rXold1=rX; rX=SPX;
Here is an example of how using the current ball position value the motor gets an equivalent angle reference and follows it.
Using Micruim uProbe the variables can be plotted easily notice the green line Set point is exactly the ball position divided by 10.
notice also the curve shape is very similar between them
Comments