
Сообщение от
Вольд
Владимир, а для чего вы завели эту тему ?
Во-первых, даже на этом форуме несколько раз всплывал вопрос Дракон-программирования применительно к ПЛК-ПР.
Во-вторых, есть люди, которые программируют ОВЕН СПК107 на ДРАКОНе (см http://forum.drakon.su/viewtopic.php...t=6068#p100306 . Ну и пример программы: http://forum.drakon.su/viewtopic.php...art=20#p100336 )
В третьих, я всё прикидываю "программу управления светом от выключателей" -- ну не очень мне нравится ST там. Конечно, сейчас как-то работает (и, да, ST гораздо лучше CFC), но описать процесс с паузами/временем по-моему гораздо упростит понимание.

Сообщение от
Вольд
Владимир, а для чего вы завели эту тему ?
Поэтому тему и завёл с целью поинтересоваться "а как вообще может выглядеть Дракон-программирование" применительно к ПЛК.
Может оказаться, что оно действительно сократит количество логических ошибок в алгоритмах.
Конечно, опечатки и ctrl c/v не исправить, а ситуации типа "если насос работал-работал и сломался, а программа забыла запустить запасной" из картинки могут быть гораздо виднее, чем из текста на таймерах.

Сообщение от
Вольд
Читаем - Для создания и редактирования дракон-схем предлагается Интегрированная Среда ДРАКОН. Разработчик программы Тышов Геннадий Николаевич. Программа умеет превращать дракон-схемы в исходные тексты программ на языках семейств 1С, Delphi, C, Oberon, ASM.
Про языки CoDeSys там ничего нет.
Вообще говоря, в среда Тышова умеет генерировать ST код примерно такого содержания (качество этого кода предлагаю не обсуждать, т.к. не в нём суть):
Код:
(*#1.1.3.Ветка. ========= ||главная||*)
(*#1.1.4.Вопрос. ||Есть пуск?||*)
IF NOT (
PUSK=TRUE
) THEN JMP L26; END_IF;(*Нет-> #1.1.26.Вопрос. ||насос 1 работает?||*)
JMP L5;(*-> #1.1.5.Вопрос. ||насос 1 работает?||*)
(*#1.1.26.Вопрос. ||насос 1 работает?||*)
L26: ;
IF NOT (
PUMP1=TRUE
) THEN JMP L31; END_IF;(*Нет-> #1.1.31.Вопрос. ||насос 2 работает?||*)
JMP L27;(*-> #1.1.27.Действие. ||насос 1= стоп||*)
(*#1.1.31.Вопрос. ||насос 2 работает?||*)
L31: ;
IF NOT (
PUMP2=TRUE
) THEN JMP L138; END_IF;(*Нет-> #1.1.138.Полка. ||код состояния = 0||*)
(*#1.1.32.Действие. ||насос 2 = стоп||*)
PUMP2:=FALSE;
JMP L138;(*-> #1.1.138.Полка. ||код состояния = 0||*)
(*#1.1.27.Действие. ||насос 1= стоп||*)
L27: ;
PUMP1:=FALSE;
(*#1.1.138.Полка. ||код состояния = 0|"останов насосов"|*)
L138: ;
...... Нет текста
(*#1.1.29.Действие. ||сброс бита аварии||*)
BIT_AVAR:=FALSE;
JMP L30;(*-> #1.1.30.Адрес. ||Завершение||*)
(*#1.1.5.Вопрос. ||насос 1 работает?||*)
L5: ;
IF NOT (
PUMP1=TRUE
) THEN JMP L13; END_IF;(*Нет-> #1.1.13.Вопрос. ||насос 2 работает?||*)
JMP L6;(*-> #1.1.6.Вопрос. ||реле давления включено?||*)
(*#1.1.13.Вопрос. ||насос 2 работает?||*)
L13: ;
IF NOT (
PUMP2=TRUE
) THEN JMP L22; END_IF;(*Нет-> #1.1.22.Вопрос. ||код состояния=5||*)
JMP L14;(*-> #1.1.14.Вопрос. ||реле давления включено?||*)
(*#1.1.22.Вопрос. ||код состояния=5||*)
L22: ;
IF
SOST=5
THEN JMP L30; END_IF;(*Да-> #1.1.30.Адрес. ||Завершение||*)
(*#1.1.23.Вопрос. ||код состояния=3||*)
IF
SOST=3
THEN JMP L30; END_IF;(*Да-> #1.1.30.Адрес. ||Завершение||*)
(*#1.1.24.Вопрос. ||код состояния=4||*)
IF
SOST=4
THEN JMP L30; END_IF;(*Да-> #1.1.30.Адрес. ||Завершение||*)
JMP L25;(*-> #1.1.25.Адрес. ||запуск насосов по переднему фронту||*)
(*#1.1.30.Адрес. ||Завершение||*)
L30: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.25.Адрес. ||запуск насосов по переднему фронту||*)
L25: ;
JMP L34;(*-> #1.1.34.Ветка. ||запуск насосов по переднему фронту||*)
(*#1.1.14.Вопрос. ||реле давления включено?||*)
L14: ;
IF NOT (
RPD=TRUE
) THEN JMP L18; END_IF;(*Нет-> #1.1.18.Пауза. ||Запуск таймера TON2 10 сек.||*)
JMP L15;(*-> #1.1.15.Вопрос. ||код состояния=3||*)
(*#1.1.18.Пауза. ||Запуск таймера TON2 10 сек.||*)
L18: ;
TON2(IN:=NOT(RPD)AND PUMP2=TRUE,PT:=t#10S);
(*#1.1.19.Вопрос. ||Q таимера TON2=1||*)
IF NOT (
TON2.Q=TRUE
) THEN JMP L21; END_IF;(*Нет-> #1.1.21.Адрес. ||Завершение||*)
JMP L20;(*-> #1.1.20.Адрес. ||АВАРИЯ НАСОСА2||*)
(*#1.1.21.Адрес. ||Завершение||*)
L21: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.20.Адрес. ||АВАРИЯ НАСОСА2||*)
L20: ;
JMP L65;(*-> #1.1.65.Ветка. ||АВАРИЯ НАСОСА2||*)
(*#1.1.15.Вопрос. ||код состояния=3||*)
L15: ;
IF
SOST=3
THEN JMP L17; END_IF;(*Да-> #1.1.17.Адрес. ||Завершение||*)
(*#1.1.137.Полка. ||код состояния = 2|"работает насос 2"|*)
...... Нет текста
JMP L17;(*-> #1.1.17.Адрес. ||Завершение||*)
(*#1.1.6.Вопрос. ||реле давления включено?||*)
L6: ;
IF NOT (
RPD=TRUE
) THEN JMP L16; END_IF;(*Нет-> #1.1.16.Пуск таймера. ||Запуск таймера TON1 10 сек.||*)
JMP L7;(*-> #1.1.7.Вопрос. ||код состояния=4||*)
(*#1.1.16.Пуск таймера. ||Запуск таймера TON1 10 сек.||*)
L16: ;
TON1(IN:=NOT(RPD)AND PUMP1=TRUE, PT:=t#10S);
(*#1.1.11.Вопрос. ||Q таимера TON1 = 1||*)
IF NOT (
TON1.Q=TRUE
) THEN JMP L17; END_IF;(*Нет-> #1.1.17.Адрес. ||Завершение||*)
JMP L12;(*-> #1.1.12.Адрес. ||АВРИЯ НАСОС 1||*)
(*#1.1.17.Адрес. ||Завершение||*)
L17: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.12.Адрес. ||АВРИЯ НАСОС 1||*)
L12: ;
JMP L56;(*-> #1.1.56.Ветка. ||АВРИЯ НАСОС 1||*)
(*#1.1.7.Вопрос. ||код состояния=4||*)
L7: ;
IF
SOST=4
THEN JMP L9; END_IF;(*Да-> #1.1.9.Адрес. ||Завершение||*)
(*#1.1.8.Действие. ||код состояния=1 "работает насос 1"||*)
SOST:=1;
(*#1.1.9.Адрес. ||Завершение||*)
L9: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.33.Левый комментарий-. ||ветка выполняется один раз при изменении пуска||*)
(*#1.1.34.Ветка. ========= ||запуск насосов по переднему фронту||*)
L34: ;
(*#1.1.35.Вопрос. ||ПУСК2>=ПУСК1?||*)
IF NOT (
PUSK2>=PUSK1
) THEN JMP L37; END_IF;(*Нет-> #1.1.37.Адрес. ||запуск насоса 2||*)
JMP L36;(*-> #1.1.36.Адрес. ||запуск насоса1||*)
(*#1.1.37.Адрес. ||запуск насоса 2||*)
L37: ;
JMP L47;(*-> #1.1.47.Ветка. ||запуск насоса 2||*)
(*#1.1.36.Адрес. ||запуск насоса1||*)
L36: ;
(*#1.1.38.Ветка.Цикл. ========= ||запуск насоса1||*)
L38: ;
(*#1.1.39.Действие. ||Насос1 = пуск||*)
PUMP1:=TRUE;
(*#1.1.40.Действие. ||Пуск1=пуск1+1||*)
PUSK1:=PUSK1+1;
(*#1.1.41.Вопрос. ||реле давления включено?||*)
IF NOT (
RPD=TRUE
) THEN JMP L28; END_IF;(*Нет-> #1.1.28.Пуск таймера. ||Запуск таймера TON3 10 сек.||*)
JMP L42;(*-> #1.1.42.Адрес. ||Завершение||*)
(*#1.1.28.Пуск таймера. ||Запуск таймера TON3 10 сек.||*)
L28: ;
TON3(IN:=NOT(RPD)AND PUMP1=TRUE,PT:=t#10S);
(*#1.1.44.Вопрос. ||Q таимера TON3 = 1||*)
IF NOT (
TON3.Q=TRUE
) THEN JMP L46; END_IF;(*Нет-> #1.1.46.Адрес. ||Завершение||*)
JMP L45;(*-> #1.1.45.Адрес. ||АВРИЯ НАСОС 1||*)
(*#1.1.46.Адрес. ||Завершение||*)
L46: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.45.Адрес. ||АВРИЯ НАСОС 1||*)
L45: ;
JMP L56;(*-> #1.1.56.Ветка. ||АВРИЯ НАСОС 1||*)
(*#1.1.42.Адрес. ||Завершение||*)
L42: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.47.Ветка.Цикл. ========= ||запуск насоса 2||*)
L47: ;
(*#1.1.48.Действие. ||Насос2 = пуск||*)
PUMP2:=TRUE;
(*#1.1.49.Действие. ||Пуск2=пуск2+1||*)
PUSK2:=PUSK2+1;
(*#1.1.50.Вопрос. ||реле давления включено?||*)
IF NOT (
RPD=TRUE
) THEN JMP L43; END_IF;(*Нет-> #1.1.43.Пуск таймера. ||Запуск таймера TON4 10 сек.||*)
JMP L51;(*-> #1.1.51.Адрес. ||Завершение||*)
(*#1.1.43.Пуск таймера. ||Запуск таймера TON4 10 сек.||*)
L43: ;
TON4(IN:=NOT(RPD)AND PUMP2=TRUE,PT:=t#10S);
(*#1.1.53.Вопрос. ||Q таимера TON4 = 1||*)
IF NOT (
TON4.Q=TRUE
) THEN JMP L55; END_IF;(*Нет-> #1.1.55.Адрес. ||Завершение||*)
JMP L54;(*-> #1.1.54.Адрес. ||АВАРИЯ НАСОСА2||*)
(*#1.1.55.Адрес. ||Завершение||*)
L55: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.54.Адрес. ||АВАРИЯ НАСОСА2||*)
L54: ;
JMP L65;(*-> #1.1.65.Ветка. ||АВАРИЯ НАСОСА2||*)
(*#1.1.51.Адрес. ||Завершение||*)
L51: ;
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.56.Ветка. ========= ||АВРИЯ НАСОС 1||*)
L56: ;
(*#1.1.57.Вопрос. ||код состояния =4||*)
IF NOT (
SOST=4
) THEN JMP L140; END_IF;(*Нет-> #1.1.140.Полка. ||код состояния = 3||*)
JMP L139;(*-> #1.1.139.Полка. ||код состояния = 5||*)
(*#1.1.140.Полка. ||код состояния = 3|"авария насоса 1"|*)
L140: ;
SOST:=3;
(*#1.1.61.Действие. ||код состояния=3 "авария насоса 1"||*)
SOST:=3;
(*#1.1.62.Действие. ||насос 1 стоп||*)
PUMP1:=FALSE;
(*#1.1.63.Действие. ||ВКЛЮЧИТЬ БИТ АВАРИИ||*)
BIT_AVAR:=TRUE;
(*#1.1.64.Адрес. ||запуск насоса 2||*)
JMP L47;(*-> #1.1.47.Ветка. ||запуск насоса 2||*)
(*#1.1.139.Полка. ||код состояния = 5|"авария всех насосов"|*)
L139: ;
SOST:=5;
(*#1.1.59.Действие. ||насос 1 стоп||*)
PUMP1:=FALSE;
(*#1.1.60.Адрес. ||Завершение||*)
JMP L74;(*-> #1.1.74.Ветка. ||Завершение||*)
(*#1.1.65.Ветка. ========= ||АВАРИЯ НАСОСА2||*)
L65: ;
(*#1.1.66.Вопрос. ||код состояния =3||*)
IF NOT (
SOST=3
) THEN JMP L141; END_IF;(*Нет-> #1.1.141.Полка. ||код состояния = 4||*)
JMP L142;(*-> #1.1.142.Полка. ||код состояния = 5||*)
(*#1.1.141.Полка. ||код состояния = 4|"авария насоса 2"|*)
L141: ;
SOST:=4;
(*#1.1.71.Действие. ||насос 2 стоп||*)
PUMP2:=FALSE;
(*#1.1.72.Действие. ||ВКЛЮЧИТЬ БИТ АВАРИИ||*)
BIT_AVAR:=TRUE;
(*#1.1.73.Адрес. ||запуск насоса1||*)
JMP L38;(*-> #1.1.38.Ветка. ||запуск насоса1||*)
(*#1.1.142.Полка. ||код состояния = 5|"авария всех насосов"|*)
L142: ;
SOST:=5;
(*#1.1.68.Действие. ||насос 2 стоп||*)
PUMP2:=FALSE;
(*#1.1.69.Адрес. ||Завершение||*)
(*#1.1.74.Ветка. ========= ||Завершение||*)
L74: ;
(*#1.1.75.Конец. ||Конец||*)
(*#1.1.2.Заголовок.Конечный текст. ||БЛОК НАСОСОВ ПОДПИТКИ||*)
...... Нужна 1 строка разделитель: ====
Но суть совсем не в этом.
Суть в том, что, есть же Hardella IDE, куда можно добавить Дракон, о чём Алексей Геннадьевич и говорил.
Но, разумеется, перед тем, как что-то куда-то добавлять я хочу примериться "а как оно вообще".