This example shows how to implement an online model predictive controller application using the OPC client supplied with the OPC Toolbox™.
The example uses the Matrikon™ Simulation OPC server to simulate the behavior of an industrial process on Windows® operating system.
Download and install the server and set it running either as a service or as an application.
This example needs OPC Toolbox.
if ~mpcchecktoolboxinstalled('opc') disp('The example needs OPC Toolbox.') end
The example needs OPC Toolbox.
Use OPC Toolbox commands to connect to the Matrikon OPC Simulation Server.
if mpcchecktoolboxinstalled('opc') % Clear any existing opc connections. opcreset % Flush the callback persistent variables. clear mpcopcPlantStep; clear mpcopcMPCStep; try h = opcda('localhost','Matrikon.OPC.Simulation.1'); connect(h); catch ME disp('The Matrikon(TM) OPC Simulation Server must be running on the local machine.') return end end
In practice, the plant would be a physical process, and the OPC tags which define its I/O would already have been created on the OPC server. However, in this case, since a simulation OPC server is used, the plant behavior must be simulated. To do so, you define tags for the plant manipulated and measured variables and create a callback function (mpcopcPlantStep
) to simulate plant response to changes in the manipulated variables. Two OPC groups are required, one to represent the two manipulated variables to be read by the plant simulator and another to write back the two measured plant outputs storing the results of the plant simulation.
if mpcchecktoolboxinstalled('opc') % Build an opc group for 2 plant inputs and initialize them to zero. plant_read = addgroup(h,'plant_read'); imv1 = additem(plant_read,'Bucket Brigade.Real8', 'double'); writeasync(imv1,0); imv2 = additem(plant_read,'Bucket Brigade.Real4', 'double'); writeasync(imv2,0); % Build an opc group for plant outputs. plant_write = addgroup(h,'plant_write'); opv1 = additem(plant_write,'Bucket Brigade.Time', 'double'); opv2 = additem(plant_write,'Bucket Brigade.Money', 'double'); plant_write.WriteAsyncFcn = []; % Suppress command line display. end
Create plant model.
plant_model = ss([-.2 -.1; 0 -.05],eye(2,2),eye(2,2),zeros(2,2)); disc_plant_model = c2d(plant_model,1);
We assume no model mismatch, a control horizon 6 steps, and prediction horizon of 20 steps.
mpcobj = mpc(disc_plant_model,1,20,6); mpcobj.weights.ManipulatedVariablesRate = [1 1];
-->The "Weights.ManipulatedVariables" property of "mpc" object is empty. Assuming default 0.00000. -->The "Weights.ManipulatedVariablesRate" property of "mpc" object is empty. Assuming default 0.10000. -->The "Weights.OutputVariables" property of "mpc" object is empty. Assuming default 1.00000.
Build an internal MPC object structure so that the MPC object is not rebuilt during each callback execution.
state = mpcstate(mpcobj); y1 = mpcmove(mpcobj,state,[1;1]',[1 1]');
-->Assuming output disturbance added to measured output channel #1 is integrated white noise. -->Assuming output disturbance added to measured output channel #2 is integrated white noise. -->The "Model.Noise" property of the "mpc" object is empty. Assuming white noise on each measured output channel.
Build two OPC groups, one to read the two measured plant outputs and the other to write back the two manipulated variables.
if mpcchecktoolboxinstalled('opc') % Build an opc group for MPC inputs. mpc_read = addgroup(h,'mpc_read'); impcpv1 = additem(mpc_read,'Bucket Brigade.Time', 'double'); writeasync(impcpv1,0); impcpv2 = additem(mpc_read,'Bucket Brigade.Money', 'double'); writeasync(impcpv2,0); impcref1 = additem(mpc_read,'Bucket Brigade.Int2', 'double'); writeasync(impcref1,1); impcref2 = additem(mpc_read,'Bucket Brigade.Int4', 'double'); writeasync(impcref2,1); % Build an opc group for mpc outputs. mpc_write = addgroup(h,'mpc_write'); additem(mpc_write,'Bucket Brigade.Real8', 'double'); additem(mpc_write,'Bucket Brigade.Real4', 'double'); % Suppress command line display. mpc_write.WriteAsyncFcn = []; end
Build two OPC groups based on the same external OPC timer to trigger execution of both plant simulation and MPC execution when the contents of the OPC time tag change.
if mpcchecktoolboxinstalled('opc') gtime = addgroup(h,'time'); time_tag = additem(gtime,'Triangle Waves.Real8'); gtime.UpdateRate = 1; gtime.DataChangeFcn = {@mpcopcPlantStep plant_read plant_write disc_plant_model}; gmpctime = addgroup(h,'mpctime'); additem(gmpctime,'Triangle Waves.Real8'); gmpctime.UpdateRate = 1; gmpctime.DataChangeFcn = {@mpcopcMPCStep mpc_read mpc_write mpcobj}; end
Log the plant measured outputs from tags 'Bucket Brigade.Money' and 'Bucket Brigade.Money'.
if mpcchecktoolboxinstalled('opc') mpc_read.RecordsToAcquire = 40; start(mpc_read); while mpc_read.RecordsAcquired < mpc_read.RecordsToAcquire pause(3) fprintf('Logging data: Record %d / %d',mpc_read.RecordsAcquired,mpc_read.RecordsToAcquire) end stop(mpc_read); end
if mpcchecktoolboxinstalled('opc') [itemID, value, quality, timeStamp, eventTime] = getdata(mpc_read,'double'); plot((timeStamp(:,1)-timeStamp(1,1))*24*60*60,value) title('Measured Outputs Logged from Tags Bucket Brigade.Time,Bucket Brigade.Money') xlabel('Time (secs)'); end