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.
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 ). , . :
, : 2 ( 2 , ), 4 , . 1 2 (OCP) . 2 ? , , .
, , , STM32F334, STM32G474, XMC4108, TMS320F28027 , .. : HRPWM, , , . , , , . , , , (OCP) , , .
… buck-boost :
buck () boost (), — 3 buck-, L1C3 LC-. 3 boost-, . , buck-, boost-. .
buck:
boost:
, buck- boost :
buck-boost 3- : ( PWM-BUCK PWM-BOOST). , .
, . , 8, Dboost 70%, Dbuck 50%. :
, 8 . , , , 2 - :
. (duty) 2- . duty, .
2. .
2 , : . , , CC/CV . :
CC CV , : REF , , ; , , , , .
-, , " " . "" (REF), , , 10. , buck-boost , (duty). - . , .
:
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) , , . :
, 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:
...
, : https://t.me/proHardware. , , , , , .
, . buck-boost-, , , - , .