1. 速度环

以控制电机转速为例,希望电机通过编码器的反馈,达到平稳变速的效果。由于增量式PID输出的是控制量增量,如果计算机出现故障,误动作影响较小,而执行机构本身有记忆功能,可仍保持原位,不会严重影响系统的工作,而位置式的输出直接对应对象的输出,因此对系统影响较大。

2. PID控制器

PID控制器

[公式]

需值得注意的事:

 PID控制器的运算必须在定时中断中执行

 采样周期和控制周期会影响系数

控制周期即控制代码的周期,一般是放置运算PID代码的定时器周期采样周期即获取传感器的周期,电机的采样周期是接收到电机实时数据的周期。

3. 调试中遇到的问题:

①电机响应出现极大的滞后:电机匀速时,下发speed=0,过了几秒才停止,响应滞后严重。

电机在启动和停止时,容易出现抖动。

4. 解决方案

4.1 积分饱和

积分持续增大会造成PID输出积分比重过大,导致响应的严重滞后,需抑制积分的过度积累。

也即:①误差较大时,抑制甚至消除积分项输出;②误差较小时,放开积分项;

  • 变速积分

变速积分的实质是用一个连续的函数进行积分的切换,但0和1之间的过渡未免太突兀了,在误差在[B,A+B]时,生成[0,1]的数值index,积分输出乘以index,代码如下所示:

static void Changing_Integral_Rate(PID_TypeDef *pid)
{
    if (pid->Err * pid->Iout > 0) // 判断积分是否为积累趋势
    {
        if (ABS(pid->Err) <= pid->ScalarB)
            return; //完整积分
        if (ABS(pid->Err) <= (pid->ScalarA + pid->ScalarB))
            //使用线性函数过渡
            pid->index *= (pid->ScalarA - ABS(pid->Err) + pid->ScalarB) / pid->ScalarA;
        else
            pid->index= 0;//取消积分环节
    }
}


PID计算

float PID_Calculate(PID_TypeDef *pid, float measure, float target)
{
  pid->Err = pid->Target - pid->Measure; //得到偏差值
  pError=pid->Err-pid->lasterror;
  iError=pid->Err;

  pid->Pout = pid->Kp * pid->Err;

  Changing_Integral_Rate(pid); // 变速积分调用
  pid->iout = pid->Ki * pid->Err *pid->index; //计算积分输出

 //计算pid增量
   pid->increment = pid->Pout + pid->Iout + pid->Dout;
   pid->output += pid->increment;
}

4.2 电机加减速

电机在启停时,出现抖动是由于下发的速度突变,加速度过大

控制电机时,对下发的速度进行梯度增加或减小,由时间量计算,返回一个范围在[0,1]的数值。用于解决下发到速度环的速度突变的问题

float MoveRamp( uint8_t status, int16_t *time, int16_t inc, int16_t dec )
{
	float  factor = 0;

	
	factor = 0.15 * sqrt( 0.15 * (*time) );  //计算速度斜坡,time累加到296.3斜坡就完成
	
	if (status == 1)//按键被按下
	
	{
		if (factor < 1)//防止time太大
		{
			*time += inc;
		}
	}
	else		//按键松开
	{
		if (factor > 0)
		{
			*time -= dec;

			if (*time < 0)
			{
				*time = 0;
			}
		}
	}

	factor = constrain_float( factor, 0, 1 );//注意一定是float类型限幅

	return factor;  //注意方向
}