{"id":695,"date":"2011-04-15T15:00:10","date_gmt":"2011-04-15T19:00:10","guid":{"rendered":"http:\/\/brettbeauregard.com\/blog\/?p=695"},"modified":"2025-03-22T06:49:15","modified_gmt":"2025-03-22T10:49:15","slug":"improving-the-beginners-pid-introduction","status":"publish","type":"post","link":"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-introduction\/","title":{"rendered":"Improving the Beginner&#8217;s PID &#8211; Introduction"},"content":{"rendered":"<p>In conjunction with the release of the new <a href=\"http:\/\/www.arduino.cc\/playground\/Code\/PIDLibrary\">Arduino PID Library<\/a> I&#8217;ve decided to release this series of posts.  The last library, while solid, didn&#8217;t really come with any code explanation.  This time around the plan is to explain in great detail why the code is the way it is.  I&#8217;m hoping this will be of use to two groups of people:<\/p>\n<ul>\n<li> People directly interested in what&#8217;s going on inside the Arduino PID library will get a detailed explanation.<\/li>\n<li> Anyone writing their own PID algorithm can take a look at how I did things and borrow whatever they like.<\/li>\n<\/ul>\n<p>It&#8217;s going to be a tough slog, but I think I found a not-too-painful way to explain my code.&nbsp; I&#8217;m going to start with what I call &#8220;The Beginner&#8217;s PID.&#8221;&nbsp; I&#8217;ll then improve it step-by-step until we&#8217;re left with an efficient, robust pid algorithm.<\/p>\n<h3>The Beginner&#8217;s PID<\/h3>\n<p>Here&#8217;s the PID equation as everyone first learns it:<\/p>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/pidalgorithm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-805\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/pidalgorithm-300x72.png\" alt=\"\" width=\"300\" height=\"72\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/pidalgorithm-300x72.png 300w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/pidalgorithm.png 337w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>This leads pretty much everyone to write the following PID controller:<\/p>\n<pre class=\"brush: css; gutter: true; title: ; notranslate\" title=\"\">\n\/*working variables*\/\nunsigned long lastTime;\ndouble Input, Output, Setpoint;\ndouble errSum, lastErr;\ndouble kp, ki, kd;\nvoid Compute()\n{\n\/*How long since we last calculated*\/\nunsigned long now = millis();\ndouble timeChange = (double)(now - lastTime);\n\n\/*Compute all the working error variables*\/\ndouble error = Setpoint - Input;\nerrSum += (error * timeChange);\ndouble dErr = (error - lastErr) \/ timeChange;\n\n\/*Compute PID Output*\/\nOutput = kp * error + ki * errSum + kd * dErr;\n\n\/*Remember some variables for next time*\/\nlastErr = error;\nlastTime = now;\n}\n\nvoid SetTunings(double Kp, double Ki, double Kd)\n{\nkp = Kp;\nki = Ki;\nkd = Kd;\n}\n<\/pre>\n<p>Compute() is called either regularly or irregularly, and it works pretty well.  This series isn&#8217;t about &#8220;works pretty well&#8221; though.  If we&#8217;re going to turn this code into something on par with industrial PID controllers, we&#8217;ll have to address a few things:<\/p>\n<ol>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-sample-time\">Sample Time &#8211;<\/a><\/strong> The PID algorithm functions best if it is evaluated at a regular interval.  If the algorithm is aware of this interval, we can also simplify some of the internal math.<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-derivative-kick\">Derivative Kick &#8211;<\/a><\/strong> Not the biggest deal, but easy to get rid of, so we&#8217;re going to do just that.<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-tuning-changes\">On-The-Fly Tuning Changes &#8211;<\/a><\/strong> A good PID algorithm is one where tuning parameters can be changed without jolting the internal workings.<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-reset-windup\">Reset Windup Mitigation &#8211;<\/a><\/strong>We&#8217;ll go into what Reset Windup is, and implement a solution with side benefits<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-onoff\">On\/Off (Auto\/Manual) &#8211;<\/a><\/strong> In most applications, there is a desire to sometimes turn off the PID controller and adjust the output by hand, without the controller interfering<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-initialization\">Initialization &#8211;<\/a><\/strong> When the controller first turns on, we want a &#8220;bumpless transfer.&#8221;  That is, we don&#8217;t want the output to suddenly jerk to some new value<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-direction\">Controller Direction &#8211;<\/a><\/strong> This last one isn&#8217;t a change in the name of robustness per se.  it&#8217;s designed to ensure that the user enters tuning parameters with the correct sign.<\/li>\n<li><strong><a href=\"http:\/\/brettbeauregard.com\/blog\/2017\/06\/proportional-on-measurement-the-code\/\">NEW: Proportional on Measurement &#8211;<\/a><\/strong> Adding this feature makes it easier to control certain types of processes<\/li>\n<\/ol>\n<p>Once we&#8217;ve addressed all these issues, we&#8217;ll have a solid PID algorithm.  We&#8217;ll also, not coincidentally, have the code that&#8217;s being used in the lastest version of the Arduino PID Library.  So whether you&#8217;re trying to write your own algorithm, or trying to understand what&#8217;s going on inside the PID library, I hope this helps you out.   Let&#8217;s get started.<br \/>\n<a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-sample-time\">Next &gt;&gt;<\/a><\/p>\n<p>UPDATE:  In all the code examples I&#8217;m using doubles.  On the Arduino, a double is the same as a float (single precision.)   True double precision is WAY overkill for PID.  If the language you&#8217;re using does true double precision, I&#8217;d recommend changing all doubles to floats.<\/p>\n<p><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/\"><img decoding=\"async\" alt=\"Creative Commons License\" style=\"border-width:0\" src=\"http:\/\/i.creativecommons.org\/l\/by-sa\/3.0\/80x15.png\"><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In conjunction with the release of the new Arduino PID Library I&#8217;ve decided to release this series of posts. The last library, while solid, didn&#8217;t really come with any code explanation. This time around the plan is to explain in &hellip; <a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-introduction\/\">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":[6,30,41],"class_list":["post-695","post","type-post","status-publish","format-standard","hentry","category-coding","category-pid","tag-arduino","tag-beginners-pid","tag-pid"],"_links":{"self":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/695","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=695"}],"version-history":[{"count":170,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/695\/revisions"}],"predecessor-version":[{"id":7242,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/695\/revisions\/7242"}],"wp:attachment":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/media?parent=695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/categories?post=695"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/tags?post=695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}