Sudak91

На Пикабу
Дата рождения: 23 октября
224 рейтинг 11 подписчиков 30 подписок 7 постов 0 в горячем
Награды:
5 лет на Пикабу За исследование параллельных миров
13

Codesys 3. Очередь для ПЛК

Здравствуйте, коллеги. Сегодня мы с вами познакомимся с организацией работы при ограниченных ресурсах. Рассмотрим что такое "Очередь" как она работает, реализуем пару вариантов очередей, затронем динамическое выделение памяти в ПЛК.

Я пишу эту статью и программирую в режиме реального времени, т.е. у меня есть задача и я ее решаю. Все свои мысли и попытки(за исключением очень глупых) я записываю в эту статью так что приятного чтения.

ТЕОРИЯ

Очередь - это абстрактный тип данных, в котором доступ организуется по принципу FIFO(first in, first out) - первый пришел, первый ушел. Имеет два метода: добавить в очередь и достать из очереди. Данные которые мы достали из очереди - удаляются.

Согласно теории есть два метода реализации - массивом и односвязным списком. В большинстве ПЛК второй способ невозможен.

РЕАЛИЗАЦИЯ

Начнем с малого. Реализуем очередь для одного типа данных. Например, мы будем вырезать отверстия. По нужным координатам нужного диаметра.

Создадим необходимы  DUT. В структуре у нас хранятся координаты по X,Y и диаметр отверстия.

Теперь организуем список необходимых операций, которые нам понадобятся. Всего их три: Ожидание, Добавить элемент, Достать элемент. Для такого типа операций я использую перечисление и CASE в реализации. Мне просто так удобнее. Можно с помощью флагов, триггеров, IF'ов, но я делаю так.

Теперь работаем с FB. Пытаемся уместить все в одном месте. Нам потребуется на вход:

1) Указатель на Глобальный UDT для чтения

2) Указатель на UDT куда будем писать.

(*тут я думаю как сделать команды*)

3) Команды управления

На выход у нас получается:

1) Сигнал об успешной записи в очередь

2) Сигнал об успешном чтении из очереди

3) Очередь пустая

4) Очередь полная

5) В работе

Пункты 3 и 4 можно объединить в ошибку и сделать какой-нибудь код для нее, но я не буду.

Под капотом:

1) Массив элементов( для теста 10)

2) Индекс старта

3) Индекс окончания

ЛОГИКА РАБОТЫ

Логика легка и проста. читаем из элемента под индексом iStart. Считали прибавили 1. Записываем в индекс iEnd. Записали прибавили единицу.

Дошли до конца, скинули счетчик. Пошли по кругу. Всего может быть 10 элементов. Если индексы пересекаются, то это неопределенность. Либо очередь полная, либо пустая. Так что этот вопрос продеться контролировать.


ДОБАВЛЕНИЕ/ИСПРАВЛЕНИЕ

При старте реализации было обнаружено, что значения пустой и полной очереди необходимо обрабатывать внутри кода. Есть два три выхода: переносим в In_Out, переносим указателями в In, создаем в области VAR и во время WAIT копируем значения.

Я выбираю третий вариант с дублированием.

Добавил в Output переменную Error.


ИТОГ

Я опять пожалуюсь, что вставлять и сюда код очень проблематично так что ссылка на PDF документ на Яндекс.Диск с листингом.

Ну и небольшая видео демонстрация как там все происходит. 

Спасибо за внимание. Если что стучите в комментарии, если что-то очень личное, то на почту info@engcore.ru.

Показать полностью 3 1
3

S7-1500. ANY_DB

Ааааааааааа.... Несколько дней прошло с зудящей мыслью, а что это за фрукт такой ANY_DB. И вот наконец-то теоретическое послание о том что такое ANY_DB и попытки разобраться, а зачем он нужен(я так и не понял, но об этом после).

Немного неофициальной теории

В целом это еще один инструмент для унификации процессов и написании мега универсальных ФБ. Особенность того, что ANY_DB хранит номер DB и может быть использован до того как мы создали дб. В ANY_DB хранится номер любой БД(Ох если все было так просто).

Вы не сможете записать в параметр ANY_DB DB с резервированием памяти

И так что мы можем точно писать в ANY_DB:

1)Экземпляры UDT и системных типов

2)Экземпляры FB

3)DB которые были созданы как массив.

Из этого списка пункты 1 и 3 имеют возможность конвертирования в Variant. В целом есть две команды:

VARIANT_TO_DB_ANY

DB_ANY_TO_VARIANT

И больше с этим типом данных нельзя сделать НИ-ЧЕ-ГО!

Как ANY_DB в VARIANT превратить и что с этим дальше делать.

В целом после столь скудной теоретической части давайте фантазировать.

ANY_DB мы можем конdертить в variant.

А дальше там скармливать что хочешь и куда хочешь, у нас же есть REF_TO и ?=

В коде это будет выглядеть следующим образом:

Ну и если подняться выше, то можно узнать, что на вход ANY_DB я подаю Data_Block_2

Тут для закрепления требуется какая-то задачка, но на ум пока ничего толкового не приходит. Разве что какая-то фантастическая сборная линия с тремя операциями по координатам. Но если вдруг у вас появились идеи как это куда-то приделать или вы использовали где-то, то пожалуйста, поделитесь информацией.

Показать полностью 3
8

S7-1500, Группа Pointers, References

Появилось желание потыкать более подробно ПЛК 1500 серии от Siemens. И немного разобрать что там интересного есть, как с этим работать и понять для чего это надо. И первыми под небольшой обзор попала такая группа данных как pointer(указатель), которых в s7-1500 аж 4 вида. Сейчас хочу быстро пробежимся по каждому и немного поработать с References

Типы данных в ПЛК.
Начнем с теории. Типы данных - определяют свойства данных, например, размер в памяти или их представление. У Siemens есть:
Элементарные типы данных(bool, int, real, char)
Сложные типы данных (DT, String, Array, Struct)
UDT - типы определяемые пользователем
УКАЗАТЕЛЬ
Тип параметров
Системные типы данных
Типы данных оборудования
Ну и если с верхней частью списка все более менее понятно, исходя из начальных уроков по программированию. То где-то с указателей начинается магия. Однако все не так просто.
Немного об оптимизированном доступе

У контроллеров S7-1200/1500 имеется возможность оптимизированного
хранения данных. В оптимизированных блоках, все теги автоматически
сортируются по их типу данных. Данный метод позволяет минимизировать
промежутки между тегами, таким образом такие теги оптимизированы по
времени доступа для процессора.
(c)Базовое системное руководство  11/2015Руководство по программированию
S7-1200/S7-1500
И теперь если просто, то в оптимизированном блоке нет доступа по адресу. Там происходит магия, данные сортируются так как надо, теперь тебе не надо играть в тетрис, когда у тебя все бинарные значения должны быть в конце. Но от этого мы получаем новые виды указателей.

УКАЗАТЕЛИ
В данную группу входят следующие ребята:
- References
- VARIANT
- POINTER
- ANY
Для наглядности где какие указатели могут быть использованы вне 1500 контроллеров ловите табличку.

References
References - это тэг, который указывает на область памяти. вы указываете тип данных, на который он ссылается, является безопасным по типу. Гарантируется, что либо она принадлежит к конкретному типу данных, либо ей присваивается NULL.
References у нас указывают только на конкретный тип и могут быть прочитаны или записаны через разыменовывание. ТОЛЬКО ДЛЯ ОПТИМИЗИРОВАННЫХ БЛОКОВ,
VARIANT
Это тэг, который указывает на различные типы данных, но не может указывать на экземпляры. Операнд типа данных VARIANT не занимает места в блоке данных экземпляра или в рабочей памяти. Однако он будет занимать место в памяти ЦП.

Тег типа VARIANT - это не объект, а ссылка на другой объект. Отдельные элементы типа VARIANT могут быть объявлены только для формальных параметров в блочном интерфейсе функции в разделах VAR_IN, VAR_IN_OUT и VAR_TEMP. По этой причине его нельзя объявить в блоке данных или в статическом разделе интерфейса блока функционального блока, например, потому что его размер неизвестен. Размер объектов, на которые имеются ссылки, может измениться.
(с) Перевод гуглом справки от Сименса
Ну и много других вещей. Вот тут уже можно себе выстрелить немножко в ножку, но радует, что мы не можем просто читать и записывать Variant.
POINTER
Еще указатель. Занимает 6 байтов. Может хранить данные о тэге.
1)Номер DB
2)Память в ЦПУ
3)Адрес тэга
Работает лишь со стандартным доступом, не работает с оптимизированным. Ну и еще область определения. В функциях - это InOut, а в функциональных блоках - это везде за исключением TEMP, а UDT - только InOut
ANY
Указывает на начало области данных и содержит ее длину. Занимает 10 байт памяти.
Может содержать:
1)Тип данных элементов
2)Количество элементов
3)Номер БД
4)Область памяти ЦП, в которой хранятся элементы
5)Начальный адрес данных в формате «байт.бит»

ПРАКТИКА
Начнем с референсов)) Объявить данный тип мы можем в FC,FB,OB, но в разных частях интерфейса
- FC: Input, Output, Temp, Return
- FB: Temp
- OB: Temp
Объявление происходит конструкцией REF_TO, присваивание значений командой REF();

А дальше мы пойдем немного усложнять задачи. И чуток поработаем в связке VARIAN и REF. Придумаем себе несуществующую задачу, которая гласит, что у нас есть функция, на вход которой могут подаваться различные UDT.
В нашем случае следующего вида:

И нам надо записать туда значения. в случае udt_2pointж 5.0, а в случае udt_3point -4.

Из всего что написано выше, что стоит понять функция TypeOf - возвращает тип тэга Variant.
Конструкция ?= пытается присвоить REF тэг Variant. Так как это слегка удобнее. Если присвоение провалилось, то тэг REF будет NULL.

Теперь на вход подаем udt_2point.

Тут должен быть примерно какой-то вывод, но в целом даже подобную конструкцию можно использовать для создания какого-нибудь максимально универсального блока с проверкой типов данных и относительной безопасностью.

Показать полностью 9
9

ООП для ПЛК. Codesys и "Стратегия"

Стратегия — это поведенческий паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.
Вот такое определение мы скопируем и вставим, чтобы начать наше повествование. И уже после прочтения определения закрадывается мысль, а как на ПЛК можно в ООП? По факту легко. И очень много подобных паттернов можно переложить на рельсы промышленного программирования.

Для реализации этого безумства нам потребуется Codesys 3.x ибо он немного, да научился в ООП.

Что нам предлагают умные статьи в интернетах?

Паттерн Стратегия предлагает определить семейство схожих алгоритмов, которые часто изменяются или расширяются, и вынести их в собственные классы, называемые стратегиями .
Вместо того, чтобы изначальный класс сам выполнял тот или иной алгоритм, он будет играть роль контекста, ссылаясь на одну из стратегий и делегируя ей выполнение работы. Чтобы сменить алгоритм, вам будет достаточно подставить в контекст другой объект-стратегию.
Важно, чтобы все стратегии имели общий интерфейс. Используя этот интерфейс, контекст будет независимым от конкретных классов стратегий. С другой стороны, вы сможете изменять и добавлять новые виды алгоритмов, не трогая код контекста.

ИНТЕРФЕЙС

Интерфейс, согласно документации Codesys,- это средство объектно-ориентированного программирования. Объект ITF("Интерфейс") описывает набор прототипов методов и свойств. В этом контексте прототип означает, что методы и свойства содержат только объявления и не содержат реализации.

Это значит, что в интерфейсе мы описываем методы. Даем им имена, перечень входных и выходных данных, но никак не трогаем реализацию.

Для создания интерфейса жмем ПКМ->Добавление объекта->Интерфейс, далее задаем ему имя. У меня это будет "StrategyInt".

Затем добавляем метод. Назовем его GetSTR. Для добавления также правая кнопка мыши и добавить метод интерфейса.

Прописываем там лишь одну выходную переменную.

Контекст

Это тот функциональный блок, который и будет у нас вызывать различные "стратегии".

Создаем обычный функциональный блок.

На вход функционального блока мы можем отправить любой объект, который будет унаследован от интерфейса StrategyInt. В реализации мы видим. что при вызове данного функционального блока, мы будем взывать метод GetSTR,а результат возвращать в выходную переменную Result.

Стратегии

Следующий шаг - реализация стратегий. Для начала сделаем две. Они не будет ничем отличаться кроме как возвращать разные значения.

Создаем функциональный блок и наследуем его от нашего интерфейса.

Имя можете указать любое, у меня просто кончилась фантазия.

Я создал два таких блока, которые и будут играть роль наших стратегий.

СБОРКА

Я тут немного разбил по шагам. Для реализации нам понадобится. Объект, который играет роль контекста - 1 шт. Наши стратегии. Тут я их включил в блок переменных, но можно и сделать указатель на объект нужной нам стратегии, а уже в коде создать через __NEW.

Ну и переменные Out_1 и Out_2 для наглядности.

Код работаем следующим образом. На первом шаге мы даем на вход MyProc переменной Object нашу стратеги POU_1. Затем происходит вызов контекста и он отрабатывает, записывая результат своей работы в переменную Out_1.

Затем мы даем на вход того же контекста стратегию POU_2, с последующим выводом, результат пишется в переменную Out_2.

Включаем эмуляцию.

Таким образом можно разносить логику работы объектов, которые похожи, но немного отличаются в реализации. Возврат строковой переменой тут просто для примера)

Показать полностью 8
5

Страх быть непринятым и ненужный элитаризм

В большей степени - это лишь размышления. Сразу хочу заметить, что мои высказывания относятся не ко всем и не всегда, скорее всего, это просто моя интерпретация того, что я вижу.

Как часто вы замечали в постах приписки: "это мой первый раз", "чукча - не писатель, а читатель", "сильно не ругайте" и прочее. Народ заранее оправдывается за что-то и просят проявить какую-то неведомую публику о нисхождении. Совершать ошибки при написании - грех? Да большая часть правил русского языка выходит из головы после написания экзаменов, а дальше мозг в целом удаляет ненужное. И тут хочется заметить, что мало кто пишет профессионально. Я не о рабочей переписке, а вот прям просто пишет. Также, как я понимаю, народ боится критики своих работ, творений или даже мыслей, словно сообщество по интересам -  самый важный ваш экзаменатор в жизни. Очень небольшая группа людей делает ради удовольствия.

И вот благодаря таким страхам у нас появляется никому не нужный элитаризм. Вы их видели. Великие комментаторы со своим мнением, которое подходи абсолютно ко всему. Особенно это развито в каких-то профессиональных средах. Человек просит совета по какой-либо проблеме. Причины такого вопроса разная. От желания научиться до простого увеличения кругозора. И вот тут появляются наши товарищи, которые считают что и вопрос глупый, да и гугл никто не отменял, да и зачем ты вообще сюда лезешь ведь есть специалисты. Такой подход способен отбить любое желание как в профессиональном развитии, так и в творчестве. И ведь все забывают какими были неофитами.

Товарищи, которые делятся своим творчеством, задают вопросы и просто пишут посты на волнующие темы - продолжайте. Не спорьте с людьми в комментариях, так как это, скорее всего, срач ради срача. Делайте то что считаете нужным, да и будет вам счастье. А все кто пытается показаться представителем элитных масс, вбрасывая свои пассивно агрессивные реплаи, прошу сходить к психологам и проработать данную проблему.

Показать полностью
9

Ответ на пост «Программирование ПЛК. Ожидание/реальность»1

Ох.... Ну и написали же тут. В целом, здрасьте. Я являюсь программистом АСУ и пишу код для этих ПЛК уже лет 6 так. В основе работают с Siemens.

И так.

1)ООП. Оно есть. Как так спросите вы? Да легко и просто. ООП - это объектно-ориентированное программирование. И мы тут и делаем что управляем объектами. У нас есть такие вещи как UDT(user data type) - что в целом и представляет собой структуру с параметрами объекта.

И мы такие умные пишем, что у нас есть какой нибудь var1, который является объектом типа UDT. Дальше мы инициализируем параметры этого объекта.

FC - она же функция. Ну тут и говорить нечего. обычная функция. с входными и выходными значениями. Служит для того для чего и служит. FB - является сборником этих функций и имеет свое место в памяти. Кстати. Можно также FC закидать в другой FC. Он у нас и обрабатывает логику и закидывает данные в нужный объект.

Можно ли ограничить видимость данных? Да, но... Скажем везде есть это НО.

Шо там дальше у нас... Наследование? А вот этот пункт я не разбирал. в CodeSys вроде есть подобные вещи.



2)Массивы и циклы.

Массивы - есть. Данные-хранят. Хочешь в энергозависимой памяти, хочешь в энергонезависимой памяти. Делаются, заполняются. Почему же массив не передается сразу всей кучей на визуализацию? А тут уже работают протоколы передачи данных. Но мы можем передавать массив из 8 элементов в 8 переменных.

Циклы есть и работают. Только стоит помнить о пороговых значениях.

Также есть циклические блоки, которые нам выдадут ответ не реже чем раз в столько-то миллисекунд. И есть один общий цикл( считай main). Единственное, так это надо следить за временем исполнения.

Есть и прерывания, правда они в основном сделаны для обработки ошибок. Иначе контролер уйдет в стоп. прерывания можешь обрабатывать, а можешь нет.

Вся суть ПЛК состоит в том, что мы получаем отклик за точное время. По большей степени это все конечные автоматы. И подход там немного другой, нежели в обычном ПО.

Так что если есть вопросы, спрашивайте. Если знаю - отвечу, если нет - буду узнавать)

Показать полностью
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества