基于直流电机PID算法的注射泵设计

该文介绍了如何使用PID算法来精确控制直流电机,特别是在设计注射泵时的应用。通过调整PID参数Kp、Ki和Kd,控制电机的电压以达到期望的速度和位置精度。文中还提到了利用旋转编码器收集脉冲以计算电机转角,并采用PWM占空比来调整电机电压,确保电机能准确停在目标位置。

基于直流电机PID算法的注射泵设计

直流电机PID算法

直流电机

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

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);
			}
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值