直流电机PID算法
直流电机
- 直流电动机的工作原理
- 在定子绕组线圈通入直流,产生励磁磁场。
- 在外加直流电源的情况下,通入直流电经过电刷,换向器把直流电转换成为交流电。
- 产生交流电压,产生制动的安培力,产生驱动的电磁转矩。
对于使用者而言,了解输入直流电即可对直流电机进行驱动控制,控制电机速度的关键在于输入的电压高低
PID算法

输出公式:

其中,e(t)为时刻t的传感器参数。需根据实际情况调整PID参数。
PID控制算法的三个最基本的参数:Kp: 比例增益、Ki: 积分增益、Kd: 微分增益。
对于调节不同参数对输出的影响,可参考下表


PID调节直流电机

上图为旋转编码器输出信号图例。电机每转过一定角度,编码器输出对应脉冲,可根据收集的脉冲总数计算电机转过的角度。
在本项目中,由于直流电机无法直接精确停止到目标位置,故采用编码器的脉冲值作为PID环节输入,控制直流电机电压值,控制电压的方式采用PWM占空比控制。即,在本项目的PID中,e(t)为t时刻编码器累计脉冲值,输出为PWM值。
经过多次实验测试,设定PID系数Position_KP=2.5,Position_KI=0.005,Position_KD=141.0;
// PID系数
float Position_KP=2.5,Position_KI=0.005,Position_KD=141.0;
//前往目标编码器脉冲值
void PID_Go(int Target_Position)
{
static int Moto = 0;
Reload_Target_Encoder_Number(Target_Position);
Moto = Position_PID(Spin_Count,Target_Position); /* 位置PID控制器 */
Moto = Xianfu_Pwm(Moto); /* 限幅 */
Set_Pwm(Moto); /* 赋值 */
}
void Set_Pwm(int moto)
{
int min=650; //驱动电机的最小PWM值
if(abs(moto)<3){
Stop();
// printf("STOP");
}
else if(moto>0) /* 正转 */
{
GoForward(abs(moto)+min);
}
else /* 反转 */
{
GoBack(abs(moto)+min);
}
}
/**************************************************************************
函数功能:限制PWM赋值
入口参数:电机PWM值
返回 值:限制后的值
**************************************************************************/
int Xianfu_Pwm(int moto)
{
if(moto<-Operating_speed) moto =-(Operating_speed);
if(moto> Operating_speed) moto = (Operating_speed);
return moto;
}
/**************************************************************************
函数功能:位置式PID控制器
入口参数:实际位置,目标位置
返回 值:电机PWM
根据位置式离散PID公式
pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)]
e(k)代表本次偏差
e(k-1)代表上一次的偏差
∑e(k)代表e(k)以及之前的偏差的累积和;其中k为1,2,...,k;
pwm代表输出
**************************************************************************/
int Position_PID(int reality,int target)
{
static float Bias,Pwm,Last_Bias,Integral_bias;
Bias=target-reality; /* 计算偏差 */
Integral_bias+=Bias; /* 偏差累积 */
if(Integral_bias> 5000) Integral_bias = 5000; /* 积分限幅 */
if(Integral_bias<-5000) Integral_bias =-5000;
Pwm = (Position_KP*Bias) /* 比例环节 */
+(Position_KI*Integral_bias) /* 积分环节 */
+Position_KD*(Bias-Last_Bias); /* 微分环节 */
Last_Bias=Bias; /* 保存上次偏差 */
return Pwm; /* 输出结果 */
}
//使用范例
//功能:多次往复运动
//参数:total_distance:前行总脉冲数;
// back_dis:后退目标脉冲数;
// times:前进次数
//返回:无
void Automatic_FB(int total_distance,int back_dis, u16 times)
{
int temp = total_distance / times;
int temp_remainder = total_distance % times; //余数
int ret_Zero = total_distance; //回初始位置,作调试
Spin_Count = 0;
text1_Spin_Count = 0;
int i = 0,last_back;
Motorflag = 2;
while(Motorflag !=0)
{
PID_Go(temp);
}
delay_ms(300);
// printf("Spincount:%d \n",Spin_Count);
printf("%dtimes forward text1 Spincount:%d ",i,text1_Spin_Count);
total_distance -= text1_Spin_Count; //11
text1_Spin_Count = 0;
Motorflag = 1;
while(Motorflag !=0)
{
PID_Go(temp-back_dis);
}
delay_ms(300);
Spin_Count = 0;
printf("%dtimes back text1_Spincount:%d \n",i,text1_Spin_Count);
last_back = text1_Spin_Count;
text1_Spin_Count = 0;
int tar;
i++;
for(;i<times;i++)
{
temp = total_distance / (times-i); //11
temp_remainder = total_distance % (times-i); //11
if(temp_remainder > 0) //处理余数
{
tar = temp + last_back+ 1;
temp_remainder -- ;
}
else
{
tar = temp+last_back;
}
Motorflag = 2;
while(Motorflag !=0)
{
PID_Go(tar);
}
delay_ms(300);
// printf("Spincount:%d \n",Spin_Count);
printf("%dtimes forward text1 Spincount:%d ",i,text1_Spin_Count);
total_distance -= (text1_Spin_Count-last_back); //11
text1_Spin_Count = 0;
Motorflag = 1;
while(Motorflag !=0)
{
PID_Go(tar-back_dis);
}
delay_ms(300);
Spin_Count = 0;
printf("%dtimes back text1_Spincount:%d \n",i,text1_Spin_Count);
last_back = text1_Spin_Count;
text1_Spin_Count = 0;
}
//回起始点
Motorflag = 2;
while(Motorflag !=0)
{
PID_Go(-ret_Zero+back_dis);
}
}
该文介绍了如何使用PID算法来精确控制直流电机,特别是在设计注射泵时的应用。通过调整PID参数Kp、Ki和Kd,控制电机的电压以达到期望的速度和位置精度。文中还提到了利用旋转编码器收集脉冲以计算电机转角,并采用PWM占空比来调整电机电压,确保电机能准确停在目标位置。
1217

被折叠的 条评论
为什么被折叠?



