PID控制减速电机

直接来干货吧

 

对于单片机来说 pid 是一个 每隔多长时间执行一次 的 代码块 而这个时间通常就是积分时间

我们令这个代码快这个代码快执行周期为15ms,

那么通常我们单片机获取速度 的更新时间需要小于15ms

也就是说  采样周期 <= 积分时间

pid输入值更新的时间 < pid代码块执行的时间

(我采用的每次数据发生更新(中断函数),就立刻行一次pid 并把输出量转化为pwm,以提高效率)

pid控制减速电机输入量是速度(V)目标速度(Vm)

输出量就是pwm的占空比了(经验来看减速电机的pwm周期尽量短)

pid输出量 = P部分 + I部分 + D部分

 

P部分 = p值 x 误差值;

D部分 = d值 x (这一次的 V - 上一次的V)  //(误差为 0 是 D部分为0)我们减速电机控制不需要考虑D

I部分  = I值(之前每次执行一次pid就把误差累加)//(积分)

         //(最后误差为0的时候 I 值得积分记累加值就是输出量,以为P值和D值此刻已经为 0了)  

代码大概如下: 

pid 参数的整定:

SPid SPidStruct1;
        SPidStruct1.dState    =    0         ;
        SPidStruct1.iState     =    0         ;
        SPidStruct1.iMAX      =    900     ;
        SPidStruct1.iMin        =    -900    ;            //    采用系统输出范围的 90 %;
        SPidStruct1.pid_P     =    3.45    ;            //    4.7  I D为0时开始震荡 取 70% 3.29
        SPidStruct1.pid_I      =    3         ;
        SPidStruct1.pid_D     =    0        ;

while(1)

{

a=UpdatePID(&SPidStruct1, 目标值-但前值 , 当前值 );

set_PWM(a);

delay_ms(10);

}

#include "pid.h"

typedef struct
{
	double dState;		        //	上一次的 实际待调值
	double iState;		        //	比例系数 i 的积分(累加结果)
	double iMAX;			// 	积分 i 的最大值
	double iMin;			//	积分i 的最小值
	double pid_P;			//	比例系数 P
	double pid_I;			//	比例系数 I
	double pid_D;			//	比例系数 D
}SPid;

double UpdatePID(SPid  *pid,double error,double TurePosition)
{
	double pTerm,iTerm,dTerm;
	
	pTerm = pid->pid_P*error;			// P部分计算
																				
	pid->iState += error;//对 误差 积分							 
	if(pid->iState > pid->iMAX)	        //  i 范围约束(提高稳定性)
			pid->iState = pid->iMAX;
	else if(pid->iState < pid->iMin)
			pid->iState = pid->iMin;
	iTerm = pid->pid_I* pid->iState;	// I部分计算
	
	dTerm = pid->pid_D* (TurePosition - pid->dState);	// D
	pid ->dState = TurePosition;        // 对 误差d 微分处理

	return pTerm+iTerm+dTerm;           // 返回pid的输出值
}

pid 调参有点痛苦的,,

这里提供 一个工具给大家,使用这个就可以不用了解使用matlab里的pid工具了

    串口波形助手 ,通过串口周期的打印数据描绘出曲线 

    使用格式 printf("A%d\r\nB%d\r\nC%d\r\nD%d\r\n",a,b,c,d);

链接:https://pan.baidu.com/s/1uHMCPOgy0iiKYNDyRZCn-w 
提取码:miak 

你可能感兴趣的:(PID)