This page (revision-25) was last changed on 2021-11-08 09:09 by Murray Altheim

This page was created on 2019-12-22 08:01 by Murray Altheim

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
25 2021-11-08 09:09 8 KB Murray Altheim to previous
24 2021-06-24 22:52 8 KB Murray Altheim to previous | to last
23 2021-01-23 22:25 8 KB Murray Altheim to previous | to last
22 2020-09-27 01:11 8 KB Murray Altheim to previous | to last
21 2020-09-27 01:11 8 KB Murray Altheim to previous | to last

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 1 changed one line
!!! Proportional–Integral–Derivative (PID) Controller
It's surprisingly difficult to drive a wheeled robot in a straight line. No two motors have exactly the same performance, and there may also be differences in the floor surface. If we want a robot to follow a more complicated trajectory or to have some indication of where it has traveled, we need to be able to measure how far each wheel has traveled, that is, how many times the left and right wheels have rotated. This is called __[odometry]__.
At line 3 changed 3 lines
This page describes information about a ''Proportional–Integral–Derivative Controller'' (PID controller or three-term controller). Rather than rely on the voltage sent to the motors to determine their speed (with
each motor and gearbox requiring slightly different voltages) this uses a __[motor encoder|MotorEncoder]__ that measures the speed of the motors themselves, then uses that to determine the difference between the intended
and actual motor speeds. This is used to determine the distance each motor has traveled.
Besides the distance traveled, we also want to control the motors in such as way that the robot's movements are both accurate and smoothly executed. Regardless of whether the robot is traveling in a straight line, a gradual curve, or turning around, we want to set the left and right motors to operate at a specified speed and be able to accurately maintain that speed.
At line 7 changed one line
More later...
Additionally, we want to gradually change the motor speed rather than make very sudden changes. This reduces the wear and tear on the motor and gear train, and the robot's movements also appear smoother. This is called __slewing__ the speed. We set a __slew rate__, which is the maximum speed at which the speed of the motor is permitted to change. You can also think of this as a maximum acceleration rate.
At line 7 added 42 lines
To do all this we can measure the speed of the motors themselves using the [motor encoders], then use that to determine the difference between the intended and actual motor speeds.
It turns out that we can find such a fancy motor controller in the field of [Control Engineering|https://en.wikipedia.org/wiki/Control_engineering]; it's called a __PID Controller__.
On a typical robot with a motor on the left and a motor on the right side, to go forward one motor will be going clockwise, the other motor counter-clockwise. It's entirely typical of DC brushed motors to have a difference in performance in each direction, so it's entirely typical that such a robot will not run in a straight line. So having motor encoders and a PID controller is __exactly__ how one fixes this problem.
See: [PID Rug Bump Challenge|PIDRugBumpChallenge], [Robot Chassis Dynamometer|RobotChassisDynamometer]
!! What is a PID Controller?
A __Proportional–Integral–Derivative__ or __PID Controller__ is a general-purpose mechanism for regulating the output of any kind of system through the use of a ''feedback loop''. The feedback signal provides an indication of the current output of the system and is used to alter the system so that its output matches the desired value. PID Controllers are used to control oven temperatures and in automobile cruise controls. One of its first industrial uses was as an automated steering system for ships.
What sets a PID Controller apart from simpler controllers is that it combines three types of __control terms__ to quickly reach and stay at the desired system output value, minimising overcorrection and maximising stability. These three control terms are what forms its acronym: ''Proportional'', ''Integral'', and ''Derivative''. Because of this a PID Controller is also sometimes called a ''three term controller''.
!! How does it work?
A PID Controller uses two numbers, the __Set Point__ (SP) or ''target value'' of the system, and the __Process Variable__ (PV), the ''output value'' providing the feedback from the system. When the SP and the PV are equal the output from the algorithm is zero and no change is necessary. When there is a difference between SP and PV we consider that the controller's ''error''. Our aim is to reduce that error to zero.
|| Term || What It Does || Considerations
|| Proportional Term | multiplies the error value by a fixed gain value to determine the corrective value influencing the system output (this value is described as a ''proportional'' to the output). | because a "P-only" controller is using the value of the error to generate its corrective value, it will overshoot its target, then undershoot, with smaller and smaller oscillations until the error approaches zero. Unfortunately, as the output of the system oscillates closer and closer to its target the amount of correction also approaches zero, so the controller never gets there.
|| Integral Term | integrates the error value into the correction over time so that it minimises this overshoot and pushes the output towards the target value. | the amount of integral applied to the formula needs to be carefully tuned, otherwise this can create its own form of oscillation. Given this tuning is quite tricky to get right, there is generally some overshoot and therefore oscillation in a PI controller. If the PID controller is used for position control the I term is used; for a motor controller the value is set to 0 since it actually represents the position of the motor if we're sampling at a fixed rate.
|| Derivative Term | projects the rate of change of the corrective value, and reduces its amount as the system nears the target. This allows the controller to move towards its Set Point as fast as possible, with as little oscillation as possible. | the Derivative Term is intended to smooth the operation of a PI Controller, but the value of the Derivative must also be tuned. If either the P or D are too high it can cause the system to oscillate.
The more I read about PID controllers the more I found that tuning the control terms is considered something of a black art. There are a number of constants in the formula, and tweaking them is done by trial and error, in other words: guessing. I did
learn one rule of thumb for a PD controller: start at three zeros, then turn up the P until it oscillates, then back off to half that value. Then do the same thing with D.
!! Slew Rate
To add another twist to a robot motor controller, as mentioned above we don't want to tell the motors to go from zero to a projected speed immediately, or from full speed to stopping suddenly, as that would both overly stress the motors and drive system, and cause the robot's movements to be very jerky, perhaps even causing it to crash. We want to gradually ''slew'' the value so that it changes at a maximum rate, called a __slew rate__. This is measured in some measure of motor speed per unit of time.
For example, when experimenting with a motor controller written in [Python], the motor speed is set as a value between 0.0 and 1.0, where half-speed is 0.5. We might set a slew rate of 0.2 per second, meaning that it would take 5 seconds to go from a stop (0.0) to full speed (1.0).
!! Conclusions
All in all, we've now got requirements for a robot motor control that includes a Proportional Term, Integral Term, Derivative Term, and a Slew Rate.
At line 13 changed one line
This needs a lot of cleanup, titles, etc.
* __[PID Controller|https://en.wikipedia.org/wiki/PID_controller]__ from Wikipedia (note the animation of adjusting P,I,D values in the ''Manual tuning'' section)
* __[Improving the Beginner’s PID – Introduction|http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/]__ by Brett Beauregard
* __[PID for Dummies|https://www.csimn.com/CSI_pages/PIDforDummies.html]__
* __[Going Straight with PID|https://projects.raspberrypi.org/en/projects/robotPID/3]__, from RaspberryPi.org
* [PID Autotune|https://platformio.org/lib/show/3/PID-AutoTune] by Brett Beauregard (C++)
* [Build a PID Controller with Python 2019|https://onion.io/2bt-pid-control-python/] from Onion.io
* [pimotors|https://github.com/pootle/pimotors] on github, by the author of Pootle's Place blog
* [RobotPID|https://projects.raspberrypi.org/en/projects/robotPID] (Complete PID in Python with integral etc.)
* [Robert O'Hanlan's Robot PID |https://github.com/martinohanlon/RobotPID]
* [Programming PID Control|https://www.societyofrobots.com/programming_PID.shtml] (Society of Robots)
* [Reading encoder Tue Apr 10, 2018 12:04 am|https://www.raspberrypi.org/forums/viewtopic.php?t=210559]
* pigpio example: [Python Rotary Encoder|http://abyz.me.uk/rpi/pigpio/examples.html#Python_rotary_encoder_py]
* [simple-pid|https://pypi.org/project/simple-pid/] in Python
* [ivPID|https://github.com/ivmech/ivPID] in Python
* [PID controller|https://solderspot.wordpress.com/2014/01/29/pid-controllers-101/], blog post
At line 69 added 3 lines
The rest needs a lot of cleanup, titles, etc.
At line 73 added one line
* [https://github.com/MrYsLab/razmq/blob/master/razmq/encoders/encoders_pigpio.py]
At line 20 removed 3 lines
* [https://projects.raspberrypi.org/en/projects/robotPID] (Complete PID in Python with integral etc.)
* [Robert O'Hanlan's Robot PID |https://github.com/martinohanlon/RobotPID]
* [Programming PID Control|https://www.societyofrobots.com/programming_PID.shtml] (Society of Robots)
At line 26 removed 3 lines
* [Reading encoder Tue Apr 10, 2018 12:04 am|https://www.raspberrypi.org/forums/viewtopic.php?t=210559]
* code: [http://abyz.me.uk/rpi/pigpio/examples.html#Python_rotary_encoder_py]
* [https://projects.raspberrypi.org/en/projects/robotPID]