Часть 3, каркас архитектуры / программирование :: длиннопост :: реактор образовательный :: АСУ ТП :: geek (Прикольные гаджеты. Научный, инженерный и айтишный юмор)

песочница АСУ ТП программирование geek реактор образовательный длиннопост 

Часть 3, каркас архитектуры

Часть 1, введение
Часть 2, приоритеты и базовые сигналы

Мда, я дико извиняюсь за большое количество опечаток в предыдщих постах. Руки не поспевают за мыслью, а при редактировании потеряется часть оформления регулярно. Не зналь(

Имея на руках пример того, с чем предлагается работать, впору поговорить об архитектуре, которая и будет обеспечивать корректное и стабильное исполнение кода, однако, перед этим сделаем ряд важных оговорок:
1) концепт ориентирован на работу с жёстким распределением памяти (Siemens, OMRON CP/CJ series)
2) ввиду пункта 1 внутри одной структуры могут быть переменные которые И читаются, И пишутся, что существенно усложняет их проброс в коммуникацию(особенно тех, которые пишутся И с панели оператора, И из программы, например запуск в ручном режиме и сброс аварий в структуре управления)
3) объём памяти оперативность и для хранения кода, а также мощность CPU–считаются достаточно большими, чтобы не обращать на них внимания, в иных случаях требуется оптимизация кода
4) при работе с контроллерами, имеющими «классическое» распределение памяти, для обеспечения корректного управления моим кодом по ModBus RTU/TCP требуется дополнительная прослойка, которая будет пересобирать структуры в WORD и обратно, когда-нибудь я это исправлю, но явно не сейчас
5) вся концепция рассчитана на применение в обще-промышленной области, где потерять 10-20-30 мс роли не сыграет никакой, если вам нужна более высокая точность – добро пожаловать в чудный мир оптимизации и распределения кусков кода по разным циклам

Ещё одно лирическое отступление

Я осознанно не буду вам рассказывать как работает Промышленный Логический Контроллер (ПЛК), распределение его памяти, времени CPU по задачам системным и пользовательским, типы данных и прочую лабуду – это вы можете узнать на любых вводных курсах от любого производителя железа. Моя задача – показать пример прикладной реализации тех или иных задач.
Кстати, на ардуине в своё время использовал Union, который прекрасно решал проблему компоновки памяти, однако подавляющее большинство сред разработки для промышленного оборудования его или не поддерживают, или имеют кастрированную реализацию.

Генерация импульсов

Начнём с терминологии:
- импульс – это нечто, существующее предельно короткое время, в нашем случае сие ровно 1 цикл контроллера.

Большинство контроллеров предлагает свои системные генераторы импульсов в том или ином виде, но выглядят они следующим образом на примере 1 секунды: 

0.5 сек <-----►
<---->
0.5 сек
------>
время,песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,реактор образовательный,длиннопост

Что это значит на практике? Предположим, время цикла ПЛК = 10 мс, тогда:

50 циклов <----->
<--->
50 циклов
<----------->
100 циклов
----->
циклы,песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,реактор образовательный,длиннопост

Ёбушки воробушки, наш самописный таймер то проверяет когда сигнал = 1, а он равен 1 в течении 50 циклов, а за это время он насчитает 50 секунд, вместо 1! Лажа какая-то. Мы должны получить следующее:

о
1 цикл
циклы
>,песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,реактор образовательный,длиннопост

Для этого есть несколько вариантов, и сначала мы отметём в сторону самый очевидный: мы НЕ будем в каждом таймере проверять фронт системного генератора импульсов, потому что каждая проверка фронта это +1 переменная в памяти ПЛК, а мы не хотим засирать его бесполезным хламом.
Итого остаётся:
1) вызывать системный импульс, проверять его передний или задний фронт и закидывать в pulse_1s;
2) вызвать стандартный таймер TON с длительностью 1 секунда и зациклить на самого себя, при срабатывании таймера взводить pulse_1s;
3) читать системное время и по внутренним часам ПЛК и при смене секунды однократно взводить pulse_1s, потребуется буфер для хранения и сравнения предыдущего времени;
4) прочитать из недр контроллера время предыдущего цикла, насуммировать несчастные наносекунды до 1 секунды и тоже записать в pulse_1s единичку, после чего очистить буфер.
5) ещё что-нибудь на ваше усмотрение.

Мне глубоко фиолетово, каким способом вы получаете в итоге pulse_1s, но вам достаточно получить его корректно 1 раз и все таймеры во всей программе сразу же заработают, причём корректно и, вау, синхронно. Т.е. если у вас в двух местах с разбегом менее 1 секунды начался счёт до 5, то закончится он тоже одновременно. В этом и плюс, и минус. Мы теряем точность. Но так ли она нужна?
Хотите точность до 100 мс? Пишем таймер Time_R для дробных значений генерируем pulse_01s.
Хотите точность до 10 мс? Ну… сделайте отдельный цикл ПЛК с такой частотой и там считайте. Или убедитесь, что ваше время цикла менее 10 мс на всю программу.

1
2
3
4
5
€
7
3
S
10
11
12
TYPE Time_R :	
STRUCT	
Start	:BOOL.
Q	:BOOL.
Pause	:BOOL.
Reset	:BOOL.
SP	:REÀL,
AP	:REAL,
One	:REÀL,
Percent	:REAL,
END_STRUCT	
END TYPE	
//вес импульса //прогресс выполнения,песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный,


FUNCTION drv_Time_R : bool VAR_IN_OUT
T	:Time_R;
END_VAR VAR
END VAR
// Таймер с произвольной кратностью счёта T.One := 0.1;
IF T.Start AND NOT T.Reset THEN // Работа таймера IF T.AP < T.SP THEN
IF NOT T.Pause THEN
IF sys.pulse_01s THEN
T.AP := T.AP + T.One; END_IF;
END_IF;
T.Q :=

Обратите внимание, что этот таймер сложнее – мы считаем прогресс времени от 0 до 1,который можно использовать для вспомогательных операций (типа на 30% всего времени моргнуть правой пяткой) и красивого прогресс-бара на экране.

Архитектура

Перейдём к тому, ради чего был затеян данный раздел. Следите за руками…

1 цикл ПЛК,песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,реактор образовательный,длиннопост

Где-то там приютилось ещё регулирование, типа ПИДов, но о них как-нибудь в другой раз.

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

К глобальным относится всё, что ранее было названо глобальным, а также туда настоятельно рекомендуется выносить:
- все структуры управления драйверами
- все структуры параметров драйверами
- все структуры состояний драйверами
- общие параметры техпроцесса
- общее управление техпроцессом, типа включить/выключить установку

Из них в раздел энергонезависимой памяти попадают только структуры параметров. 

1
2
3
4
5
€
7
3
з
10
11
12
13
14
15
1€
17
13
13
20
21
22
23
24
25
2 €
27
23
23
30
31
32
VAR GLOBAL RETAIN
//Дискретные входа
DIx_cfg	¡ARRAY
//Дискретные вы:-:ода	
D0x_cfg	¡ARRAY
//Приводы с ЧП	
MDx_cfg	¡ARRAY
//Пневмоцилиндр	>ы
VDx_cfg	¡ARRAY
[0..10] OF

REQ – Request, запрос запуска. Сюда мы из авторежима будем писать команду для устройства, а затем скармливать драйверам в CMD.Start_A.
DONE – состояние устройств, если оно выключено или в аварии то соответствующий флаг =0, если успешно запущен = 1. Это хорошо заходит для минимизации алгоритма авторежима и всяких вспомогательных операций.

А что же тогда попадает в call’ы?Нерадивые любители звонков с автонабором? Увы, их неплохо бы там запереть, но места маловато. Там будут вызваны непосредственно экземпляры драйверов на исполнение со всей обвязкой. На примере уже рассмотренных дискретных входов это выглядит так… опс, в этом проекте их нет, вот вам выхода:


FUNCTION_BLOCK call_DO
VAR_INPUT
END_VAR
VAR_OUTPUT
END_VAR
VAR
DOx ¡ARRAY [0..10] OF drv_DO; END VAR
//Пневматика
//выталкиватель трубы из захвата dev := 0;
DOx[dev](
Signal := REQ.KC[0],
CHD := DOx_CHD[dev], cfg := DOx_cfg[dev],
Result => KC_0_CMD );
//выталкиватель трубы из

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

Подробнее
0.5 сек <-----► <----> 0.5 сек ------> время
50 циклов <-----> <---> 50 циклов <-----------> 100 циклов -----> циклы
о 1 цикл циклы >
1 2 3 4 5 € 7 3 S 10 11 12 TYPE Time_R : STRUCT Start :BOOL. Q :BOOL. Pause :BOOL. Reset :BOOL. SP :REÀL, AP :REAL, One :REÀL, Percent :REAL, END_STRUCT END TYPE //вес импульса //прогресс выполнения
 FUNCTION drv_Time_R : bool VAR_IN_OUT T :Time_R; END_VAR VAR END VAR // Таймер с произвольной кратностью счёта T.One := 0.1; IF T.Start AND NOT T.Reset THEN // Работа таймера IF T.AP < T.SP THEN IF NOT T.Pause THEN IF sys.pulse_01s THEN T.AP := T.AP + T.One; END_IF; END_IF; T.Q := FALSE; ELSE // Заданное время достигнуто T.Q := TRUE; END_IF; ELSE // Выключение и сброс таймера T.AP := 0.0; T.Q := FALSE; T.Reset := FALSE; END_IF; // Прогресс таймера IF T.AP > 0 AND T.SP > 0 THEN T.Percent := T.AP / T.SP; ELSE T.Percent := 0.0; END IF
1 цикл ПЛК
1 2 3 4 5 € 7 3 з 10 11 12 13 14 15 1€ 17 13 13 20 21 22 23 24 25 2 € 27 23 23 30 31 32 VAR GLOBAL RETAIN //Дискретные входа DIx_cfg ¡ARRAY //Дискретные вы:-:ода D0x_cfg ¡ARRAY //Приводы с ЧП MDx_cfg ¡ARRAY //Пневмоцилиндр >ы VDx_cfg ¡ARRAY [0..10] OF cfg_DI; [0..10] OF cfg_D0; [0..2] OF cfg_MD; [0..4] OF cfg_VD; ENDJVAR [VAR GLOBAL //Сбшее управление All_Block :BOOL; All_Reset All_Sim All_Auto sys second :BOOL; :BOOL; :BOOL; :mt_system; ¡REAL; //Управление устройствами и их состояние REQ :REQ_list; DONE :REQ list; //Дискретные входа DIx_CMD :ARRAY //Дискретные вы:-:ода D0x_CHD :ARRAY //Приводы с ЧП MDx_CHD :ARRAY MDx_state ¡ARRAY //Пневмоцилиндры VDx_CHD ¡ARRAY VDx_state ¡ARRAY end_vaf) [0..10] OF mt_CMD; [0..10] OF mt_CMD; [0..2] OF mt_CMD; [0..2] OF state_MD; [0..4] OF mt_CHD; [0..4] OF state_VD;
 FUNCTION_BLOCK call_DO VAR_INPUT END_VAR VAR_OUTPUT END_VAR VAR DOx ¡ARRAY [0..10] OF drv_DO; END VAR //Пневматика //выталкиватель трубы из захвата dev := 0; DOx[dev]( Signal := REQ.KC[0], CHD := DOx_CHD[dev], cfg := DOx_cfg[dev], Result => KC_0_CMD ); //выталкиватель трубы из рольганга dev := 1; DOx[dev]( Signal := REQ.KC[1], CHD := D0x_CHD[dev], cfg := DOx_cfg[dev], Result => KC_1_CMD ); //сдвиг рольганга dev := 2; DOx[dev]( Signal := REQ.KC[2], CHD := D0x_CHD [dev], cfg := DOx_cfg[dev], Result => KC_2_CHD ); //резерв dev := 3; DOx[dev]( Signal := REQ.KC[3], CHD := DOx_CHD [dev], cfg := DOx_cfg[dev], Result => KC_3_CHD );
песочница,АСУ ТП,программирование,geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор,реактор образовательный,длиннопост
Еще на тему
Развернуть
за статью - плюс, за зажиленные пробелы - минус :)
Прошу прощения, после создания поста они почему-то теряются и приходится по два-три раза редактировать пост, вылавливая каждый раз новые.(
Это я удачно зашел. Как раз новый ПЛК нужно освоить.
Segard Segard 28.05.202222:59 ответить ссылка 0.3
^ Без имени"!.project - CODESYS
Файл Правка Вид Проект Компиляция Онлайн Отладка Инструменты Окно Справка
^ У
о Oi & % Ш X
А:- Л4 А £
•>Е:
я «а «я ¡¡Ат*ff \т\щщ ► ■
о
X
Т
Устройства
▼ ¥ X
1— ЧЭ Без имени 1
ь ■ Device (Agava PLC-40/50 TV+WV)
4 ®(l Plc Logic
f“ О Application
|Jj)
Segard Segard 28.05.202222:59 ответить ссылка 0.0
О, хороший повод продолжить.) если пригодилось хотя бы одному человеку - значит уже не зря.)
Пиши, дорогой человек, потому как документация документацией, но подводных камней и "очевидных особенностей" хватает.
Segard Segard 28.05.202223:35 ответить ссылка 0.0
А сам пойду пилить запрос на добавление в FAQ списка портов для форвардинга ПЛК во внешнюю сеть.
Segard Segard 28.05.202223:44 ответить ссылка 0.0
Рапортую о первичном контроле над устройством, сбор и регистрация данных для последующего анализа во внешнюю БД налажены.
Segard Segard 13.06.202201:51 ответить ссылка 0.3
-0.75	-150.00
-0.37	-150.00
-1.12	-149.63
-2.25	-149.63
Connection State	O
Host	192.168.0.196
Database	plc_test
plc_test
-149.25
0.00
0.00
0.00
0.00
Segard Segard 13.06.202201:57 ответить ссылка 0.3
Бро спасибо за мотивацию. Как задумаешь пропасть, просьба - шлепни постик с координатами где планируешь тусить
PLC programming
де. Siemens - E:\siemens\Project1\Project1
_ il X
Project Edit View Insert Online Options Tools Window Help
Project tree
X 111 i X	c*±	ш ш a is	Go online ¿t Go offline	¿i? IIS IS	X	d JJ	1 <Search in project*
vi
Totally Integrated Automation
PORTAL
4 Project! ► PLC_1 [CPU
sametoy sametoy 29.05.202203:30 ответить ссылка 0.0
Реактор проверяю чаще почты.) пиши в личку - увижу сразу, отвечу может и не очень. Следующий пост будет в течении пары дней, дальше надо мысли аккуратнее структурировать и больше референса по закромам собирать, хех.

Если работаешь с сименсом - могу огромной библиотекой PLC+HMI на LAD поделиться, приближенной к функционалу PCS7 во многом и хорошо отлаженной. На ST баги мелкие каждый проект вылавливаю пока что ^_^
Друже пили пост про ПИД. Реализацию на SCL. Я пытался, но что-то пошло не так хаха. Сколько я его изучал и пытался реализовать. Это тот момент, когда знаешь как работает, но словами объяснить не можешь. Когда долго не сталкиваешься всё улетает с головы вместе с ветром.
Если ты хочешь самописный ПИД, то обрати внимание на библиотеки OSCAT (или OSKAT, не помню точно). Переносил его на овен когда-то. Когда дойду до регулирования - уделю внимание этому вопросу, хорошо.
Только зарегистрированные и активированные пользователи могут добавлять комментарии.
Похожие темы

Похожие посты
Как делают пластиковые бутылки. Производство пластиковых бутылок,People & Blogs,Как делают пластиковые бутылки,из +чего делают пластиковые бутылки +для воды,как делают пластиковые бутылки видео,производство пластиковых бутылок,производство бутылок пэт,производство пластиковых бутылок видео,Как делаю
подробнее»

песочница АСУ ТП программирование geek,Прикольные гаджеты. Научный, инженерный и айтишный юмор автоматика напитки завод политика,политические новости, шутки и мемы длиннопост реактор образовательный

Как делают пластиковые бутылки. Производство пластиковых бутылок,People & Blogs,Как делают пластиковые бутылки,из +чего делают пластиковые бутылки +для воды,как делают пластиковые бутылки видео,производство пластиковых бутылок,производство бутылок пэт,производство пластиковых бутылок видео,Как делаю