// 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]= ref; referencia // in[1]= sal; variable a controlar // in[2]= Fcpu; frecuencia del oscilador de la uC // in[3]= 0; // in[4]= 0; // in[5]= 0; // in[6]= 0; // Incluye librerias especiales o datos .h //#include "dll.h" //#include //#include "ganancias.h" //#define Vpp 10 // Ganacia del actuador // Coeficientes del controlador Deadbeat: #define p1 0.5515 #define p2 0.4420 #define p3 0.0065 #define q0 0.2751 #define q1 -0.3003 #define q2 0.0252 #define q3 -0.000018635 // Registros internos del microcontrolador #define PER 3125 // Define el periodo del Timer. #define PRESC 32 // Define el prescaler del Timer. // Para flags y demás: #define OFF 0 // Apagado. #define ON 1 // Encendido. // PER: 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: Ts = PER*PRESC/Fosc // // Para este caso se tiene: Ts = 0.4 seg; PRESC = 32 y Fosc = 250 kHz => PER = Ts*Fosc/PRESC = 3125 // El contador en este caso se setea para que sea ascendente, con reset en Ts. // PROGRAMA QUE SE EJECUTA EN CADA PASO DE SIMULACION void __declspec(dllexport) simuser (double t, double delt, double *in, double *out){ // Variables con doble precisión static double y=0; // Variable controlada static double ref; static double ek = 0; // Error actual. static double ekm1 = 0; // Error anterior. static double ekm2 = 0; static double ekm3 = 0; static double uk = 0, uc=0, uk1=0; // Acc. de control actual. static double ukm1 = 0; // Acc. de control anterior. static double ukm2 = 0; static double ukm3 = 0; static double Ts; // Periodo de muestreo static double Fosc, Tosc; // Variables p/calculo del valor máximo del contador Ncont // Variables enteras static int contador=0, Ncont, direccion = 1; static int PWM; static int ComparReg; // Variables booleanas: static char FLAG_calculo; // Flag p/indicar si se calcula la acc. de control. static char FLAG_muestreo = OFF; // Flag p/indicar si se muestrea. static char muestra = 0; static char update = 0; // Se calcula el numero de conteos en un periodo: Valor máximo del contador //---------------------------------------------------------------------------------- // CÁLCULOS INICIALES //---------------------------------------------------------------------------------- Fosc = in[2]; // Adquiere frecuencia del oscilador externo Tosc = 1/Fosc; // Calcula periodo de la señal de reloj de la CPU. Ts = (PER*PRESC)/Fosc; // Calcula el periodo de muestreo Ncont=Ts/delt; // Calculo del valor máximo del contador del timer PWM o ADC //muestra = 0; // Se realiza el muestreo de las variables controladas if(FLAG_muestreo == ON){ FLAG_muestreo = OFF; muestra = 0; y = in[1]; FLAG_calculo = ON; } // Calculo de la estrategia de control if(FLAG_calculo == ON){ FLAG_calculo = OFF; ref = in[0]; // Adquiere la referencia (igual que generar adentro del uC) /*********************************************************************************/ /* Se calcula el error entre la salida de la planta y la referencia */ /*********************************************************************************/ ek = ref - y; /*****************************************************************************************/ /* Calculo del controlador deadbeat */ /* u(k)=p1*u(k-1) + p2*u(k-2) + p3*u(k-3) + q0*e(k) + q1*e(k-1) + q2*e(k-2) + q3*e(k-3) */ /*****************************************************************************************/ uk = p1*ukm1 + p2*ukm2 + p3*ukm3 + q0*ek + q1*ekm1 + q2*ekm2 + q3*ekm3; // Almacena variables anteriores para el proximo periodo de muestreo. ukm3 = ukm2; ukm2 = ukm1; ukm1 = uk; ekm3 = ekm2; ekm2 = ekm1; ekm1 = ek; //Para lazo abierto //uk = ref; out[2] = uk; // Se realiza la actualización de la acción de control, enseguida después de finalizado el cálculo uc = uk*Ncont; // Acción de control cargada al registro de comparación para genrear el PWM } //termina el calculo de la estrategia de control //************************************************************// // Incrementamos o decrementamos el contador segun corresponda if(contador == 0){ FLAG_muestreo = ON; muestra = 1; } contador = contador + 1; if(contador == Ncont){ contador = 0; ComparReg = uc; //uk1 = uk; // debido al atraso de implementación digital se // actualiza la acción de control con 1 periodo de muestreo de atraso } // Maquina de estado que define el patrón PWM if(ComparReg >= contador) PWM = 1; else PWM = 0; // Se actualizan los valores de las salidas out[0] = PWM; // *Vpp si no está normalizado out[1] = uc; out[3] = ref; out[4] = y; out[5] = ek; out[6] = contador; out[7] = ComparReg; out[10]= muestra; }