gjhk001 发表于 2019-12-30 14:47:56

基于STM32F334的BUCK同步降压数字电源设计

本帖最后由 gjhk001 于 2019-12-30 14:50 编辑

1. 方案概述
1.1. 概述数字电源并不是简单的指在系统中应用了数字器件,如单片机及DSP等,而是指整个系统的控制应用数字器件的计算能力和离散控制方法来完成,随着电力电子的发展,电源越来越趋向数字化与智能化发展。本设计采用STM32F334作为控制器的同步降压变换器的数字电源,可以实现降压控制,也可以实现升压控制,能量双向流动。数字控制不只能让电源更简单,还可以让电源实现四遥功能。四遥:遥测、遥信、遥控及遥调。本设计将介绍同步降压的数字控制方案硬件和软件的设计说明,并附相关电路原理图及参考代码。1.2. 系统主要结构如图-1所示,BUCK同步降压系统由辅助电路、控制电路、驱动电路、BUCK电路、信号调理电路构成。具体硬件的介绍及说明见第2章节内容。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/205445l7ojj787hyhx77tg.jpg
图-1 基于STM32F334微控制器的BUCK同步降压的数字控制方案结构图本设计应用了STM32F334的PWM模块发出对称的PWM波驱动BUCK电路;通过ADC模块采集直流母线电压,输出电压、输出电流及远端测量,特别说明的是远端测量,认为在电池充放电应用是有效的,因为其可以解决电缆电线的压降问题;预留一个串口通信接口,可以实现与上位机,操作面板等设备通信。1.3. 主要功能和指标
[*]输入电压:10~64V,输出电压:5~60V;
[*]最大电流:5A;
[*]最大功率:240w;
[*]高效率设计,支持的最大效率超过95%;
[*]250 KHz开关频率支持更小的无源组件,从而减小电路板面积并延长寿命;
[*]三个满足各种应用场合的控制模式:1) 输出电压控制 2) MPPT 控制(输入电流控制)3) 反向电压控制。
[*]保护机制:过压保护,欠压保护,过流保护。
1.4. 应用对象适合于太阳能微转换器、数字电源和电池充放电、直流UPS应用2. 方案硬件设计
2.1. 功率电路

如图-2所示,同步BUCK由经典的BUCK变换而来,具体是使用mos替换二极管实现。输入端与输出端都采用LC滤波,使得输入输出电流连续,便于滤波。输出端的-极采用采用电阻实现电流采样,并经过放大电路放大之后送入MCU的ADC口,具体将在第2.3节介绍。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/205653fj66r7wpwptmm6ot.jpg
图-2 BUCK同步降压电路原理图2.2. 驱动电路如图-3所示,MOS管驱动电路采用TI的半桥驱动芯片UCC27211。该器件内部集成自举电容充电用二极管,耐压120V,驱动电流达4A。特别注意,该器件内部不带死区时间功能,为避免上下桥臂同时导通,死区时间必须在MCU上实现。http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/205737qew7ag7mbpvzvt7a.jpg
图-3 MOS管驱动电路2.3. 信号调理电路信号调理电路包含输入电压检测,输出电压检测,远端电压测量,输出电流检测等,这些功能都是基于TLV2374运算放大器实现并且采用差分形式。1)输入电压检测如图-4所示,输入电压检测直接采用电阻分压实现。表达式:Vin   =   ADC_V_IN * 31            (式1)http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/205835h5lxmmgnmgong053.jpg

图-4 输入电压检测电路
2)输出电压检测如图-5所示,输出电压检测电路基于TLV2374的差分电路实现,由于主电路的输出端的低端电流采样会对电压检测形成干扰,并且差分电路具有很高的共模信号抑制,有利于猜到准确的信号。表达式:Vout   =   ADC_V_OUT * 30            (式2)http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/210059l3rlrhb3j7ljqzys.jpg

图-5 输出电压检测电路3)远端电压检测如图-6所示,远端电压检测电路基于TLV2374的差分电路实现,远端电压测量对于电池充放电是有效的,可以避免由于导线压降产生的影响。用法:直接接入电池两端,请注意正负极。表达式:Vext   =   ADC_EXT_SENSN * 30            (式3)http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/210203jigmzook9s1wm8qo.jpg

图-6 远端电压检测电路4)输出电流检测如图-7所示,输出电流检测电路基于TLV2374的差分放大电路实现,在主电路中采样电阻采用10mΩ,要使MCU能够识别该信号,必须经过放大到一定值。由因为本应用要实现双向DCDC功能,这就使得电流有正负,但是MCU无法采集负信号,这里得认为将电压提高,保证电流在负值时,ADC_I_OUT输出还是为正。所以,采用1:1电阻分压,然后经过一个跟随器(提高驱动能力)输出一个1.65V的参考电压,如图-8所示。到这里,该检测电路就可实现正负点流的采样。表达式:Iout   =   (ADC_I_OUT - 1.65) / 0.20         (式3)http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/210458jrqzcoyrhhiuzzqc.png

图-7 输出电流检测电路http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/210409jczgnon0izhkhcen.png

图-8 参考电压1.65V产生电路

2.4. 控制电路

http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/213506wryzuuyi5iu7854s.png
图-9 控制电路如图-9所示,控制电路采用STM32F334微控制器,有下载接口,串口通信等接口以及运行指示LED灯。STM32资源分配如表1所示。
表1 STM32资源分配
功能分类引脚名称对应信号说明
PWM信号PA8PWM1A上桥臂驱动信号
PA9PWM1B下桥臂驱动信号
ADC信号PA0ADC_I_OUT输出电流检测
PA1ADC_V_OUT输出电压检测
PA2ADC_EXT_SENSN远端电压检测
PA3ADC_V_IN输入电压检测
串口通信PB6USART1_TXUSART1发送
PB7USART1_RXUSART1接收
程序下载接口PA13SWDATSWD仿真接口
PA14SWCLK
LED指示灯PB3LED2故障指示灯
PB4LED1运行指示灯

2.5. 辅助电源电路如图-10所示图-10 辅助电源电路产生12V、3.3V两种电压等级。XL7005A将输入端降压到12V,SPX3819-M-3.3将12V稳压到3.3V。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/210614dtg6zjenkzetg8t8.png

图-10 辅助电源电路
3. 方案主要算法介绍
3.1. PID算法PID算法是一个很经典的自动控制算法,经过几十年的认证,在我们生活发挥了重大作用。PID的资料已经太多了,此处不再讲述其原理,直接给出C代码,若想了解其根本原理,请自行学习。
PID算法用到的数据:typedef struct_PID{   pid_float32      SetPoint;                //输入:给定值      pid_float32      Feedback;                //输入:反馈值
      pid_float64      T;                //采样时间      pid_float64      Kp;                //比例常数      pid_float64      Ti;                //积分时间      pid_float64      Td;                //微分时间
      pid_float32      a0;                //系数1:a0 = Kp(1 + T/Ti + Td/T)      pid_float32      a1;                //系数2: a1 = Kp(1 + 2Td/T)      pid_float32      a2;                //系数3:a2 = Kp*Td/T
      pid_float32      Ek;       //当前误差      pid_float32      Ek_1;   //前一次误差      pid_float32      Ek_2;   //第二次误差
      pid_float32      Output;                        //输出值      pid_float32      Last_Output;      //上一次输出值      pid_float32      Increment;                //增量值
      pid_float32      OutMax;                        //输出限制最大值      pid_float32      OutMin;                        //输出限制最小值
} PID_TypeDef;

PID的数据初始化程序:void PID_init ( PID_TypeDef *p){   
      p->a0                = p->Kp*(1 + 1.0*p->T/p->Ti + 1.0*p->Td/p->T);      p->a1                = p->Kp*(1 + 2.0*p->Td/p->T);      p->a2                = 1.0*p->Kp*p->Td/p->T;}

增量式PID算法:pid_float32 PID_Calc( PID_TypeDef *p, pid_float32 feedback, pid_float32 ref){      p->Ek      = ref - feedback;                //¼ÆËãÎó²î
      p->Increment                = (p->a0*p->Ek      - p->a1*p->Ek_1 + p->a2*p->Ek_2 );      //PID¼ÆËã
      p->Output = p->Last_Output + p->Increment;
      if(p->Output > p->OutMax)p->Output   =      p->OutMax;      if(p->Output < p->OutMin)p->Output   =      p->OutMin;      p->Ek_2         = p->Ek_1;      p->Ek_1         = p->Ek;                     p->Last_Output    = p->Output;      return p->Output;}
附件:http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/211613x07vvtv77f8f7tyy.jpghttp://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/211627cypabai36268anp3.jpghttp://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/211636otpswyhhyzwzwyaw.jpg**** Hidden Message *****

gjhk001 发表于 2019-12-30 14:49:40

. BUCK同步减压拓扑及控制方式说明
4.1. BUCK同步降压
降压转换器仅能提供比输入电压低的平均输出电压,这正如其名称所表示的一样。降压转换器的基本原理图和开关波形如图-11所示。在降压转换器中,开关(Q1)与输入电压源VIN 串联。输入电压源VIN 通过功率开关和低通滤波器馈送到输出,而低通滤波器则由电感和电容构成。在稳态运行中,若开关导通时间为TON,输入将向输出和电感(L)提供能量。在TON 期间,电感电流流经功
率开关且VIN 和VOUT 之间的正向电压差将加在电感两端,如图-11(C)所示。因此,电感电流IL 将呈线性规律从当前值IL1 上升到IL2,如图-11(E)所示。在TOFF 期间,当开关关闭,电感电流的方向与前面相同,这是由于电感中的储能继续提供负载所需电流。在Q1 关闭期间(TOFF),二极管D1 提供电感电流回路;因此,该二极管称为续流二极管。在TOFF 期间,输出电压VOUT 将以反方向加在电感两端,如图-11(C)所示。因此,电感电流将从当前值IL2 减小至IL1,如图-11所示。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/213024xadd5beyypbaxe0c.jpg
图-11 电压模式控制
当输出电流要求较高时,续流二极管D1 中过高的功耗将限制可达到的最小输出电压。为减少大电流下的功耗并获得较低的输出电压,采用具有极低导通电阻RDSON的MOSFET替代续流二极管。该MOSFET的导通与关断与降压MOSFET同步。因此,这一结构称为同步降压转换器。该同步MOSFET的栅极驱动信号需与降压开关栅极驱动信号呈现互补关系。
4.2. 控制模式
1)电压模式控制
在电压模式控制中,对输出电压进行测量并将测量结果与参考值(期望的输出电压)进行比较。随后补偿电路将对误差进行处理以产生下一个占空比值,如图-12所示。该模式只有一个控制环,因此易于设计和分析。然而,在这种控制方法中,当输出电压变化时,必须首先对线电压或负载变化进行检测,随后通过反馈环对它们进行校正。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/213024ixhfpsbb45bxfbva.jpg
图-12 电压模式控制
2)电流模式控制
电流模式控制技术需要两个反馈环,如图13 所示。在这一模式,需对两个参数进行检测以实现控制目的。在输出电容侧或负载端(称为远程检测)对输出电压进行检测。还需对输出电感/ 原边开关电流进行检测。在电流模式控制中,首先将输出电压和参考电压(期望输出电压)进行比较。补偿电路随后对该误差进行处理以产生电流环的参考信号。这一电流参考信号将与测量电流进行比较。电流补偿电路将对由电压补偿电路产生的参考信号与实际从输入汲取的电流进行比较得到的误差进行处理。这将产生所需占空比以保持输出电压在限定范围之内。由于电流模式控制对电路电流进行检测,因此任何输出负载电流或输入电压的变化在影响输出电压之前都会被校正。由于输入电流取决于输入电压,因此对输入电流的检测具有内在的前馈控制特性。电流模式控制提供了推挽式或桥式转换器内在的输入电流对称特性、内在电流限制特性和多转换器并联连接时的负载分流特性。由于采用电流内环,因此阶跃负载响应和瞬态响应特性也得到改善。
http://www.stmcu.org.cn/module/forum/data/attachment/forum/201607/11/213024imy77egzzuruugju.jpg
图-13 电流模式控制

4.3. 参考代码
此处给出固定电压输出的DEMO 代码,采用电流模式控制:(此处只给出主函数程序,若要详细代码,请自行到Q群下载)


/*--------Includes--------*/
#include "system_typedef.h"
#include "hp_pid_code.h"
#include "onboard_led.h"
#include "timer.h"
#include "usart.h"
#include "hrpwm.h"
#include "stdio.h"
#include "adc.h"
#include "stdio.h"
#include "string.h"


#define fabs(x)      (x < 0 ? -x : x)      //¾ø¶ÔÖµ¼ÆËã

#define Err_OK               0x00
#define Err_HV      0x01
#define Err_LV      0x02
#define Err_      0x03



float32      VIPWR      = 0;
float32      VOPWR      = 0;
float32      VOEXT      = 0;
float32      IOPWR      = 0;
float32      PWRIN      = 0;
float32      PWROUT      = 0;
float32 VoutREF = 24;
float32 VinREF          = 28;

uint16ADC_VIPWR_Value;
uint16ADC_VOPWR_Value;
uint16ADC_VOEXT_Value;
uint16ADC_IOPWR_Value;

uint32 PWM_Period;
uint32 PWM_Duty;
PID_TypeDef pid_voltage_loop;
PID_TypeDef pid_current_loop;

void Get_Voltage_Current(void);

int main(void)
{
static uint64 i      = 0;

u8 Status = 0;
GPIO_InitTypeDefGPIO_Struct;
SysTick_Config(SystemCoreClock / 1000);//Systick³õʼ»¯,SysTick end of count event each 1ms
Delay_ms(100);

LED_Init();
LED1_On();
LED2_On();
Delay_ms(200);
LED1_Off();
LED2_Off();
Delay_ms(200);
LED1_On();
LED2_On();
Delay_ms(200);
LED1_Off();
LED2_Off();
//-----------USART1_Rx == PB7-------------//
GPIO_Struct.GPIO_Pin      = GPIO_Pin_7;
GPIO_Struct.GPIO_Mode      = GPIO_Mode_OUT;
GPIO_Struct.GPIO_OType = GPIO_OType_PP;
GPIO_Struct.GPIO_PuPd      = GPIO_PuPd_UP;
GPIO_Struct.GPIO_Speed      = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_Struct);

TIMER3_init(0.1e3);
USART1_init(115200);
PWM_Period      = HrPWM_CHA_Init(200e3);//PWM³õʼ»¯

ADC_init();//ADCÍâÉè³õʼ»¯

PID_DeInit( &pid_voltage_loop );
pid_voltage_loop.T      = 1000;//PI²ÉÑùÖÜÆÚ£¬µ¥Î»Îªus
pid_voltage_loop.Kp      = 0.2;
pid_voltage_loop.Ti      = 2000;
pid_voltage_loop.Td      = 0;
pid_voltage_loop.OutMax      = 5;
pid_voltage_loop.OutMin      = -4;
PID_init(&pid_voltage_loop);//µçѹ»·PI²ÎÊý³õʼ»¯

PID_DeInit( &pid_current_loop );
pid_current_loop.T      = 10;//PI²ÉÑùÖÜÆÚ£¬µ¥Î»Îªus
pid_current_loop.Kp      = 12;
pid_current_loop.Ti      = 100;
pid_current_loop.Td      = 0;
pid_current_loop.OutMax      = 0.90*PWM_Period;
pid_current_loop.OutMin      = 0.05*PWM_Period;
PID_init(&pid_current_loop);//µçÁ÷»·PI²ÎÊý³õʼ»¯
Delay_ms(5);
HrPWM_CHA_Update(PWM_Period, 0.05*PWM_Period);
HRTIM_WaveformOutputStart(HRTIM1, HRTIM_OUTPUT_TA1 | HRTIM_OUTPUT_TA2 );
Delay_ms(300);
LED1_Off();
LED2_Off();


while (1)
{
VIPWR      = ADC_VIPWR_Value * 3.3/4095.0*30.00;
VOPWR      = ADC_VOPWR_Value * 3.3/4095.0*30.00;
VOEXT      = ADC_VOEXT_Value * 3.3/4095.0*30.00;
if(((VIPWR < 26 + 1.0)|| fabs(IOPWR) > 6.0) && i > 5 )
{
HRTIM_WaveformOutputStop(HRTIM1, HRTIM_OUTPUT_TA1 | HRTIM_OUTPUT_TA2 );
LED2_Off();
if(i%50 == 0)LED1_Toggle();//ָʾµÆ½»ÌæÉÁ˸
}
else
{
LED1_Off();
if(i%50 == 0)LED2_Toggle();//ָʾµÆ½»ÌæÉÁ˸
}
PID_Calc( &pid_voltage_loop, VOPWR, VoutREF);      //µçѹ»·PI¼ÆËã
if(i%1000 == 0)
{
printf("Vin= %fv\r\nVout = %fv\r\nVext = %fv\r\nIout = %fA\r\nPWM= %f\r\n", VIPWR, VOPWR, VOEXT, IOPWR, (float)PWM_Duty/PWM_Period);
}
Delay_ms(1);


i++;      //¼Æʱ
   }
}

void TIM3_IRQHandler(void)   //TIM3ÖжÏ
{
if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)      {
GPIOB->ODR ^= GPIO_Pin_7;
ADC_IOPWR_Value      = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
ADC_VOPWR_Value      = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
ADC_VOEXT_Value      = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3);
ADC_VIPWR_Value      = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_4);

IOPWR      = -(ADC_IOPWR_Value * 3.3/4095 - 1.585)/0.265;

PWM_Duty      = PID_Calc( &pid_current_loop, IOPWR, pid_voltage_loop.Output);
HrPWM_CHA_Update(PWM_Period, PWM_Duty);//¸üÐÂPWMÕ¼¿Õ±È
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);         //Çå³ýTIMxµÄÖжϴý´¦Àíλ:TIM ÖжÏÔ´
}

#pragma arm section code = "RAMCODE"
void Get_Voltage_Current(void)
{
//      IOPWR      = (float32)(-((ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1) * 3.3)/4095.0 - 1.681)/0.201 );
//      VOPWR      = (float32)((ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2) * 3.3)/4095.0*31.50);
//      VOEXT      = (float32)((ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3) * 3.3)/4095.0*31.60);
//      VIPWR      = (float32)((ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_4) * 3.3)/4095.0*32.30);
}
#pragma arm section

rsrc 发表于 2019-12-30 19:00:48

感谢分享      

kunchen 发表于 2019-12-30 20:46:36

学习一下

liuxingsong 发表于 2019-12-31 10:22:17

感谢分享

love2008 发表于 2020-1-1 15:20:13

看看PID算法

chenghelin 发表于 2020-1-1 21:11:04

好东西,学习了,我也刚做了一个。


悠悠三千载 发表于 2020-1-2 22:19:34

学习一下,真正学习这方面知识

harry26 发表于 2020-1-3 10:51:54

感谢分享

wangweiguo 发表于 2020-1-9 08:16:37

自制BLDC/PMSM电机驱动板汇总开源分享:PCB+元件库+程序+教程
页: [1] 2 3 4 5 6
查看完整版本: 基于STM32F334的BUCK同步降压数字电源设计