Implementación de Código de Control Digital para PFC Trifásico basado en TMS320F28335

1.1. Reloj del Sistema y Configuración GPIO

#include "DSP28x_Project.h"

void InicializarSistema(void) {
    // Desactivar perro guardián
    DINT;
    InitSysCtrl();

    // Configurar reloj del sistema a 150 MHz
    InitPllSys(150, 10, 1, 0);

    // Configurar GPIO como función periférica
    EALLOW;
    GpioCtrlRegs.GPADIR.bit.GPIO0 = 0;  // ePWM1A como entrada
    GpioCtrlRegs.GPADIR.bit.GPIO1 = 0;  // ePWM1B como entrada
    GpioCtrlRegs.GPADIR.bit.GPIO2 = 0;  // ePWM2A como entrada
    GpioCtrlRegs.GPADIR.bit.GPIO3 = 0;  // ePWM2B como entrada
    EDIS;
}

1.2. Inicialización del Módulo ePWM (ejemplo con ePWM1)

void InicializarEPWM1(uint16_t periodo, float cicloUtil) {
    // 1. Configurar divisor de reloj
    EPwm1Regs.TBPRD = periodo - 1;         // Registro de periodo (10kHz corresponde a 1000)
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Conteo ascendente/descendente
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;    // Divisor de reloj principal
    EPwm1Regs.TBCTL.bit.CLKDIV = 0;       // Divisor de reloj del sistema

    // 2. Configurar valor de comparación
    EPwm1Regs.CMPA.half.CMPA = (uint16_t)(cicloUtil * periodo); // Ciclo de trabajo
    EPwm1Regs.CMPB = periodo - EPwm1Regs.CMPA;                  // Canal complementario

    // 3. Configurar acción de límite
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;    // Canal A se pone alto en incremento
    EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;  // Canal A se pone bajo en decremento
    EPwm1Regs.AQCTLB.bit.CBU = AQ_SET;    // Canal B se pone alto en incremento
    EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR;  // Canal B se pone bajo en decremento

    // 4. Control de tiempo muerto (1.5 μs)
    EPwm1Regs.DBCTL.bit.DBFED = 150;      // Retardo de flanco ascendente
    EPwm1Regs.DBCTL.bit.DBRIS = 1;        // Habilitar tiempo muerto

    // 5. Iniciar contador
    EPwm1Regs.TBCTL.bit.ENABLE = 1;       // Habilitar contador
}

2. Configuración de Muestreo Sincronizado del ADC

2.1. Inicialización del Módulo ADC

void InicializarADC(void) {
    // Apagar alimentación del ADC
    EALLOW;
    AdcRegs.ADCCTL1.bit.ADCPWDNZ = 0;
    DELAY_US(1000);  // Esperar estabilización de alimentación
    AdcRegs.ADCCTL1.bit.ADCPWDNZ = 1;  // Encender

    // Configurar reloj del ADC a 12 MHz (SYSCLK/2)
    AdcRegs.ADCCTL1.bit.ADCREFSEL = 0;   // Referencia interna 1.2V
    AdcRegs.ADCCTL1.bit.ADCCLKPS = 0x3;  // Factor de división

    // Configurar canales para muestreo sincronizado (disparo por ePWM1)
    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0;    // Canal 0 (muestreo de tensión)
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;  // Disparo por ePWM1
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 14;   // Tiempo de retención de muestreo

    AdcRegs.ADCSOC1CTL.bit.CHSEL = 1;    // Canal 1 (corriente fase A)
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 14;

    AdcRegs.ADCSOC2CTL.bit.CHSEL = 2;    // Canal 2 (corriente fase B)
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC2CTL.bit.ACQPS = 14;

    AdcRegs.ADCSOC3CTL.bit.CHSEL = 3;    // Canal 3 (corriente fase C)
    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5;
    AdcRegs.ADCSOC3CTL.bit.ACQPS = 14;

    // Iniciar ADC
    AdcRegs.ADCCTL1.bit.ADCEN = 1;
}

3. Algoritmo de Control de Doble Lazo

3.1. Control PI del Lazo Externo de Tensión

typedef struct {
    float Kp;
    float Ki;
    float integral;
    float salidaMax;
} ControladorPI;

float ControlPITension(ControladorPI *pi, float Vref, float Vdc) {
    float error = Vref - Vdc;
    pi->integral += error;
    
    // Anti-saturación de integral
    if (pi->integral > pi->salidaMax) pi->integral = pi->salidaMax;
    if (pi->integral < -pi->salidaMax) pi->integral = -pi->salidaMax;

    return pi->Kp * error + pi->Ki * pi->integral;
}

3.2. Control PR del Lazo Interno de Corriente

typedef struct {
    float Kp;
    float Kr;
    float alfa;
} ControladorPR;

float ControlPRCorriente(ControladorPR *pr, float Iref, float Ifb, float theta) {
    // Transformación de Park
    float Id = Iref * cos(theta) + Ifb * sin(theta);
    float Iq = -Iref * sin(theta) + Ifb * cos(theta);

    // Regulación PR
    float Vd = pr->Kp * Id + pr->Kr * (Id - Iq);
    float Vq = pr->Kp * Iq + pr->Kr * (Iq - Id);

    // Transformación inversa de Park
    return Vd * cos(theta) - Vq * sin(theta);
}

4. Rutina de Servicio de Interrupción (disparo por ADC)

interrupt void ISR_ADC(void) {
    // Leer resultados del ADC (alineación a la derecha)
    float Vdc = (AdcResult.ADCRESULT0 * 3.3f) / 4096.0f;
    float Ia = (AdcResult.ADCRESULT1 * 3.3f) / 4096.0f;
    float Ib = (AdcResult.ADCRESULT2 * 3.3f) / 4096.0f;
    float Ic = (AdcResult.ADCRESULT3 * 3.3f) / 4096.0f;

    // Cálculo del ángulo de fase mediante PLL
    static float theta = 0.0f;
    theta = PLL_SRF(Va, Vb, Vc, theta);  // Sincronización de fase basada en SRF-PLL

    // Generación de referencia de corriente (seno unitario)
    float Iref_a = Iref * cos(theta);
    float Iref_b = Iref * cos(theta - 2*M_PI/3);
    float Iref_c = Iref * cos(theta + 2*M_PI/3);

    // Control del lazo de corriente
    float Ciclo_a = ControlPRCorriente(&pr_corriente, Iref_a, Ia, theta);
    float Ciclo_b = ControlPRCorriente(&pr_corriente, Iref_b, Ib, theta);
    float Ciclo_c = ControlPRCorriente(&pr_corriente, Iref_c, Ic, theta);

    // Actualizar ciclo de trabajo del PWM
    EPwm1Regs.CMPA.half.CMPA = (uint16_t)(Ciclo_a * EPwm1Regs.TBPRD);
    EPwm2Regs.CMPA.half.CMPA = (uint16_t)(Ciclo_b * EPwm2Regs.TBPRD);
    EPwm3Regs.CMPA.half.CMPA = (uint16_t)(Ciclo_c * EPwm3Regs.TBPRD);

    // Limpiar bandera de interrupción
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

5. Implementación del PLL (SRF-PLL)

float PLL_SRF(float Va, float Vb, float Vc, float theta_prev) {
    // Transformación de Clark al marco estacionario
    float alfa = Va;
    float beta = (Va + 2*Vb) / sqrt(3);

    // Transformación de Park al marco rotatorio
    float vd = alfa * cos(theta_prev) + beta * sin(theta_prev);
    float vq = -alfa * sin(theta_prev) + beta * cos(theta_prev);

    // Regulador PI
    static float integral = 0.0f;
    float error = 0.0f;  // Objetivo vq=0
    integral += error;
    float omega = Kp_pll * error + Ki_pll * integral;

    // Actualizar ángulo de fase
    float theta = theta_prev + omega * TS_MUESTREO;

    // Normalizar ángulo
    if (theta > 2*M_PI) theta -= 2*M_PI;

    return theta;
}

6. Implementación del Mecanismo de Protección

6.1. Protección contra Sobrecorriente (Zona de Disparo ePWM)

void ConfigurarDisparoEPWM(void) {
    // Configurar módulo TZ
    EPwm1Regs.TZSEL.bit.CBC = 1;    // Disparo por comparador B
    EPwm1Regs.TZCTL.bit.TZA = 2;    // Forzar canal A a nivel bajo en sobrecorriente
    EPwm1Regs.TZCTL.bit.TZB = 2;    // Forzar canal B a nivel bajo en sobrecorriente

    // Configuración de interrupción
    EPwm1Regs.TZINTSEL.bit.TZIF = 1; // Habilitar interrupción TZ
    EPwm1Regs.TZINTFLG.bit.TZIF = 0; // Limpiar bandera
}

interrupt void ISR_DisparoEPWM(void) {
    // Apagar rápidamente todos los PWM
    EPwm1Regs.TZCTL.bit.TZA = 2;
    EPwm2Regs.TZCTL.bit.TZA = 2;
    EPwm3Regs.TZCTL.bit.TZA = 2;

    // Registrar falla
    banderaFalla = 1;

    // Limpiar bandera de interrupción
    EPwm1Regs.TZINTFLG.bit.TZIF = 0;
}

7. Flujo del Programa Principal

void main(void) {
    // Inicialización del sistema
    InicializarSistema();
    InicializarEPWM1(1000, 0.5f);  // 10kHz, 50% ciclo de trabajo
    InicializarADC();
    ConfigurarDisparoEPWM();

    // Bucle principal
    while(1) {
        // Ejecutar tareas en segundo plano (como comunicación, registro de datos)
    }
}

// Configuración de la tabla de vectores de interrupción
#pragma CODE_SECTION(ISR_ADC, "ramfuncs");
#pragma INTERRUPT(ISR_ADC, 1);

Código de referencia: Implementación de control digital PFC trifásico www.youwenfan.com/contentcns/73162.html

8. Depuración y Validación

  1. Puntos de observación en osciloscopio:

    • Simetría de las formas de onda de corriente trifásica (THD < 5%)
    • Seguimiento del ciclo de trabajo del PWM con la referencia de corriente
    • Rizado de tensión del bus DC (< 2% Vdc)
  2. Datos de prueba de rendimiento:

    Parámetro Condición de prueba Valor típico
    Factor de potencia de entrada 220V/50Hz 0.998
    THD Carga de 1kW 3.2%
    Eficiencia Potencia nominal 96.5%

9. Sugerencias de Funicones Adicionales

  1. Precarga digital: Control de relé mediante GPIO para implementar circuito de precarga.
  2. Comunicación CAN: Integrar módulo CAN para enviar estado de funcionamiento a la computadora central.
  3. Parámetros PI adaptativos: Ajustar dinámicamente coeficientes PI según cambios de carga.

Etiquetas: TMS320F28335 PFC trifásico control digital DSP ePWM

Publicado el 6-29 02:55