<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>PID on Rancho&#39;s Notes</title>
    <link>https://fan-pengfei.top/tags/pid/</link>
    <description>Recent content in PID on Rancho&#39;s Notes</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sun, 09 Apr 2023 04:47:04 +0000</lastBuildDate>
    <atom:link href="https://fan-pengfei.top/tags/pid/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>PID进阶教程</title>
      <link>https://fan-pengfei.top/posts/pid%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B/</link>
      <pubDate>Sun, 09 Apr 2023 04:47:04 +0000</pubDate>
      <guid>https://fan-pengfei.top/posts/pid%E8%BF%9B%E9%98%B6%E6%95%99%E7%A8%8B/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;PID精进教程；
这篇文章的主要内容是如何改进初学者的PID控制器。文章中提到，初学者的PID控制器设计的目的是不规则地调用。这会导致两个问题：您无法从PID获得一致的行为，因为有时它被频繁调用，有时则没有。您需要进行额外的数学计算，以计算导数和积分，因为它们都依赖于时间的变化。作者提出了一种新的方法，称为“Proportional on Measurement”，可以解决这些问题。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;任何编写自己的 PID 算法的人都可以看看我是如何做的，并可以从中学到他们需要的东西。&lt;/p&gt;
&lt;p&gt;这将是一个艰难的过程，但我想我找到了一种不太痛苦的方式来解释我的代码。我将从所谓的“初学者的 PID”开始。然后我将逐步改进它，直到我们得到一个高效、健壮的 pid 算法。&lt;/p&gt;
&lt;h2 id=&#34;pid的开始&#34;&gt;PID的开始&lt;/h2&gt;
&lt;p&gt;这是初学PID的人都知道的公式：&lt;/p&gt;
&lt;p&gt;Output=K_pe(t)+K_t\int{e(t)dt}+K_D{\frac{d}{dt}}e(t)
Where:e=Setpoint-Input&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;公式(2)也就是指偏差e等于设定值和当前值的差别；&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;根据这个公式，大多数都能写出下面的代码：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/*working variables*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;long&lt;/span&gt; lastTime;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; Input, Output, Setpoint;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; errSum, lastErr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; kp, ki, kd;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Compute&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;/*How long since we last calculated*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;long&lt;/span&gt; now &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;millis&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; timeChange &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt;)(now &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; lastTime);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;/*Compute all the working error variables*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; error &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Setpoint &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; Input;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   errSum &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; (error &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; timeChange);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; dErr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (error &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; lastErr) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; timeChange;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;/*Compute PID Output*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Output &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; kp &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; error &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; ki &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; errSum &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; kd &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; dErr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;/*Remember some variables for next time*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   lastErr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; error;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   lastTime &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; now;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SetTunings&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; Kp, &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; Ki, &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; Kd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   kp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Kp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ki &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Ki;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   kd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Kd;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Compute()&lt;/code&gt;被定期或不定期地调用，并且运行良好。不过，这个系列并不是关于“工作得很好”。如果我们要将这段代码变成与工业 PID 控制器相当的东西，我们必须解决一些问题：&lt;/p&gt;</description>
    </item>
    <item>
      <title>PID中积分饱和及其解决办法</title>
      <link>https://fan-pengfei.top/posts/pid%E4%B8%AD%E7%A7%AF%E5%88%86%E9%A5%B1%E5%92%8C%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/</link>
      <pubDate>Thu, 10 Mar 2022 02:41:07 +0000</pubDate>
      <guid>https://fan-pengfei.top/posts/pid%E4%B8%AD%E7%A7%AF%E5%88%86%E9%A5%B1%E5%92%8C%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;PID控制中常出现的积分饱和概念及其解决方案；&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;积分饱和的概念&#34;&gt;积分饱和的概念：&lt;/h2&gt;
&lt;p&gt;这种现象往往发生在误差有大幅变化（例如大幅增加），积分器因为误差的大幅增加有很大的累计量，因为积分器的输出满足下式：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;pIYBAGBYOGKAMGJyAAAKa3yzFcw010.png&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/pid%E4%B8%AD%E7%A7%AF%E5%88%86%E9%A5%B1%E5%92%8C%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/img-1.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;离散化形式表示为：&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;pIYBAGBYOJqATzZgAAALkxL3jOw485.png&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/pid%E4%B8%AD%E7%A7%AF%E5%88%86%E9%A5%B1%E5%92%8C%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/img-2.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;所以随着时间的增加，每次累积较大的误差，很容易造成积分饱和并产生较大的过冲，而且当误差变为负时，其过冲仍维持一段时间之后才恢复正常的情形。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;通常会产生的输出如下图所示：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;o4YBAGBYOR-APSCrAAIJXwZqBuo640.png&#34; loading=&#34;lazy&#34; src=&#34;https://fan-pengfei.top/posts/pid%E4%B8%AD%E7%A7%AF%E5%88%86%E9%A5%B1%E5%92%8C%E5%8F%8A%E5%85%B6%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/img-3.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;从图中我们不难发现，这里有三个过程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;因为这个过程存在 较大幅度变化的误差，因此积分器累积了较大的值，从图中可以看到，积分器的面积比较大（阴影部分）；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;此时积分已经饱和，产生了较大的过冲，并且在较长的一段时间内，一直处于过冲的状态；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;积分脱离饱和状态，产生了积极的调节作用，消除静差，系统输出达到设定值；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;如何防止积分饱和&#34;&gt;如何防止积分饱和：&lt;/h2&gt;
&lt;p&gt;为了防止PID控制器出现积分饱和，需要在算法加入抗积分饱和（&lt;code&gt;anti-integral windup&lt;/code&gt;）的算法；通常有以下几种措施；&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;积分分离或者称为去积分算法；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在饱和的时候将积分器的累计值初始化到一个比较理想的值；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;若积分饱和因为目标值突然变化而产生，将目标值以适当斜率的斜坡变化可避免此情形；&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;将积分累计量限制上下限，避免积分累计量超过限制值；&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;如果 PID输出已经饱和，则重新计算积分累计量，使输出恰好为合理的范围；&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;参考&#34;&gt;参考：&lt;/h2&gt;
&lt;p&gt;1、&lt;a href=&#34;https://www.elecfans.com/d/1544295.html&#34;&gt;一文详细解析到底什么是积分饱和&lt;/a&gt;；&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
