exponenta event banner

Управление в реальном времени с помощью OPC Toolbox

В этом примере показано, как реализовать оперативное приложение контроллера прогнозирования модели с помощью клиента OPC, поставляемого с Toolbox™ OPC.

В примере используется OPC-сервер Matrikon™ Simulation для моделирования поведения промышленного процесса в операционной системе Windows ®.

Загрузите сервер моделирования Matrikon™ OPC с «www.matrikon.com»

Загрузите и установите сервер и установите его в качестве службы или приложения.

В этом примере требуется OPC Toolbox.

if ~mpcchecktoolboxinstalled('opc')
    disp('The example needs OPC Toolbox.')
end
The example needs OPC Toolbox.

Установление соединения с сервером OPC

Используйте команды OPC Toolbox для подключения к серверу моделирования OPC Matrikon.

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

Конфигурирование ввода-вывода OPC завода

На практике установка будет представлять собой физический процесс, и теги OPC, определяющие ее ввод-вывод, уже будут созданы на сервере OPC. Однако в этом случае, поскольку используется сервер OPC моделирования, поведение завода должно быть смоделировано. Для этого необходимо определить теги для обрабатываемых и измеряемых переменных завода и создать функцию обратного вызова (mpcopcPlantStep) для моделирования реакции завода на изменения в обрабатываемых переменных. Требуются две группы OPC, одна для представления двух манипулированных переменных, которые должны быть считаны имитатором установки, а другая для записи двух измеренных выходных данных установки, в которых хранятся результаты моделирования установки.

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

Укажите контроллер MPC для управления моделируемой установкой

Создание модели завода.

plant_model = ss([-.2 -.1; 0 -.05],eye(2,2),eye(2,2),zeros(2,2));
disc_plant_model = c2d(plant_model,1);

Мы предполагаем отсутствие несоответствия модели, горизонт управления 6 шагами и горизонт прогнозирования 20 шагами.

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.

Создайте внутреннюю структуру объекта MPC, чтобы объект MPC не перестраивался во время каждого выполнения обратного вызова.

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.

Сборка ввода-вывода OPC для контроллера MPC

Создайте две группы OPC, одна для считывания двух измеренных выходов установки, а другая для записи двух управляемых переменных.

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

Создание OPC-групп для запуска симулятора и контроллера

Создайте две группы OPC на основе одного и того же внешнего таймера OPC, чтобы инициировать выполнение как моделирования установки, так и выполнения MPC при изменении содержимого метки времени OPC.

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

Данные журнала из результатов измерений на заводе

Занесите в журнал данные об измеренных выходах завода по меткам «Bucket Brigade.Money» и «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