Convertidor Buck-boost con control digital en STM32F334 en modo CC / CV

Las topologías dc / dc de buck y boost más populares tienen una limitación significativa: la topología de buck solo puede reducir el voltaje de entrada, y la topología de boost solo lo aumenta. Sin embargo, hay tareas cuando el rango de voltaje de entrada requiere un trabajo simultáneo tanto para aumentar como para disminuir, por ejemplo, tenemos una entrada de 3 ... 15V, y en la salida es necesario obtener un 12V estabilizado. Situación familiar?



Hay 2 posibles soluciones:



  • Usando el convertidor elevador, aumente el voltaje de entrada de 3 ... 15V a 15V estable en la salida, y luego, usando la topología de reducción, baje el voltaje a los 12V requeridos;
  • Aplique la topología buck-boost, que le permite resolver este problema de manera óptima.


La desventaja obvia del primer método es la necesidad de usar 2 estranguladores, un mayor número de condensadores y no el modo de operación más óptimo, lo que significa una menor eficiencia. La topología Buck-boost carece de estos inconvenientes, por lo que hoy hablaremos de ello. Para hacerlo interesante, decidí no tomar un controlador listo e implementé un convertidor de CC / CC controlado digitalmente basado en STM32F334C8T6.



Convertidor de fotos



El resultado del trabajo para aquellos que no quieren leer el muro de texto.


En este artículo, hablaré brevemente sobre la implementación de hardware del convertidor y cómo implementar un sistema de control para varios modos de operación. ¿Interesante? Entonces vamos ...



1. Brevemente sobre cómo funciona la topología buck-boost



: 2 2 , .. , 2 (4 ). , . :



Estructura de refuerzo



, : 2 ( 2 , ), 4 , . 1 2 (OCP) . 2 ? , , .



, , , STM32F334, STM32G474, XMC4108, TMS320F28027 , .. : HRPWM, , , . , , , . , , , (OCP) , , .



… buck-boost :



Circuito buck-boost equivalente



buck () boost (), — 3 buck-, L1C3 LC-. 3 boost-, . , buck-, boost-. .



buck:



Vout=VinD



boost:



Vout=Vin(1D)



, buck- boost :



Voutboost=VinbuckDbuck1Dboost



buck-boost 3- : ( PWM-BUCK PWM-BOOST). , .



, . , 8, Dboost 70%, Dbuck 50%. :



Voutboost=VinbuckDbuck1Dboost=8V0,510,7=13,33V



, 8 . , , , 2 - :



Tabla de osciloscopio



. (duty) 2- . duty, .



2. .



2 , : . , , CC/CV . :



Diagrama de bloques de control



CC CV , : REF , , ; , , , , .



-, , " " . "" (REF), , , 10. , buck-boost , (duty). - . , .



:

error=VreferenceVout



Que nos da Y ahora sabemos cuánto se ha desviado el valor real del voltaje de salida del valor establecido ( REF ). Esto nos permite comprender si es necesario "dar una orden" para aumentar o disminuir el voltaje. Por ejemplo, en la topología de inversión , para aumentar el voltaje, debe aumentar el trabajo del transistor superior, y para disminuir el voltaje, reduzca el llenado en consecuencia. Para la topología de boost, por el contrario, hay 2 señales para buck-boost , y aquí es más complicado: necesita equilibrar, pero creo que la idea es clara en promedio, para mayor claridad, le daré un pseudocódigo para controlar buck :

//      -
uint16_t dutyPWM = 0;

//  ,     
const float referenceOutputVoltage = 10.0f;

//    , ,  1 
void sTim3::handler (void) {
    float outputVoltage = GetOutputVoltage();
    if (outputVoltage > referenceOutputVoltage) {
        dutyPWM--;
    } else {
        dutyPWM++;
    }
}


, . - ( ), , -, -:



//      -
uint16_t dutyPWM = 0;

//  ,     
const float referenceOutputVoltage = 10.0f;

//    
const float Kp = 1.0f;

//    , ,  1 
void sTim3::handler (void) {
    float outputVoltage = GetOutputVoltage();
    float error = referenceOutputVoltage - outputVoltage;
    dutyPWM += Kp * error;
}


… , , (dutyPWM) buck , , . , (reference), dutyPWM .



, 1 , . error -. , dutyPWM .



buck dc/dc , 20. dutyPWM 0, 1000, buck Vout = Vin x dutyPWM = 20V x 0 = 0V, 0. ( №1) error = 10 — 0 = 10 dutyPWM = 10, Vout = Vin x dutyPWM = 20V x (10/1000) = 0.2V. 1 ( №2) error = 10 — 0.2V = 9.8V, dutyPWM = 19.8, (reference). , reference 10 ( ).



Kp, , . 1, . , 0.2 . () , , . Kp 10 : dutyPWM = Kp x error = 10 x (10 — 0) = 100, 0.2, Vout = Vin x dutyPWM = 20V x (100/1000) = 2V, " " 10 . Kp . , , , , .



… ? , .



3. CV mode



CV mode, . ( ), , , : - ++. , . , .



STM32F334C8T6, , HRPWM . , , . , (2-3-4) , , .



CV :



/***********************************************************
*       200 ,
*    HRPWM    - 30 000.
*     : 3...15
*    : 20 
*
*      : 12
***********************************************************/

void sTim3::handler (void) {
    TIM3->SR &= ~TIM_SR_UIF;

    float inputVoltage = Feedback::GetInputVoltage();

    //   boost,  Vin < 90% * Vref
    if (inputVoltage <= (Application::referenceOutputVoltage * 0.9)) {
        Hrpwm::SetDuty(Hrpwm::Channel::buck, 29000);
        float outputVoltage = Feedback::GetOutputVoltage();

        pidVoltageMode
            .SetReference(Application::referenceOutputVoltage)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputVoltage, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBoost += pidVoltageMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::boost, Application::dutyBoost);
    }

    //   buck,  Vin > Vref * 110%
    if (inputVoltage >= (Application::referenceOutputVoltage * 1.1)) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 1000);
        float outputVoltage = Feedback::GetOutputVoltage();

        pidVoltageMode
            .SetReference(Application::referenceOutputVoltage)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputVoltage, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBuck += pidVoltageMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }

    //   buck-boost,  (90% * Vref) < Vin < (110% * Vref)
    if ((inputVoltage > (Application::referenceOutputVoltage * 0.9)) && (inputVoltage < (Application::referenceOutputVoltage * 1.1))) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 6000);
        float outputVoltage = Feedback::GetOutputVoltage();

        pidVoltageMode
            .SetReference(Application::referenceOutputVoltage)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputVoltage, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBuck += pidVoltageMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }    
}


buck-boost, , 2- buck boost . 2- : . , , , .



/***********************************************************
*       200 ,
*    HRPWM    - 30 000.
*     : 3...15
*    : 20 
*
*      : 12
***********************************************************/

void sTim3::handler (void) {
    TIM3->SR &= ~TIM_SR_UIF;

    //          boost
    float inputVoltage = Feedback::GetInputVoltage();
    if (inputVoltage < 6.0f) { Application::dutyBoost = 25000; }
    if ((inputVoltage >= 6.0f) && (inputVoltage < 12.0f)) { Application::dutyBoost = 18000; }
    if (inputVoltage >= 12.0f) { Application::dutyBoost = 6000; }
    Hrpwm::SetDuty(Hrpwm::Channel::boost, Application::dutyBoost);

    //         buck 
    float outputVoltage = Feedback::GetOutputVoltage();

    pidVoltageMode
        .SetReference(Application::referenceOutputVoltage)
        .SetSaturation(-29800, 29800)
        .SetFeedback(outputVoltage, 0.001)
        .SetCoefficient(10,0,0,0,0)
        .Compute();

    Application::dutyBuck += pidVoltageMode.Get();
    Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);    
}


3 : 3...6, 6...12 12...15 boost , buck. , — , . , ( ), .



3 , , , , . dutyBoost : , buck boost-, 90% ( ). , 3...15 . dutyBoost — 3 15, , .. . dutyBuck 90% 3 "" boost- 3 x 0,9 = 2,7, boost 15 2.7! dutyBoost 1 — (Vout / Vin) = 1 — 2,7 / 15 = 82%, , - 30000, 30 000 x 82% = 24 600, 25000.



3, 5, buck 3. , dutyBoost, buck 90% 12. , ~3,2% . ? , , "" .



6...12 60% 18000, 12...15 20% 6000. - ...



3- . , , buck 100% boost-, boost dc/dc . , , — boost- 0% buckDuty, buck dc/dc . — , buck, boost buck-boost...



boost , "" 90% , Vref x 90% = 12 x 0,9 = 10,8. dutyBoost = 1 — (Vref x 90%) / (Vref x 110%) = 1 — 0,9 / 1,1 = 19% = 5700, 6000 . buck- buckDuty. "" buck-boost , . , :





4. CC mode



, . , , , LED, - , . , dc/dc , .. (duty), ?



— : U = I x R. , , , 10 . dc/dc 10 , I = U / R = 1, , .. . Li-ion , , 15, - 5, . , , I = U / R = const.



, , , . , , , I = U / R = const.



, 1. 1 1: I = 1 = const = U / R = 1 / 1 . 5 , 5: I = 1 = const = U / R = 5 / 5 . 5, 1 0.2 .



, , (error) , (dutyPWM). :




/***********************************************************
*       200 ,
*    HRPWM    - 30 000.
*     : 3...15
*    : 20 
*
*      : 1
***********************************************************/

void sTim3::handler (void) {
    TIM3->SR &= ~TIM_SR_UIF;

    float inputVoltage = Feedback::GetInputVoltage();

    //   boost,  Vin < 90% * Vref
    if (inputVoltage <= (Application::referenceOutputVoltage * 0.9)) {
        Hrpwm::SetDuty(Hrpwm::Channel::buck, 29000);
        float outputCurrent = Feedback::GetOutputCurrent();

        pidCurrentMode
            .SetReference(Application::referenceOutputCurrent)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputCurrent, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBoost += pidCurrentMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::boost, Application::dutyBoost);
    }

    //   buck,  Vin > Vref * 110%
    if (inputVoltage >= (Application::referenceOutputVoltage * 1.1)) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 1000);
        float outputCurrent = Feedback::GetOutputCurrent();

        pidCurrentMode
            .SetReference(Application::referenceOutputCurrent)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputCurrent, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBuck += pidCurrentMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }

    //   buck-boost,  (90% * Vref) < Vin < (110% * Vref)
    if ((inputVoltage > (Application::referenceOutputVoltage * 0.9)) && (inputVoltage < (Application::referenceOutputVoltage * 1.1))) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 6000);
        float outputCurrent = Feedback::GetOutputCurrent();

         pidCurrentMode
            .SetReference(Application::referenceOutputCurrent)
            .SetSaturation(-29800, 29800)
            .SetFeedback(outputCurrent, 0.001)
            .SetCoefficient(10,0,0,0,0)
            .Compute();

        Application::dutyBuck += pidCurrentMode.Get()
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }    
}


, buck-boost . , (outputCurrent) - (referenceOutputCurrent) , , . :



error=IreferenceIout



, CV mode. - , 2 : , , , .



LED 10 1, :





5. CC/CV mode



, … :



  • 10 Li-ion , , . , , ( ) , .




  • 1, Li-ion , . … ? , , , , , — .


- , ? CC/CV, . : 1 Li-ion 4.2 , CC/CV 3...15 1. , 1 , CC , . , 15, CV, 15 ( ).



2 , .. , 15 , , 1 — , . 3, , , CV , . , :




/***********************************************************
*       200 ,
*    HRPWM    - 30 000.
*     : 3...15
*    : 20 
*
*      : 10 1
***********************************************************/

void sTim3::handler (void) {
    TIM3->SR &= ~TIM_SR_UIF;

    float resultPID = 0.0f;

    float inputVoltage = Feedback::GetInputVoltage();

    //   boost,  Vin < 90% * Vref
    if (inputVoltage <= (Application::referenceOutputVoltage * 0.9)) {
        Hrpwm::SetDuty(Hrpwm::Channel::buck, 29000);

        float outputVoltage = Feedback::GetOutputVoltage();
        float outputCurrent = Feedback::GetOutputCurrent();

        //   CC mode,  Vout < Vref
        if (outputVoltage < (Application::referenceOutputVoltage - 0.2f)) {
            pidCurrentMode
                .SetReference(Application::referenceOutputCurrent)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputCurrent, 0.001)
                .SetCoefficient(20,0,0,0,0)
                .Compute();
            resultPID = pidCurrentMode.Get();
        }

        //   CV mode,  (Iout -> 0)  (Vout => Vref)
        if ((outputCurrent < 0.05f) || (outputVoltage >= (Application::referenceOutputVoltage - 0.2f))) {
            pidVoltageMode
                .SetReference(Application::referenceOutputVoltage)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputVoltage, 0.001)
                .SetCoefficient(50,0,0,0,0)
                .Compute();
            resultPID = pidVoltageMode.Get();
        }

        Application::dutyBoost += resultPID;
        Hrpwm::SetDuty(Hrpwm::Channel::boost, Application::dutyBoost);
    }

    //   buck,  Vin > Vref * 110%
    if (inputVoltage >= (Application::referenceOutputVoltage * 1.1)) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 1000);

        float outputVoltage = Feedback::GetOutputVoltage();
        float outputCurrent = Feedback::GetOutputCurrent();

        //   CC mode,  Vout < Vref
        if (outputVoltage < (Application::referenceOutputVoltage - 0.2f)) {
            pidCurrentMode
                .SetReference(Application::referenceOutputCurrent)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputCurrent, 0.001)
                .SetCoefficient(20,0,0,0,0)
                .Compute();
            resultPID = pidCurrentMode.Get();
        }

        //   CV mode,  (Iout -> 0)  (Vout => Vref)
        if ((outputCurrent < 0.05f) || (outputVoltage >= (Application::referenceOutputVoltage - 0.2f))) {
            pidVoltageMode
                .SetReference(Application::referenceOutputVoltage)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputVoltage, 0.001)
                .SetCoefficient(50,0,0,0,0)
                .Compute();
            resultPID = pidVoltageMode.Get();
        }

        Application::dutyBuck += resultPID;
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }

    //   buck-boost,  (90% * Vref) < Vin < (110% * Vref)
    if ((inputVoltage > (Application::referenceOutputVoltage * 0.9)) && (inputVoltage < (Application::referenceOutputVoltage * 1.1))) {
        Hrpwm::SetDuty(Hrpwm::Channel::boost, 6000);

        float outputVoltage = Feedback::GetOutputVoltage();
        float outputCurrent = Feedback::GetOutputCurrent();

        //   CC mode,  Vout < Vref
        if (outputVoltage < (Application::referenceOutputVoltage - 0.2f)) {
            pidCurrentMode
                .SetReference(Application::referenceOutputCurrent)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputCurrent, 0.001)
                .SetCoefficient(20,0,0,0,0)
                .Compute();
            resultPID = pidCurrentMode.Get();
        }

        //   CV mode,  (Iout -> 0)  (Vout => Vref)
        if ((outputCurrent < 0.05f) || (outputVoltage >= (Application::referenceOutputVoltage - 0.2f))) {
            pidVoltageMode
                .SetReference(Application::referenceOutputVoltage)
                .SetSaturation(-29800, 29800)
                .SetFeedback(outputVoltage, 0.001)
                .SetCoefficient(50,0,0,0,0)
                .Compute();
            resultPID = pidVoltageMode.Get();
        }

        Application::dutyBuck += resultPID;
        Hrpwm::SetDuty(Hrpwm::Channel::buck, Application::dutyBuck);
    }    
}


, , if, . .



, 2 -, , — -. CC mode CV mode. : (Application::referenceOutputVoltage) , CV mode, 15. , CC mode 1.



, / , . , LED 2 . , , 10 STM32F334 .



buck-boost dc/dc CC/CV:





...



lamerok veydlin, (, , ), !



, : https://t.me/proHardware. , , , , , .



, . buck-boost-, , , - , .




All Articles