Здравствуйте, коллеги. Сегодня мы с вами познакомимся с организацией работы при ограниченных ресурсах. Рассмотрим что такое "Очередь" как она работает, реализуем пару вариантов очередей, затронем динамическое выделение памяти в ПЛК.
Я пишу эту статью и программирую в режиме реального времени, т.е. у меня есть задача и я ее решаю. Все свои мысли и попытки(за исключением очень глупых) я записываю в эту статью так что приятного чтения.
ТЕОРИЯ
Очередь - это абстрактный тип данных, в котором доступ организуется по принципу FIFO(first in, first out) - первый пришел, первый ушел. Имеет два метода: добавить в очередь и достать из очереди. Данные которые мы достали из очереди - удаляются.
Согласно теории есть два метода реализации - массивом и односвязным списком. В большинстве ПЛК второй способ невозможен, но в Codesys 3 можно чуть чуть поиграть с динамическим выделением памяти.
РЕАЛИЗАЦИЯ
Реализация для одного типа
Начнем с малого. Реализуем очередь для одного типа данных. Например, мы будем вырезать отверстия. По нужным координатам нужного диаметра.
Создадим необходимый DUT
В структуре у нас хранятся координаты по X,Y и диаметр отверстия.
Основа FB
Теперь организуем список необходимых операций, которые нам понадобятся. Всего их три: Ожидание, Добавить элемент, Достать элемент. Для такого типа операций я использую перечисление и CASE в реализации. Мне просто так удобнее. Можно с помощью флагов, триггеров, IF'ов, но я делаю так.
Теперь работаем с FB. Пытаемся уместить все в одном месте. Нам потребуется на вход:
- Указатель на Глобальный UDT для чтения
- Указатель на UDT куда будем писать.
(*тут я думаю как сделать команды*)
3. Команды управления
На выход у нас получается:
- Сигнал об успешной записи в очередь
- Сигнал об успешном чтении из очереди
- Очередь пустая
- Очередь полная
- В работе
Пункты 3 и 4 можно объединить в ошибку и сделать какой-нибудь код для нее, но я не буду.
Под капотом:
- Массив элементов( для теста 10)
- Индекс старта
- Индекс окончания
Логика работы
Логика легка и проста. читаем из элемента под индексом iStart. Считали прибавили 1. Записываем в индекс iEnd. Записали прибавили единицу.
Дошли до конца, скинули счетчик. Пошли по кругу. Всего может быть 10 элементов. Если индексы пересекаются, то это неопределенность. Либо очередь полная, либо пустая. Так что этот вопрос придется контролировать.
ДОБАВЛЕНИЕ/ИСПРАВЛЕНИЕ
При старте реализации было обнаружено, что значения пустой и полной очереди необходимо обрабатывать внутри кода. Есть два три выхода: переносим в In_Out, переносим указателями в In, создаем в области VAR и во время WAIT копируем значения.
Я выбираю третий вариант с дублированием.
Добавил в Output переменную Error.
ИТОГ
Как же неудобно тут вставлять что-то связанное с кодом.
Вот тут лежит PDF файл с кодом. Можно ознакомится и скопировать.
Ну и демонстрация работы...
Тут немного видео(рубрика эксперименты)
А в следующий раз мы расскажем как сделать очередь для любых типов данных
Подпишись, ставь лайк, вопросы в комментарии или на почту info@engcore.ru