Showing posts with label Simulink. Show all posts
Showing posts with label Simulink. Show all posts

Jul 12, 2015

Estimated MIMO feedback control in Simulink

I've used the full-state Luenberger observer successfully in my control problems, using Digital Control of Dynamic Systems, 2nd edition, Franklin et. al., chapter 6 as my reference.  The key block diagram that allows for control commands and current estimation is this:
Although this structure does NOT have error integral portion and may therefore have a non-zero steady-state error, the later part of the above mentioned chapter does give the modified solution, and besides in my experience, integral control ALWAYS requires anti-windup correction, so the simpler feedback gain formulation given above is a good first attempt at a non-full-state-feedback MIMO (multi-input, multi-output) control problem.

I in fact learned about the observers from Control System Design Guide, George Ellis, who to his credit, tried to make a dent against the perversely pedantic approach to control engineering, by creating an excellent control system simulation software (for nearly free!).  In my opinion, for SISO (single-input-single-output) design, the Visual Model Q is superior to Matlab/Simulink because it helps (forces?) me to understand what is going on under the hood.

Unfortunately, I have to solve MIMO control, estimation, and optimization problems, and Matlab toolboxes are a faster way to tackle those problems.  And after avoiding Simulink all these years, I finally bought into it recently.  Part of the entry fee into the Simulink was implementing the above block diagram in Simulink.  Here is my first attempt (where problem specific--proprietary--labels are erased):
The predictor that is driven by U (control input into the openloop model) and Y (measurement, or observation) is fairly standard, with the predictor's system matrix A modified to (A - Lp C), and the B matrix B modified to [B Lp], where Lp is the predictor feedback gain.  The 2 inputs on the left is the R vector to follow, the 2 independent commands in this problem.

But there are some important differences:

  • I did not put in Nx, because in this problem, Nx = I.  But adding a matrix gain between R and the difference junction (circle above) is easy; its gain parameter will just be the Nx matrix, available in Matlab workspace.
  • Feedback is calculated only on the subset of the full Xest, so I use another gain (a 2x5 matrix consisting of only 2 rows from a 5x5 identity matrix).
  • Because controller saturation is so important, I explicitly modeled it.  In fact, when the saturation limit varies as a function of the states, I modeled that relationship as well, and feed Simulink's dynamic saturation block.

Future work

Note that I don't deal with the system or the measurement noise, by using the Kalman filter, for example.  The full-state predictor/estimator in fact averages out noise nicely, but the Kalman filter will dynamically adjust the optimal weight for the current vs. past estimates.



Jun 30, 2015

System parameter estimation with Simulink

In previous blog entries, I created custom Simscape components for TEC and forced air heatsink for a thermal control system.  I built an open-loop system model with a current source, and now I want to find reasonable values for the model's parameters using openloop data.  While I've done this exercise many times in the past, I always did it within Matlab itself rather than in Simulink.  In an effort to catch up to the modern Matlab workflow, I will document my new work procedure.

Create input/output ports for the model

I already have my model (creatively called "take1") open, but it is currently missing output signal.  I dragged an out1 port from the Simulink Library Browser --> Simulink --> Sinks, and changed the port property to show port name and number.  Similarly, I dragged an in1 port from the Library Browser and connected to the ideal current source in my model.

Bring the openloop data into Matlab workspace

My data is already in a CSV file in my Matlab folder (~/Documents/MATLAB), so I can easily bring it into the workspace by right clicking on the file in the Current Folder view  --> Import Data... --> Import.  Now my Matlab Workspace is choke-full of column vectors.

I believe the csvread() command would work just as well.  In there, I identify the vectors I want to use for this experiment:
  • input1: TECValue, commanded value to the current generating FW
  • output1: CenterTemp
  • ouput2: I have several thermistor readings, which I should average, like this:

    >> center = mean([Sensor5 Sensor6 Sensor9 Sensor10], 2);
    >> center = center(4215:6000); % Just deal with relevant data

  • output3: HeatsinkTemp
The data was captured at 2 Hz, but the time was not recorded.  So I just make it up with this Matlab command:

>> time = (0 : 0.5 : 0.5*(size(center,1)-1))';

Note the transpose (') operator to keep the time as a column vector, just like the other openloop data columns.  I suppose I could have defined a sampling frequency as a constant, but let's just keep moving for now.

Create an experiment

In the Simulink model window, select Analysis > Parameter Estimation.  This action opens a new session, Parameter Estimation - take1, in the Parameter Estimation tool.  Click "New Experiment" in the toolbar to bring up "Edit Experiment: Exp" wizard--"Exp" is the default name of the experiment.
  • Select all output ports I created in the model, and supply the openloop data
    • output 1: [time, CenterTemp(4215:6000)]
    • output 2: [time, center]
    • output 3: [time, HeatsinkTemp] I ignored the heatsink temperature because it is actively controlled.
  • In the "Inputs" category, select only some of the rows: [time, TECValue(4215:6000)]
  • Select Initial States. Optional?
  • Select parameters: Simulink found all parameters in my model: those that were left in symbolic form.  I checked all of them.  If necessary (usually a good idea), the parameters should be constrained to sensible bounds. when expanded, the parameter tab shows the minimum and maximum bounds.  For almost all physical parameters, the minimum should be some small value.

Clean up data

To view the imported data, click  Add Plot on the Parameter Estimation tab and select the experiment name--"Exp" here.

Since the open loop data covers many different cases, here is a way to restrict the data range: in the "EXPERIMENTAL PLOT" tab, click "Extract Data" button, and specify the "Start/End Time", as shown below:
Then I clicked "Save As", which created another experiment "Exp1".  I renamed Exp1 to "Exp TEC".  In the EXPERIMENT PLOT tab above, there are other ways to clean up the experiment data:
  • Remove outlier, offset
  • Scale, filter data

Estimate parameters

When I click on the "Estimate" button shown below, the GUI runs optimization loop, and adjusts the parameters until the score (sum of the squared error) stops converging.
The EsitmatedParams "Scales Value" shows that my initial guess for one of the parameters was particularly poor.  Going back to the Experiments browser --> Edit --> Parameters, the parameter values at the end of the estimation iteration are shown, and I can just read them off.

Clicking on "Plot Model Response" button above overlays the simulation result against the experimental data.
The fit is not all that great, suggesting that my simple model is missing at least 1 first order dynamics between the TEC and the out1, and maybe the TEC data I have is somewhat off.  Rather than complicate the model further, I let the parameter estimator vary the TEC parameters to obtain a better fit, as shown below:

If I had more openloop data, I could validate the model + parameter against it.

Next step

I have to design a feedback and feed-forward controller for this system.   The feedback controller will be relatively easy, but the feed-forward tends to have lots of heuristics and tuning knobs.