Библиотека предназначена для выполнения программ на языке FBD (Язык функциональных диаграмм) для ПЛК (Программируемых Логических Контроллеров).
Подробнее о языке FBD можно прочитать на сайте Wikipedia.
FBD - один из языков программирования описанных в международном стандарте IEC 61131-3. Данная реализация не полностью совместима с указанным стандартом, однако большинство его требований реализовано.
Редактор и симулятор выполнения программ FBD вы можете скачать по ссылке.
На YoTube создан плейлист, посвященный контроллеру САТ-500, использующем бибилиотеку.
Библиотека использована при разработке универсального контроллера САТ-500, подробная информация о контроллере на доступна на сайте www.sat500.ru.
- Введение
- Возможности
- Основные понятия
- Ограничения
- Производительность
- Описания элементов
- Установка библиотеки
- Выполнение
Язык функциональных диаграмм создан для описания функционирования одного или нескольких (соединенных через информационную сеть) логических контроллеров. Язык описывает входящие в состав схемы элементы и соединяющие их цепи.
- Нет зависимости от аппаратуры, возможность применения на любой платформе где есть компилятор языка C
- Алгоритм оптимизирован для встроенных контроллеров: PIC, AVR, ARM и т.п. Вычисление не использует рекурсию, стек данных используется очень экономно
- Поддержка архитектур Big-Endian и Litle-Endian
- Экономное использование RAM: схема из 400 элементов использует только около 1 kb ОЗУ
- Широкий диапазон поддерживаемых элементов: логические, арифметические, сравнение, таймеры, триггеры, регулятор. Набор элементов может быть легко расширен
- Сохранение промежуточных результатов в NVRAM (для триггеров, таймеров, точек регулирования и т.п.)
- Поддержка работы по сети (Ethernet, ModBus или подобное)
- Базовая поддержка интерфейса с оператором (HMI)
ПЛК – программируемый логический контроллер, представляют собой микропроцессорное устройство, предназначенное для сбора, преобразования, обработки, хранения информации и выработки команд управления, имеющий конечное количество входов и выходов, подключенных к ним датчиков, ключей, исполнительных механизмов к объекту управления, и предназначенный для работы в режимах реального времени с ограниченным вмешательством человека. Наиболее часто ПЛК используются для автоматизации технологических процессов.
Типовая структура ПЛК показана на рисунке:
Обычно ПЛК предусматривает выполнение следующих функций:
- Выполнение управляющей программы реализующей алгоритм управления
- Подключение входных сигналов (input pins) внешних датчиков (температура, давление, дискретные входы, напряжение и т.п.)
- Подключение выходных сигналов (output pins) для управления внешним оборудованием (дискретные выходы, сигналы тока или напряжения)
- Подключение к информационной сети (network), объединяющей несколько ПЛК и обеспечивающей их совместное функционирование
- Содержит средства реализации интерфейса с человеком (HMI) с помощью индикатора, дисплея, клавиатуры и т.п.
Рабочий цикл ПЛК включает 4 фазы:
- Чтения значений входных сигналов
- Выполнение программы обработки
- Установку значений выходных сигналов
- Вспомогательные операции (обмен данными по информационной сети, реализация HMI и т.п.).
Схема на языке FBD это набор элементов, значений их параметров и соединений (цепей) между элементами.
Элемент схемы это минимальный функциональный блок, выполняющий определенную операцию (логическую, арифметическую, задержку и т.п.) или обеспечивающий подключение схемы к входным или выходным цепям программируемого контроллера.
- Каждый элемент должен иметь уникальное в рамках схемы идентифицирующее его имя.
- Элемент может иметь некоторое количество входов (а может и не иметь) и один или ни одного выхода. Количество входов и выходов зависит от типа элемента. На графическом изображении элементов входы всегда расположены слева, а выходы справа от элемента. Каждый вход элемента должен быть подключен к цепи, которая соединяет его с выходом другого элемента. Выход элемента может быть подключен к одному или нескольким входам других элементов (в том числе и его собственным входам). Выход элемента может быть никуда не подключен, в этом случае элемент не имеет смысла.
- Элементы, которые не имеют выхода обычно используются для обозначения аппаратных выходов программируемого контроллера, выходных сетевых переменных или точек отображения.
- Элементы, которые не имеют входа обычно используются для обозначения аппаратных входов программируемого контроллера, входных сетевых переменных или точек регулирования.
- Элемент может иметь (а может и не иметь: это зависит от типа элемента) параметры, влияющие на его функционирование. Параметры имеют фиксированное значение и задаются при разработке схемы.
Цепь это логическая связь между входами и выходами элементов предназначенная для передачи состояния (значения) сигнала. Каждая цепь должна быть подключена строго к одному выходу и одному или нескольким входам элементов схемы. Состояние цепи к которой не подключен ни один выход элемента является неопределенным. Цепь, которая не подключена ни к одному входу элемента, является не используемой и ее состояние не вычисляется. Аналогично элементам, цепи имеют уникальные в рамках схемы имена. Цепи служат для передачи значений сигналов между элементами схемы. На графическом изображении схемы цепи изображаются в виде линий, которые соединяют входы и выходы элементов.
Сигнал представляет собой целое число со знаком. В зависимости от параметров, указанных при сборке библиотеки, сигнал может занимать 1, 2 или 4 байта. Сигналы можно использовать для логических операций. При этом значение сигнала равное 0 интерпретируется как логический "0" (False), а значение сигнала не равное 0 - как логическая "1" (True). Для входов некоторых элементов важно не само значение сигнала, а факт его нарастания (передний фронт). Такие входы на графическом изображении элемента обозначены наклонной чертой. Факт наличия переднего фронта фиксируется при любом изменении сигнала в большую сторону (Si > Si-1). Элементы, выполняющие логические функции, формируют значение сигнала "1" для логической "1" и значение сигнала "0" для логического "0".
Точка регулирования является составной частью организации интерфейса контроллера с оператором (HMI). При помощи точек регулирования оператор может установить значения параметров, используемых при работе схемы.
Точка контроля является составной частью организации интерфейса контроллера с оператором (HMI). При помощи точек контроля оператор может просматривать значения сигналов в различных цепях схемы.
Сетевые переменные служат для обмена данными между контроллерами по информационной сети. В схеме могут быть определены входные и выходные сетевые переменные. Каждая сетевая переменная идентифицируется номером. Значение сигнала поданное на выходную сетевую переменную становится доступным через имеющие тот же номер входные сетевые переменные, описанные в схемах на других контроллерах, подключенных к единой информационной сети.
Пример простой схемы показан на рисунке:
Используемый алгоритм расчета содержит определенные ограничения:
- Элемент не может иметь более одного выхода
- Поддерживается только один тип данных (
tSignal
). Это относится ко всем входам и выходам всех элементов, значениям сигналов цепей, констант. Размерность типа данных определяется при компиляции проекта. Обычно используется тип целое число со знаком.
Один цикл вычисления схемы производится в ходе выполнения функции fbdDoStep()
. В ходе одного цикла производится расчет значений всех элементов схемы и установка значений всех сетевых переменных и выходных контактов. Время расчета зависит от множества факторов, в первую очередь от количества и типов используемых элементов в схеме. Результаты тестирования времени выполнения небольшой схемы из 10 элементов показаны в таблице:
CPU@Freq | Компилятор | Длительность цикла | Расчет одного элемента (среднее) |
[email protected] | xc8 v1.21 | ~5ms | ~500µs |
Si8051@48MHz | Keil C51 | ~2.5ms | ~250µs |
ARM920T@180MHz | gcc v4.1.2 | ~61µs | ~6.1µs |
STMF437@168MHz | Keil | ~31µs | ~3.1µs |
[email protected] | gcc v4.4.1 | ~279ns | ~27.9ns |
Элемент имеет один выходной контакт. Входов у элемента нет. Элемент является источником значения сигнала для других подключенных к нему элементов. В зависимости от настроек, элемент может выполнять четыре разные функции:
В этом случае у элемента имеется один параметр: номер контакта контроллера. Выходное значение сигнала элемента зависит от номера контакта и особенностей аппаратной реализации контроллера. Обычно используется для получения значений подключенных дискретных входов, датчиков температуры, давления, АЦП и т.п. Активное состояние дискретного входа (замкнут, подано напряжение) должно соответствовать значению сигнала "1".
В этом случае у элемента имеется один параметр: значение константы. Выходное значение сигнала элемента всегда соответствует значению параметра (константе).
Точка регулирования необходима для реализации возможности корректировки значений настроек, используемых при вычислении схемы. В отличие от константы, значение выходного сигнала элемента может быть изменено эксплуатирующим персоналом (или наладчиком) контроллера. Изменение значения точки регулирование может быть организовано через средства человеко-машинного интерфейса (HMI) контроллера (клавиатуру, индикатор и т.п.). Точка регулирования имеет 4 параметра: значение по умолчанию, минимальное значение, максимальное значение, текстовая строка с описанием.
Библиотека предусматривает возможность подключения контроллера в информационную сеть, которая объединяет несколько однотипных или разнородных контроллеров. Такая сеть может быть построена с использованием интерфейсов Ethernet, RS-485, CAN и т.п. Значение выходного сигнала соответствует значению, полученному от другого контроллера по информационной сети. У элемента есть два параметра: номер сетевой переменной и значение переменной "по умолчанию". Последние полученные по сети значения переменных сохраняются в NVRAM и доступны в дальнейшем при возникшей неисправности сети, в том числе после выключения и включения контроллера. Значение сетевой переменной "по умолчанию" используется после загрузки новой программы в контроллер до получения нового значения переменной из сети.
Элемент имеет один входной контакт. Выходов у элемента нет. В зависимости от настроек, элемент может выполнять две разные функции:
У элемента имеется один параметр: номер выходного контакта контроллера. Интерпретация входного значения зависит от особенностей аппаратной реализации на конкретном контроллере. Обычно используется для управления дискретными и аналоговыми выходами контроллера.
У элемента имеется один параметр: номер выходной сетевой переменной. Значение поданного на вход элемента сигнала передается по информационной сети и доступно на других контроллерах через элемент "Входная сетевая переменная". Не рекомендуется иметь в рамках одной схемы элементы "Входная сетевая переменная" и "Выходная сетевая переменная" с одинаковыми номерами.
Элемент выполняет функцию логической инверсии "NOT". Элемент имеет один вход и один выход. Таблица истинности:
Вход | Выходной сигнал |
Логический "0" | 1 |
Логическая "1" | 0 |
Элемент выполняет логическую функцию "И" ("AND"). Элемент имеет два входа и один выход. Элемент имеет настройку инвертирования выходного сигнала. Таблица истинности:
Вход 1 | Вход 2 | Выход | Инвертированный выход |
Логический "0" | Любое значение | 0 | 1 |
Any value | Логический "0" | 0 | 1 |
Логическая "1" | Логическая "1" | 1 | 0 |
Элемент выполняет логическую функцию "ИЛИ" ("OR"). Элемент имеет два входа и один выход. Элемент имеет настройку инвертирования выходного сигнала. Таблица истинности:
Вход 1 | Вход 2 | Выход | Инвертированный выход |
Логический "0" | Логический "0" | 0 | 1 |
Логическая "1" | Любое значение | 1 | 0 |
Любое значение | Логическая "1" | 1 | 0 |
Элемент выполняет логическую функцию "Исключающее ИЛИ" ("XOR"). Элемент имеет два входа и один выход. Элемент имеет настройку инвертирования выходного сигнала. Таблица истинности:
Вход 1 | Вход 2 | Выход | Инвертированный выход |
Логический "0" | Логический "0" | 0 | 1 |
Логический "0" | Логическая "1" | 1 | 0 |
Логическая "1" | Логический "0" | 1 | 0 |
Логическая "1" | Логическая "1" | 0 | 1 |
RS - триггер имеет два входа (R-Reset и S-Set) и один выход (Q).
RS - триггер, сохраняет своё предыдущее состояние при неактивном состоянии обоих входов (сигнал логического "0") и изменяет своё состояние при подаче на один из его входов сигнала логической "1". Пока на входы R и S подан сигнал логический "0", выход Q находится в неизменном состоянии. Если на вход S (Set) подать сигнал логическая "1", то сигнал на выходе Q принимает значение "1". Если на вход R (Reset) подать сигнал логическая "1", то сигнал на выходе Q принимает значение "0". При переводе сигнала на входе S или R в состояние логического "0", сигнал на выходе Q сохраняет своё предыдущее значение. При подаче на оба входа S и R сигнала логическая "1" состояние выхода Q не определено. Элемент имеет настройку инвертирования выходного сигнала.
Таблица истинности:
S | R | Qnext | Действие |
0 | 0 | Q | Хранение |
0 | 1 | 0 | Сброс |
1 | 0 | 1 | Установка |
1 | 1 | ? | Не разрешено |
Каждый раз, когда триггер изменяет своё состояние, новое значение сохраняется в энергонезависимой памяти NVRAM (путём вызова функции FBDsetProc(1, index, *value)
). При инициализации схемы, ранее сохранённые значения триггера восстанавливаются (путём вызова функции FBDgetProc(1, index)
).
D - триггер имеет два входа (D-Data и C-Clock) и один выход (Q).
D - триггер при положительном перепаде (нарастании) сигнала на входе C запоминает состояние входа D и выдаёт его на выход Q. При отсутствии положительного перепада на входе C, состояние выхода Q сохраняется постоянным.
Таблица истинности:
D | C | Qnext | Действие |
Любое значение | Нарастание | D | Запоминание |
Любое значение | Нет нарастания | Сохранённое значение D | Хранение |
В отличие от традиционных D - триггеров значения сигнала на входе D и выходе Q может принимать любое значение (не только "0" и "1").
Каждый раз, когда триггер изменяет своё состояние, новое значение сохраняется в энергонезависимой памяти NVRAM (путём вызова функции FBDsetProc(1, index, *value)
). При инициализации схемы, ранее сохранённые значения триггера восстанавливаются (путём вызова функции FBDgetProc(1, index)
).
Элемент имеет три входа и один выход. Если на вход R (Reset) подан сигнал логической "1", то сигнал на выходе Q принимает значение "0" (сброс счётчика). Если на вход R подан сигнал логического "0", то значение сигнала на выходе Q увеличивается на 1 при положительном перепаде на входе "+" или уменьшается на 1 при положительном перепаде на входе "-". При отсутствии положительного перепада на входах "+" и "-" значение сигнала на выходе Q не изменяется.
Таблица истинности:
+ | - | R | Qnext | Действие |
Любое значение | Любое значение | 1 | 0 | Сброс |
Нарастание | Нет нарастания | 0 | Q+1 | Увеличение на 1 |
Нет нарастания | Нарастание | 0 | Q-1 | Уменьшение на 1 |
Нет нарастания | Нет нарастания | 0 | Q | Нет изменений |
Нарастание | Нарастание | 0 | Q | Нет изменений |
Каждый раз, когда счётчик изменяет своё состояние, новое значение сохраняется в энергонезависимой памяти NVRAM (путём вызова функции FBDsetProc(1, index, *value)
). При инициализации схемы, ранее сохранённые значения счётчика восстанавливаются (путём вызова функции FBDgetProc(1, index)
).
Элемент имеет два входа и один выход. Значение выходного сигнала вычисляется, как арифметическая сумма значений сигналов на входах.
Элемент имеет два входа и один выход. Значение выходного сигнала вычисляется, как арифметическая разность сигнала на первом (уменьшаемое) и на втором (вычитаемое) входах.
Элемент имеет два входа и один выход. Значение выходного сигнала вычисляется, как арифметическое произведение сигналов на первом и втором входах.
Элемент имеет два входа и один выход. Значение выходного сигнала вычисляется, как арифметическое деление значения сигнала на первом входе (делимое) на значение сигнала на втором входе (делитель).
Особые случаи:
Вход 1 | Вход 2 | Выход |
0 | 0 | 1 |
Любое положительное значение | 0 | MAX_SIGNAL |
Любое отрицательное значение | 0 | MIN_SIGNAL |
О том, что делить на 0 нельзя я знаю. :-)
Элемент имеет один вход и один выход. Значение выходного сигнала есть абсолютное значение сигнала на входе.
Побитовое «И» — это бинарная операция, действие которой эквивалентно применению логического «И» к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях значений входных сигналов. Другими словами, если оба соответствующих бита значений входных сигналов равны 1, результирующий двоичный разряд равен 1; если же хотя бы один бит из пары равен 0, результирующий двоичный разряд равен 0.
Побитовое «ИЛИ» — это бинарная операция, действие которой эквивалентно применению логического «ИЛИ» к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях значений входных сигналов. Другими словами, если оба соответствующих бита значений входных сигналов равны 0, двоичный разряд результата равен 0; если же хотя бы один бит из пары равен 1, двоичный разряд результата равен 1.
Исключающее« ИЛИ» (сложение по модулю 2) — это бинарная операция, результат действия которой равен 1, если число складываемых единичных битов нечётно и равен 0, если чётно. Другими словами, если оба соответствующих бита значений входных сигналов равны между собой, двоичный разряд результата равен 0; в противном случае, двоичный разряд результата равен 1.
Элемент имеет четыре входа и один выход. Входы:
- U - текущее значение контролируемого процесса (обратная связь)
- REF - значение, которое должно быть достигнуто в процессе регулирования (уставка)
- DT - время реакции регулятора (мс)
- P - коэффициент пропорциональности
Выход Q - сигнал влияния на регулируемый процесс.
В отличие от множества других подобных реализаций, данный элемент не использует традиционный алгоритм PID регулирования. Вместо этого применен алгоритм Эйлера-Лагранжа, обеспечивающий простоту настройки, высокую скорость сходимости и отсутствие склонности к возникновению колебаний. Данный алгоритм широко используется при стыковке космических аппаратов. Подробности можно узнать из специальной литературы, на сайте проекта Wikipedia имеется статья, которая поясняет некоторые моменты алгоритма.
Подробности реализации можно увидеть в исходном коде и примерах.
Элемент используется для интегрирования (суммирования) во времени значения входного сигнала. Элемент часто используется совместно с описанным выше регулятором. Элемент имеет три входа и один выход. Входы:
- X - интегрируемый сигнал
- DT - время интегрирования (мс)
- Lim - ограничение значения выходного сигнала
Выход Q - значение величины интеграла (суммы).
Каждый интервал времени DT значение входного сигнала X складывается с текущим накопленным значением. Если новое значение больше значения Lim или меньше значения -Lim, то результат ограничивается значением Lim или -Lim. Сигнал на выходе Q принимает значение результата.
TON - это таймер с задержкой включения. Элемент может быть использован в генераторах периодических сигналов и счетчиках времени. Элемент имеет два входа и один выход:
- D - запуск таймера
- T - величина задержки (мс)
- Q - выходной логический сигнал
Если на входе D присутствует сигнал логического "0", то на выходе Q всегда сигнал "0". Если на вход D подать сигнал логической "1", то на выходе Q появится сигнал "1" через промежуток времени, соответствующий сигналу на входе T. Элемент имеет настройку, инвертирующую значение выходного сигнала.
Таблица истинности:
D | Условие | Выход | Инвертированный выход |
Логический "0" | Любое | 0 | 1 |
Логическая "1" | Время T не истекло | 0 | 1 |
Логическая "1" | Время T истекло | 1 | 0 |
Временная диаграмма таймера TON:
Элемент имеет два входа и выход:
- D - запуск таймера
- T - время задержки (мс)
- Q - выход
Положительный фронт сигнала на входе D запускает таймер и устанавливает на выходе Q значение сигнала "1". По истечении времени T значение выходного сигнала принимает значение "0". Элемент имеет настройку, инвертирующую значение выходного сигнала.
Временная диаграмма таймера TP:
Генератор может быть использован для формирования периодических сигналов различной формы. Элемент имеет два входа и выход:
- A - амплитуда формируемого сигнала
- T - период последовательности (мс)
- Q - выход
Если на входе T присутствует значение сигнала меньшее или равное "0", то генератор остановлен и на его выходе Q формируется сигнал со значением "0". При положительном значении сигнала на входе T генератор формирует на выходе Q периодический сигнал с амплитудой A и периодом T. В зависимости от настройки элемента, выполненной при проектировании схемы, форма сигнала может быть следующих видов:
- Прямоугольные импульсы (меандр со значениями сигнала "0" и "A")
- Пилообразный сигнал (сигнал с линейно нарастающим значением и последующим сбросом в "0")
- Импульсы треугольной формы
- Синусоидальный сигнал
Значение сигнала на выходе Q лежит в диапазоне от "0" до "A" для генераторов меандра, пилообразных и треугольных импульсов. Для генератора синусоидального сигнала выход Q принимает значение от "-A" до "A".
Степень достоверности формы выходного сигнала генератора зависит от соотношения заданного периода сигнала и времени выполнения расчета схемы. Рекомендуется устанавливать значение периода T большим, чем время расчета одного шага схемы умноженное на коэффициент 15-20. В противном случае форма выходного сигнала генератора может значительно отличаться от требуемой.
Элемент имеет два входа и выход, выполняет сравнение значений сигналов на входах 1 и 2. Элемент имеет настройку, инвертирующую значение выходного сигнала. Таблица истинности:
Условие | Выход | Инвертированный выход |
Input1Val > Input2Val | 1 | 0 |
Input1Val <= Input2Val | 0 | 1 |
Элемент имеет два входа и выход. Выходное значение сигнала соответствует входному сигналу с максимальным значением. Таблица истинности:
Условие | Выход |
Input1Val > Input2Val | Input1Val |
Input1Val <= Input2Val | Input2Val |
Элемент имеет два входа и выход. Выходное значение сигнала соответствует входному сигналу с минимальным значением. Таблица истинности:
Условие | Выход |
Input1Val > Input2Val | Input2Val |
Input1Val <= Input2Val | Input1Val |
Расширяемый мультиплексор. Элемент имеет пять входов (D0-D3, A) и один выход. Значение выходного сигнала соответствует значению сигнала на выбранном входе D0-D3. Выбор выхода производится на основании значения сигнала на входе A. Таблица истинности:
A | Выход Q |
0 | D0 |
1 | D1 |
2 | D2 |
3 | D3 |
Ограничитель сигнала имеет 3 входа и один выход:
- D - входной сигнал
- MX - верхнее ограничение сигнала
- MN - нижнее ограничение сигнала
Выходное значение сигнала элемента соответствует входному значению ограниченному значениями сигналов на входах MX (верхнее ограничение) и MN (нижнее ограничение).
Установка библиотеки заключается в копировании файлов fbdrt.h
и fbdrt.c
в свой проект. Настройка состоит в редактировании файла fbdrt.h
в соответствии со своими требованиями.
Вы можете изменить следующие определения в файле fbdrt.h
:
- Выберите тип данных, используемый для хранения значений сигналов.
- Выберите тип данных используемый для индекса элементов.
- Если необходимо измените определения
ROM_CONST
иDESCR_MEM
. - Выберите необходимость использования оптимизации по скорости выполнения (определение
SPEED_OPT
). - Выберите необходимость использования функций HMI (определение
USE_HMI
). - Напишите свою реализацию функций
FBDgetProc()
иFBDsetProc()
. - Если вы используете экраны HMI напишите свою реализацию функций
FBDdrawXXXXXX()
.
От выбора типа данных для хранения сигналов зависит то, сигналы каких значений сможет обрабатывать ваша схема. Кроме того, от этого выбора
зависят объем программы и объем используемой ею памяти и скорость расчета схемы. Для небольших встариваемых микроконтроллеров это может быть важным. В общем случае тип данных должен обеспечивать хранение целого числа со знаком. Если вы не уверены в выборе, то рекомендую остановиться на
значении "по умолчанию": 32-х битное целое число со знаком. Выбор типа производится установкой значения определения SIGNAL_SIZE
:
// размер памяти для сигнала схемы (1, 2 или 4)
#define SIGNAL_SIZE 4
Выбор типа данных для индекса элемента определяет как много элементов может быть в вашей схеме. Тип данных должен обеспечивать возможность хранения целых чисел без знака. Выбор типа производится установкой значения определения INDEX_SIZE
. Рекомендуем остановить свой выбор на значении "по умолчанию" 2, в этом случае в вашей схеме может быть до 65535 элементов.
// размер пямяти для индекса элемента (1 или 2)
#define INDEX_SIZE 2
Определения ROM_CONST
и DESCR_MEM
используются для описания памяти в которой размещаются константы и массив описания схемы соответственно. Значения зависят от используемого вами компилятора. Для примера, при использовании компилятора xc8 (Microchip) и размещении данных в памяти FLASH необходимо использовать const
:
// data in ROM/FLASH
#define ROM_CONST const
// schema description
#define DESCR_MEM const
Использование определения SPEED_OPT
уменьшает время расчета схемы примерно в 6 раз(для средних и больших схем), объем необходимой памяти RAM при этом увеличивается примерно в 3 раза. Когда вы включаете определение SPEED_OPT
, то в момент инициализации производится предварительный расчет некоторых таблиц с указателями, использование которых уменьшает время расчета схемы.
Определение USE_HMI
необходимо в случае, когда ваш PLC содержит средства организации интрерфейса с человеком. Такими средствами могут быть например экран и кнопки. Будьте внимательны: если вы отключите HMI точки управления будут возвращать неопределенные данные! Пример:
// needed if you use HMI functions
#define USE_HMI
// speed optimization reduces the calculation time, but increases the size of memory (RAM) required
#define SPEED_OPT
Если вы установили USE_HMI
, то дополнительно необходимо указать разрешение экране вашего контроллера в определениях:
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
Функции FBDgetProc()
и FBDsetProc()
служат для связи схемы с реальными входами и выходами вашего PLC.
Функция FBDgetProc()
используется для чтения состояния входных сигналов (контактов) или значений, сохраненных в памяти NVRAM.
Функция FBDsetProc()
используется для записии значений выходных сигналов (контактов) или для сохранения значений в память NVRAM.
Реализация этих функций зависит от специфики ваших задач. В общем случае рекомендуем придерживаться следующих правил:
- Для дискретных входов и выходов использовать значения
0
и1
. При этом значение0
должно соответствовать пассивному состоянию: выключен, разомкнут и т.п. - Для аналоговых входов и выходов значения которых представлены в инженерных единицах измерения (градусы, бары, вольты) необходимо использовать множитель, который преобразует эти значения в целые числа. Например для входа к которому подключен датчик температуры можно использовать множитель 100, который преобразует значение температуры на датчике +10.5 C в значение сигнала схемы 1050.
Не используйте прямую запись в EEPROM при каждом вызове FBDsetProc()
: библиотека далает такие вызовы при каждом изменении состяния тригеров, таймеров и генератора. Частая запись в EEPROM может значительно сократить срок ее службы. Решением может быть отложенная запись или использование памяти RAM с питанием от батарейки.
tSignal FBDgetProc(char type, tSignal index)
{
switch(type) {
case 0:
printf(" request InputPin(%d)\n", index);
return 0;
case 1:
printf(" request NVRAM(%d)\n", index);
return 0;
}
}
void FBDsetProc(char type, tSignal index, tSignal *value)
{
switch(type)
{
case 0:
printf(" set OutputPin(%d) to value %d\n", index, *value);
break;
case 1:
printf(" set NVRAM(%d) to value %d\n", index, *value);
break;
}
}
Инициализация схемы должна быть выполнена один раз в начале работы. Инициализация можут быть выполнена повторно для сброса состояния схемы. Для инициализации схемы необходимо выполнить вызов функции:
int fbdInit(DESCR_MEM unsigned char *descr)
descr - указатель на массив описания схемы.
Отрицательное значение результата функции означает ошибку:
-1 - неверный код элемента в описании схемы;
-2 - несовпадение размерности сигнала или элемента;
-3 - массив описания содержит схему с неподдерживаемой версией;
-4 - ошибка при проверке контрольной суммы описания схемы.
Положительное значение результата функции - требуемый объем RAM для выполнения схемы.
Если вызов инициализаии схемы выполнен без ошибок и вы имеете необходимый объем RAM, то следующим шагом необходимо выполнить вызов инициализации памяти:
void fbdSetMemory(char *buf, bool needReset)
buf - указатель на буфер памяти, размер буфера должен быть не меньше величины, которую вернул вызов функции fbdInit()
;
needReset - необходимость сброса содержимого EEPROM.
Параметр needReset должен быть установлен в значение TRUE
после записи в контроллер новой схемы. При этом значения всех элементов с "пямятью" (точек регулирования, тригеров и генероаторов) сбрасываются в состояние "по умолчанию".
После инициализации памяти схема готова к работе.
Для вычисления схемы необходимо периодически (например в главном цикле программы) выполнять функцию:
void fbdDoStep(tSignal period)
period - время, прошедшее с момента предыдущего вызова функции, при первом вызове необходимо указать значение 0.
В результате каждого вызова функции выполняется вычисление всех элементов схемы и производится установка всех выходных контактов и переменных.
Некоторые элементы схемы используют значение времени или временных интервалов. К таким элементам относятся генератор, таймер, интегратор сигнала, регулятор. Для каждого элемента библиотека организует независимый таймер, значение которого хранится в RAM. Для хранения значения таймера используется тип tSignal
.
Timer values changes by period
every time the function fbdDoStep(tSignal period)
is called. Time can be expressed in any units: sec, ms, µs. Unit selection depends on the time scale in which the PLC should work. In my opinion, a decent selection of milliseconds for most cases.
The library contains basic functions support HMI. This can be used if your PLC has a display (LCD). You can make character or graphical menu with which to perform the following functions:
- View values of schema points (
Watchpoints
) - Set the values of set points (
Setpoints
)
Watchpoints is used to display the values of the signals for operator. Setpoints are used to set the reference values, used in the operation of the circuit. Each watchpoint and setpoint has the associated text caption, that can be displayed on LCD. Moreover, for setpoints are stored maximum and minimum values of the signal that it can receive.
To get the value of the watchpoint, use the function:
bool fbdHMIGetWP(tSignal index, tHMIdata *pnt);
// index - number of watchpoint (0..watch points count-1)
// pnt - pointer to data struct:
typedef struct {
tSignal value; // current point value
tSignal lowlimit; // low limit for value (only for setpoints)
tSignal upperLimit; // upper limit for value (only for setpoints)
DESCR_MEM char *caption; // pointer to text caption (asciiz)
} tHMIdata;
If the point exists, the function returns true
and the data in the structure of pnt
, otherwise the function returns a value false
. Items lowlimit
and upperlimit
not used.
To get the value of the setpoint, use the function:
bool fbdHMIGetSP(tSignal index, tHMIdata *pnt);
// index - number of setpoint (0..set points count-1)
// pnt - pointer to data structure
If the point exists, the function returns true
and the data in the structure of pnt
, otherwise the function returns a value false
. Watchpoints and setpoints numbering starts with 0.
To set the new setpoint value, use the function:
void fbdHMISetSP(tSignal index, tSignal value);
// index - number of setpoint (0..set points count-1)
// value - new value of setpoint
Это работает. Библиотека используется в некоторых "боевых" проектах и не содержит известных автору проблем.
Дальнейшие планы:
- оптимизация скорости выполнения
- доработка документации
- Modbus-Master
- Alarms
- журнал событий
Алексей Лутовинин -- [email protected]