В этой статье рассмотрим основные операции выполняемые над входами выходами и аналоговыми данными. Рассмотрим конфигурирование и использование таймеров и счетчиков, а также создание и работу с функциями.
Коротко пробежим по основным операциям.
Логические операции. Доступны через вкладку Bit Logic
Что мы здесь видим. Нормально разомкнутый контакт -| |-. Мы его уже применяли. Он пропустит на свой выход сигнал если его состояние равно логической «1». Нормально замкнутый контакт -| \ |-. Он пропустит на выход сигнал если его состояние равно логическому «0». Сигнал инверсии –| NOT |- инвертирует входной сигнал. Сигнал выделения фронта -| P |- формирует на своем выходе импульс в течении одного цикла программы при обнаружении на своем входе положительного фронта. –( )- сигнал установки бита. Приравнивает бит или группу битов логическому состоянию на входе. –( S )- устанавливает бит или группу битов при появлении логической 1 на входе. –( R )- сбрасывает бит или группу битов при появлении на входе логической единицы. Всякие триггеры и так далее.
Создание ветвлений в программе осуществляется стрелками
На рисунке показано как реализовать комбинированную логическую схему. Входа I0.1и I0.2 объединены по ИЛИ и вместе они объединены по И с входом I0.0.
Операции сравнения – Compare. Используются понятное дело для сравнения различных аналоговых величин. На выходе формируют логический сигнал соответствующий результату сравнения. Например
Сделайте такую схему и экспортируйте ее в awl файл. Запустите симулятор S7-200 от canal. Два раза щелкните по полю с надпись 0. Откроется окно в котором выберем модуль EM 231
Теперь у нас есть аналоговый модуль с входами AIW0 AIW1 AIW2. Нажимаем Program -> load program и загружаем наш файл awl. Откроется окно
Нажимаем RUN. И теперь двигая ползунок аналогового входа AI0 видим что при превышении значения 10000 устанавливается выход Q0.0.
Еще одна тонкость – полезность. В симуляторе и при работе с реальным ПЛК доступен режим state program (состояние программы).
При нажатии на эту кнопку в редакторе кода будет отображаться состояние булевых переменных, входов выходов, аналоговые значения и результат логической операции.
При результате логической операции равной 1 – сама операция подсвечивается синим цветом. Видно что аналоговое значение 32760 это больше 10000 следовательно результат операции сравнения = логической 1. Значение выхода Q0.0 тоже становиться равным 0.
Математические операции делятся на математику целочисленную Integer Math и математику с плавающей запятой Floating Point Math. Тут важно заметить что нельзя напрямую величины типа integer 16 бит и аналоговые входа с размерностью WORD 16 бит засовывать в математику типа REAL. Необходимо преобразовать сначала Integer в Double Integer а затем DI в REAL. Функции преобразования лежат во вкладке convert.
Для примера напишем программу которая считывает аналоговый вход и делит его на 2,5.
Вот как будет выглядеть программа
Вот опять используем системный меркер SM0.0 и используем аккумулятор АС0 для хранения промежуточных результатов.
Таймеры
Есть несколько видов таймеров. TON – с задержкой включения. Когда на его входе появляется логическая 1 то таймер начинает считать до заданного значения по достижении которого он выставляет бит своего состояния в логическую единицу.
TOF – таймер с задержкой выключения. Бит состояния выставляется в 1 сразу по появлению на входе логической 1 и сбрасывается по достижению таймером заданного значения.
Таймеры в S7-200 делятся по дискретности устанавливаемого времени. Так таймеры с номерами T32, T96 имеют дискретность 1 мс и максимальное время 32.767 с.
Таймеры с номерами T33-T36, T97-T100 имеют дискретность 10 мс и максимальное время 327.67 секунды.
Таймеры с номерами T37-T63, T101-T255 имеют дискретность 100 мс и максимальное время 3276.7 секунды.
Для настройки таймера необходимо выбрать его номер из группы с необходимой дискретностью и задать значение до которого считать (максимум 32767).
На рисунке приведен пример мигалки на двух таймерах
Логика работы такая. Так как логическое состояние таймера при первом старте равно 0 то результат опроса команды -| / |- Q0.0 равно 1. Оно приводит к тому, что стартует таймер Т35. Как только таймер Т35 досчитал до 1 секунды то выставляется выход Q0.0 в 1. Это приводит к тому что стартует таймер Т36. Когда он досчитывает до 1 секунды то в сбрасывается Q0.0 и стартует таймер Т35 и так по кругу. Загрузите этот пример в симулятор и нажав state program посмотрите как это работает в железе.
Необходимо заметить, что можно опрашивать не только логическое состояние таймера но и его текущее значение. Важно помнить, что значение таймера имеет разрядность 16 бит и при сравнении используется целочисленная математика и сравнение Integer.
На рисунке пример программы реализующей мигалку на одном таймере. Логика работы такая. Так как в первый момент состояние меркера m0.0 равно 0 то результат опроса команды -| / |- M0.0 равно 1. Оно приводит к тому, что стартует таймер Т35. Как только таймер Т35 досчитал до 1 секунды то выставляется выход Q0.0 в 1. Как только таймер досчитал до 2 секунд, то сбрасывается выход Q0.0 в 0 и устанавливается на один цикл меркер m0.0. Установка меркера (результат опроса команды -| / |- М0.0 становиться равен 0) приводит к рестарту таймера Т35 и цикл повторяется.
Высокоскоростные счетчики
На практике часто необходимо осуществлять подсчет импульсов (например при измерении оборотов). Для этого в ПЛК S7-200 предусмотрены высокоскоростные 32-х разрядные счетчики HSC (High Speed Counter). В линейке S7-200 есть ПЛК имеющие от 4 до 6 скоростных счетчиков с максимальной частотой счета 30кГц и CPU 224XP имеющий к четырем 30кГц счетчикам еще два с максимальной частотой 200кГц. Аппаратно входы счетчиков подключены на ноги порта I0 (нужно смотреть в документации). Для конфигурации счетчиков я рекомендую использовать мастер.
На примере рассмотрим как настроить счетчик на подсчет импульсов за определенное время (классическое измерение частоты). Запускаем мастер настройки счетчика.
Выбираем какой счетчик настраиваем и режим работы (я использую режим Mode 0 – простой счет без сброса и старта). Mode 12 например используется ля генерации PWM сигнала (подробнее можно найти в Help). Нажимаем Next.
Даем название процедуре настройки счетчика (например «настройка счетчика импульсов»). Выбираем начальное значение, значение до которого считать и направление счета. В нашем случае выбираем Preset = 0, Current = 0, Direct = UP. Нажимаем Next.
Здесь все оставляем без изменений так как мы считаем импульсы за период времени (если бы считали импульсы до определенного значения то в предыдущем окне установили бы Preset на необходимую величину и в текущем окне поставили бы галку «генерировать прерывание по достижению PV). Нажимаем Next и в следующем окне Finish.
В окне Program Block появились две новые процедуры
Настройка счетчика импульсов SBR0 и процедура прерывания INT_0. В коде блока OB1 вставляем нормально разомкнутый контакт sm0.1 (First Scan) и из списка Call Soubrutines выбираем «Настройка счетчика импульсов SBR0».
Теперь мы можем убедиться, что счетчик считает. Допишем в Network2 следующий код.
Делаем экспорт в awl. Открываем симулятор S7_200. Двойной щелчок по CPU и выбираем CPU 226. Загружаем наш awl файл и переводим ПЛК в RUN. Теперь если переключать тумблер I0.0 то счетчик будет считать и его значение будет отображаться на байте выходов Q0.
Теперь попишем программу для автоматического подсчета импульсов за период времени.
В настройках счетчика вставляем network и дописываем в него следующий код
Тут необходимо сделать следующие пояснения.
В системе есть специальный таймер тикающий с периодом равным 1мс*SMB34 и вызывающий так называемое событие №10. Функция ATCH из выпадающего списка Intertupt имеет следующие входа выхода. Вызываемое прерывание (в нашем случае INT_0) и вход номера события запускающее это прерывание (в нашем случае №10). Таким образом мы настроили вызов прерывания INT_0 каждые 250мс.
Теперь заходим в прерывание INT_0 и вставляем следующий код
Теперь в переменной VD0 мы имеем число импульсов измеренное за 250мс.
Работа с функциями
Часто целесообразно для выполнения типовых действий создать функцию. Делается это следующим образом. Правым щелчком мыши на поле Program block -> Insert -> Subroutine.
Появляется еще одна подпрограмма SBR1. Ее можно переименовать по клику правой кнопкой -> rename.
Теперь для ее вызова необходимо в нужном месте программы (например в основном цикле при включение входа i0.0 должна вызываться наша подпрограмма func_1 (имена могут быть и на русском языке)) необходимо встать на линию после опроса входа -| |- i0.0 и два раза щелкнуть по имени нашей подпрограммы в списке call subroutine. Функция автоматически встанет на место.
Теперь наша функция вызывается. Что бы изменить начинку функции необходимо кликнуть ее два раза в списке Program block.
Откроется окно аналогичное основному блоку, где можно написать свою программу. Например как на рисунке.
Это пример функции ни чего не возвращающей и не имеющей входных параметров. Этот прием используется в основном для структурирования программы путем разбития ее на отдельные сегменты. Часто на практике требуются функции обрабатывающие входной сигнал и возвращающие результат. Это делается следующим образом. Заходим в нашу функцию и вверху видим поля для данной функции. In это входа Out выхода Temp внутренние переменные. В поле symbol пишем символьное имя входной переменной (например «вход 1»), в поле data type определяем какого типа будет эта переменная , если это аналоговый вход то тип word и так далее. Добавляем например «вход 2» типа word и выход «выход 1» типа BOOL.
Теперь пишем программу. Будем например сравнивать значение переменной вход 1 и вход 2 и если вход 1 больше то устанавливать выход в 1.
Вот как выглядит эта программа.
При заполнении символов в программе знак # писать не надо, он ставиться автоматически.
Теперь вызовем нашу функцию. В основном цикле после условия вызова (например sm0.0 вызывать всегда) выбираем нашу функцию func_1 из списка call subroutines.
Появляется наша подпрограмма в таком виде
Заполняем знаки вопроса необходимыми нам переменными. Например в первом нетворке сравнивается значение аналогового входа AIW0 с уставкой 10000 и если вход больше то устанавливается выход q0.0. Во втором нетворке сравнивается значение аналогового входа AIW2 с уставкой 20000 и если вход больше то устанавливается выход q0.1.
Как верно замети Сергей в симуляторе от Canals этот пример не работает. Зато он нормально работает в симуляторе S7_200_SIM, просто замените AIW0 на IB0 и AIW2 на IB1, а впроцедуре тип WORD входных переменных на BYTE. В сравнении естественно нужно сравнивать не INT а BYTE. Можно загрузить готовый проект подрограмма.mwp. Естественно на практике внутри функции выполняется как правило больше действий. Например я использую подобные функции чтобы получить значение давления в кгс с датчиков с токовым выходом 4-20мА. На вход передаю значение из аналогового модуля и величину давления соответствующего току 20мА для данного датчика. Внутри функции по формуле вычисляю давление соответствующее текущему току и возвращаю из функции.
Теперь о дополнительных тонкостях и хитростях.
Например необходимо узнать где у нас используется та или иная переменная. Для это служит средство cross reference.
В таблице видно, что мы использовали слово памяти VW0 один раз в основном цикле OB1.
Системный меркер sm0.0 Always_On мы использовали три раза. Два раза в основном цикле OB1 и один раз в подпрограмме func_1. Если в этой таблице два раза щелкнуть по имени переменной то автоматически произойдет переход в то место программы где произошло использование этой переменной.
Допишем в программе OB1 код
Нажимаем PLC -> compile All. Открываем опять cross reference.
Открываем вкладку Byte Usage
Здесь показано как у нас занята память. У нас занята память под VW0 и VW2, а так как они используют по два байта то отображаются буквами W, и занимают каждая по две клетки байтовой области. Меркер M0.0 занимает бит в байте MB0. Также мы используем специальный меркер sm0.0 Always_On из байта SMB0. Здесь удобно смотреть какие ячейки еще свободны что бы случайно не использовать уже занятый.
На вкладке Bit Usage уже показывается распределение занятых битов в байте.
Здесь видно, что в программе мы уже использовали два дискретных выхода Q0.0 и Q0.1 и один дискретный вход I0.0. Эту табличку я смотрю когда необходимо заиметь свободный меркер типа BOOL для какого либо флага в программе и при необходимости узнать какие еще входа выхода свободны в контроллере.
Отладка программы
Для просмотра значений переменных и состояния входов выходов используется инструмент Chart Status
В таблице вбиваем нужные нам переменные и смотрим их значения. Можно задать свои значения в поле New Value и нажать карандашик Write All и эти значения передадутся в программу.
Состояние выполнения программы можно увидеть нажав кнопку program status (как в симуляторе) и при включенном ПЛК будут отображаться состояния входов выходов и текущие значения переменных
В следующей статье рассмотрим создание HMI интерфейса с контроллером SIMATIC S7-200 на базе панели оператора TD и на базе PC с помощью программы ProTool.