基于STM32F103C8T6的同步电机驱动-电流环PI与力矩模式
本系列文章:
- 基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用
- 基于STM32F103C8T6的同步电机驱动-PWM驱动代码以及SVPWM的实现
- 基于STM32F103C8T6的同步电机驱动-ADC采样与基于MT6701的角度获取
- 基于STM32F103C8T6的同步电机驱动-电流采样去直流偏置
- 基于STM32F103C8T6的同步电机驱动-电流环PI与力矩模式
一、电流环PI控制器代码编写
本文中选用的电流环控制器为抗积分饱和PI控制器。
/****file:my_pid.c*****/
#include "my_pid.h"
//电流环参数
uint16_t wb = 200; //电流环带宽
float Kp_c = 0.168f; //电流环P参数:Kp_c=wb*L
float Ki_c = 0.0612f; //电流环I参数:Ki_c=wb*R*Ts
float Ka_c = 5.9523f; //电流环A参数:Ka_c=1/Kp_c
/**********************************************************************
* 函数名称: id_pi_contral
* 功能描述: 电流环PI控制器
* 输入参数: _iq id_now;_iq id_tar;
* 输出参数: _iq id_out;
* 返 回 值: 无
* 修改日期 版本号 修改人 修改内容
* -----------------------------------------------
* 2024/07/05 V1.0 TONY0925 创建
***********************************************************************/
_iq id_pi_contral(_iq id_now,_iq id_tar)
{
static _iq err_id = _IQ(0);
static _iq u_id = _IQ(0);
static _iq out_id = _IQ(0);
static _iq excess_id = _IQ(0);
static _iq sum_id = _IQ(0);
//PI电流环1.预期值与测量值作差得到偏差值
err_id = id_tar - id_now;
//PI电流环2.计算PI控制器预输出值
u_id = sum_id + _IQmpy( _IQ(Kp_c) , err_id );
//PI电流环3.进行限幅输出,得到最终输出值
if (u_id >_IQ(Umax))
{
out_id = _IQ(Umax);
}
else if (u_id <_IQ(-Umax))
{
out_id = _IQ(-Umax);
}
else
{
out_id = u_id;
}
//PI电流环4.将预输出值与实际输出值作差得到饱和差值
excess_id = u_id - out_id;
//PI电流环5.将饱和差值代入积分累计项
sum_id = sum_id + _IQmpy( _IQ(Ki_c) , err_id ) - _IQmpy( _IQ(Ka_c) , excess_id );
return out_id;
}
/**********************************************************************
* 函数名称: iq_pi_contral
* 功能描述: 电流环PI控制器
* 输入参数: _iq iq_now;_iq iq_tar;
* 输出参数: _iq iq_out;
* 返 回 值: 无
* 修改日期 版本号 修改人 修改内容
* -----------------------------------------------
* 2024/07/05 V1.0 TONY0925 创建
***********************************************************************/
_iq iq_pi_contral(_iq iq_now,_iq iq_tar)
{
static _iq err_iq = _IQ(0);
static _iq u_iq = _IQ(0);
static _iq out_iq = _IQ(0);
static _iq excess_iq = _IQ(0);
static _iq sum_iq = _IQ(0);
//PI电流环1.预期值与测量值作差得到偏差值
err_iq = iq_tar - iq_now;
//PI电流环2.计算PI控制器预输出值
u_iq = sum_iq + _IQmpy( _IQ(Kp_c) , err_iq );
//PI电流环3.进行限幅输出,得到最终输出值
if (u_iq >_IQ(Umax))
{
out_iq = _IQ(Umax);
}
else if (u_iq <_IQ(-Umax))
{
out_iq = _IQ(-Umax);
}
else
{
out_iq = u_iq;
}
//PI电流环4.将预输出值与实际输出值作差得到饱和差值
excess_iq = u_iq - out_iq;
//PI电流环5.将饱和差值代入积分累计项
sum_iq = sum_iq + _IQmpy( _IQ(Ki_c) , err_iq ) - _IQmpy( _IQ(Ka_c) , excess_iq );
return out_iq;
}
二、电流环PI应用于力矩模式
/****file:main.c*****/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim4)
{
my_Driver_Contral();
}
}
/****file:my_foc.c*****/
/**********************************************************************
* 函数名称: my_Driver_Contral
* 功能描述: 驱动控制运行函数
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 修改日期 版本号 修改人 修改内容
* -----------------------------------------------
* 2024/07/05 V1.0 TONY0925 创建
***********************************************************************/
void my_Driver_Contral(void)
{
//中断进来先改变占空比,此时占空比为上一周期计算得到的值
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PWM1_PULSE);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_2, PWM2_PULSE);
__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, PWM3_PULSE);
//电流电压ADC采样与计算
get_ADCvalue();
//计算相电流、母线电压、母线电流值
g_current.i_a = _IQmpy(_IQmpy(_IQ(ADC_Value[2]), _IQ(K_1)) - _IQ(1.65), _IQ(K_2)) -i_a_offect;
g_current.i_b = _IQmpy(_IQmpy(_IQ(ADC_Value[3]), _IQ(K_1)) - _IQ(1.65), _IQ(K_2)) -i_b_offect;
g_current.i_c = -g_current.i_a - g_current.i_b;
g_current.i_dc_now = _IQmpy(_IQmpy(_IQ(ADC_Value[0]), _IQ(K_1)) - _IQ(1.65), _IQ(K_2))-i_dc_offect;
g_voltage.u_dc_now = _IQmpy( _IQ(ADC_Value[1]) , _IQ(0.00793)) ;
//CLARK、PARK变换
g_current.i_alpha = _IQmpy((g_current.i_a - _IQmpy(_IQ(0.5), g_current.i_b) - _IQmpy(_IQ(0.5), g_current.i_c)), _IQ(K_park));
g_current.i_beta = _IQmpy((_IQmpy(_IQ(sqrt3_2), g_current.i_b) - _IQmpy(_IQ(sqrt3_2), g_current.i_c)), _IQ(K_park));
g_current.i_d = _IQmpy( _IQcos(g_theta.now_radian) , g_current.i_alpha ) +_IQmpy( _IQsin(g_theta.now_radian) , g_current.i_beta );
g_current.i_q = _IQmpy( -_IQsin(g_theta.now_radian) , g_current.i_alpha ) +_IQmpy( _IQcos(g_theta.now_radian) , g_current.i_beta );
//编码器获取角度
g_theta.now_angle = spi_get_angle();
g_theta.now_theta_M = _IQmpy( _IQ(g_theta.now_angle) , _IQ(0.02197266) );
g_theta.now_theta_E = _IQfrac(_IQmpy( g_theta.now_theta_M , _IQ(0.01944444) ));
g_theta.now_theta_E = _IQmpy( g_theta.now_theta_E, _IQ(360) );
g_theta.now_radian = _IQmpy( g_theta.now_theta_E , _IQ(pi_180) );
//编码器获取速度
get_speed();
//转速PI控制器
//电流PI控制器
g_current.i_d_tar = _IQ(g_current.i_d_tar_f);
g_current.i_q_tar = _IQ(g_current.i_q_tar_f);
g_voltage.u_d=id_pi_contral(g_current.i_d,g_current.i_d_tar);
g_voltage.u_q=iq_pi_contral(g_current.i_q,g_current.i_q_tar);
//SVPWM
// g_voltage.u_d = _IQ(0);
// g_voltage.u_q = _IQ(3);
g_voltage.u_alpha = _IQmpy( g_voltage.u_d , _IQcos(g_theta.now_radian) ) - _IQmpy( g_voltage.u_q , _IQsin(g_theta.now_radian) ) ;
g_voltage.u_beta = _IQmpy( g_voltage.u_q , _IQcos(g_theta.now_radian) ) + _IQmpy( g_voltage.u_d , _IQsin(g_theta.now_radian) ) ;
iq_svpwm(g_voltage.u_alpha ,g_voltage.u_beta);
//计算占空比值
PWM1_PULSE = 400*_IQtoF(g_duty_ratio1);
PWM2_PULSE = 400*_IQtoF(g_duty_ratio2);
PWM3_PULSE = 400*_IQtoF(g_duty_ratio3);
//串口信息打印
Sendtwodata(_IQtoF(g_current.i_q)*100+500,_IQtoF(g_current.i_d)*100+500);
//Sendtwodata(_IQtoF(g_speed.Mnow_rpm_iq)*1,_IQtoF(g_theta.now_theta_E)*10);
}
g_current.i_d_tar_f设定始终为0,通过改变g_current.i_q_tar_f即可控制力矩模式下的力矩/电流大小。其中g_current.i_q_tar_f为正,则电机正转;为负,则电机反转。