Table of Contents

Cascade control

This example considers a cascade control scheme consisting of a rapid inner loop(process1 and pid) and a slower outer loop(process2 and pid2), both being subjected to simulated disturbances. (In a real-world case, the inner loop of a cascade is often a (rapid) valve flow-rate controller, while the outer loop could for instance be a level that depends on the flow rate.)

Cascade system

A sinusoidal disturbance D1 is introduced on process1, whereas a step disturbance is introduced halfway through the simulation in D2, and the aim is for the cascade controllers to reject both disturbances as well as possible.

The code to implement the controllers:


   var processParameters1 = new UnitParameters
   {
       TimeConstant_s = 2,//rapid
       LinearGains = new double[] { 1.1 },
       U0 = new double[] { 50 },
       TimeDelay_s = 0,
       Bias = 50
   };

   var processParameters2 = new UnitParameters
   {
       TimeConstant_s = 30,//slow
       LinearGains = new double[] { 1 },
       U0 = new double[] { 50 },
       TimeDelay_s = 5,
       Bias = 50
   };
   var pidParameters1 = new PidParameters()
   {
       Kp = 3,
       Ti_s = 2 //rapid
   };
   var pidParameters2 = new PidParameters()
   {
       Kp = 1,
       Ti_s = 40 //slow
   };
   var process1
       = new UnitModel(processParameters1, "Process1");
   var process2
       = new UnitModel(processParameters2, "Process2");
   var pid1 = new PidModel(pidParameters1, "PID1");
   var pid2 = new PidModel(pidParameters2, "PID2");

   var sim = new PlantSimulator(new List<ISimulatableModel> { process1, process2, pid1, pid2 });

//  pid1.SetManualOutput(50);
//   pid1.SetToManualMode();

//   pid2.SetManualOutput(50);
//   pid2.SetToManualMode();

   sim.ConnectModels(process1, process2);
   sim.ConnectModels(process1, pid1);
   sim.ConnectModels(pid1, process1);
   sim.ConnectModels(process2, pid2);
   sim.ConnectModels(pid2, pid1,(int)PidModelInputsIdx.Y_setpoint);

   var inputData = new TimeSeriesDataSet();

   inputData.Add(sim.AddExternalSignal(pid2,SignalType.Setpoint_Yset),TimeSeriesCreator.Constant(50, N));
   inputData.Add(sim.AddExternalSignal(process1,SignalType.Disturbance_D),TimeSeriesCreator.Sinus(5,20,timeBase_s,N));
   inputData.Add(sim.AddExternalSignal(process2,SignalType.Disturbance_D),TimeSeriesCreator.Step(300, N, 0, 1));
   inputData.CreateTimestamps(timeBase_s, N);

   var isOK = sim.Simulate(inputData,out var simResult);

  // Shared.EnablePlots();
   Plot.FromList(new List<double[]>
       {
       simResult.GetValues(process1.GetID(),SignalType.Output_Y),
       simResult.GetValues(process2.GetID(),SignalType.Output_Y),
       inputData.GetValues(pid2.GetID(),SignalType.Setpoint_Yset),
       simResult.GetValues(pid1.GetID(),SignalType.PID_U),
       simResult.GetValues(pid2.GetID(),SignalType.PID_U)
       },
       new List<string> { "y1=y1", "y2=y2[right]","y2=y2_set[right]", "y3=u1", "y4=u2[right]" },
       timeBase_s, "CascadeEx");
  // Shared.DisablePlots();

The resulting results.

Cascade system

To observe the open-loop behavior of the system for the same disturbances but with both controllers in manual mode, comment in the code lines:

    pid1.SetManualOutput(50);
    pid1.SetToManualMode();

    pid2.SetManualOutput(50);
    pid2.SetToManualMode();

The resulting open-loop simulation results: Cascade system

These simulations show the benefits of the cascade control over open-loop:

  • transients in y2 of +/-0.5, are reduced to approximately +/-0.1, and
  • the step disturbance in y2 is rejected.
Note

There are slight "bumps" in both the open-loop and closed-loop cases above. This is because the simulations by design start in steady-state, whereas for the rest of the simulation the entire process is in never-ending transient state because of the sinusoidal disturbance on y1. Thus this bump is unavoidable, therefore in cases such as this, models should only be evaluated after a run-in-time.