c - 如何使用 PID Controller ?

标签 c pid-controller

我目前正在研究温度 Controller 。

我有一个 Temperature_PID() 函数,它返回操纵变量(它是 P、I 和 D 项的总和),但是我该如何处理这个输出?

温度由 PWM 控制,因此 0% 占空比 = 加热器关闭,100% 占空比 = 加热器开启。

到目前为止我已经尝试过了

Duty_Cycle += Temperature_PID();
if(Duty_Cycle > 100) Duty_Cycle = 100;
else if(Duty_Cycle < 0) Duty_Cycle = 0;

这对我不起作用,因为 I 术语基本上使这个系统非常不稳定。想象一下整合一个区域,再增加一个小数据点,再次整合这个区域,然后求和。一遍又一遍。这意味着每个数据点都会使该控制方案呈指数级恶化。

我想尝试的另一件事是

Duty_Cycle = Expected_Duty_Cycle + Temperature_PID();

其中 Expected_Duty_Cycle 是一旦 Controller 达到稳定点且 Temperature_PID() 为 0 时应设置的温度。但是,这也不起作用,因为 Expected_Duty_Cycle 将始终根据加热器的条件而变化,例如不同的天气。

所以我的问题是我应该如何处理 PID 的输出?我不明白如何根据 PID 输出分配占空比。理想情况下,这将保持在 100% 的占空比,直到温度几乎达到设定点并开始下降到较低的占空比。但是使用我的第一种方法(我的 I 增益设置为零)它只会在它已经过冲后才开始降低占空比。

这是我的第一篇文章。希望我能找到答案。谢谢 stackoverflow。

编辑: 这是我的 PID 函数。

double TempCtrl_PID(PID_Data *pid)
{
    Thermo_Data tc;
    double error, pTerm, iTerm, dTerm;

    Thermo_Read(CHIP_TC1, &tc);

    pid->last_pv = pid->pv;
    pid->pv = Thermo_Temperature(&tc);
    error = pid->sp - pid->pv;
    if(error/pid->sp < 0.1)
        pid->err_sum += error;

    pTerm = pid->kp * error;
    iTerm = pid->ki * pid->err_sum;
    dTerm = pid->kd * (pid->last_pv - pid->pv);

    return pTerm + iTerm + dTerm;
}

编辑 2: 以前从未使用过,所以如果链接断开,请告诉我。 https://picasaweb.google.com/113881440334423462633/January302013

抱歉,当我尝试重命名坐标轴或标题时,Excel 崩溃了。注意:系统中还没有风扇,所以我无法像加热一样快地冷却加热器,因此与上面相比,它在设定点以下花费的时间很少。 第一张图是一个简单的开关 Controller 。 第二张图是我的PD Controller 。如您所见,温度降低需要更长的时间,因为它不会在温度过冲之前减去,它会等到温度过冲后再从占空比中减去,而且这样做的速度太慢了。我该如何告诉我的 Controller 在达到最高温度之前降低占空比?

最佳答案

PID 的输出占空比。您必须调整 kpkikd 以将 PID 输出置于 Duty_Cycle 范围内,例如, 0 到 100。明确限制 PID 函数本身的输出通常是个好主意。

您应该通过简单的步骤“调整”您的 PID。

  1. 关闭积分项和导数项(将kikd 设置为零)

  2. 慢慢增加您的kp,直到设置点 10% 的阶跃变化使输出振荡

  3. kp 降低 30% 左右,这应该可以消除振荡

  4. ki 设置为 kp 的一小部分并进行调整以获得您想要的超调量与达到设定点的时间之间的权衡

  5. 希望您不需要kd,但如果需要,请将其缩小

关于c - 如何使用 PID Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14614124/

相关文章:

java - 如何用Java实现多线程PID Controller ?

c - PID在arduino中的实现

c - 'ld' 无法链接符号,尽管它们在库中

mysql - 如何将带有单引号和双引号的字符串(文件中的 10000 条记录)传递给 mysql 查询?

使用 gcc -O1 优化检查 unsigned int 中是否设置了第 31 位

c++ - 平衡机器人PID整定

c# - 将入站消息的等待延迟限制为每秒消息数

c - 如何获取选项卡项的TCITEM结构?

c - 如何只交换堆节点的数据