I'm developing/tuning a software PID for a quadcopter. For now I'm only trying to stabilise the pitch angle using the front and back motors, and I'm only looking at Kp. The motors have a control resolution: input variations need to reach a threeshold to have any effect at all.

The process output does reach the setpoint, but not precisely enough for my requirements. There is no steady-state error (aka droop), the hunting range is centered on the setpoint, just too wide for my requirements. Also the instability is not an oscillation, but more of a random drift which needs to be large enough before the PID attempts to correct it.

  • With a lower Kp the output needs to diverge from the setpoint significantly before the error is big enough for the PID to attempt to correct it.
  • With a higher Kp the PID oscillates.

I could not find a reasonable compromise.

I'm thinking about applying the cuberoot function (or similar) to the error before feeding it to the PID: that way small errors should be significant enough for the PID to attempt to correct them, and large errors would be reduced and might not trigger oscillations. I suppose someone must have been through this before: is this a good solution? Are there any better alternatives?

This is not a steady-state error (aka droop) or oscillation issue as far as I can tell: please don't suggest using Ki or Kd

EDIT: I have clarified the problem description and suggested using cuberoot rather than logarithm which was a bad idea indeed.

Thanks, Marc.

  • $\begingroup$ It's expected that in PID you will not always reach the setpoint using P only. That's where the integrator comes in. It's unclear what you mean when you say "control kicks in" but obviously as you get closer to your setpoint your error signal goes down and the impact of P diminishes. If you set P too large the system becomes unstable. That's how PID loops behave. p.s. do not use the logarithm of the error. Use an integrator. $\endgroup$ – Guy Sirton Apr 21 '14 at 23:02
  • $\begingroup$ Thanks @GuySirton, but I do not believe Ki is the problem: my bad I should have explained better in the question. As far as I understand PIDs, Ki is useful when the process output settles nicely to a value which is slightly above or below the setpoint. Here the process output stays in a range perfectly centered on the setpoint, but the fluctuations above and below it are too large for my requirements. $\endgroup$ – marcv81 Apr 22 '14 at 12:38
  • 1
    $\begingroup$ FYI, using the log of the error is a bad idea for a couple of reasons. First, the log is only defined for positive numbers; what would you do for a negative error? Secondly, for very small positive numbers the log is very negative. In your ideal case, error=0, the log goes to negative infinity. As Damjen states in his answer, to reduce oscillations increase Kd. Generally speaking, Kp reduces error, Kd improves stability and reduces oscillations, and Ki reduces steady state error while reducing stability. $\endgroup$ – ryan0270 Apr 22 '14 at 14:12
  • $\begingroup$ Thanks very much for your comment @ryan0270. I'd upvote your comment but I think I'm too low on rep here. Clearly I should get back to school as log it a totally inappropriate function to solve my problem. I meant a function more like cuberoot, which is defined for both positive and negative errors and would reduce the higher errors while keeping the smaller ones. $\endgroup$ – marcv81 Apr 22 '14 at 16:33
  • 1
    $\begingroup$ @marcv81 don't use a cube root either. It has to be linear. If the issue is that a small P (i.e. stable) results in a signal too small to have an effect the answer is still to add an integrator. If you have a physical system you also have steady state error (even if you think you don't) so you'll need an integrator for that reason as well. Also saying that integrator is only for steady-state error is simplistic/wrong. $\endgroup$ – Guy Sirton Apr 22 '14 at 17:34

Since posting the question I tried to tune the 3 PID parameters a lot but I never reached any acceptable result. I didn't try to modify the error curve as I suggested in the question, but I found an alternative solution which works reasonably well. There might be other good solutions.

I was using a PID as follows:

  • process setpoint: angle
  • process output: difference between motors speed (used in motor mix equation)

While in theory this might very well work, I could not find good values for Kp, Ki, and Kd to obtain satisfying results. I changed my program to use 2 cascaded PIDs as follows:

Outer PID:

  • process setpoint: angle
  • process output: angular rate

Inner PID:

  • process setpoint: angular rate
  • process output: difference between motors speed (used in motor mix equation)

I first tuned the inner PID so as to get no oscillation but a slight resistance against angular change when the target angular rate is zero. I then tuned the outer PID so as to get no oscillation but a reasonably responsive attitude matching the stick inputs. Even with a very basic tuning the results are acceptable.

Thanks again to all the participants, your input encouraged me to learn more about PIDs and avoided me some errors.

  • $\begingroup$ When you say "motor speed" are you referring to the signal value you're sending to the ESC for a given motor? $\endgroup$ – Jacksonkr Aug 8 '16 at 15:25
  • $\begingroup$ I meant the difference between the PWM signals I am sending to some ESCs. For instance on a + configuration the PID for the roll depends on the PWM difference between the left and right ESCs. This is hopefully close to the difference between the matching motors speed. $\endgroup$ – marcv81 Aug 11 '16 at 5:05

It sounds like the problem stems from your motors. The motors are fine, but they have a threshold that prevents you from setting their speed to exactly the value you want. This is a problem because you are attempting to map your PID directly to their output, which has a minimum value.

You need to alter your motor control code so that if the desired thrust is below the motor's threshold, you pulse the motor so that its average over time is the thrust you need. There are several ways of accomplishing this, depending on how your control loop works.

  • $\begingroup$ Given that I found a solution which does not require this, this is not the root of the problem. However this is a very interesting and relevant comment. I'll upvote when I have some rep :) $\endgroup$ – marcv81 Apr 23 '14 at 22:12

I am unsure of why you said "please don't suggest using Ki or Kd" and will suggest them anyway. From the comments from the original post I understood that it is not the problem that you settle near the setpoint but that you oscillate around it.

If that is the case then you need to add Kd to dampen the oscillations.

If your problem is in fact that you settle near the setpoint then you need to add Ki to compensate that error.

This is the reason why there are all three terms in the PID regulator and not just one. Such behavior from using proportional term only is expected. Introducing nonlinearity such that you suggested is not something you should generally do.


  • $\begingroup$ Thanks @DamjanDakic. The PID does not settle near the setpoint nor does it oscillate around it. It hunts randomly in a range around the setpoint which is too large for my requirements. Would you please know if I can use Kd to reduce the hunting range, even if I technically do not have an oscillation problem? $\endgroup$ – marcv81 Apr 22 '14 at 16:27
  • $\begingroup$ Yes, adding Kd should dampen your movements even if they're not sinewave oscillations. If the center of that movement is your setpoint then everything will be good like that, if it settles at some other point then adding Ki will shift that point towards the setpoint. $\endgroup$ – Damjan Dakic Apr 22 '14 at 19:14

I'm going to suggest it anyways. Add an integrator.

What you've described is a textbook description of how a proportional only controller would work. If your output is stable, you will never reach your setpoint. From Wikipedia:

Because a non-zero error is required to drive it, a proportional controller generally operates with a steady-state error, referred to as droop. Droop is proportional to the process gain and inversely proportional to proportional gain. Droop may be mitigated by adding a compensating bias term to the setpoint or output, or corrected dynamically by adding an integral term.

Biasing is typically a static value added to the output based on some known quantity. If the droop is a know stable constant, you can do this. But my personal feeling is that it is usually a hack that requires constant adjustment.

You're attempting to achieve dynamic biasing by using the logarithm of the error. Don't mess with the input to the controller. It will only cause you headaches down the line. You will achieve much better results if you use an integrator.

The alternative is to use a lead-lag filter:

A lead compensator can increase the stability or speed of reponse[sic] of a system; a lag compensator can reduce (but not eliminate) the steady-state error.

But you will achieve the same thing with a lot less math if you manually tune using an integrator.

  • $\begingroup$ Thanks for your answer. Sorry for the poor explanation, but I clearly don't have any steady state error (aka droop). What I have is an unstable output (not oscillating though) in a range centered on the setpoint. I don't believe a I term would solve that. $\endgroup$ – marcv81 Apr 22 '14 at 16:24
  • $\begingroup$ @marcv81 From your updated description, it now does not sound like it's controlling at all. A controller should not "hunt". Could you perhaps include some code/psuedocode? If plots of the input and the output are available, those would also be helpful. $\endgroup$ – embedded.kyle Apr 22 '14 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.