各位,9月份,我花了差不多1个月时间,实现了STM32用六步换相法驱动无刷电机的程序编制和调试。那么,既然电机都转起来了,怎么也得搞个PID实现速度环控制嘛。于是,我就开始学习无刷电机的速度环PID控制,抱歉我是对PID一无所知的小白。
结果,花了我3天时间,居然实现了速度环PID控制,本着传播优秀知识,造福中华民族和全人类的宗旨,我现在来写个保姆级教程,来教大家怎么实现这个速度环PID。
首先,还是要感谢下列人员,在我开发PID中对我的帮助。
1. 参考了下列文章:
使用stm32实现电机的PID控制_stm32pid控制电机-CSDN博客
使用STM32实现对电机的PID控制_stm32 pid控制算法代码-CSDN博客
UM2124_基于STM32F单片机的six-step固件库的入门指南 | STMCU中文官网
感谢安富利的Cavin, 感谢QQ群的 GuanGuan和Medivh。
2. 这个没有什么好配置的,直接上代码吧
pid.h
#define KP_GAIN_VM 4000 /*!< Kp parameter for PI regulator */
#define KI_GAIN_VM 30 /*!< Ki parameter for PI regulator */
#define KP_DIV_VM 8192 /*!< Kp parameter divider for PI regulator */
#define KI_DIV_VM 8192 /*!< Ki parameter divider for PI regulator */
#define LOWER_OUT_LIMIT_VM 400 /*!< Low Out value of PI regulator */
#define UPPER_OUT_LIMIT_VM (int16_t)(period*0.8) /*!< High Out value of PI regulator */
typedef struct
{
int16_t Kp_Gain; /*!< Kp value for PI regulator */
int16_t Ki_Gain; /*!< Ki value for PI regulator */
int16_t Lower_Limit_Output; /*!< Min output value for PI regulator */
int16_t Upper_Limit_Output; /*!< Max output value for PI regulator */
int8_t Max_PID_Output; /*!< Max Saturation indicator flag */
int8_t Min_PID_Output; /*!< Min Saturation indicator flag */
int32_t Integral_sum;
}PID_Handle_t;
pih.c
void PID_HandleInit(PID_Handle_t *pHandle)
{
pHandle->Kp_Gain = KP_GAIN_VM;
pHandle->Ki_Gain = KI_GAIN_VM;
pHandle->Lower_Limit_Output = LOWER_OUT_LIMIT_VM;
pHandle->Upper_Limit_Output = UPPER_OUT_LIMIT_VM;
pHandle->Max_PID_Output = RESET;
pHandle->Min_PID_Output = RESET;
pHandle->Integral_sum = 0;
}
uint16_t PI_Controller(PID_Handle_t *pHandle, int32_t hError)
{
int32_t wProportional_Term=0, wIntegral_Term=0, wOutput_32=0,wIntegral_sum_temp=0;
wProportional_Term = pHandle->Kp_Gain * hError;
if(pHandle->Ki_Gain == 0)
{
pHandle->Integral_sum=0;
}
else
{
wIntegral_Term=pHandle->Ki_Gain * hError;
wIntegral_sum_temp = pHandle->Integral_sum + wIntegral_Term;
pHandle->Integral_sum = wIntegral_sum_temp;
}
if(pHandle->Integral_sum > KI_DIV_VM*pHandle->Upper_Limit_Output)
{
pHandle->Integral_sum = KI_DIV_VM*pHandle->Upper_Limit_Output;
}
if(pHandle->Integral_sum < -KI_DIV_VM*pHandle->Upper_Limit_Output)
{
pHandle->Integral_sum = -KI_DIV_VM*pHandle->Upper_Limit_Output;
}
wOutput_32 = (wProportional_Term/KP_DIV_VM) + (pHandle->Integral_sum/KI_DIV_VM);
if(wOutput_32 > pHandle->Upper_Limit_Output)
{
wOutput_32 = pHandle->Upper_Limit_Output;
}
else if(wOutput_32 < pHandle->Lower_Limit_Output)
{
wOutput_32 = pHandle->Lower_Limit_Output;
}
return (uint16_t)wOutput_32;
}
uint16_t Speed_Controller(PID_Handle_t *PISpeed, int32_t targetSpeed, int32_t realSpeed)
{
uint16_t hDutyCycleReference=0;
int32_t hError;
hError = targetSpeed - realSpeed;
hDutyCycleReference = PI_Controller(PISpeed, hError);
// usb_printf("pulse is %d\r\n", hDutyCycleReference);
return hDutyCycleReference;
}
电机控制程序重要片段
if(htim->Instance==TIM2)
{
if(M1_motor_status==2) // motor is running
{
M1_hall_pos = M1_get_hall_pos();
if(M1_pre_hall_pos!=M1_hall_pos)
{
M1_pre_hall_pos=M1_hall_pos;
//__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)(period/1.2)); //1.2
//__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, (uint32_t)(period/1.8)); //1.8
//__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (uint32_t)(period/2.5)); //2.5
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)Speed_Controller(&speedPID, M1_target_speed, M1_motor_speed));
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, (uint32_t)Speed_Controller(&speedPID, M1_target_speed, M1_motor_speed));
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (uint32_t)Speed_Controller(&speedPID, M1_target_speed, M1_motor_speed));
M1_motor_change(M1_hall_pos, motor_direction);
}
}
}
3.运行结果确认
将target_speed设定为800rpm, 下面是实际PID调速的结果。
基本实现了800rpm的调速。
至此,STM32 无刷电机的PID速度环控制,大功告成,亲个嘴儿。
标签:sum,环控制,PID,VM,无刷电机,M1,pHandle,Output From: https://blog.csdn.net/dqsh06/article/details/142885287