0

Корпоративная многозадачность в CoDeSys

Допустим, нам нужно управлять тремя устройствами. Можно бы поставить три отдельных ПЛК, но устройства несложные и вполне можно попробовать обойтись одним контроллером. В таком случае, возникает логичная мысль не сваливать весь программный код в одну кучу, а разделить его на три программы.

Теперь представьте себе, что мы имеем обычный однозадачный ПЛК с классическим рабочим циклом: 1)чтение входов, 2) вызов прикладной программы, 3) запись выходов. Мы можем поступить очень просто:

написать 3 программы и добавить их вызовы один за другим в главную прикладную программу:

PRG_A;

PRG_B;

PRG_C.

Вполне работоспособное решение. Но может оказаться, что общий цикл стал слишком медленным для PRG_A, хотя PRG_C можно бы, напротив, вызывать значительно реже. Тоже не проблема. Запрограммируем в главной программе некие счетчики, так чтобы каждая программа вызывалась не в каждом цикле, а только через определенное число циклов (например, 1 раз на 10 рабочих циклов). Изменяя параметры этих счетчиков, мы можем настраивать интервалы вызова наших программ. По сути дела мы реализовали три параллельно работающих задачи. Естественно, что в один момент времени работает только одна из них, но с позиции наблюдателя они работают параллельно.

Конечно, не очень удобно возиться со счетчиками. Это лишняя работа, лучше бы поручить ее системе исполнения. Собственно это и достигается с помощью конфигуратора задач CoDeSys.

Описанный выше механизм называется корпоративной многозадачностью либо многозадачностью без вытеснения. Корпоративность обозначает тот факт, что для нормальной работы всей системы, задачи должны сотрудничать между собой. Очевидно, что если одна из задач станет выполнять очень длинные вычисления, длиннее чем заданное время рабочего цикла, то она задержит выполнение других задач. Для корректной работы каждая задача не должна содержать длительных вычислений. Их необходимо разбивать на несколько циклов вызова задачи. Например, не использовать поиск в массиве с помощью итераций по циклу FOR, а обрабатывать каждый следующий элемент массива при очередном вызове задачи. В случае ‘зацикливания’ в одной задаче, останавливается все. Каждая задача должна аккуратно отработать свой цикл, прежде чем сможет получить управление другая задача. В этом главный минус корпоративной многозадачности. В каждой задаче нужно не забывать о других задачах и аккуратно избегать длительных вычислений в одном цикле вызова.

С другой стороны, в том, что каждая задача всегда дорабатывает свой цикл и не может быть прервана в произвольный момент, состоит и большой плюс. Мы можем абсолютно спокойно использовать результаты вычислений одной задачи в другой. Почему это так, станет понятно ниже при описании вытесняющей многозадачности. Отсюда следует, что ‘корпоративная’ многозадачность не означает ‘плохая’. Часто она удобнее. В первую очередь тогда, когда задачи должны тесно взаимодействовать между собой. Без всяких ограничений в нескольких задачах можно использовать глобальные переменные любого типа. Все входы ПЛК опрашиваются перед вызовом каждой задачи, после каждой задачи происходит синхронное обновление всех выходов. Каждая задача может работать с произвольными входами/выходами, в том числе может контролировать выходы, изменяемые в другой задаче. Никакой опасности считать с них некие промежуточные, недостоверные значения нет. Практически мы пишем программы для нескольких корпоративных циклических задач точно так, как и в случае с одной задачей. Если в программе допущена серьезная ошибка, приводящая к зацикливанию, то при корпоративной многозадачности контроллер полностью теряет работоспособность. Это равносильно фатальному сбою контроллера и его приходится перезапускать вручную. Преодолеть эту проблему в CoDeSys позволяют программные сторожевые таймеры. Алгоритм их работы предельно прост: если задача не возвращает управление дольше заданного времени, то таймер ‘срабатывает’ и происходит вызов специального обработчика системного события. По умолчанию этот обработчик выполняет перезапуск контроллера. Вы можете заменить его собственной реализацией, например, включить индикацию ошибки или инициализировать зависшую программу. Как писать обработчики системных событий, мы рассмотрим позднее.

Вытесняющая многозадачность

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

Основной плюс состоит в том, что задачи с низким приоритетом не влияют на задачи с высоким приоритетом. Каждая задача может делать сколь угодно длинные вычисления. Она автоматически будет прервана, при необходимости выполнить более приоритетную задачу и затем снова получит управление и продолжит работу с того места, где она была прервана. Таким образом, отпадает нужда думать об обеспечении заданного времени вычислений в рамках одного цикла вызова программы.

При вытесняющей многозадачности система исполнения CoDeSys плотно взаимодействует с операционной системой ПЛК. Каждая прикладная МЭК задача является отдельным потоком ОС. Каждая задача имеет свой собственный рабочий цикл ПЛК. Опрос ‘своих’ входов, вызов ‘своих’ программ, запись ‘своих’ выходов происходит автономно, независимо от остальных задач. При компиляции проекта CoDeSys автоматически распределяет входы/выходы по задачам, в которых они задействованы и передает соответствующую конфигурацию драйверам аппаратуры.

Грубо можно считать, что при вытесняющей многозадачности мы имеем несколько ПЛК в одном корпусе. К сожалению, в CoDeSys V2.3 текст задач нельзя компилировать, перезагружать и отлаживать автономно, не нарушая работу других задач (это возможно в CoDeSys V3).

Проблемы в многозадачных проектах при вытесняющей многозадачности возможны при использовании общих аппаратных ресурсов и глобальных переменных. Представьте себе, что одна задача начала изменять некую глобальную переменную, например, структуру или строку. Пока изменение не полностью закончено, содержимое данной переменной не определено. Теперь представьте, что в этот момент другая задача получает управление и читает или, хуже того, записывает данную переменную. Результат непредсказуем. Ситуация может проявиться один раз после многих дней нормальной работы ПЛК. ‘Поймать’ ее отладчиком не реально. Остается только не допускать. Классическим приемом защитой от такой ситуации является использование семафоров. Одна задача захватывает некий ресурс для себя и взводит семафор, другие задачи ждут ‘зеленый свет’. Семафоры в CoDeSys реализованы в библиотеке SysLibSem.lib. Работа с ними описана в файле SysLibSem_RU.pdf.

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

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

Есть два способа реализации функций. При синхронной реализации функция не возвращает управления вплоть до получения результата. Ее использование очень просто – вызываем функцию, получаем результат. Если такие функции сосредоточены в низкоприоритетной задаче, то их задержки не критичны, при вытесняющей многозадачности. Альтернативный вариант – это асинхронная реализация длительных операций. Одна функция начинает операцию и моментально возвращает управление. Некоторая отдельная функция проверяет факт окончания операции. Ее нужно вызывать периодически. Задержек в функциях нет, но программа усложняется. Трудно сказать, что удобнее. Поэтому для работы с файлами в CoDeSys есть две библиотеки: SysLibFile с синхронными функциями и SysLibFileAsync с асинхронными функциями.

Альтернативой циклическим задачам является ‘событийный’ вызов задач. Вариант ‘по событию’ в конфигураторе задач позволяет вызвать данную задачу при изменении указанной логической переменной, например, дискретного входа. Такая задача также имеет приоритет и работает с вытеснением или корпоративно, как и циклические задачи.

В некоторых моделях ПЛК существуют устройства, способные генерировать так называемые ‘внешние события’. Например, аппаратные таймеры, счетчики, компараторы и др. Вызов такой задачи может инициироваться аппаратным прерыванием.

Все отладочные средства CoDeSys доступны и в многозадачных проектах. Тонкость состоит в том, что для пошагового выполнения и контроля стека вызовов, CoDeSys нужно знать какую именно задачу мы отлаживаем. Не забудьте в конфигурации задач выбрать нужную и в контекстном меню дать команду ‘Отлаживать эту задачу’.

Мы детально рассмотрели отличия корпоративной и вытесняющей многозадачности. Вытесняющая многозадачность реализована в ПЛК с CoDeSys, выполненных на базе 32-х разрядных процессоров с многозадачной ОС. Во всех остальных случаях в системе исполнения реализуется корпоративная многозадачность.

Как точно проверить, что в имеющемся у нас ПЛК реализована вытесняющая или корпоративная многозадачность? Давайте для практики напишем тестер качества реализации многозадачности. Если вы сможете самостоятельно придумать, как написать такую программу в CoDeSys, то это означает, что вы являетесь пользователем высшей квалификации и можете смело браться за любые задачи с многозадачностью. В противном случае, следуйте за изложением ниже. Начнем с создания классической простейшей программы для ПЛК, инкрементирующей целую глобальную переменную при каждом вызове. Например, так:

g_udiQuickCounter := g_udiQuickCounter + 1;

Свяжем ее с циклической задачей названной QuickTask. Дадим ей высокий приоритет 5. Пусть она вызывается с интервалом в 2 мс.

Корпоративная многозадачность в CoDeSys, image0025

Рис 1. Задача QuickTask

Теперь делаем вторую ‘вредную’ программу. Она будет содержать аналогичный счетчик и делать некие сложные математические вычисления в цикле. Никакого смысла кроме траты процессорного времени в этих вычислениях нет:

g_udiMainCounter := g_udiMainCounter + 1;

FOR iActIndex := 0 TO iMaxIndex DO

rArg := (2 * rPI * (iActIndex MOD 360)) / 360.0;

rRes := 40 * SIN(rArg / (2 * rPI)) + 40;

END_FOR

Ее мы поместим в другую циклическую задачу с меньшим приоритетом 10 и интервалом 10мс. Вредность этой программы заключена в том, что она будет тратить на свои бессмысленные вычисления 8мс, оставляя’окно’ 2мс. При корпоративной многозадачности в это окно будет вписываться ровно один вызов первой задачи. Мы увидим, что оба счетчика меняются одинакового, несмотря на заданные разные интервалы задач.

Соотношение счетчиков должно быть один к одному. При качественной вытесняющей многозадачности, более приоритетная задача будет вызываться четко в пять раз чаще. Соотношение счетчиков должно быть пять к одному. Отклонения от этих идеальных величин возможны, если выполнение системных сервисов (например, обслуживание сети) вызовет нарушение точности выдержки интервалов прикладных задач. Подстраивать время вычислений нашей ‘вредной’ программы мы можем, изменяя число итераций цикла iMaxIndex. Конечно, его можно просто подобрать вручную под быстродействие испытуемого ПЛК, дабы вычисления занимали 8мс. Но это не технично. Добавим в программу регулятор, который будет автоматически поддерживать заданную длительность цикла вычислений:

TickBase(SystemTime:=SystemTime);

t1 := SystemTime.ulLow;

(* тут стоит цикл вычислений FOR, см выше*)

TickBase(SystemTime:=SystemTime);

t2 := SystemTime.ulLow;

t3 := t2 — t1;

IF t3 < 7950 THEN

iMaxIndex := iMaxIndex + 100;

END_IF

IF t3 > 8050 AND iMaxIndex > 1000 THEN

iMaxIndex := iMaxIndex — 100;

END_IF

Здесь TickBase – это системный таймер CurTime из библиотеки SysLibTime. При объявлении переменная iMaxIndex получает начальное значение 20000. В данном фрагменте она регулируется так, чтобы интервал задачи составлял 8000мкс +-50.

Осталось вычислить соотношение счетчиков:

g_rRatio := UDINT_TO_REAL(g_udiQuickCounter) / UDINT_TO_REAL(g_udiMainCounter);

Полная реализация этой программы и конфигурация задачи показана на рис. 2.

Корпоративная многозадачность в CoDeSys, image0044

Рис 2.Реализация задачи MainTask

Результаты запуска тестовой программы таковы:

CoDeSys SP RTE: соотношение 4.99. Ничего удивительного, так и должно быть в качественном контроллере с вытесняющей многозадачностью.

Овен ПЛК-150: соотношение 1.00. Проследив трассировкой значение в течении нескольких минут, мы видим стабильную единицу практически без джиттера. Можно сделать вывод, что в данном ПЛК реализована корпоративная многозадачность, причем работает она идеально.

Итак, для использованных нами ПЛК множество задач не стало проблемой.

Раздел: CoDeSys. Теория. Метки: ,

Оставить комментарий

Отправить сообщение

CoDeSys GSM/GPRS модем Lectus OPC MasterSCADA Modbus MX110 Omron OPC-сервер owen OWEN Easy Logic owen logic PLC Configuration PROFIBUS s-200 SCADA scada системы siemens siemens plc SIMATIC Simplight SMS step7 TRACE MODE Динамизация ИП-320 ОВЕН ОВЕН ПЛК ОВЕН ПЧВ ПЛК ПЛК ОВЕН ПР 110 Панель оператора Программируемое реле Частотный преобразователь библиотека в CoDeSys визуализация диспетчеризация конфигурация панели программирование ПЛК серия NS сименс плк частотник частотное управление язык CFC язык ST
.