Where to put the PID windup guard?











up vote
2
down vote

favorite












Should I put a windup guard on each term of the PID, or just the I, or maybe the whole output?










share|improve this question




















  • 1




    Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
    – Eugene Sh.
    12 hours ago






  • 1




    The I term only. Switch it's input to zero when it just enters saturation
    – Chu
    12 hours ago






  • 1




    @Chu If you switch it's input to zero, it will never go down.
    – Eugene Sh.
    12 hours ago










  • @EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
    – TimWescott
    12 hours ago










  • @TimWescott I would call it a general instability. Can be caused by integrator windup of course.
    – Eugene Sh.
    11 hours ago















up vote
2
down vote

favorite












Should I put a windup guard on each term of the PID, or just the I, or maybe the whole output?










share|improve this question




















  • 1




    Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
    – Eugene Sh.
    12 hours ago






  • 1




    The I term only. Switch it's input to zero when it just enters saturation
    – Chu
    12 hours ago






  • 1




    @Chu If you switch it's input to zero, it will never go down.
    – Eugene Sh.
    12 hours ago










  • @EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
    – TimWescott
    12 hours ago










  • @TimWescott I would call it a general instability. Can be caused by integrator windup of course.
    – Eugene Sh.
    11 hours ago













up vote
2
down vote

favorite









up vote
2
down vote

favorite











Should I put a windup guard on each term of the PID, or just the I, or maybe the whole output?










share|improve this question















Should I put a windup guard on each term of the PID, or just the I, or maybe the whole output?







pid-controller






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 12 hours ago

























asked 12 hours ago









Dirk Bruere

5,31322755




5,31322755








  • 1




    Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
    – Eugene Sh.
    12 hours ago






  • 1




    The I term only. Switch it's input to zero when it just enters saturation
    – Chu
    12 hours ago






  • 1




    @Chu If you switch it's input to zero, it will never go down.
    – Eugene Sh.
    12 hours ago










  • @EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
    – TimWescott
    12 hours ago










  • @TimWescott I would call it a general instability. Can be caused by integrator windup of course.
    – Eugene Sh.
    11 hours ago














  • 1




    Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
    – Eugene Sh.
    12 hours ago






  • 1




    The I term only. Switch it's input to zero when it just enters saturation
    – Chu
    12 hours ago






  • 1




    @Chu If you switch it's input to zero, it will never go down.
    – Eugene Sh.
    12 hours ago










  • @EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
    – TimWescott
    12 hours ago










  • @TimWescott I would call it a general instability. Can be caused by integrator windup of course.
    – Eugene Sh.
    11 hours ago








1




1




Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
– Eugene Sh.
12 hours ago




Windup is mostly an issue of the integral term. If you are getting windups from other terms, these are probably not designed properly.
– Eugene Sh.
12 hours ago




1




1




The I term only. Switch it's input to zero when it just enters saturation
– Chu
12 hours ago




The I term only. Switch it's input to zero when it just enters saturation
– Chu
12 hours ago




1




1




@Chu If you switch it's input to zero, it will never go down.
– Eugene Sh.
12 hours ago




@Chu If you switch it's input to zero, it will never go down.
– Eugene Sh.
12 hours ago












@EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
– TimWescott
12 hours ago




@EugeneSh. I'm not sure if "windup" is the correct official term, but in some circumstances plant states can get out of hand. In my experience it's been mechanical assemblies driven by torquer motors, putting the traveler into a combination of velocity and position such that even at maximum braking torque it'll whack into a stop.
– TimWescott
12 hours ago












@TimWescott I would call it a general instability. Can be caused by integrator windup of course.
– Eugene Sh.
11 hours ago




@TimWescott I would call it a general instability. Can be caused by integrator windup of course.
– Eugene Sh.
11 hours ago










3 Answers
3






active

oldest

votes

















up vote
7
down vote













Integrator anti-windup is a measure you need to take because of output saturation or other limits in the system, and such limits are nonlinear behavior. When you start doing nonlinear control, a lot of the nice, clear, procedural things that we're taught in undergraduate control theory classes don't entirely apply.



In general you should apply integrator anti-windup to just the integrator term, although you may also need to apply limiting to the output term before it's applied to a DAC (assuming you're doing the work in software). There are a lot of ways to do this. My preference is to either limit the integrator state to certain bounds by itself:



// (Calculate integrator_state)
if (integrator_state > integrator_max) {integrator_state = integrator_max;}
if (integrator_state < integrator_min) {integrator_state = integrator_min;}


Or to calculate a candidate output, then trim the integrator state:



output_candidate = integrator_state + error * prop_gain;
if (output_candidate > output_max) {
integrator_state = output_max - error * prop_gain;
} else if (output_candidate < output_min) {
integrator_state = output_min - error * prop_gain;
}
// Re-calculate the actual output, possibly with a D term


The method that @Chu mentions would work, if you remember to only apply it when the integrator is being pulled to excess, not pulled back (but my first method is equivalent). Another method that is used often is to hold the integrator term at zero when the error is large, then allow integrator action when the error gets below some threshold, or if you're doing a motion controller that knows when a "move" starts to set the integrator at zero at the start of a move and hold it there for some finite time. I'm not a big fan of either of those methods, but others are.



Because you're venturing into nonlinear control, even if you're so far in the shallow end of the pool you can lie down without drowning, there are options on options on options, and there's no one right way to do it. Moreover, you can't find an answer by analysis -- you have to either implement the real system and give it a whirl, or make a simulation and try your algorithm out on that.






share|improve this answer























  • I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
    – Dirk Bruere
    11 hours ago






  • 1




    You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
    – TimWescott
    11 hours ago










  • Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
    – Drew Fowler
    11 hours ago






  • 1




    @DrewFowler: I thought I recognized that code.
    – TimWescott
    11 hours ago






  • 2




    The young Padawan meets his master.
    – Harry Svensson
    11 hours ago


















up vote
3
down vote













Windup guard is typically referred to as the protector of the integral term in order that it will not accumulate continually. The controller can overshoot significantly and will continue to overshoot with the integral continuing to grow.



Therefore, the windup guard is just the integral term. As this term can "windup" and keep growing. But, the output of a PID can/should be limited on the output as well.



For example the following code calculates the integral term and then limits it according to a set value. It also limits the output of the controller, but according to a different limiting term.



void PID_Compute(PID *pid)
{

//Find all error variables
pid->lastError = pid->error;
pid->error = pid->setpoint - pid->input;
pid->derivative = pid->error - pid->lastError;
pid->integral += pid->Ki * pid->error;



//Anti-integral Windup
if(pid->integral > pid->IntegralLimit){
pid->integral = pid->IntegralLimit;
}
else if(pid->integral < -pid->IntegralLimit){
pid->integral = -pid->IntegralLimit;
}

//Calculate PID
pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);

//Set limits
if(pid->output > pid->Outmax){
pid->output = pid->Outmax;
}
else if(pid->output < pid->Outmin){
pid->output = pid->Outmin;
}
}


For anything pertaining to writing or understanding a PID controller, refer to Tim Wescott's article.






share|improve this answer






























    up vote
    0
    down vote













    As others have already said, windup is only a problem for the I term.



    Where I differ from almost everything else that I've seen, is that I don't like to arbitrarily limit my I. I want it to be able to saturate the output no matter what it takes to do that, but there's no point in going beyond that. So my limits are floating, based on the final output.



    So I use a bigger datatype to hold the output than what I actually need, so I can detect out-of-range and clamp it. Then as part of that clamp, I also unwind the I. For one project, I actually back-calculated what it should have been to saturate exactly, but for another, I just switched on an exponential decay:



    I_acc += Error;

    //other code here

    if (OUTPUT_OUT_OF_RANGE())
    {
    CLAMP_OUTPUT();

    //anti_windup
    I_acc -= (I_acc >> 2);
    }





    share|improve this answer





















      Your Answer





      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("mathjaxEditing", function () {
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      });
      });
      }, "mathjax-editing");

      StackExchange.ifUsing("editor", function () {
      return StackExchange.using("schematics", function () {
      StackExchange.schematics.init();
      });
      }, "cicuitlab");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "135"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f411868%2fwhere-to-put-the-pid-windup-guard%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      7
      down vote













      Integrator anti-windup is a measure you need to take because of output saturation or other limits in the system, and such limits are nonlinear behavior. When you start doing nonlinear control, a lot of the nice, clear, procedural things that we're taught in undergraduate control theory classes don't entirely apply.



      In general you should apply integrator anti-windup to just the integrator term, although you may also need to apply limiting to the output term before it's applied to a DAC (assuming you're doing the work in software). There are a lot of ways to do this. My preference is to either limit the integrator state to certain bounds by itself:



      // (Calculate integrator_state)
      if (integrator_state > integrator_max) {integrator_state = integrator_max;}
      if (integrator_state < integrator_min) {integrator_state = integrator_min;}


      Or to calculate a candidate output, then trim the integrator state:



      output_candidate = integrator_state + error * prop_gain;
      if (output_candidate > output_max) {
      integrator_state = output_max - error * prop_gain;
      } else if (output_candidate < output_min) {
      integrator_state = output_min - error * prop_gain;
      }
      // Re-calculate the actual output, possibly with a D term


      The method that @Chu mentions would work, if you remember to only apply it when the integrator is being pulled to excess, not pulled back (but my first method is equivalent). Another method that is used often is to hold the integrator term at zero when the error is large, then allow integrator action when the error gets below some threshold, or if you're doing a motion controller that knows when a "move" starts to set the integrator at zero at the start of a move and hold it there for some finite time. I'm not a big fan of either of those methods, but others are.



      Because you're venturing into nonlinear control, even if you're so far in the shallow end of the pool you can lie down without drowning, there are options on options on options, and there's no one right way to do it. Moreover, you can't find an answer by analysis -- you have to either implement the real system and give it a whirl, or make a simulation and try your algorithm out on that.






      share|improve this answer























      • I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
        – Dirk Bruere
        11 hours ago






      • 1




        You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
        – TimWescott
        11 hours ago










      • Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
        – Drew Fowler
        11 hours ago






      • 1




        @DrewFowler: I thought I recognized that code.
        – TimWescott
        11 hours ago






      • 2




        The young Padawan meets his master.
        – Harry Svensson
        11 hours ago















      up vote
      7
      down vote













      Integrator anti-windup is a measure you need to take because of output saturation or other limits in the system, and such limits are nonlinear behavior. When you start doing nonlinear control, a lot of the nice, clear, procedural things that we're taught in undergraduate control theory classes don't entirely apply.



      In general you should apply integrator anti-windup to just the integrator term, although you may also need to apply limiting to the output term before it's applied to a DAC (assuming you're doing the work in software). There are a lot of ways to do this. My preference is to either limit the integrator state to certain bounds by itself:



      // (Calculate integrator_state)
      if (integrator_state > integrator_max) {integrator_state = integrator_max;}
      if (integrator_state < integrator_min) {integrator_state = integrator_min;}


      Or to calculate a candidate output, then trim the integrator state:



      output_candidate = integrator_state + error * prop_gain;
      if (output_candidate > output_max) {
      integrator_state = output_max - error * prop_gain;
      } else if (output_candidate < output_min) {
      integrator_state = output_min - error * prop_gain;
      }
      // Re-calculate the actual output, possibly with a D term


      The method that @Chu mentions would work, if you remember to only apply it when the integrator is being pulled to excess, not pulled back (but my first method is equivalent). Another method that is used often is to hold the integrator term at zero when the error is large, then allow integrator action when the error gets below some threshold, or if you're doing a motion controller that knows when a "move" starts to set the integrator at zero at the start of a move and hold it there for some finite time. I'm not a big fan of either of those methods, but others are.



      Because you're venturing into nonlinear control, even if you're so far in the shallow end of the pool you can lie down without drowning, there are options on options on options, and there's no one right way to do it. Moreover, you can't find an answer by analysis -- you have to either implement the real system and give it a whirl, or make a simulation and try your algorithm out on that.






      share|improve this answer























      • I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
        – Dirk Bruere
        11 hours ago






      • 1




        You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
        – TimWescott
        11 hours ago










      • Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
        – Drew Fowler
        11 hours ago






      • 1




        @DrewFowler: I thought I recognized that code.
        – TimWescott
        11 hours ago






      • 2




        The young Padawan meets his master.
        – Harry Svensson
        11 hours ago













      up vote
      7
      down vote










      up vote
      7
      down vote









      Integrator anti-windup is a measure you need to take because of output saturation or other limits in the system, and such limits are nonlinear behavior. When you start doing nonlinear control, a lot of the nice, clear, procedural things that we're taught in undergraduate control theory classes don't entirely apply.



      In general you should apply integrator anti-windup to just the integrator term, although you may also need to apply limiting to the output term before it's applied to a DAC (assuming you're doing the work in software). There are a lot of ways to do this. My preference is to either limit the integrator state to certain bounds by itself:



      // (Calculate integrator_state)
      if (integrator_state > integrator_max) {integrator_state = integrator_max;}
      if (integrator_state < integrator_min) {integrator_state = integrator_min;}


      Or to calculate a candidate output, then trim the integrator state:



      output_candidate = integrator_state + error * prop_gain;
      if (output_candidate > output_max) {
      integrator_state = output_max - error * prop_gain;
      } else if (output_candidate < output_min) {
      integrator_state = output_min - error * prop_gain;
      }
      // Re-calculate the actual output, possibly with a D term


      The method that @Chu mentions would work, if you remember to only apply it when the integrator is being pulled to excess, not pulled back (but my first method is equivalent). Another method that is used often is to hold the integrator term at zero when the error is large, then allow integrator action when the error gets below some threshold, or if you're doing a motion controller that knows when a "move" starts to set the integrator at zero at the start of a move and hold it there for some finite time. I'm not a big fan of either of those methods, but others are.



      Because you're venturing into nonlinear control, even if you're so far in the shallow end of the pool you can lie down without drowning, there are options on options on options, and there's no one right way to do it. Moreover, you can't find an answer by analysis -- you have to either implement the real system and give it a whirl, or make a simulation and try your algorithm out on that.






      share|improve this answer














      Integrator anti-windup is a measure you need to take because of output saturation or other limits in the system, and such limits are nonlinear behavior. When you start doing nonlinear control, a lot of the nice, clear, procedural things that we're taught in undergraduate control theory classes don't entirely apply.



      In general you should apply integrator anti-windup to just the integrator term, although you may also need to apply limiting to the output term before it's applied to a DAC (assuming you're doing the work in software). There are a lot of ways to do this. My preference is to either limit the integrator state to certain bounds by itself:



      // (Calculate integrator_state)
      if (integrator_state > integrator_max) {integrator_state = integrator_max;}
      if (integrator_state < integrator_min) {integrator_state = integrator_min;}


      Or to calculate a candidate output, then trim the integrator state:



      output_candidate = integrator_state + error * prop_gain;
      if (output_candidate > output_max) {
      integrator_state = output_max - error * prop_gain;
      } else if (output_candidate < output_min) {
      integrator_state = output_min - error * prop_gain;
      }
      // Re-calculate the actual output, possibly with a D term


      The method that @Chu mentions would work, if you remember to only apply it when the integrator is being pulled to excess, not pulled back (but my first method is equivalent). Another method that is used often is to hold the integrator term at zero when the error is large, then allow integrator action when the error gets below some threshold, or if you're doing a motion controller that knows when a "move" starts to set the integrator at zero at the start of a move and hold it there for some finite time. I'm not a big fan of either of those methods, but others are.



      Because you're venturing into nonlinear control, even if you're so far in the shallow end of the pool you can lie down without drowning, there are options on options on options, and there's no one right way to do it. Moreover, you can't find an answer by analysis -- you have to either implement the real system and give it a whirl, or make a simulation and try your algorithm out on that.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 11 hours ago









      Harry Svensson

      6,28632346




      6,28632346










      answered 11 hours ago









      TimWescott

      2,26429




      2,26429












      • I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
        – Dirk Bruere
        11 hours ago






      • 1




        You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
        – TimWescott
        11 hours ago










      • Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
        – Drew Fowler
        11 hours ago






      • 1




        @DrewFowler: I thought I recognized that code.
        – TimWescott
        11 hours ago






      • 2




        The young Padawan meets his master.
        – Harry Svensson
        11 hours ago


















      • I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
        – Dirk Bruere
        11 hours ago






      • 1




        You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
        – TimWescott
        11 hours ago










      • Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
        – Drew Fowler
        11 hours ago






      • 1




        @DrewFowler: I thought I recognized that code.
        – TimWescott
        11 hours ago






      • 2




        The young Padawan meets his master.
        – Harry Svensson
        11 hours ago
















      I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
      – Dirk Bruere
      11 hours ago




      I have opted for your first solution, and will try it out tomorrow. It's just a heater control with no safety critical features
      – Dirk Bruere
      11 hours ago




      1




      1




      You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
      – TimWescott
      11 hours ago




      You may find this article useful. Note that the model of a heating system in there is completely fake; you probably don't want to use it in your work. What you'll find useful is the code, and the discussion of integrator windup.
      – TimWescott
      11 hours ago












      Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
      – Drew Fowler
      11 hours ago




      Tim's article has been fundamental to my understanding of controls. It is well worth the short read and will help out immensely! I highly recommend it. Thank you @TimWescott!
      – Drew Fowler
      11 hours ago




      1




      1




      @DrewFowler: I thought I recognized that code.
      – TimWescott
      11 hours ago




      @DrewFowler: I thought I recognized that code.
      – TimWescott
      11 hours ago




      2




      2




      The young Padawan meets his master.
      – Harry Svensson
      11 hours ago




      The young Padawan meets his master.
      – Harry Svensson
      11 hours ago












      up vote
      3
      down vote













      Windup guard is typically referred to as the protector of the integral term in order that it will not accumulate continually. The controller can overshoot significantly and will continue to overshoot with the integral continuing to grow.



      Therefore, the windup guard is just the integral term. As this term can "windup" and keep growing. But, the output of a PID can/should be limited on the output as well.



      For example the following code calculates the integral term and then limits it according to a set value. It also limits the output of the controller, but according to a different limiting term.



      void PID_Compute(PID *pid)
      {

      //Find all error variables
      pid->lastError = pid->error;
      pid->error = pid->setpoint - pid->input;
      pid->derivative = pid->error - pid->lastError;
      pid->integral += pid->Ki * pid->error;



      //Anti-integral Windup
      if(pid->integral > pid->IntegralLimit){
      pid->integral = pid->IntegralLimit;
      }
      else if(pid->integral < -pid->IntegralLimit){
      pid->integral = -pid->IntegralLimit;
      }

      //Calculate PID
      pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);

      //Set limits
      if(pid->output > pid->Outmax){
      pid->output = pid->Outmax;
      }
      else if(pid->output < pid->Outmin){
      pid->output = pid->Outmin;
      }
      }


      For anything pertaining to writing or understanding a PID controller, refer to Tim Wescott's article.






      share|improve this answer



























        up vote
        3
        down vote













        Windup guard is typically referred to as the protector of the integral term in order that it will not accumulate continually. The controller can overshoot significantly and will continue to overshoot with the integral continuing to grow.



        Therefore, the windup guard is just the integral term. As this term can "windup" and keep growing. But, the output of a PID can/should be limited on the output as well.



        For example the following code calculates the integral term and then limits it according to a set value. It also limits the output of the controller, but according to a different limiting term.



        void PID_Compute(PID *pid)
        {

        //Find all error variables
        pid->lastError = pid->error;
        pid->error = pid->setpoint - pid->input;
        pid->derivative = pid->error - pid->lastError;
        pid->integral += pid->Ki * pid->error;



        //Anti-integral Windup
        if(pid->integral > pid->IntegralLimit){
        pid->integral = pid->IntegralLimit;
        }
        else if(pid->integral < -pid->IntegralLimit){
        pid->integral = -pid->IntegralLimit;
        }

        //Calculate PID
        pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);

        //Set limits
        if(pid->output > pid->Outmax){
        pid->output = pid->Outmax;
        }
        else if(pid->output < pid->Outmin){
        pid->output = pid->Outmin;
        }
        }


        For anything pertaining to writing or understanding a PID controller, refer to Tim Wescott's article.






        share|improve this answer

























          up vote
          3
          down vote










          up vote
          3
          down vote









          Windup guard is typically referred to as the protector of the integral term in order that it will not accumulate continually. The controller can overshoot significantly and will continue to overshoot with the integral continuing to grow.



          Therefore, the windup guard is just the integral term. As this term can "windup" and keep growing. But, the output of a PID can/should be limited on the output as well.



          For example the following code calculates the integral term and then limits it according to a set value. It also limits the output of the controller, but according to a different limiting term.



          void PID_Compute(PID *pid)
          {

          //Find all error variables
          pid->lastError = pid->error;
          pid->error = pid->setpoint - pid->input;
          pid->derivative = pid->error - pid->lastError;
          pid->integral += pid->Ki * pid->error;



          //Anti-integral Windup
          if(pid->integral > pid->IntegralLimit){
          pid->integral = pid->IntegralLimit;
          }
          else if(pid->integral < -pid->IntegralLimit){
          pid->integral = -pid->IntegralLimit;
          }

          //Calculate PID
          pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);

          //Set limits
          if(pid->output > pid->Outmax){
          pid->output = pid->Outmax;
          }
          else if(pid->output < pid->Outmin){
          pid->output = pid->Outmin;
          }
          }


          For anything pertaining to writing or understanding a PID controller, refer to Tim Wescott's article.






          share|improve this answer














          Windup guard is typically referred to as the protector of the integral term in order that it will not accumulate continually. The controller can overshoot significantly and will continue to overshoot with the integral continuing to grow.



          Therefore, the windup guard is just the integral term. As this term can "windup" and keep growing. But, the output of a PID can/should be limited on the output as well.



          For example the following code calculates the integral term and then limits it according to a set value. It also limits the output of the controller, but according to a different limiting term.



          void PID_Compute(PID *pid)
          {

          //Find all error variables
          pid->lastError = pid->error;
          pid->error = pid->setpoint - pid->input;
          pid->derivative = pid->error - pid->lastError;
          pid->integral += pid->Ki * pid->error;



          //Anti-integral Windup
          if(pid->integral > pid->IntegralLimit){
          pid->integral = pid->IntegralLimit;
          }
          else if(pid->integral < -pid->IntegralLimit){
          pid->integral = -pid->IntegralLimit;
          }

          //Calculate PID
          pid->output = (pid->Kp*pid->error) + (pid->integral) + (pid->Kd * pid->derivative);

          //Set limits
          if(pid->output > pid->Outmax){
          pid->output = pid->Outmax;
          }
          else if(pid->output < pid->Outmin){
          pid->output = pid->Outmin;
          }
          }


          For anything pertaining to writing or understanding a PID controller, refer to Tim Wescott's article.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 10 hours ago

























          answered 11 hours ago









          Drew Fowler

          13710




          13710






















              up vote
              0
              down vote













              As others have already said, windup is only a problem for the I term.



              Where I differ from almost everything else that I've seen, is that I don't like to arbitrarily limit my I. I want it to be able to saturate the output no matter what it takes to do that, but there's no point in going beyond that. So my limits are floating, based on the final output.



              So I use a bigger datatype to hold the output than what I actually need, so I can detect out-of-range and clamp it. Then as part of that clamp, I also unwind the I. For one project, I actually back-calculated what it should have been to saturate exactly, but for another, I just switched on an exponential decay:



              I_acc += Error;

              //other code here

              if (OUTPUT_OUT_OF_RANGE())
              {
              CLAMP_OUTPUT();

              //anti_windup
              I_acc -= (I_acc >> 2);
              }





              share|improve this answer

























                up vote
                0
                down vote













                As others have already said, windup is only a problem for the I term.



                Where I differ from almost everything else that I've seen, is that I don't like to arbitrarily limit my I. I want it to be able to saturate the output no matter what it takes to do that, but there's no point in going beyond that. So my limits are floating, based on the final output.



                So I use a bigger datatype to hold the output than what I actually need, so I can detect out-of-range and clamp it. Then as part of that clamp, I also unwind the I. For one project, I actually back-calculated what it should have been to saturate exactly, but for another, I just switched on an exponential decay:



                I_acc += Error;

                //other code here

                if (OUTPUT_OUT_OF_RANGE())
                {
                CLAMP_OUTPUT();

                //anti_windup
                I_acc -= (I_acc >> 2);
                }





                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  As others have already said, windup is only a problem for the I term.



                  Where I differ from almost everything else that I've seen, is that I don't like to arbitrarily limit my I. I want it to be able to saturate the output no matter what it takes to do that, but there's no point in going beyond that. So my limits are floating, based on the final output.



                  So I use a bigger datatype to hold the output than what I actually need, so I can detect out-of-range and clamp it. Then as part of that clamp, I also unwind the I. For one project, I actually back-calculated what it should have been to saturate exactly, but for another, I just switched on an exponential decay:



                  I_acc += Error;

                  //other code here

                  if (OUTPUT_OUT_OF_RANGE())
                  {
                  CLAMP_OUTPUT();

                  //anti_windup
                  I_acc -= (I_acc >> 2);
                  }





                  share|improve this answer












                  As others have already said, windup is only a problem for the I term.



                  Where I differ from almost everything else that I've seen, is that I don't like to arbitrarily limit my I. I want it to be able to saturate the output no matter what it takes to do that, but there's no point in going beyond that. So my limits are floating, based on the final output.



                  So I use a bigger datatype to hold the output than what I actually need, so I can detect out-of-range and clamp it. Then as part of that clamp, I also unwind the I. For one project, I actually back-calculated what it should have been to saturate exactly, but for another, I just switched on an exponential decay:



                  I_acc += Error;

                  //other code here

                  if (OUTPUT_OUT_OF_RANGE())
                  {
                  CLAMP_OUTPUT();

                  //anti_windup
                  I_acc -= (I_acc >> 2);
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 38 mins ago









                  AaronD

                  4,066528




                  4,066528






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Electrical Engineering Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2felectronics.stackexchange.com%2fquestions%2f411868%2fwhere-to-put-the-pid-windup-guard%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Morgemoulin

                      Scott Moir

                      Souastre