////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ****FUNCTION: simuser **** PARA PSIM 9.0.3 32 bit // ****FUNCTION: SimulationStep**** PARA PSIM 2022 64 bit // double t: (read only) time // double delt: (read only) time step as in Simulation control // double *in: (read only) zero based array of input values. in[0] is the first node, in[1] second input... // double *out: (write only) zero based array of output values. out[0] is the first node, out[1] second output... // int *pnError: (write only) assign *pnError = 1; if there is an error and set the error message in szErrorMsg // strcpy(szErrorMsg, "Error message here..."); // DO NOT CHANGE THE NAME OR PARAMETERS OF THIS FUNCTION // Las entradas del sistema son // in[0]= ref; referencia // in[1]= y; variable a controlar // in[2]= Fosc; frecuencia del oscilador deL uC // in[3]= 0; // in[4]= 0; // in[5]= 0; // in[6]= 0; // Incluye librerias especiales o datos .h //#include //#include "ganancias.h" // Coeficientes del controlador de adelanto. Mp = 2 % y ts menor a 2 seg. // Periodo de muestreo T = 0.0978 seg. #define a1 24.03 #define a2 -19.76 #define a3 0.06546 // ** Configurar el registro de periodo del contador para el periodo de muestreo elegido // TPER: Registro de periodo para timer de 16 bits, puede ser cualquier valor entero de 1 a 65535. // PRESC: Pre-scaler que pueden ser valores de 1, 2, 4, 16, 32. // Periodo de muestreo: Tm = TPER*PRESC/Fosc // Ejemplo: Tm = 0.01024seg, Fosc = 500kHz y PRESC = 32 => TPER = Tm*Fosc/PRESC = 160 // Para Tm=0.0978 s; Fosc = 1 MHz; PRESC = 32 => TPER = Tm*Fosc/PRESC = 3056 // Registros internos del microcontrolador #define TPER 3056 // Define el periodo del Timer del PWM (97.80 ms). #define PRESC 32 // Define el prescaler del Timer1. //****Función para PSIM 9.0.3**** Compilar usando TDM-GCC 32-bit Release //void __declspec(dllexport) simuser (double t, double delt, double *in, double *out){ //****Función para PSIM 2022**** Compilar usando TDM-GCC 64-bit Release void SimulationStep(double t, double delt, double *in, double *out) { // Variables reales static double y=0; // Variable controlada static double uk=0, ukm1=0; // Acción de control static double ek=0, ekm1=0; // Error de control static double ref; // Referencia static double Tm; // Periodo de muestreo static double Fclock; // Variables para el cálculo de la relación Ncont. // Variables enteras static int contador=0, Ncont, calculo_u, muestreo = 1, muestra, direccion = 1; // Se calcula el número de conteos en un periodo: Valor máximo del contador //---------------------------------------------------------------------------------- // CÁLCULOS INICIALES //---------------------------------------------------------------------------------- Fclock = in[2]; // Adquiere frecuencia del oscilador Tm = (TPER*PRESC)/Fclock; Ncont=Tm/delt; // Número de conteos del timer muestra=0; if(muestreo == 1) { muestreo=0; // Se realiza el muestreo de las variables controladas y = in[1]; calculo_u=1; // Llama a rutina de cálculo de la acción de control } if (calculo_u==1) { calculo_u=0; ref = in[0]; // Toma la referencia impuesta en PSIM /*********************************************************************************/ /* Se calcula el error entre la salida de la planta y la referencia */ /*********************************************************************************/ ek = ref - y; /*********************************************************************************/ /* Calculo del controlador */ /*********************************************************************************/ // Se utiliza un controlador de adelanto de fase // u(k) = a1*e(k) + a2*e(k-1) + a3*u(k-1); uk = a1*ek + a2*ekm1 + a3*ukm1; // Calcula acc. de control // Se actualizan los valores anteriores de las variables de error y acción de control ekm1 = ek; ukm1 = uk; //Para lazo abierto //uk = ref; } //termina el cálculo de la estrategia de control //**********************************************************// // Incrementamos o decrementamos el contador segun corresponda // Aqui se implementa un contador up-down contador = contador + direccion; if (contador == 0) { direccion=1; muestreo=1; muestra=1; out[0] = uk; // La acción de control se actualiza con atraso de 1 periodo Tm } if (contador == Ncont/2) { direccion=-1; muestreo=0; muestra=0; } // Se actualizan los valores de las salidas out[1] = ref; out[2] = y; out[3] = ek; out[4] = contador; out[5] = muestra*50000; }