{"id":765,"date":"2011-04-15T15:02:34","date_gmt":"2011-04-15T19:02:34","guid":{"rendered":"http:\/\/brettbeauregard.com\/blog\/?p=765"},"modified":"2025-03-22T06:50:58","modified_gmt":"2025-03-22T10:50:58","slug":"improving-the-beginners-pid-derivative-kick","status":"publish","type":"post","link":"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-derivative-kick\/","title":{"rendered":"Improving the Beginner\u2019s PID &#8211; Derivative Kick"},"content":{"rendered":"<p><small>(This is Modification #2 in a <a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-introduction\">larger series<\/a> on writing a solid PID algorithm)<\/small><\/p>\n<h3>The Problem<\/h3>\n<p>This modification is going to tweak the derivative term a bit.  The goal is to eliminate a phenomenon known as &#8220;Derivative Kick&#8221;.<\/p>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonE.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-926\" title=\"Derivative Kick\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonE.png\" alt=\"\" width=\"336\" height=\"466\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonE.png 336w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonE-216x300.png 216w\" sizes=\"auto, (max-width: 336px) 100vw, 336px\" \/><\/a><\/p>\n<p>The image above illustrates the problem.  Since error=Setpoint-Input, any change in Setpoint causes an instantaneous change in error.  The derivative of this change is infinity (in practice, since dt isn&#8217;t 0 it just winds up being a really big number.)  This number gets fed into the pid equation, which results in an undesirable spike in the output.  Luckily there is an easy way to get rid of this.<\/p>\n<h3>The Solution<\/h3>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonMExplain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-952\" title=\"DonMExplain\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonMExplain.png\" alt=\"\" width=\"254\" height=\"131\" \/><\/a><br \/>\nIt turns out that the derivative of the Error is equal to negative derivative of Input, EXCEPT when the Setpoint is changing.  This winds up being a perfect solution.  Instead of adding (Kd * derivative of Error), we subtract (Kd * derivative of Input).  This is known as using &#8220;Derivative on Measurement&#8221;<\/p>\n<h3>The Code<\/h3>\n<pre class=\"brush: css; gutter: true; highlight: [4,16,19,22]; title: ; notranslate\" title=\"\">\n\/*working variables*\/\nunsigned long lastTime;\ndouble Input, Output, Setpoint;\ndouble errSum, lastInput;\ndouble kp, ki, kd;\nint SampleTime = 1000; \/\/1 sec\nvoid Compute()\n{\n   unsigned long now = millis();\n   int timeChange = (now - lastTime);\n   if(timeChange&gt;=SampleTime)\n   {\n      \/*Compute all the working error variables*\/\n      double error = Setpoint - Input;\n      errSum += error;\n      double dInput = (Input - lastInput);\n\n      \/*Compute PID Output*\/\n      Output = kp * error + ki * errSum - kd * dInput;\n\n      \/*Remember some variables for next time*\/\n      lastInput = Input;\n      lastTime = now;\n   }\n}\n\nvoid SetTunings(double Kp, double Ki, double Kd)\n{\n  double SampleTimeInSec = ((double)SampleTime)\/1000;\n   kp = Kp;\n   ki = Ki * SampleTimeInSec;\n   kd = Kd \/ SampleTimeInSec;\n}\n\nvoid SetSampleTime(int NewSampleTime)\n{\n   if (NewSampleTime &gt; 0)\n   {\n      double ratio  = (double)NewSampleTime\n                      \/ (double)SampleTime;\n      ki *= ratio;\n      kd \/= ratio;\n      SampleTime = (unsigned long)NewSampleTime;\n   }\n}\n<\/pre>\n<p>The modifications here are pretty easy.  We&#8217;re replacing +dError with -dInput.  Instead of remembering the lastError, we now remember the lastInput<\/p>\n<h3>The Result<\/h3>\n<p><a href=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-927\" title=\"DonM\" src=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonM.png\" alt=\"\" width=\"336\" height=\"466\" srcset=\"http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonM.png 336w, http:\/\/brettbeauregard.com\/blog\/wp-content\/uploads\/2011\/03\/DonM-216x300.png 216w\" sizes=\"auto, (max-width: 336px) 100vw, 336px\" \/><\/a><\/p>\n<p>Here&#8217;s what those modifications get us.  Notice that the input still looks about the same.  So we get the same performance, but we don&#8217;t send out a huge Output spike every time the Setpoint changes.<\/p>\n<p>This may or may not be a big deal.  It all depends on how sensitive your application is to output spikes.  The way I see it though, it doesn&#8217;t take any more work to do it without kicking so why not do things right?<br \/>\n<a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginner\u2019s-pid-tuning-changes\">Next >><\/a><br \/>\n<br \/>\n<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>(This is Modification #2 in a larger series on writing a solid PID algorithm) The Problem This modification is going to tweak the derivative term a bit. The goal is to eliminate a phenomenon known as &#8220;Derivative Kick&#8221;. The image &hellip; <a href=\"http:\/\/brettbeauregard.com\/blog\/2011\/04\/improving-the-beginners-pid-derivative-kick\/\">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-765","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\/765","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=765"}],"version-history":[{"count":64,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/765\/revisions"}],"predecessor-version":[{"id":7245,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/posts\/765\/revisions\/7245"}],"wp:attachment":[{"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/media?parent=765"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/categories?post=765"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/brettbeauregard.com\/blog\/wp-json\/wp\/v2\/tags?post=765"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}