{"id":1544,"date":"2011-07-24T09:21:08","date_gmt":"2011-07-24T13:21:08","guid":{"rendered":"http:\/\/brettbeauregard.com\/blog\/?p=1544"},"modified":"2024-06-03T15:50:23","modified_gmt":"2024-06-03T19:50:23","slug":"pid-when-should-i-compute-the-integral-term","status":"publish","type":"post","link":"http:\/\/brettbeauregard.com\/blog\/2011\/07\/pid-when-should-i-compute-the-integral-term\/","title":{"rendered":"PID: When Should I Compute the Integral Term?"},"content":{"rendered":"<p>Recently there was a suggestion posted to the <a href=\"\/blog\/2011\/04\/improving-the-beginners-pid-introduction\/\">Beginner&#8217;s PID Series<\/a>. The contention was that if you solve things in the Laplace domain, it specifies a different way of executing the Integral Term.  Rather than looking at the sum of error for THIS point, the commenter suggested, you should look at the sum from the last point.<\/p>\n<p>So the current code is this:<\/p>\n<pre class=\"brush: css; gutter: true; highlight: [4,5,6]; title: ; notranslate\" title=\"\">\r\n      \/*Compute all the working error variables*\/\r\n\t  double input = *myInput;\r\n      double error = *mySetpoint - input;\r\n      ITerm+= (ki * error);\r\n      if(ITerm &gt; outMax) ITerm= outMax;\r\n      else if(ITerm &lt; outMin) ITerm= outMin;\r\n      double dInput = (input - lastInput);\r\n \r\n      \/*Compute PID Output*\/\r\n      double output = kp * error + ITerm- kd * dInput;\r\n<\/pre>\n<p>and the suggestion was this:<\/p>\n<pre class=\"brush: css; gutter: true; highlight: [10,11,12]; title: ; notranslate\" title=\"\">\r\n      \/*Compute all the working error variables*\/\r\n\t  double input = *myInput;\r\n      double error = *mySetpoint - input;\r\n\r\n      double dInput = (input - lastInput);\r\n \r\n      \/*Compute PID Output*\/\r\n      double output = kp * error + ITerm- kd * dInput;\r\n      \r\n\t  ITerm+= (ki * error);\r\n      if(ITerm &gt; outMax) ITerm= outMax;\r\n      else if(ITerm &lt; outMin) ITerm= outMin;\r\n<\/pre>\n<p>I had never seen it done this way, but I figured I&#8217;d give it a shot.  The test I devised was a simple setpoint step, followed by a ramp down.  <\/p>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-DefaultSetpoint.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-DefaultSetpoint.png\" alt=\"\" title=\"ITermTest-DefaultSetpoint\" width=\"481\" height=\"289\" class=\"aligncenter size-full wp-image-1550\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-DefaultSetpoint.png 481w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-DefaultSetpoint-300x180.png 300w\" sizes=\"auto, (max-width: 481px) 100vw, 481px\" \/><\/a><\/p>\n<p>With the controller set at the default sample time, the difference was imperceptible. To try and highlight the difference between the two methods, I decided to bump up the PID sample time from the default of 100mS to 5 seconds.<\/p>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secSetpoint.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secSetpoint.png\" alt=\"\" title=\"ITermTest-5secSetpoint\" width=\"481\" height=\"289\" class=\"aligncenter size-full wp-image-1552\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secSetpoint.png 481w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secSetpoint-300x180.png 300w\" sizes=\"auto, (max-width: 481px) 100vw, 481px\" \/><\/a><\/p>\n<p>Ok so here we can see a clear winner.  The existing PID code performs better than suggested, probably because the integral term gets to react to process changes 5 seconds sooner.  But just to make sure I wasn&#8217;t missing anything, I decided to do another test.  Instead of a setpoint change, I induced a load change in the system.<\/p>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secDisturb.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secDisturb.png\" alt=\"\" title=\"ITermTest-5secDisturb\" width=\"481\" height=\"289\" class=\"aligncenter size-full wp-image-1553\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secDisturb.png 481w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/07\/ITermTest-5secDisturb-300x180.png 300w\" sizes=\"auto, (max-width: 481px) 100vw, 481px\" \/><\/a><\/p>\n<p>Once again, the existing PID code performed better, handling the load change more quickly.  <\/p>\n<p>So the verdict? While this was a fun excersize, I think the results are clear. I&#8217;ll leave the code as it is.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently there was a suggestion posted to the Beginner&#8217;s PID Series. The contention was that if you solve things in the Laplace domain, it specifies a different way of executing the Integral Term. Rather than looking at the sum of &hellip; <a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/07\/pid-when-should-i-compute-the-integral-term\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31,7],"tags":[],"class_list":["post-1544","post","type-post","status-publish","format-standard","hentry","category-coding","category-pid"],"_links":{"self":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/1544","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/comments?post=1544"}],"version-history":[{"count":16,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/1544\/revisions"}],"predecessor-version":[{"id":1563,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/1544\/revisions\/1563"}],"wp:attachment":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/media?parent=1544"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/categories?post=1544"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/tags?post=1544"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}