Reduce steady error
Distinguish system type, tracking error, disturbances, and integral action. This module has 3 lessons and takes about 2h 25m. Each lesson has a practice exercise that runs real Python in your browser and a short quiz.
Start module 07 in the Learning LabSystem type and the final value theorem
Predict step and ramp error for stable feedback loops.
For unity negative feedback, E(s)=R(s)/(1+L(s)), where L=P*C. The final value theorem gives e_inf=lim(s*E(s)) as s approaches zero only when all poles of s*E(s) are in the open left half plane. Check stability first.
System type counts uncancelled integrators in L at the origin. For a stable type 0 loop with position constant Kpos=L(0), step error is 1/(1+Kpos). A type 1 loop has zero unit-step error and finite unit-ramp error 1/Kv, where Kv=lim(s*L(s)).
These statements assume ideal linear operation and a reachable reference. Saturation can prevent the controller from reaching the target even with an integrator. More integrators can improve low frequency tracking while making stability harder.
See it in action
gain = 4.
# L = 4/(s*(s+2)) is type 1; its closed-loop poles are stable.
velocity_constant = gain/2
ramp_error = 1/velocity_constant
print('Kv:',velocity_constant,'Unit-ramp error:',ramp_error)
Error constants describe stable ideal loops, not arbitrary real systems.
Integral action and load rejection
Explain how a PI controller holds a nonzero command at zero error.
A PI controller is u=Kp*e+Ki*z with dz/dt=e. The state z accumulates error. Unlike proportional action alone, integral action can hold a nonzero command after e has reached zero.
For dy/dt=-y+u+d with a constant load d, equilibrium at y=r needs u=r-d. A PI controller can store that required command in Ki*z. The closed-loop characteristic polynomial is s^2+(1+Kp)*s+Ki.
Positive Ki and Kp>-1 make this ideal second order polynomial stable. In a higher order plant, integral action can destabilise the loop. If u is limited, continuing to integrate an unreachable error causes windup.
See it in action
kp, ki, reference, load = 2., 1., 1., -0.3
required_u = reference-load
integral_state = required_u/ki
print('Steady command:', required_u)
print('Stored integral:', integral_state)
print('Closed-loop denominator:', [1,1+kp,ki])
Integral action solves constant offsets only within stability and actuator limits.
Practical: reject a load step
Compare P and PI on the same plant and disturbance.
Use dy/dt=-y+u+d, reference=1, and a load d=-0.4 beginning at 10 seconds. With Kp=2, P alone settles at y=(2+d)/3 after the load, so error increases. PI can recover y=1.
Use the current error to calculate u, then update both y and the integral state using the same time step. This makes the discrete implementation explicit. Do not silently change the integration convention between controllers.
The checked exercise uses an unlimited actuator to isolate integral action. The next module adds saturation and anti-windup. Compare a settled post-disturbance window, not just a transient sample.
Your experiment plan
Use the browser editor or the downloadable notebook. All plant data are simulated. Keep a notebook with parameters, predictions, results, and units.
- Overlay the P and PI outputs and mark the load time.
- Plot the actuator command and integral state.
- Measure error just before the load and after settling.
- Try loads -0.2 and -0.6, then explain what would happen with a 1.2-unit actuator limit.
What to hand in
- Output and command plots.
- A before-and-after error table.
- A prediction of the effect of actuator limits.
Reflect on your results
Which assumption matters most? Describe one result that surprised you and one experiment that would test your explanation.
The automatic exercise checks the core code behaviour. Review observations and written deliverables yourself or with a mentor.
See it in action
def simulate(ki):
dt, y, z = 0.01, 0., 0.
for k in range(4000):
e = 1-y
u = 2*e+ki*z
d = -0.4 if k*dt>=10 else 0.
y += dt*(-y+u+d)
z += dt*e
return y
print('P final:',simulate(0))
print('PI final:',simulate(1))
Test tracking and disturbance rejection as separate experiments.
Free, open and run by a nonprofit.
This page is part of Control Engineering, a free course of 20 modules and 60 lessons in the engineering.fit( ) Learning Lab. The Learning Lab is built and run by engineering.fit( ), a nonprofit founded by Abdullateef Opeyemi Bakare that helps African engineering students gain research experience. You do not need an account or pay a fee to learn.