Создать программу в UNITY PRO для управления 3 мя бункерами: один - сахарного сиропа, два - воды, алгоритм которых описывается в быстром старте. В напорных баках необходимо поддерживать заданный пределами уровень жидкости с помощью насосов M1 При выбранном режиме START, насос М1 должен: - включаться при отключении сигнализатора LS1 (нижний предел) - отключаться при срабатывании сигнализатора LS2 (верхний предел). Таким образом в напорном баке будет всегда жидкость в пределах размещения сигнализаторов предельных уровней. При выбранном режиме STOP, насос М1: - включается при нажатии оператором кнопки ManPump, - отключается через 5с по отключении кнопки. Питание датчиков, переключателя, кнопки и реле цепи управления пускателя =24В. Самый простой способ решения задачи - написать программу для одного бункера (в быстром старте она приведена), отладить её и размножить методом копирования еще на два бункера. Кроме простоты, преимуществом даного подхода является возможность индивидуального подхода к алгоритму управления каждым бункером, а также относительная простота отладки. Однако если индивидуального подхода не требуется, а количество бункеров будет намного больше, например десятки, то возникает ряд недостатков в таком подходе: -при необходимости изменения программы, это нужно будет делать в каждой копии; -величина программы увеличивается пропорционально количеству копий; Учитывая однотипность бункеров и одинаковый алгоритм управления, есть смысл уменьшить программу одним из следующих способов: - используя массивы и циклы: то есть все переменные заложить в массив с количеством еллементов, равным количеству бункеров, а программу обработки вставить в тело цикла; - используя подпрограммы Решение 1. С помощью DDT и SR. SR (Подпрограммы) очевидно остались в UNITY для совместимости со старыми приложениями PL7, при их конвертировании в новые версии UNITY PRO. Без них обойтись можно, используя более удобный механизм DFB. Тем не менее в этом решении мы вопсользуемся SR а также пользовательскими структурами DDT. Как мы уже знаем, подпрограммы UNITY PRO не могут принимать фактических параметров при вызове. Однако реализация вызова функций/процедур с передачей параметров всё равно на нижнем уровне реализуется приблизительно следующим способом: - в стек помещаются нужные входные параметры процедуры/функции; - запускается нужная процедура/функция, код которой использует значения стека; - по окончанию процедуры или ранее, идет возврат в основную программу, с помещением в стек возвращаемых параметров; Мы можем воспользоваться этим же приниципом. Однако вместо стека мы будем использовать какую-то выделенную область памяти. Чтоб работать с ней как с единым целым, удобно воспользоваться структурными переменными. Таким образом последовательность работы программы будет следующей: - в структурную переменную записываются нужные значения входных параметров; - запускается подпрограмма, код которой использует значение структурной переменной; - по окончанию подпрограммы идет возврат в основную программу, где значение выходных параметров считывается со структурной переменной; Создаем пользовательский структурный тип DDT "Bunker": Предназначение полей StartDelay и TimeOFF описываются немного позже. Далее создаем 4-ре структурных переменных типа Bunker: D - переменная, используемая в подпрограмме, аля формальный параметр; B_Sugar, B_Water1, B_Water2 - переменные, используемые как фактические параметры. Основу подпрограммы, которую назовем "Bunker" будет содержать код, приведенный в быстром старте как 2-й вариант на яызке LD. Однако программу пришлось модифицировать, а именно: - обычные переменные заменены на структурные по причинам, описаным ранее по тексту; - вместо таймеров использован подсчет импульсов. Таймер в подпрограмме использовать можно, но это будет один екземпляр на все вызовы, а нужно чтоб таймеры работали независимо друг от друга. Поэтому таймеры TOF в подпрограмме были заменены счетчиком импульсов (см. генерация импульсов), которые далее в тексте называются таймерами. Эти таймеры характеризуются следующими значениями: - TimeOFF - поакзывающим обратное время в масштабе 100 мс; - StartDelay - сигнализирующим о пуске таймера; Рассмотрим работу программы. В режиме Start, всё работает аналогично как во 2-м варианте LD быстрого старта. В режиме Stop (-|/|- D.Start) включение D.M1 производится нажатием кнопки D.ManPump, а отключение - по отключению D.ManPump и когда остановится таймер D.StartDelay=FALSE, алгоритм работы которого описан далее. Как описано выше, механизм таймера основан на подсчете импульсов определенной периодичности. В режиме Stop, при включенном двигателе D.M1, отключенной кнопке ручного запуска насоса (-|/|- D.ManPump) и не запущенном таймере (-|/|- D.StartDelay), что соответствует ситуации отпускания кнопки ручного запуска насоса, - время обратного отсчета устанавливается в исходную точку D.TimeOFF:=50, и выставляется в TRUE перем D.StartDelay (таймер запущен). Во время работы таймера (-| |- D.StartDelay), при каждом срабатывании импульса Imp100ms, D.TimeOFF уменьшается на 1. Таким образом скорость уменьшения D.TimeOFF будет зависеть от периодичности срабатывания Imp100ms. В основной программе нужно обеспечить, чтоб Imp100ms срабатывал через каждые 100 мс ровно на один цикл. При этих же условиях проверяется достиг ли таймер нижнего предела, и если да - D.StartDelay скидывается, что означает окончание работы таймера. Основную программу напишем на ST. Первые две строки обеспечивают генерацию импульсов Imp100ms длительностью один цикл и с периодичностью 100 мс. Остальные три - вызывают подпрограмму Dozator, передавая туда фактические параметры путем присвоения перемнной D (аля формальному параметру) значение нужных переменных. После вызова подпрограммы, происходит обратное присвоение выходных параметров. Решение 2. С помощью DFB. Использование DFB более удобный механизм, чем использование подпрограмм. Создадим пользовательский тип функционального блока (DFB Type) с именем BunkerDFB: Как видно с рисунка секция Logic практически не отличается от прдеставленой в 1-м варианте решения быстрого старта. Единственным отличием является привязка уставки таймера Timer1.PT к переменной OFFTime, которая определена в секции public функционального блока. Этого не было в постановке задачи, мы его ввели для максимального раскрытия использования DFB. Таким образом, екземпляры DFB можно настраивать на конкретное время задержки отключения в режиме Stop. В переменных проекта достаточно создать три экземпляра DFB и вызвать их в программе, привязав входыи выходы блоков к нужным фактичесим параметрам. Кроме того в любом месте программы можно определить настройку времени отключения OFF_Time нужного функционального блока. |