Cascade Controller
Demonstration of a two-loop cascade PID control system with inner and outer loops.
You can also find this example as a single file in the GitHub repository.
System Architecture
The cascade controller consists of:
- An outer loop (primary controller) that regulates the main process variable
- An inner loop (secondary controller) that controls an intermediate variable
- A plant modeled as a subsystem with two cascaded transfer functions and noise disturbances
The inner loop responds faster to disturbances, improving the overall system response.

First let's import the Simulation, Connection, Subsystem, and Interface classes along with the required blocks:
Plant Definition
We define the plant as a Subsystem containing two cascaded transfer functions with noise disturbances. The plant uses TransferFunctionZPG blocks (zero-pole-gain representation) and WhiteNoise blocks for disturbances.
Control Loops
We set up two PID controllers:
- c1: Outer loop PID controller (primary) - c2: Inner loop PID controller (secondary)
The inner controller is typically tuned to be faster than the outer controller. The setpoint changes at different time intervals to demonstrate the tracking performance.
We initialize the simulation with all blocks and connections. We use the RKCK54 solver (Runge-Kutta-Cash-Karp 5(4) method) with adaptive time-stepping for accurate integration of the transfer function dynamics.
12:43:21 - INFO - LOGGING (log: True) 12:43:21 - INFO - BLOCKS (total: 9, dynamic: 3, static: 6, eventful: 0) 12:43:21 - INFO - GRAPH (nodes: 9, edges: 14, alg. depth: 5, loop depth: 0, runtime: 0.127ms)
Now let's run the simulation for 100 seconds:
12:43:21 - INFO - STARTING -> TRANSIENT (Duration: 100.00s) 12:43:21 - INFO - -------------------- 1% | 0.0s<2.2s | 731.2 it/s 12:43:22 - INFO - ####---------------- 20% | 0.5s<03:34:07 | 747.4 it/s 12:43:22 - INFO - ########------------ 40% | 1.0s<1.0s | 703.7 it/s 12:43:22 - INFO - ############-------- 60% | 1.5s<01:04:33 | 735.9 it/s 12:43:23 - INFO - ################---- 80% | 1.9s<0.3s | 730.4 it/s 12:43:23 - INFO - #################### 100% | 2.3s<--:-- | 718.0 it/s 12:43:23 - INFO - FINISHED -> TRANSIENT (total steps: 1662, successful: 1229, runtime: 2325.23 ms)
The Simulation class has a convenient plot method that plots all Scope blocks in the simulation: