Используя как пример задачу управления шлагбаумом, мы построили табличную программу, в которой реализовали алгоритм управления реальным объектом. Простой алгоритм занимал всего 7 строк. С дополнительными функциями контроля времени исполнения операций программа занимает 23 строки, из которых 6 – это заголовки, не имеющие ни данных, ни логических операций. При этом таблица не потеряла своей наглядности. В ней ясно отображаются значения входных и выходных переменных, внутренние цепи формирования сигналов. Видна работа таймеров. Просто и понятно производится предварительная обработка входных значений. При необходимости выходные значения могут быть инвертированы. Но это не все положительные качества табличного программирования контроллеров. Мы имеем не просто таблицу, а практически комплект документации. Распечатка программы умещается на один лист инструкции по эксплуатации и даже может быть напечатана на корпусе устройства. В случае потери файла с программой управления табличного контроллера ее можно ввести с клавиатуры за короткое время. Назначение входов и выходов нетрудно определить из таблицы. В случае отсутствия в системе монитора работу программы можно наблюдать на любом компьютере или смартфоне. Специалист, знакомый с табличным программированием, может определить неисправность дистанционно, по фотографии таблицы, причем не имея инструкции по эксплуатации или других документов. Программы в таблице может быть достаточно для подключения сигнальных проводов к контроллеру, так как номера контактов находятся в столбце «Адрес», а назначения входов и выходов – в столбце «Комментарий». Использование табличного программирования контроллеров не только упростит поиск неисправностей, но также снизит оговоренные ранее риски, связанные с эксплуатацией систем с закрытым программным кодом или требующих использования компьютера с установленной на нем средой разработки.
Одно из требований, предъявляемых к формату файла табличной программы, – это возможность просмотра содержимого в любом текстовом редакторе. Поэтому для сохранения таблицы был выбран текстовый файл, в котором строки, содержащие данные таблицы, состоят из полей, отделяющихся друг от друга знаком табуляции (рис. 25). Конечно, в таком виде таблицу редактировать неудобно, поэтому текстовый формат рассматривался только как самый простой способ сохранения содержимого таблицы.
Рис. 25. Формат текстового файла табличной программы:
\t – символ табуляции, \r – символ перевода каретки, \n – символ перевода строки
Для редактирования и отладки программ, организованных в виде таблиц, была написана специальная программа[3]. Чтобы не зависеть от конкретной операционной системы, эта программа была написана на языке JavaScript и может запускаться офлайн в любом современном браузере. По сути, это HTML-файл размером немногим более 100 килобайт. Безусловно, возможны и другие реализации, так как формат файла таблицы полностью открыт, а алгоритм пересчета таблицы несложен. Редактирование таблицы в окне браузера не вызывает каких-либо трудностей, все функции интуитивно понятны человеку, работавшему в любой электронной таблице. От обычных приложений в такой реализации отличается только метод сохранения файла. Из окна браузера файл можно только выгрузить в папку «Загрузки» или другую папку, для этого назначенную. Поэтому при сохранении изменений файл не перезаписывается, а сохраняется как дополнительная копия. Так как файлы таблиц небольшого размера, то хранение нескольких последовательно сохраненных файлов дает возможность контролировать ход редактирования и при необходимости возвращаться на необходимое число шагов назад. Недостаток такого метода сохранения файла в том, что периодически необходимо удалять ненужные копии.
Рассмотрим структуру файла таблицы. Каждая строка файла разделена на поля символом табуляции. Как и у любого текстового файла Windows, строка оканчивается возвратом каретки (\r) и переводом строки (\n). Первая строка текстового файла табличной программы представлена на рис. 26 – это заголовок всей таблицы.
Рис. 26. Первая строка текстового файла табличной программы
Первое поле содержит выражение «строк – столбцов – активных ячеек – >» и введено для того, чтобы проверить, соответствует ли содержимое файла табличной программе. Если текстовый файл начинается с другой фразы, то это не табличная программа. Далее идут поля с набором чисел 42, 5, 33 – это количество строк, столбцов и активных ячеек таблицы. Следующее поле – это имя файла длиной до 32 символов. В нашем случае имя файла – «проба_01.txt». Первое число после имени файла отвечает за адреса битовых переменных. Второе число отвечает за адреса аналоговых переменных. В данном случае битовые переменные имеют адреса с 1 по 99. Для аналоговых переменных выделены адреса со 100 по 140. При этом не учитывается, какие из переменных входные, а какие выходные или внутренние. Нумерация входов и выходов контроллера, а также распределение переменных по адресам будут зависеть от реализации самого контроллера. Одним из решений может быть назначение адресов входных и выходных переменных равными соответствующим номерам контактов на разъеме контроллера. Тогда табличной программой можно воспользоваться как списком сигналов, подключенных к разъемам контроллера.
На рис. 27 представлена вторая строка рассматриваемого текстового файла. Это заголовок раздела с информацией о содержимом входных строк табличной программы. Заголовок не только помогает понять, что и в каком поле находится, но и является атрибутом начала считывания содержимого таблицы. Еще по нему можно определить, что идет чтение файла табличной программы, а не другого текстового файла. В нашем примере следующие 42 строки текстового файла будут содержать данные о 42 входных строках таблицы.
Рис. 27. Вторая строка текстового файла табличной программы
Рассмотрим назначение полей строки. Первое поле с названием «Комментарий строки» содержит комментарий к данной строке. Это может быть имя переменной, описание назначения входа или что-то другое. В пересчете таблицы поле комментария не участвует. Второе поле, «Адрес входной», – это, собственно, адрес переменной, по которому к этой переменной обращаются. Несмотря на то что тип переменной можно определить, используя данные об адресах переменных в первой строке файла, следующее поле, «Тип входной», определяет, является ли переменная битовой или аналоговой или же это указатель. Поле «Начальное значение» соответствует своему названию и содержит значение, которое подставляется в ячейку при первом пересчете таблицы. Если значение в поле «Тип входной» будет определяться как указатель, то поле «Начальное значение», будет содержать номер одной из строк, результат которой используется в данной строке. Следующие два поля, «Код операции» и «Тип результата», определяют операцию над входными переменными и тип получаемого результата.
Так как в текстовый файл таблицы легко могут быть внесены изменения, то для контроля соответствия между типом входных данных, типом результата и применяемой операцией введены поля, которые могут показаться избыточными. Дополнительные поля типов помогают быстро найти ошибки в случае некорректных изменений в текстовом файле таблицы.
Поле «Таймер» содержит код таймера. Если это поле равно нолю, то результат входной операции может быть использован в активных ячейках без задержки. В поле «Уставка» записывается время работы таймера в миллисекундах. Пример входной строки табличной программы, содержащей только комментарий, представлен на рис. 28.
Рис. 28. Пример записи данных строки табличной программы в текстовом виде
Следующий раздел файла содержит данные о выходных переменных. Номер первой строки раздела в текстовом файле можно получить, прибавив к числу во втором поле заголовка файла число 2. Это количество строк таблицы плюс две первые строки с заголовками. Первая строка раздела представлена на рис. 29. Это заголовок столбцов табличной программы.
Рис. 29. Заголовок раздела с данными столбцов табличной программы
Далее идут строки файла, в которых находится информация о выходных переменных и операциях над ними. Пример такой строки – на рис. 30.
Рис. 30. Пример записи данных столбца табличной программы в текстовом виде
В первом поле «Комментарий столбца» записан комментарий к выходной переменной, который может содержать произвольную информацию. Следующее за ним поле «Адрес выходной» содержит адрес выходной переменной, которой будет присвоено значение, получаемое при пересчете столбца таблицы. Далее идет поле «Тип выходной» с типом выходной переменной, которая может быть битовой или аналоговой. Поле «Код операции» содержит код операции над результатом по столбцу перед присвоением значения выходной переменной. Количество строк файла, содержащих данные о выходных переменных, указано в третьем поле заголовка файла.
После этих строк идет раздел с данными активных ячеек таблицы. Раздел начинается с заголовка (рис. 31), после которого идут строки файла, содержащие по три поля.
Рис. 31. Заголовок раздела с данными активных ячеек табличной программы
Первое поле, «Строка», содержит номер строки таблицы, поле «Столбец» – номер столбца таблицы, а поле «Код операции» указывает, какое действие будет произведено при пересчете таблицы. Пример записи данных активной ячейки – на рис. 32.
Рис. 32. Пример записи данных активной ячейки табличной программы в текстовом виде
Другими словами, в полях «Строка» и «Столбец» указано положение активной ячейки в таблице, а поле «Код операции» определяет, каким образом активная ячейка будет влиять на результат по столбцу.
Для обработки аналоговых сигналов, например от датчиков температуры, давления, уровня жидкости и других подобных измерителей, контроллеру необходимо иметь аналоговые входы. Получаемые от аналоговых датчиков данные и значения их пределов присваиваются аналоговым переменным, которые обычно представлены числами с плавающей запятой. Эти переменные обрабатываются с помощью математических операций, результаты которых могут поступать как на дискретные, так и на аналоговые выходы контроллера. Например, результат операции сравнения будет представлен в дискретном виде, а результат умножения – в аналоговом. Диапазон адресов аналоговых переменных, применяемых в табличной программе, находится в заголовке текстового файла табличной программы. По предпоследней и последней цифрам в заголовке можно определить адреса возможных аналоговых переменных. На конец адресного пространства битовых переменных указывает предпоследняя цифра в заголовке. Прибавив к этой цифре единицу, мы получим начало диапазона адресов аналоговых переменных. Последняя цифра заголовка указывает на конец адресного пространства аналоговых переменных. Так как все возможные адреса аналоговых переменных известны, то тип переменой легко определить по ее адресу.
Полученное при помощи операций над входными переменными аналоговое значение может быть присвоено выходной аналоговой переменной. Какие из аналоговых переменных будут входными, какие выходными, а какие внутренними – зависит от используемого контроллера. Чтобы вычисленное значение было присвоено выходной переменной, необходимо на пересечении строки с аналоговым значением и столбца с интересующей нас выходной переменной вставить аналоговую активную ячейку. Такую ячейку мы будем обозначать символом «А». Пример использования аналоговых переменных в табличной программе – на рис. 33.
Рис. 33. Пример операции с аналоговыми переменными
Использование аналоговых переменных в таблице подчиняется определенному правилу. Для аналоговых входных и выходных переменных используется только операция присвоения «=». Операция «NOT», инвертирующая битовые входные и выходные значения, для аналоговых операций не применяется. При необходимости для того, чтобы получить отрицательное значение переменной, можно воспользоваться умножением на отрицательное число. Если в столбце под аналоговой переменной находятся несколько ячеек с символом «А» или активные ячейки битовых операций, то при проверке таблицы или ее пересчете должна быть выдана соответствующая ошибка. Таким образом, в столбце аналоговой выходной переменной может быть только одна аналоговая активная ячейка, при помощи которой результат по строке присваивается выходной переменной. Также в строке с аналоговым результатом не используется таймер. Для улучшения читаемости таблицы ячейки с символом «А» и значения выходных переменных выделяются бежевым цветом, а в ячейках битовых операций «Логич. И» и «RS» ничего не пишется. Различные уставки и граничные значения для аналоговых сигналов присваиваются внутренним аналоговым переменным, для которых не назначены аналоговые входы контроллера. При загрузке таблицы таким внутренним переменным присваивается число, которое записано в поле «Начальное значение» текстового файла таблицы. При необходимости внутреннюю переменную можно изменить, присвоив ей новое значение. Для этого при помощи входных операций определяется новое значение и присваивается внутренней переменной с помощью активной аналоговой ячейки.
Некоторые задачи управления, решаемые с помощью контроллеров, требуют измерения температуры. Для этого в контроллерах предусматриваются входы подключения датчиков температуры. В табличной программе таким входам соответствуют аналоговые переменные с назначенными для этого адресами. Программа пересчета таблицы считывает значение с аналого-цифрового преобразователя, подключенного к датчику, и преобразует его в температуру. В ячейке состояния входной переменной будет стоять привычное значение температуры, а не целочисленное значение, полученное от аналого-цифрового преобразователя.
При проектировании систем управления с использованием табличных контроллеров не стоит нагружать табличную программу объемными математическими вычислениями. И это не из-за того, что контроллер не справится или табличные программы непригодны для вычислений. Большое количество вычислений может сделать таблицу громоздкой и затруднит обслуживание устройства во время эксплуатации. Низкая цена и высокая производительность современных контроллеров позволяют обрабатывать входные сигналы от датчиков в реальном времени и передавать готовые данные на головной контроллер с помощью скоростных последовательных интерфейсов. Разделение задач управления и первичной обработки данных повышает надежность системы, упрощает алгоритм управляющей программы, улучшает восприятие графической информации о состоянии системы. На вспомогательные контроллеры обработки сигналов возлагается только преобразование физических величин в привычные числовые значения. Задача по принятию решений в зависимости от получаемых данных остается за программой головного контроллера. Если по каким-то причинам необходимо принимать решение во вспомогательном контроллере, то вместе с обработанным значением сигнала в основную программу должна быть передана информация о принятом вспомогательным контроллером решении.
Нередко при работе программы возникает необходимость сохранять в энергонезависимой памяти переменные, отвечающие за текущее состояние системы. Для этого в контроллерах предусматриваются блоки энергонезависимой памяти, сохраняющей записанные в нее данные после отключения питания. Для табличной программы это обычные внутренние переменные, значение которых изменяется только с помощью активных ячеек. Обращение к сохраняемым переменным не отличается от обращения к обычным переменным. Достаточно определить адреса для битовых и аналоговых переменных, значения которых нужно сохранять, чтобы системная программа записывала их в специальный раздел памяти.
Программа пересчета таблицы после подачи на контроллер питания не присваивает сохраняемой переменной начальное значение из файла таблицы. В момент загрузки такие переменные получают значения, сохраненные в энергонезависимой памяти. Чтобы присвоить начальные значения переменным, сохраняемым в энергонезависимой памяти, в программе следует предусмотреть для них режим инициализации. Для этого каждой такой переменной добавляется обычная внутренняя переменная, которая при загрузке получит начальное значение и будет оставаться неизменной во время выполнения программы. При необходимости инициализировать переменную, сохраняемую в энергонезависимой памяти, можно в любой момент присвоить ей значение добавленной переменной. Пример реализации такого алгоритма показан на рис. 34. В режиме инициализации сохраняемая переменная получит начальное значение от соответствующей внутренней переменной.
Рис. 34. Пример организации сохранения в энергонезависимой памяти значений аналоговой и битовой переменных
Можно заметить, что при отпускании кнопки, устанавливающей начальные значения, сохраняемая переменная с адресом 31 получит значение переменной с адресом 21. То есть начальное значение переменная с адресом 31 будет иметь, только пока нажата кнопка. На рис. 34. представлено состояние табличной программы, когда кнопка, устанавливающая начальные значения, не нажата.
Если переменная с адресом 21 отображает состояние одного из аналоговых входов, то присвоение ей начального значения не имеет особого смысла. Но если это вычисляемая переменная и в ее расчетах участвует переменная с адресом 31, то за время, пока кнопка нажата, программа пересчета таблицы сделает большое количество циклов и обновит значение переменной с адресом 21. После отпускания кнопки обновленное значение запишется в сохраняемую переменную. Для битовой переменной с адресом 15, сохраняемой в энергонезависимой памяти, начальное значение равно нолю и в программе соответствует вращению против часовой стрелки.
В примере на рис. 35 начальное значение битовой переменной с адресом 15 устанавливается триггерной активной ячейкой в строке 9. Предполагаемое начальное значение этой переменной равно нолю, поэтому выбрана триггерная ячейка «R», которая сбросит в ноль сохраняемую битовую переменную при нажатии на кнопку, устанавливающую начальные значения.
Рис. 35. Пример присвоения начальных значений переменным, сохраняемым в энергонезависимой памяти
В зависимости от задачи возможны различные варианты установки начальных значений для переменных, сохраняемых в энергонезависимой памяти.