Understand feedback
Identify the signals in a control loop and run your first feedback experiment. 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 01 in the Learning LabSignals, units, and the feedback loop
Label a reference, measurement, error, and actuator command.
A control system makes a measured quantity follow a target. A fan speed controller measures speed, compares it with the requested speed, and changes motor voltage. The plant is the physical process. The sensor measures its output. The actuator changes its input.
Use r for reference, y for output, and e = r - y for error in a negative feedback loop. A proportional controller uses u = Kp * e. If speed is in rad/s and u is in volts, Kp has units V/(rad/s). A positive error should make the plant move toward the reference.
Convert units before comparing signals. One revolution is 2*pi radians, so rpm * 2*pi/60 gives rad/s. A sensor fault is not a disturbance: a disturbance changes the plant, while a sensor fault changes what the controller believes.
See it in action
import math
reference_rpm = 600
measured_rpm = 540
error_rad_s = (reference_rpm - measured_rpm) * 2 * math.pi / 60
command_v = 0.4 * error_rad_s
print('Error:', round(error_rad_s, 3), 'rad/s')
print('Command:', round(command_v, 3), 'V')
Write the signal names, units, and feedback sign before writing a controller.
Open loop and closed loop
Predict how feedback changes steady output and sensitivity.
An open loop command does not use a measurement. For the static plant y = G*u, setting u = r/G works only when the gain G is known and no disturbance enters. Feedback corrects some modelling errors by measuring the result.
With u = Kp*(r-y) and y = G*u + d, substitute and collect y terms: (1+G*Kp)*y = G*Kp*r + d. Therefore y = G*Kp*r/(1+G*Kp) + d/(1+G*Kp). Feedback reduces an output disturbance by 1/(1+G*Kp).
The static formula alone cannot prove dynamic stability. Large gains can cause oscillation when delays or extra dynamic states matter. A controller also needs enough actuator range to supply the required command.
See it in action
gain, kp, reference, disturbance = 2.0, 3.0, 1.0, 0.2
loop_gain = gain * kp
output = (loop_gain * reference + disturbance) / (1 + loop_gain)
print('Output:', output, 'Error:', reference-output)
Feedback trades reduced error for sensitivity to dynamics, noise, and limits.
Practical: regulate a motor speed
Compare proportional control gains on a simulated first order motor.
The normalised motor model is dy/dt = -y + u. Forward Euler approximates it with y_next = y + dt*(-y+u). The variable dt is the simulation step in seconds. Start at rest and request unit speed.
With u = Kp*(1-y), the exact steady output is Kp/(1+Kp), and the closed loop time constant is 1/(1+Kp). Faster does not mean exact: proportional feedback leaves a steady error for this plant.
Use a step small enough for the numerical model. Here dt = 0.01 s is well below the fastest time constant tested. Record peak command as well as output because higher gain asks the actuator to work harder.
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.
- Predict each final speed on paper before running the example.
- Run gains 1, 4, and 9. Plot the three outputs on the same axes.
- Add a plot of command u. Record its maximum and the final error for each gain.
- Repeat with dt=0.005 and compare final values. Explain the remaining error.
What to hand in
- An output plot with reference and labelled axes.
- A table of gain, final error, and peak command.
- A short explanation of the speed versus effort tradeoff.
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
import numpy as np
import matplotlib.pyplot as plt
dt = 0.01
for kp in [1, 4, 9]:
y, history = 0.0, []
for k in range(500):
history.append(y)
y += dt * (-y + kp * (1-y))
plt.plot(np.arange(500)*dt, history, label=f'Kp={kp}')
plt.axhline(1, color='black', linestyle='--', label='Reference')
plt.xlabel('Time (s)'); plt.ylabel('Normalised speed'); plt.legend(); plt.show()
Plot both performance and actuator demand when comparing controllers.
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.