我们在用C-Block进行数字电源编程的时候,最常用到的是PI控制算法,如下一个常见的电压外环PI代码:
/**********************************************************************************/
//INV电压环参数定义
double Inv_U_PID;
const double Inv_U_K1=0.205;
const double Inv_U_K2=0.2;
double Inv_U_Error_0=0;
double Inv_U_Error_1=0;
//INV电流环参数
Inv_U_Error_1 = Inv_U_Error_0; //偏差计算(比例)
Inv_U_Error_0 =U_bus_avg-U_bus_set; //偏差计算(积分)
Inv_U_PID+= Inv_U_K1 * Inv_U_Error_0 - Inv_U_K2 * Inv_U_Error_1 ;
//PID计算式,更改系数以获得理想的输出
if( Inv_U_PID<-40) //限制电压环输出
Inv_U_PID=-40;
if( Inv_U_PID>40)
Inv_U_PID=40;
/**********************************************************************************/
PI算法的格式都是一样的,中间会涉及多个中间变量,如果我们的系统比较复杂,涉及多个PI环路,那这样我们的变量定义PI算法就会非常冗余,代码的可移植性就比较差;
比如下面这个三相四桥臂正负序闭环控制系统:
正序QD轴外环电压内环电流环和负序QD轴外环电压内环电流环,总共有8个PI控制环路,如果直接定义变量,以及各个环路的PI代码,这样代码量就非常大,而且相当冗余;
怎样才能将代码简洁化,以及可移植性:我们可以用C语言的结构体去定义PI中间参数变量;以及把PI控制算法写成一个函数,单要调用PI算法时,就通过结构体变量调用PI算法函数,这样就可以避免同样结构的代码结构重复性编写;
/----------------------------------------------------------------------------------/
比如我们要用到电压外环,电流内环控制架构的时候;我们只需要定义下面结构体变量:
/---------------------------------结构体变量定义--------------------------------------------/
static stNamePID InvVoltPid={0}; //电压环PI结构体
double VpidCalTemp=0;
static stNamePID InvCurrPid={0}; //电流环PI结构体
double pidCalTemp=0;
/----------------------------------------------------------------------------------/
//**************电压外环*************//
Inv_V_ref=U_out_cmd*cos(angle);
pid_set_tag(&InvVoltPid,Inv_V_ref);
pid_set_Kp(&InvVoltPid, 0.02);
pid_set_Ki(&InvVoltPid, 0.01);
pid_set_OutputLimit(&InvVoltPid,Iout_max,-Iout_max);
VpidCalTemp=pi_calc(&InvVoltPid, U_out);
//**************电流内环**************//
Inv_I_ref=VpidCalTemp ;
pid_set_tag(&InvCurrPid, Inv_I_ref);
pid_set_Kp(&InvCurrPid, 0.05);
pid_set_Ki(&InvCurrPid, 0.005);
pid_set_OutputLimit(&InvCurrPid,100,-100);
pidCalTemp=pi_calc(&InvCurrPid, I_out_avg);
总结:在编程中学会一些小技巧,我们的代码编程就更加简洁,增强软件可移植性和可读性;