PID控制回路具有较大且不可预测的异常


10

简短的问题
是否存在一种通用方法来处理否则为均匀控制区域内的非常大的异常(数量级)?

背景信息
我正在研究一种控制算法,该算法可在通常均匀的控制区域上驱动电动机。在无负载/无负载的情况下,PID控制效果很好(响应速度快,几乎没有过冲)。我遇到的问题通常是至少有一个高负载位置。该位置由用户在安装过程中确定,因此没有合理的方法让我知道何时/何地可以使用它。

当我调整PID以处理高负载位置时,它会在无负载区域上引起大的过度拍摄(这是我完全预期的)。虽然OK旅行过冲中旬,有在外壳没有机械硬盘停止。缺少硬停止装置意味着任何明显的超调都会/确实会导致控制臂与电动机断开连接(产生死机)。

我正在制作原型的东西

  • 嵌套的PID(在远离目标时非常激进,在靠近目标时很保守)
  • 固定增益,远处为PID,关闭时为PID
  • 保守的PID(无负载工作)+外部控制,寻找PID停止运行并施加额外的能量,直到达到目标或检测到快速变化率(即离开高负载区域)为止

局限性

  • 全程旅行
  • 不能添加硬停止(此时)
  • 错误可能永远不会归零
  • 可以通过小于10%的行程获得高负载(这意味着没有“运行开始”)

Answers:


2

使用导数项时,您的错误计算似乎不会累积错误,并且您可能需要修改此错误,因为只有导数项才能够对过程中的快速变化做出反应。

如果我理解正确,您的代码

// Determine the error delta
dE = abs(last_error - new_error);
last_error = new_error;

将始终根据当前误差来计算控制项,这是PID实施的传统方式。很好,因为无论如何我应该用I术语来处理累积的错误。

但是,我有一个客户提出了以下您可能想尝试的想法。由于您的过程曲线中有一部分需要更激进的更改,因此您甚至可以累积D部分错误:

if(TD)                                                 // Calculate D term
{  
   Last_C += (Error - Last_C) / TD;                    // D term simulates
   Dterm = (Error - Last_C) * KD;                      // capacitor discharging
}
else    
   Dterm = 0;                                          // D term is OFF (TD is 0)

这里有两个有趣的事情要注意:

  • TD值不是微分增益(KD),而是微分时间,微分时间是控制误差累积时间的用户常数。如果将其设置为零,则不管KD增益值设置如何,都将禁用PID的D部分。

  • 请注意,在将当前错误用于D部分计算之前,如何使用当前错误对Last_C值进行“计费”。Last_C变量就像电容器一样工作,它会在误差较大时累积,因此您的导数部分也将基于最近的误差“历史”来起作用,之后(误差较小时)该“历史”会像电容器一样放电。

当然,您应该以可能已经做过的方式限制总输出(抗饱和重置,无扰动自动到手动传输以及其他常规功能)。

如果发现有用,我可以发布有关PID算法其他术语的更多详细信息,但是您可能想尝试一下,看看会发生什么。多年来一直为我的客户服务。


感谢您的输入。我必须尝试一下。乍一看似乎很有意义。
亚当·刘易斯

我知道了,因此您在“主要” PID中有一个D项贡献,加上任何失速检测都会给计算带来影响。
Drazen Cika

1
没错 PID的Dterm在调整期间会使用,但不是很严格。使这个问题更加困难的是,负载可以在短的时间内释放。IE浏览器的连接被解除。当将任何平滑函数(求和)应用于失速力时,这种突然的力去除会导致较大的过冲。
亚当·刘易斯

邪恶的问题,弄清楚某些模糊逻辑算法将如何处理这个问题将很有趣。至少您可以将更多与问题相关的经验纳入算法中,而不是局限于标准解决方案中。无论如何,祝您好运:-)
Drazen Cika

1

初始解决方案

stalled_pwm_output = PWM / | ΔE|

PWM =最大PWM值
ΔE= last_error-new_error

初始关系基于电动机中无变化而成功地提高了PWM输出。有关示例输出,请参见下图。

这种方法使得非侵入性PID停顿的情况成为可能。但是,它具有一个不幸(很明显)的问题,即当非侵略性PID能够达到设定值并尝试减慢速度时,stalled_pwm_output会上升。当上升到空载位置时,该上升会引起较大的过冲。

1 /ΔE与ΔE

当前解决方案

理论

stalled_pwm_output =(kE * PID_PWM)/ | ΔE|

kE =缩放常数
PID_PWM =来自非
主动PID的当前PWM请求ΔE= last_error-new_error

我当前的关系仍然使用1 /ΔE概念,但是使用非侵略性PID PWM输出来确定stall_pwm_output。这样,当PID开始接近目标设定值时,PID可以将stall_pwm_output调速,但在堵转时允许100%PWM输出。需要比例常数kE来确保PWM进入饱和点(下图中的10,000以上)。

伪码

请注意,cal_stall_pwm的结果已添加到我当前控制逻辑中的PID PWM输出中。

int calc_stall_pwm(int pid_pwm, int new_error)
{
    int ret = 0;
    int dE = 0;
    static int last_error = 0;
    const int kE = 1;

    // Allow the stall_control until the setpoint is achived
    if( FALSE == motor_has_reached_target())
    {
        // Determine the error delta
        dE = abs(last_error - new_error);
        last_error = new_error;

        // Protect from divide by zeros
        dE = (dE == 0) ? 1 : dE;

        // Determine the stall_pwm_output
        ret = (kE * pid_pwm) / dE;
    }

    return ret;
}

输出数据

失速PWM输出 失速PWM输出

请注意,在停转的PWM输出图中,由于电机无法在给定时间内到达位置,因此激活了内置安全功能,导致〜3400处的PWM突然下降。

空载PWM输出 空载PWM输出


1

你不说你在控制什么...电机速度?位置?不管是什么,第一步将是定义一个可接受的错误。例如,如果控制用于速度,则可以将最大误差设置在目标值的1%之内。如果没有定义可接受的误差,就无法确定ADC或PWM计数所需的分辨率。否则,PID补偿可能是完美的,但仍然会出现极限循环振荡。

然后,您需要了解开环系统的动态。否则,您将不知道环路的比例(P),积分(I)和微分(D)部分需要什么增益。您可以通过输入阶跃(驱动电平或PWM的阶跃变化)或负载的阶跃变化(似乎与您相关)来测量动态。

在控制算法的分母中使用逐周期误差变化来修改PWM值,可确保环路永远不会稳定下来。这确保了控制中的极限循环振荡。大多数客户都不愿意。

循环的P部分负责处理即时错误(迅速响应错误)。但是它将具有有限的增益,因此会留下一些误差。循环的I部分随时间响应缓慢,以应用无限增益(无限时间代表无限增益),以纠正由P部分留下的误差。

由于I部分很慢,因此即使您为其设置了正确的增益,它也可能与最小化误差所需的校正不一致。因此,它会缠绕起来,需要很长时间才能恢复。或者,它与P部分相反。

处理结束的最佳方法是将积分器中的最大存储值限制为仅比最坏情况下校正比例误差所需的值大一点。如果积分器异相并且与P分开,则最好将积分器值设置为零。可以将算法设计为感知到这种情况,并在必要时重置积分器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.