Hello, I have been attempting to resolve following issue related to the simulation in Scilab/Xcos. I have been developing a control software and at the time being I have been developing a library of the building blocks. One of the building blocks is a PID controller. I have written the C code of the PID controller in velocity form and my idea was to verify its behavior via simulation in Scilab/Xcos with the CBLOCK usage. For that purpose I have developed following simulation in Scilab/Xcos
<http://mailinglists.scilab.org/file/t497955/PID_simulace_diagram.jpg> The internal details of the PID Controller super block: <http://mailinglists.scilab.org/file/t497955/PID_CBLOCK.jpg> the code inside the CBLOCK: #include <math.h> #include <stdlib.h> #include <scicos_block.h> #include <stdio.h> FILE *f; // U(k-1) double U1 = 0.0; // E(k-1) double E1 = 0.0; // E(k-2) double E2 = 0.0; // Ud(k-1) double Ud1 = 0.0; // Ud(k-2) double Ud2 = 0.0; // act(k-1) double A1 = 0.0; // act(k-2) double A2 = 0.0; void PID_controller(scicos_block *block,int flag) { /* int block->nevprt; int block->nz; double* block->z; int block->nx; double* block->x; double* block->xd; double* block->res; int block->nin; int *block->insz; double **block->inptr; int block->nout; int *block->outsz; double **block->outptr; int block->nevout; int block->nrpar; double *block->rpar; int block->nipar; int *block->ipar; int block->ng; double *block->g; int *block->jroot; char block->label[41]; */ if (flag == 4) { /* initialization */ PID_controller_bloc_init(block,flag); } else if(flag == 1) { /* output computation*/ set_block_error(PID_controller_bloc_outputs(block,flag)); } else if(flag == 2) { /* computation of next discrte state*/ set_block_error(PID_controller_bloc_states(block,flag)); } else if (flag == 5) { /* ending */ set_block_error(PID_controller_bloc_ending(block,flag)); } } int PID_controller_bloc_init(scicos_block *block,int flag) { f = fopen("PID.txt", "w"); fprintf(f, "R A2 A1 A E2 E1 E DUp DUi DUd U1 U SatU\n"); fprintf(f, "==============================================================================================================================================================================================================\n"); return 0; } int PID_controller_bloc_outputs(scicos_block *block,int flag) { // block parameters double Kp; double Ti; double Td; double N; double Umin; double Umax; double T; // reference value double R; // actual value double A; // control error double E; // control value double U; double SatU; // increment of proportional part double DUp; // increment of integration part double DUi; // increment of derivative part double DUd; // derivative part double Ud; // increment of control value double DU; // reading in of the block inputs R = block->inptr[0][0]; A = block->inptr[1][0]; // reading in of the block parameters Kp = block->rpar[0]; Ti = block->rpar[1]; Td = block->rpar[2]; N = block->rpar[3]; Umin = block->rpar[4]; Umax = block->rpar[5]; T = block->rpar[6]; // current control error E = R - A; DUp = Kp*(E - E1); // increment of proportional part DUi = (Kp*T)/(2*Ti)*(E + E1); // increment of integration part DUd = (Td)/(Td + N*T)*(Ud1 - Ud2) - (Kp*Td*N)/(Td + N*T)*(A - 2*A1 + A2); // increment of derivative part with filtering pole Ud = Ud1 + DUd; // derivative part DU = DUp + DUi + DUd; // increment of control value U = U1 + DU; // control value // saturation of the control value according to the limits of the actuator if(U > Umax) { SatU = Umax; } else if(U < Umin) { SatU = Umin; } else { SatU = U; } U1 = SatU; // writing at the outputs block->outptr[0][0] = SatU; fprintf(f, "%f, %f, %f, %f, %f, %f, %f %f %f %f %f %f %f \n", R, A2, A1, A, E2, E1, E, DUp, DUi, DUd, U1, U, SatU); // memory refresh E2 = E1; E1 = E; A2 = A1; A1 = A; Ud2 = Ud1; Ud1 = Ud; return 0; } int PID_controller_bloc_states(scicos_block *block,int flag) { return 0; } int PID_controller_bloc_ending(scicos_block *block,int flag) { fclose(f); return 0; } I have run the simulation with below given setup <http://mailinglists.scilab.org/file/t497955/PID_simulace_nastaveni.jpg> and I have received following outcomes <http://mailinglists.scilab.org/file/t497955/PID_simulace_diagram_vystupy_Scilab.gif> The outcomes seemed strange to me. So I have decided to develop the whole simulation in C language in parallel. The C code of my simulation: #include <stdio.h> #include <stdlib.h> #include <math.h> // random noise in <-0.01; +0.01> #define RANDOM_NOISE (0.02*((double)rand()/(double)RAND_MAX) - 0.01) FILE *f; typedef struct { float T; float tau; float out1; }FilterLP_t; typedef struct { float T; float Kp; float Ti; float Td; float N; float OutMin; float OutMax; float Ud1; float Ud2; float U1; float Err1; float Err2; float Act1; float Act2; }PID_t; void filter(float *in, float *out, FilterLP_t *instance); void pid(float *ref, float *act, float *out, PID_t *instance); /* * */ int main(int argc, char** argv) { f = fopen("PID_Sim.txt", "w"); FilterLP_t sysModel; sysModel.T = 0.01; sysModel.tau = 10.0; sysModel.out1= 0.0; PID_t controller; controller.T = 0.01; controller.Kp = 3.0; controller.Ti = 0.125; controller.Td = 2.0; controller.N = 2.0; controller.OutMin = 0.0; controller.OutMax = 1.5; controller.Ud1 = 0.0; controller.Ud2 = 0.0; controller.U1 = 0.0; controller.Err1 = 0.0; controller.Err2 = 0.0; controller.Act1 = 0.0; controller.Act2 = 0.0; float ref = 1.0; float sysIn; float sysOut = 0.0; float sysOutMeasured = 0.0; fprintf(f, "r(k), u(k), y(k)\n"); fprintf(f, "====================\n"); uint16_t i; for(i = 0; i < 3000; i++) { pid(&ref, &sysOutMeasured, &sysIn, &controller); filter(&sysIn, &sysOut, &sysModel); sysOutMeasured = sysOut; fprintf(f, "%f, %f, %f \n", ref, sysIn, sysOut); } fclose(f); return (EXIT_SUCCESS); } void filter(float *in, float *out, FilterLP_t *instance) { float tmp; tmp = instance->out1 + (instance->T/(instance->T + instance->tau))*(*in - instance->out1); instance->out1 = tmp; *out = tmp; } void pid(float *ref, float *act, float *out, PID_t *instance) { double Ki, Ad, Bd; double Err, DUp, DUi, DUd, Ud, DU, U, SatU; Ki = (instance->Kp*instance->T)/(2*instance->Ti); Ad = instance->Td/(instance->Td + instance->N*instance->T); Bd = (instance->Kp*instance->Td*instance->N)/(instance->Td + instance->N*instance->T); Err = *ref - *act; DUp = instance->Kp*(Err - instance->Err1); DUi = Ki*(Err + instance->Err1); DUd = Ad*(instance->Ud1 - instance->Ud2) - Bd*(*act - 2*instance->Act1 + instance->Act2); Ud = instance->Ud1 + DUd; DU = DUp + DUi + DUd; U = instance->U1 + DU; if(U > instance->OutMax) { SatU = instance->OutMax; } else if(U < instance->OutMin) { SatU = instance->OutMin; } else { SatU = U; } instance->U1 = SatU; *out = SatU; instance->Err2 = instance->Err1; instance->Err1 = Err; instance->Act2 = instance->Act1; instance->Act1 = *act; instance->Ud2 = instance->Ud1; instance->Ud1 = Ud; } I have run the simulation with exactly the same PID controller settings and I have received these outcomes <http://mailinglists.scilab.org/file/t497955/PID_simulace_diagram_vystupy_C.jpg> There are obvious differences between what the Scilab/Xcos gives and what gives my simulation in C language. I trust more the C language simulation. So I would say that there is some problem in my simulation in the Scilab/Xcos. Unfortunatelly I don't know what is wrong. It seems that the control loop in the Scilab/Xcos has lower damping than in the C language simulation. Does anybody have any idea why this behavior occurs? -- Sent from: http://mailinglists.scilab.org/Scilab-users-Mailing-Lists-Archives-f2602246.html _______________________________________________ users mailing list [email protected] http://lists.scilab.org/mailman/listinfo/users
