Konverter buck-boost dengan kontrol digital pada STM32F334 dalam mode CC / CV

Topologi buck dan boost konverter dc / dc yang paling populer memiliki batasan yang signifikan: topologi buck hanya dapat menurunkan tegangan input, dan topologi boost hanya meningkatkannya. Namun, ada tugas ketika rentang tegangan input membutuhkan operasi simultan untuk meningkatkan dan menurunkan, misalnya, kami memiliki input 3 ... 15V, dan pada output perlu untuk mendapatkan 12V yang stabil. Situasi yang familier?



Ada 2 solusi yang mungkin:



  • Menggunakan boost converter, naikkan tegangan input dari 3 ... 15V menjadi stabil 15V pada output, dan kemudian, dengan menggunakan topologi buck, turunkan tegangan ke 12V yang diperlukan;
  • Terapkan topologi buck-boost yang secara optimal menyelesaikan masalah ini.


Kerugian yang jelas dari metode pertama adalah kebutuhan untuk menggunakan 2 choke, peningkatan jumlah kapasitor dan bukan mode operasi yang paling optimal, yang berarti efisiensi yang lebih rendah. Topologi buck-boost sama sekali tidak memiliki kekurangan ini, jadi hari ini kita akan membicarakannya. Untuk membuatnya menarik, saya memutuskan untuk tidak mengambil beberapa kontroler yang sudah jadi dan mengimplementasikan dc / dc converter yang dikontrol secara digital berdasarkan STM32F334C8T6.



Pengonversi foto



Hasil karya bagi mereka yang tidak ingin membaca dinding teks


Dalam kerangka artikel ini, saya akan secara singkat berbicara tentang implementasi perangkat keras dari konverter dan bagaimana menerapkan sistem kontrol untuk berbagai mode operasi. Menarik? Kalau begitu mari kita pergi ...



1. Secara singkat tentang pengoperasian topologi buck-boost



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



Struktur buck-boost



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



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



… buck-boost :



Sirkuit buck-boost yang setara



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 - :



Grafik osiloskop



. (duty) 2- . duty, .



2. .



2 , : . , , CC/CV . :



Diagram blok kontrol



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



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



:

error=VreferenceVout



Apa yang memberi kita? Dan sekarang kita tahu berapa nilai nyata dari tegangan output yang menyimpang dari nilai yang ditetapkan ( REF ). Ini memungkinkan kita untuk memahami apakah perlu "memberi perintah" untuk menambah atau mengurangi tegangan. Misalnya, dalam topologi buck , untuk meningkatkan tegangan, Anda perlu meningkatkan faktor tugas untuk transistor atas, dan untuk mengurangi tegangan, kurangi siklus tugasnya. Untuk topologi boost, sebaliknya, ada 2 sinyal untuk buck-boost , dan ini lebih rumit - Anda perlu menyeimbangkan, tapi saya pikir idenya jelas rata-rata, untuk kejelasan, saya akan memberikan kode pseudo untuk mengendalikan 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