// t: Time, passed from PSIM by value // delt: Time step, passed from PSIM by value // in: input array, passed from PSIM by reference // out: output array, sent back to PSIM (Note: the values of out[*] can // be modified in PSIM) // The maximum length of the input and output array "in" and "out" is 30. // Las entradas del sistema son // in[0]= Vref; frecuencia de la red // in[1]= y; variable controlada // in[2]= Fosc; frecuencia del cristal #include "dll.h" #include // Coeficientes del controlador de adelanto. Mp = 16 % y ts menor a 2 seg. // Periodo de muestreo T = 0.08144 seg. #define a1 19.38 #define a2 -16.47 #define a3 0.5003 // 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: Para timer de 16 bits, puede ser cualquier valor entero de 1 a 65535. // PRESC: Puede ser 1, 2, 4, 16, 32. // Periodo de muestreo: Tm = TPER*PRESC*Tosc // Ejemplo: fs=100 Hz; Tm = 0.01024seg, Fosc = 500kHz y PRESC = 32 => TPER = Tm*Fosc/PRESC = 160 // Para Tm=0.08144 s; Fosc = 1 MHz; PRESC = 32 => TPER = Tm*Fosc/PRESC = 2545 // Para Tm=0.0978 s; Fosc = 1 MHz; PRESC = 32 => TPER = Tm*Fosc/PRESC = 3056 #define TPER 2545 // Define el periodo del Timer del PWM (81.44 ms). //#define TPER 3056 // Define el periodo del Timer del PWM (97.80 ms). #define PRESC 32 // Define el prescaler del Timer1. void __declspec(dllexport) simuser (double t, double delt, double *in, double *out) { static double y=0; // Variable controlada static double uk=0, ukm1=0; static double ek=0, ekm1=0; static double ref; static double Tm; // Periodo de muestreo static double Fclock, Tclock; // Variables p/calculo de la relación Ncont. static double muestra=0; // Variables enteras static int contador=0, Ncont, calculo_u, muestreo = 1, direccion = 1; static int PWM1, PWM2; static int ComparReg1, ComparReg2; // 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*30000; } BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: { break; } case DLL_PROCESS_DETACH: { break; } case DLL_THREAD_ATTACH: { break; } case DLL_THREAD_DETACH: { break; } } /* Return TRUE on success, FALSE on failure */ return TRUE; }