A continuación expongo un caso de un controlador PID Discreto, la idea es poder contrastar los resultados con Simulink. Ademas quiero mantener las constantes Kp, Ki, Kd del controlador continuo al discreto, para no tener que volver a calcularlas.
La planta utilizada es mostrada a continuación (La planta se discretizo con la Aproximacion Bilineal y Ts=0.2):
Para la planta continua se utilizo un controlador PID con parametros Kp=80, Ki=100, Kd=5.
Ahora buscare una formula que permita crear un algoritmo de un PID Discreto, al cual se le ingresen las constantes Kp, Ki, Kd del controlador continuo. Para ello utilizo el metodo expuesto en el Libro: Sistemas de Control Discreto de Katsuhiko Ogata, Segunda Edicion, Paginas 115 y 116. Los calculos realizados son mostrados a continuacion.
Entonces la funcion discreta del controlador es la siguiente:
Simulacion del Sistema en Simulink
Resultados
Ahora los resultados del microcontrolador: Primero el algoritmo.
#include <16F877A.h>
#device adc=8
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
// VARIABLES SISTEMA CONTINUO
float Xi = 1.34097047;
float Wn = 4.474371464;
float Ganancia = 0.099900099;
float SalidaSist2[3] = {0,0.0,0.0}; //0=Actual, 1=Anterior, 2=AnteriorAnterior
float EntradaSist2[3] = {0.0,0.0,0.0};//0=Actual, 1=Anterior, 2=AnteriorAnterior
// DEFINICIONES APROXIMACION BILINEAL
#define fs 5
#define Ts 0.2
#define A (4*fs*fs-4*Xi*Wn*fs+Wn*Wn)
#define B (2*Wn*Wn-8*fs*fs)
#define C (4*fs*fs+4*Xi*Wn*fs+Wn*Wn)
#define D (Ganancia*Wn*Wn)
// DEFINICIONES PID
float Kp = 80;
float Ki = 100;
float Kd = 5;
float Referencia = 1;
#define A_PID (2*Kp*Ts+Ki*Ts*Ts+2*Kd)
#define B_PID (Ki*Ts*Ts-2*Kp*Ts-4*Kd)
#define C_PID (2*Kd)
#define D_PID (2*Ts)
float M[2] = {0,0}; //0=Actual, 1=Anterior,
float Error[3] = {1,0,0}; //0=Actual, 1=Anterior, 2=AnteriorAnterior
int contador = 0;
void main(){
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
while(true){
Error[0] = Referencia - SalidaSist2[0]; //Calcula el Error
M[0] = (1/D_PID)*(A_PID*Error[0]+B_PID*Error[1]+C_PID*Error[2]+D_PID*M[1]);
M[1] = M[0];
Error[2] = Error[1];
Error[1] = Error[0];
//___PLANTA___
EntradaSist2[0] = M[0]; //La salida del PID es la entrada de la Planta
SalidaSist2[0] = (1/C)*(D*(EntradaSist2[2]+2*EntradaSist2[1]+EntradaSist2[0])-A*SalidaSist2[2]-B*SalidaSist2[1]);
EntradaSist2[2] = EntradaSist2[1];
EntradaSist2[1]=EntradaSist2[0];
SalidaSist2[2] = SalidaSist2[1];
SalidaSist2[1] = SalidaSist2[0];
//___MUESTRA LOS RESULTADOS___
printf("%3.2f seg) %3.4f \r",(1.0*contador
)/5.0,SalidaSist2
[0]); contador++;
delay_ms(200);
}
}
Resultados del microcontrolador
Se ve que los resultados de la salida no corresponden a los entregados por simulink. Pense en que los modelos del algoritmos estaban mal, asi que probe el controlador con la planta en lazo abierto como muestra la figura.
Los datos obtenidos en Simulink:
Se comenta la linea 47 del codigo anterior y se obtienen los siguientes datos:
Entonces supongo que los modelos en el microcontrolador estan bien, pero al retroalimentar no funciona el control.
¿Alguien me puede ayudar?.
Gracias