Search Results for

    Show / Hide Table of Contents

    Feedforward control

    pid-feedforward.

    Simulating pid-control against an external disturbance without feed-forward

    The first part of this example shows the performance of the process and PID-controller when a step change occurs in the disturbance signal. Note that while the PID-controller is able to stabilize the process, it does create significant offset in y, it falls to about y=46.5 at its lowest.

    var processParameters = new UnitParameters
    {
        TimeConstant_s = 30,
        LinearGains = new double[] { 1.1 },
        U0 = new double[] { 50 },
        TimeDelay_s = 0,
        Bias = 50
    };
    var disturbanceParameters = new UnitParameters
    {
        TimeConstant_s = 30,
        LinearGains = new double[] { 1 },
        U0 = new double[] { 0 },
        TimeDelay_s = 5,
        Bias = 0
    };
    var pidParameters = new PidParameters()
    {
        Kp = 0.3,
        Ti_s = 20
    };
    
    var processModel
        = new UnitModel(processParameters,  "Process1");
    var disturbanceModel
        = new UnitModel(disturbanceParameters, "Disturbance1");
    var pidModel = new PidModel(pidParameters, "PID");
    
    var simNoFeedF = new PlantSimulator(
        new List<ISimulatableModel> { processModel, disturbanceModel, pidModel });
    
    simNoFeedF.ConnectModels(pidModel, processModel);
    simNoFeedF.ConnectModels(processModel, pidModel);
    simNoFeedF.ConnectModelToOutput(disturbanceModel, processModel);
    
    var inputData = new TimeSeriesDataSet();
    
    inputData.Add(simNoFeedF.AddExternalSignal(pidModel, SignalType.Setpoint_Yset),
        TimeSeriesCreator.Constant(60, 600));
    inputData.Add(simNoFeedF.AddExternalSignal(disturbanceModel, SignalType.External_U),
        TimeSeriesCreator.Step(100, 600, 25, 0));
    inputData.CreateTimestamps(timeBase_s);
    var isOk = simNoFeedF.Simulate(inputData,out var dataNoFeedF);
    
    Plot.FromList(new List<double[]>
        {
        dataNoFeedF.GetValues(processModel.GetID(),SignalType.Output_Y),
        inputData.GetValues(pidModel.GetID(),SignalType.Setpoint_Yset),
        dataNoFeedF.GetValues(disturbanceModel.GetID(),SignalType.Output_Y),
        dataNoFeedF.GetValues(pidModel.GetID(),SignalType.PID_U),
        inputData.GetValues(disturbanceModel.GetID(),SignalType.External_U)
        },
        new List<string> { "y1=y_meas", "y1=y_setpoint", "y2=y_dist[right]", "y3=u_pid", "y3=u_dist" }, timeBase_s, "FeedForwardEx1");
    
    

    Example 5 result

    Adding feed-forward to the simulation

    In the second part of this example a feed-forward term is added to the PID-controller. The input to the disturbance process is assumed to be measured and is used as the feed-forward variable. Since this variable moves slightly in advance of the disturbance as seen on y due to a time delay and time constant, a feed-forward from this variable should improve performance. As seen, the offset between y and y_set is less during the same disturbance step as in the previous part of this example, with y falling to just y=50.4 at its lowest, but at the expense of a slight overshoot in y.

    
    var processParameters = new UnitParameters
    {
        TimeConstant_s = 30,
        LinearGains = new double[] { 1.1 },
        U0 = new double[] { 50 },
        TimeDelay_s = 0,
        Bias = 50
    };
    var disturbanceParameters = new UnitParameters
    {
        TimeConstant_s = 30,
        LinearGains = new double[] { 1 },
        U0 = new double[] { 0 },
        TimeDelay_s = 5,
        Bias = 0
    };
    var pidParameters = new PidParameters()
    {
        Kp = 0.3,
        Ti_s = 20,
        FeedForward = new PidFeedForward()
        {
            isFFActive = true,
            FF_Gain = -0.7,
            FFHP_filter_order = 1,
            FFLP_filter_order = 1,
            FF_HP_Tc_s = 60,
            FF_LP_Tc_s = 0//120
        }
    };
    
    var processModel
        = new UnitModel(processParameters, "Process1");
    var disturbanceModel
        = new UnitModel(disturbanceParameters, "Disturbance1");
    var pidModel = new PidModel(pidParameters, "PID");
    
    var simNoFeedF = new PlantSimulator(
        new List<ISimulatableModel> { processModel, disturbanceModel, pidModel });
    
    simNoFeedF.ConnectModels(pidModel, processModel);
    simNoFeedF.ConnectModels(processModel, pidModel);
    simNoFeedF.ConnectModelToOutput(disturbanceModel, processModel);
    
    var inputData = new TimeSeriesDataSet();
    int N = 600;
    inputData.Add(simNoFeedF.AddExternalSignal(pidModel, SignalType.Setpoint_Yset),
        TimeSeriesCreator.Constant(60, N));
    string dSignalID = simNoFeedF.AddExternalSignal(disturbanceModel, SignalType.External_U);
    inputData.Add(dSignalID, TimeSeriesCreator.Step(300, N, 25, 0));
    inputData.CreateTimestamps(timeBase_s, N);
    
    simNoFeedF.ConnectSignalToInput(dSignalID, pidModel, (int)PidModelInputsIdx.FeedForward);
    
    var isOk = simNoFeedF.Simulate(inputData,out var dataNoFeedF);
    
    Plot.FromList(new List<double[]>
        { 
            dataNoFeedF.GetValues(processModel.GetID(),SignalType.Output_Y),
            inputData.GetValues(pidModel.GetID(),SignalType.Setpoint_Yset),
            dataNoFeedF.GetValues(disturbanceModel.GetID(),SignalType.Output_Y),
            dataNoFeedF.GetValues(pidModel.GetID(),SignalType.PID_U),
            inputData.GetValues(disturbanceModel.GetID(),SignalType.External_U)
        },
        new List<string> { "y1=y_run1", "y1=y_setpoint", "y2=y_dist[right]", "y3=u_pid", "y3=u_dist" }, 
        timeBase_s, "FeedForwardEx2");
    

    Example 5 result

    • Edit this page
    In this article
    Back to top Generated by DocFX