我不理解PID控制器的组成部分.让我们假设来自维基百科的这个伪代码:
previous_error = 0
integral = 0
start:
error = setpoint - measured_value
integral = integral + error*dt
derivative = (error - previous_error)/dt
output = Kp*error + Ki*integral + Kd*derivative
previous_error = error
wait(dt)
goto start
Run Code Online (Sandbox Code Playgroud)
积分在开始时设置为零.然后在循环中它整合了错误随着时间的推移.当我对测量值或设定值进行(正)变化时,误差将变为正值,积分将在整个时间内(从头开始)"吃掉"值.但我不明白的是,当误差稳定回零时,积分部分仍然会有一些值(随时间积分的误差),并且仍然会对控制器的输出值有所贡献,但它不应该.
请问有人解释一下吗?
我目前正在研究温度控制器.
我有一个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;
Run Code Online (Sandbox Code Playgroud)
这对我不起作用,因为I术语基本上使得这个系统非常不稳定.想象一下,整合一个区域,添加另一个小数据点,再次整合该区域,并对它们求和.一遍又一遍.这意味着每个数据点使得该控制方案呈指数级恶化.
我想尝试的另一件事是
Duty_Cycle = Expected_Duty_Cycle + Temperature_PID();
Run Code Online (Sandbox Code Playgroud)
其中Expected_Duty_Cycle是控制器达到稳定点并且Temperature_PID()为0时应设置的温度.但是,这也不起作用,因为Expected_Duty_Cycle将始终根据加热器的条件而变化,例如不同的天气.
所以我的问题是我究竟如何处理PID的输出?我不明白如何根据PID输出分配占空比.理想情况下,这将保持100%的占空比,直到温度几乎达到设定点并开始下降到较低的占空比.但是使用我的第一种方法(我的增益设置为零)它只会在已经超调之后开始降低占空比.
这是我的第一篇文章.希望我找到答案.谢谢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 …Run Code Online (Sandbox Code Playgroud) 我需要在具有相当大延迟的系统中调整PI(D)增益.这是一种常见的温度控制器,但温度探头远离加热器.更多信息:
从加热器的任何变化开始,探头的响应延迟大约10秒
温度采样@ 1 Hz,分辨率为0.01°C
加热器是PWM控制器,周期为1 Hz,带有10位PWM
目标是将振荡保持在±0.05°C以下
目前我正在使用控制器作为PI.我无法避免振荡.增益越高,振荡越小且越快.仍然太高(约±0.15°C).降低P和I增益会导致非常长且深的振荡.
我认为这是由于延误.结算时间不是问题,可能需要它所需的所有时间.
我很困惑如何使系统工作.让我们考虑只使用I.当探头达到目标值并且I输出开始减小时,温度将上升一段时间.我不能使用导数项,因为变化太慢而且dError非常接近于零(如果我将dGain设置为一个巨大的值,则噪声太大).
任何的想法?