>
section 11 of 123 min read

11. Things to Try

Hands-on practice is essential. None of this material sticks until you have made an oscillation happen, then suppressed it.

  1. Simulate a PID in Python with scipy.signal or the control library. Plant: G(s)=1/(s2+s+1)G(s) = 1/(s^2 + s + 1). Try P-only, PI, then PID. Watch the step response evolve. Tune for a target overshoot of 10% and settling time of 5 seconds.
python
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import lti, step
 
# Plant
plant = lti([1], [1, 1, 1])
t, y = step(plant)
plt.plot(t, y, label='open-loop step')
 
# Closed-loop with PID
from scipy.signal import TransferFunction, feedback
Kp, Ki, Kd = 5, 2, 1
pid = TransferFunction([Kd, Kp, Ki], [1, 0])
loop = pid * plant  # series
# closed-loop = loop / (1 + loop) -- this needs careful symbolic handling
  1. Plot a Bode plot by hand for G(s)=100/(s(s+1)(s+10))G(s) = 100 / (s(s+1)(s+10)). Identify breakpoints, sketch asymptotic magnitude (sloping at 20,40,60-20, -40, -60 dB/dec at corners 0, 1, 10 rad/s). Compute phase margin and gain margin.

  2. Sketch a root locus for G(s)=K/(s(s+2)(s+5))G(s) = K / (s(s+2)(s+5)). Three open-loop poles, no zeros. Three branches; one departs from the origin to the right, the other two break away from the real axis between 0 and -2 toward jωj\omega asymptotes. At what KK does the locus cross the imaginary axis? (Use Routh-Hurwitz on the characteristic polynomial s(s+2)(s+5)+K=0s(s+2)(s+5) + K = 0.)

  3. Tune a real PID on a 3D printer or DIY oven. Most printer firmware (Marlin, Klipper) has a M303 command that automates a Ziegler-Nichols-style identification.

  4. Build a self-balancing project. Inverted pendulum on a cart, two-wheel balancing robot, or "Segway clone." Use an Arduino + IMU + motor driver. Implement state feedback or PID. This is the canonical "your first control system" project; it teaches you everything.

  5. Implement a Kalman filter to fuse accelerometer and gyroscope into a clean attitude estimate. Compare to the raw sensors. The Kalman estimate will be much smoother and more stable.

  6. Sketch the Nyquist plot for G(s)H(s)=K/(s(s+1)2)G(s) H(s) = K / (s(s+1)^2) for K=1K=1 and K=10K=10. Find the KK at which encirclement of 1-1 first occurs. Compare with Routh-Hurwitz prediction.

  7. Convert a transfer function to state-space with Python's scipy.signal.tf2ss. Verify the eigenvalues of AA equal the poles. Place new poles with scipy.signal.place_poles and verify the closed-loop matrix has the desired eigenvalues.

When all of the above feel mechanical, you have the chapter under your belt.