Skip to content

Adding PID controller Chapter. #346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* [Verlet Integration](contents/verlet_integration/verlet_integration.md)
* [Quantum Systems](contents/quantum_systems/quantum_systems.md)
* [Split-Operator Method](contents/split-operator_method/split-operator_method.md)
* [PID Controller](contents/pid_controller/pid_controller.md)
* [Data Compression](contents/data_compression/data_compression.md)
* [Huffman Encoding](contents/huffman_encoding/huffman_encoding.md)
* [Quantum Information](contents/quantum_information/quantum_information.md)
46 changes: 46 additions & 0 deletions contents/pid_controller/code/c/pid_controller.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <stdio.h>

struct pid_context {
double kp;
double ki;
double kd;
double setpoint;
double last_error;
double integral;
double dt; // Normally you calculate the change in time.
};

struct pid_context get_pid(double setpoint, double dt, double kp, double ki,
double kd) {

struct pid_context ctx = {0};
ctx.setpoint = setpoint;
ctx.dt = dt;
ctx.kp = kp;
ctx.ki = ki;
ctx.kd = kd;

return ctx;
}

double pid_calculate(struct pid_context ctx, double input) {
// Here you would calculate the time elapsed.
double error = ctx.setpoint - input;
ctx.integral += error * ctx.dt;
double derivative = (error - ctx.last_error) / ctx.dt;
ctx.last_error = error;

return ctx.kp * error + ctx.ki * ctx.integral + ctx.kd * derivative;
}

int main() {
struct pid_context ctx = get_pid(1.0, 0.01, 1.2, 1.0, 0.001);
double input = 0.0;

for (int i = 0; i < 100; ++i) {
input += pid_calculate(ctx, input);
printf("%g\n", input);
}

return 0;
}
86 changes: 86 additions & 0 deletions contents/pid_controller/pid_controller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Proportional-Integral-Derivative Controller

The Proportional-Integral-Derivative controller (PID controller) is a control loop feedback mechanism, used for continuously modulated control.
The PID controller is comprised of three parts: proportional controller, integral controller, and derivative controller.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I might do something like this:

The PID controller has three components:

  1. proportional controller: quick description
  2. integral controler: quick description
  3. derivative controller: quick description


Before we get into how a PID controller works, we need a good example to explain things.
Imagine you are making a self-driving RC car that drives on a line, how would make it work given that the car moves with a constant speed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean "how would make it work"? Do you mean: "how would we keep the car on the line"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's what I mean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant this as a fix. The sentence doesn't currently make sense.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a sentence here like:

This could be done with a PID controller, which is a combination of Proportional, Integral, and Derivative (PID) controllers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer introducing it over time, to make it easier to follow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My argument was that it was not followable without a transitional sentence.

### Proportional Controller

If the car is too far to the right then you should turn left and vice versa.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think sticking to "we" instead of "you" makes sense, but that's personal preference. Maybe something like:

Imagine our RC car is moving too far to the right, in this case it makes sense to turn left.

Since there are a range of angles you can turn the wheel, so you should turn proportional to the distance from the line.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are a range of angles you can turn the wheel, so you should turn proportional to the distance from the line.

This is what the proportional controller (P controller) does, which is described by,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a comma at the end


$$ P = K_{p} e(t), $$

Where $K_{p}$ is a constant and $e(t)$ is the current distance from the line, which is called the error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Where $K_{p}$ is a constant and $e(t)$ is the current distance from the line, which is called the error.
Where $$K_{p}$$ is an arbitrary constant and $$e(t)$$ is the current distance from the line, which is called the error.

The performance of the controller improves with larger $K_{p}$;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The performance of the controller improves with larger $K_{p}$;
The performance of the controller improves with larger $$K_{p}$$;

if $K_{p}$ is too high then when the error is too high, the system becomes unstable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if $K_{p}$ is too high then when the error is too high, the system becomes unstable.
however, if $$K_{p}$$ and $$e(t)$$ are too high then the system becomes unstable.

In this case, the car would turn in circles, since there is a maximum angle the wheel can turn, else it would zig zag around the line.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence feels weird. Maybe:

In this case, the car would turn in circles because there is a maximum angle the wheel can turn, otherwise it would zig zag around the line.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a note should be made here that the car's motion can be completely corrected with the Proportional controller, but it has the problem of overshooting a lot, thus additional controllers are necessary to maintain proper control of the car.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this was not addressed.

### Derivative Controller

The P controller works well but it has the added problem of overshooting a lot, we need to dampen these oscillations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the P controller really provide an oscillation? It seems like just an overshooting, right? If that's the case, it makes more sense to say "dampen this motion" then "dampen these oscillations"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P controllers may over shoot then it will start to oscillate around the track. So you're dampening this oscillation not the motion of the car.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me how we can model the error in the P controller as an oscillation. Again, an animation or some depiction could help here.

One way to solve this is to make the rc car resistant to sudden changes of error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
One way to solve this is to make the rc car resistant to sudden changes of error.
One way to do this is to make the RC car resistant to sudden changes of error.

This is what the derivative controller (D controller) does, which is described by,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No comma at the end here either


$$ D = K_{d} \frac{de(t)}{dt}$$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are de and dt? Maybe note that this is something like a derivative?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a derivative.


Where $K_{d}$ is a constant.
If $K_{d}$ is too high then the system is overdamped, i.e. the car takes too long to get back on track.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Where $K_{d}$ is a constant.
If $K_{d}$ is too high then the system is overdamped, i.e. the car takes too long to get back on track.
Where $$K_{d}$$ is a constant.
If $$K_{d}$$ is too high then the system is overdamped, i.e. the car takes too long to get back on track.

If it's too low the system is underdamped, i.e. the car oscillates around the line.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If it's too low the system is underdamped, i.e. the car oscillates around the line.
If it's too low, the system is underdamped, i.e. the car oscillates around the line.

When the car is getting back on track quickly with little to no oscillations then the system is called critically damped.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the car returns to the track quickly...


### Integral Controller

The Proportional and Derivative controllers are robust enough to get the on course.
We start driving, but then some wind starts pushing the car which introduces a constant error.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe combine these two sentences?

The Proportional and Derivative controllers are robust enough to get the on course, but what if some wind starts pushing the car and introduces a constant error?

We need to know if we are spending too long on one side and account for that.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To correct this error, we need...

The way to do that is to sum up all the errors and multiply it by a constant.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

Well, we would need to know if we are spending too long on one side and account for that, and we can figure that out by summing up all the errors and multiply it by a constant.

This is what the integral controller (I controller) does, which is described by,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, no comma (I think)


$$ I = K_{i} \int_{0}^{t} e(\uptau) d\uptau, $$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\uptau doesn't seem to exist in mathjax, can we use tau?


Where $K_{i}$ is a constant.
The peformance of the controller is better with higher $K_{i}$; but with higher $K_{i}$ it can introduce oscillations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, a side-by-side animation would do well here


### Proportional-Integral-Derivative Controller

The PID controller is just a sum of all three controllers and is of the form,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again no comma (I think)


$$ U = K_{p} e(t) + K_{i} \int_{0}^{t} e(x) dx + K_{d} \frac{de(t)}{dt} $$

To use a PID controller, you need to tune it by setting the constants, $K_{p}$, $K_{i}$, and $K_{d}$.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To use a PID controller, you need to tune it by setting the constants, $K_{p}$, $K_{i}$, and $K_{d}$.
To use a PID controller, you need to tune it by setting the constants, $$K_{p}$$, $$K_{i}$$, and $$K_{d}$$.

If you choose the parameters for your PID controller incorrectly, the output will be unstable, i.e., the output diverges.
There are multiple methods of tuning like, manual tuning, Ziegler–Nichols, Tyreus Luyben, Cohen–Coon, and Åström-Hägglund.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will these be covered? If so, leave a note.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They aren't algorithms it's just done by hand so I don't imagine there being a chapter on it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then for completeness we might want to differentiate these.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are mentioned, they should be described. You can add a simple list with all of them and how they are differentiated from each other.

It might be worth adding a separate heading for tuning and discussing these in-turn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, it would be nice to have citations for all of these with bibtex-cite

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you cite?

Copy link
Member

@leios leios Dec 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the appropriate bibtex citation in the literature.bib file at the start of the directory, then put {{ "ct1965" | cite } where you want to cite it and add a

### Bibliography

{% references %} {% endreferences %}

at the bottom

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, Thanks.


Theoretically, PID controllers can be used for any process with a measurable output and a known ideal output,
but controllers are used mainly for regulating temperature, pressure, force, flow rate, feed rate, speed and more.

## The Algorithm
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## The Algorithm
## Putting it all together


Luckily the algorithm is very simple, you just need to make the PID equation discrete.
Thus, the equation looks like this:

$$ U = K_{p} e(t_{j}) + \sum_{l=0}^{j} K_{i} e(t_{l}) \Delta t + K_{d} \frac{e(t_{j-1}) - e(t_{j})}{\Delta t}. $$

In the end the code looks like this:

{% method %}
{% sample lang="c" %}
[import:26-34, lang:"c_cpp"](code/c/pid_controller.c)
{% endmethod %}

## Example Code

This example is not calculating the time elapsed, instead it is setting a value called dt.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear from the code what this example is supposed to output or do, in general.

I just need a clear description of what this example code is trying to do. I am having a little trouble figuring out what the code is supposed to be doing, but I think it's a 1D analog to the car example, right? We are trying to keep the car on setpoint?


{% method %}
{% sample lang="c" %}
[import, lang:"c_cpp"](code/c/pid_controller.c)
{% endmethod %}

<script>
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
</script>