Страница 3 из 5 ПерваяПервая 12345 ПоследняяПоследняя
Показано с 21 по 30 из 47

Тема: Использование ООП в CODESYS V3.5

  1. #21
    Пользователь
    Регистрация
    27.11.2011
    Адрес
    Краснодар
    Сообщений
    10,582

    По умолчанию

    с циклами все не так однозначно. Многое зависит от выбранного ПЛК, некоторые например умеют в цикле программы опросить вход и записать выход кроме штатных сперва спрашиваем состояние входов, потом цикл программы, потом запись выходов.

    Да и таймеры есть различные, онли софтовые как в CodeSys так и хардовые.

    з.ы. еще раз, зависит от выбранного ПЛК и что в нем производители учудили...

  2. #22

    По умолчанию

    Ну мы же сейчас конкретно про codesys говорим...

  3. #23
    Пользователь
    Регистрация
    27.11.2011
    Адрес
    Краснодар
    Сообщений
    10,582

    По умолчанию

    я с версией 3,5 особо не знаком, и 210-й ПЛК не смотрел, не знаю что там можно придумать и как.
    Но в общих чертах в основном у всех одинаково - опрос входов, цикл программы, запись выходов.
    Выполнение отдельных POU можно по таймеру отдельной задачей и т.д.

    Думаю растягивать специально цикл не стоит, пусть себе крутится за то время, какая у вас там программа получится. Хуже ему не будет.
    Последний раз редактировалось melky; 30.04.2020 в 10:44.

  4. #24

    По умолчанию

    Написал код для ворот. Проверить на реальном объекте на текущий момент не могу - надо там кое-что по "физике" допилить. Попинайте код кому не сложно:

    Код:
    FUNCTION_BLOCK TSH_Portal						//префикс: tshp
    VAR_INPUT
    	xEnabled: BOOL:=TRUE;						//Включение/выключение управляющего блока ворот
    	xButtonEnabled: BOOL:=FALSE;					//Включение/выключение кнопки управления воротами на столбе
    	xManual: BOOL:=FALSE;						//флаг режима ручного управления (чтобы можно было самому дергать релюшки в щите)
    	xRepeatCommand: BOOL:=FALSE;				//повторять ли команду, если ворота не закрылись через установленное время
    	
    	xgpioIsOpen: BOOL:=FALSE;					//вход от концевика "открыто"
    	xgpioIsClosed: BOOL:=FALSE; 					//вход от концевика "закрыто"
    	
    	timMovingDutarion: TIME:=T#35S;				//время движения ворот между конечными положениями
    	timCommandImpulseDuration: TIME:=T#500MS; 	//длительность импульса команды открывания/закрывания ворот
    	timCommandRepeatTime: TIME:=T#150S;			//время ожидания между повторной попыткой открытия/закрытия, если в предыдущий раз не получилось (препятствие и тд)
    	timNotClosedLimit: TIME:=T#5M;				//максимальная допустимая продолжительность нахождения ворот в не закрытом состоянии
    END_VAR
    VAR_IN_OUT
    	xOpen: BOOL:=FALSE;						//команда "открыть"
    	xClose: BOOL:=FALSE;						//команда "закрыть"
    END_VAR
    VAR_OUTPUT
    	xgpioEnabled: BOOL;							//выход на реле "вкл/выкл"
    	xgpioButtonEnabled: BOOL;					//выход на реле "вкл/выкл кнопки управления воротами"
    	xgpioOpen: BOOL;							//выход на реле сигнала команды "открыть"
    	xgpioClose: BOOL; 							//выход на реле сигнала команды "закрыть"
    	
    	eState: TSH_PortalStates;						//состояние ворот
    	
    	xerrLimitSwitches: BOOL;						//ошибка концевиков - оба показывают, что замкнуты
    	xerrForbidden: BOOL;							//запрещенная операция (одновременная подача команд октрыто и закрыто)
    	xerrNoAction: BOOL;							//нет реакции на команду
    	xerrObstacle: BOOL;							//препятствие в створе ворот
    	xerrNotClosedLimitExceed: BOOL;				//слишком долго открыты
    	
    	timNotClosed: TIME;							//количество времени, которое ворота не закрыты
    END_VAR
    VAR	
    	//сигнал концевика "закрыто"
    	ftrigIsClosed: F_TRIG;						//триггер спада
    	rtrigIsClosed: R_TRIG;						//триггер фронта
    	xRaiseIsClosed: BOOL;						//флаг фронта
    	xFadeIsClosed: BOOL;						//флаг спада
    
    	//сигнал концевика "открыто"
    	rtrigIsOpen: R_TRIG;							//триггер фронта
    	ftrigIsOpen: F_TRIG;							//триггер спада
    	xRaiseIsOpen: BOOL;							//флаг фронта
    	xFadeIsOpen: BOOL;							//флаг спада
    	
    	//команды
    	rtrigOpen: R_TRIG;							//триггер фронта команды Open
    	rtrigClose: R_TRIG;							//триггер фронта команды Close	
    	xRaiseOpen: BOOL;							//флаг фронта сигнала "открыть"
    	xRaiseClose: BOOL;							//флаг фронта сигнала "закрыть"
    	xLastCommandIsOpen: BOOL;					//какая была последняя команда: true - открытие
    	
    	//таймеры
    	tpCMDImpulse: TP;							//импульс команды
    	tpMoving: TP;								//перемещение ворот между конечными положениями
    	tpCMDRepeat: TP;							//пауза между повторной отправкой команды, если ворота в ожидаемое время не пришли в конечное положение
    	timStartMoving: TIME;						//время начала движения ворот
    END_VAR
    
    
    xgpioEnabled:=xEnabled;
    
    //если ворота выключены, то остальные сигналы также false
    xgpioButtonEnabled:=xButtonEnabled AND xEnabled;
    xOpen:=xOpen AND xEnabled AND NOT xManual;
    xClose:=xClose AND xEnabled AND NOT xManual;
    
    //******ОБРАБОТКА КОМАНД******
    //определяем наличие фронтов сигналов команд
    rtrigOpen(CLK:=xOpen, Q=>xRaiseOpen);
    rtrigClose(CLK:=xClose, Q=>xRaiseClose);
    
    IF xRaiseOpen AND xRaiseClose THEN //два фронта одновременно - ошибка
    	xerrForbidden:=TRUE;
    	xRaiseOpen:=FALSE;
    	xRaiseClose:=FALSE;
    	xOpen:=FALSE;
    	xClose:=FALSE;	
    END_IF	
    
    //Если вторая команда пришла во время импульса первой, отменить первую запустить вторую
    IF xOpen AND xClose AND (xRaiseClose XOR xRaiseOpen) THEN
    	//актуализируем активную команду
    	xOpen:=xRaiseOpen;
    	xClose:=xRaiseClose;
    	
    	//сбрасываем таймеры
    	tpCMDImpulse(IN:=FALSE, PT:=T#0S);	
    	tpMoving(IN:=FALSE, PT:=T#0S);
    	tpCMDRepeat(IN:=FALSE, PT:=T#0S);
    END_IF
    
    tpCMDImpulse(IN:=xRaiseOpen XOR xRaiseClose, PT:=timCommandImpulseDuration);	//если прошла команда, запускаем таймер длительности импульса команды
    xOpen:=xOpen AND tpCMDImpulse.Q;		//приводим импульс команды на входе ФБ в соответствие реальному импульсу
    xClose:=xClose AND tpCMDImpulse.Q;		//приводим импульс команды на входе ФБ в соответствие реальному импульсу
    xgpioOpen:=xOpen;
    xgpioClose:=xClose;
    
    //запоминаем последнюю команду (для того, чтобы ее повторить, если потребуется)
    IF xOpen THEN
    	xLastCommandIsOpen:=TRUE;
    ELSIF xClose THEN
    	xLastCommandIsOpen:=FALSE;
    END_IF
    //******ОБРАБОТКА КОМАНД******
    
    
    //******ОБРАБОТКА СИГНАЛОВ КОНЦЕВИКОВ******
    xerrLimitSwitches:=xgpioIsOpen AND xgpioIsClosed;	//оба концевика включены - ошибка
    
    //Определение изменений состояний концевиков
    rtrigIsOpen(CLK:=xgpioIsOpen, Q=>xRaiseIsOpen);
    ftrigIsOpen(CLK:=xgpioIsOpen, Q=>xFadeIsOpen);
    rtrigIsOpen(CLK:=xgpioIsClosed, Q=>xRaiseIsClosed);
    ftrigIsOpen(CLK:=xgpioIsClosed, Q=>xFadeIsClosed);
    
    //обработка начала движения (по спаду сигнала концевика)
    IF xFadeIsOpen OR xFadeIsClosed THEN
    	timStartMoving:=TIME();
    	tpMoving(IN:=xEnabled, PT:=2*timMovingDutarion);				//запускаем таймер длительности перемещения ворот между конечными положениями, на двойное время, т.к. часто в процессе движения напрвление движения меняется через другие каналы (кнопка, пульт)
    END_IF
    timNotClosed:=SEL(NOT xgpioIsOpen AND NOT xgpioIsClosed, 0, TIME()-timStartMoving);
    xerrNotClosedLimitExceed:=(timNotClosed>timNotClosedLimit);
    xerrNotClosedLimitExceed:=(timNotClosed>timNotClosedLimit);
    
    //обработка прихода ворот в конечное положение
    IF xRaiseIsOpen OR xRaiseIsClosed THEN
    	//сбрасываем таймеры
    	tpCMDImpulse(IN:=FALSE, PT:=T#0S);	
    	tpMoving(IN:=FALSE, PT:=T#0S);
    	tpCMDRepeat(IN:=FALSE, PT:=T#0S);
    	
    	//сбрасываем сигналы команд
    	xOpen:=FALSE;
    	xClose:=FALSE;	
    	
    	//и ошибки "препятствие в створе" и предела времени в незакрытом состоянии
    	xerrObstacle:=FALSE;	
    	xerrNotClosedLimitExceed:=FALSE;
    END_IF
    
    //импульс команды закончился, а ворота так и не сдвинулись с места - ошибка
    //выражение идет после обработки прихода ворот в конечное положение, т.к. за время 
    //импульса они могли начать движение и успеть вернуться обратно, что не является ошибкой
    xerrNoAction:=tpCMDImpulse.IN AND (tpCMDImpulse.ET=tpCMDImpulse.PT) AND (xgpioIsOpen OR xgpioIsClosed);
    //******ОБРАБОТКА СИГНАЛОВ КОНЦЕВИКОВ******
    
    
    //******ОБРАБОТКА ТАЙМЕРОВ ******
    //ожидаемое время движения ворот между конечными положениями истекло дважды
    IF tpMoving.IN AND tpMoving.ET=tpMoving.PT THEN
    	xerrObstacle:=TRUE;		//считается, что обнаружено препятствие
    	tpCMDRepeat(IN:=xRepeatCommand AND xEnabled, PT:=timCommandRepeatTime);	//запускаем таймер ожидания перед повторной отправкой команды
    	tpMoving(IN:=FALSE, PT:=T#0S);	//сбрасываем таймер движения
    END_IF
    
    //время ожидания перед повторной отправкой команды истекло
    IF tpCMDRepeat.IN AND tpCMDRepeat.ET=tpCMDRepeat.PT THEN
    	xOpen:=xLastCommandIsOpen;
    	xClose:=NOT xLastCommandIsOpen;
    
    	//сбрасываем таймер
    	tpCMDRepeat(IN:=FALSE, PT:=T#0S);	
    END_IF
    //******ОБРАБОТКА ТАЙМЕРОВ******
    
    //Устанавливаем состояние ворот
    IF xgpioIsOpen THEN
    	eState:=TSH_PortalStates.tshpsIsOpen;
    ELSIF xgpioIsClosed THEN
    	eState:=TSH_PortalStates.tshpsIsClosed;
    ELSE
    	eState:=TSH_PortalStates.tshpsInBetween;
    END_IF
    Последний раз редактировалось turkish945; 02.05.2020 в 00:31.

  5. #25

    По умолчанию

    1. У тебя там в сигналах ошибки )) Написано про триггер фронта и спада, а стоят везде F_TRIG. А на спаде на R_TRIG.
    2. Дальше непонятно: вот если ворота выключены, то ты выставил FALSE на выходы... а дальше-то что? Идёт логика, которая эти же выходы меняет. И на выходе FB они и будут всё равно чего-то значить. Совсем ты ни хрена не так прогаешь чего-то!

    Вообще это бы написать бы на конечном автомате... взять переменную типа State, к ней ENUM, и дальше что-то типа
    Код:
    CASE State OF
    stManual : ****
    stCmdOpen : ****
    stCmdClose : ****
    stMoving : ****
    stNotClosed : ****
    и так далее...

  6. #26

    По умолчанию

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    1. У тебя там в сигналах ошибки )) Написано про триггер фронта и спада, а стоят везде F_TRIG. А на спаде на R_TRIG.
    Где? Посмотрел, не нашел ошибки, вроде все верно.

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    Дальше непонятно: вот если ворота выключены, то ты выставил FALSE на выходы... а дальше-то что? Идёт логика, которая эти же выходы меняет.
    Нет такой логики, везде, где на что-то меняется есть условия, которые не выполняются. По крайней мере я не нашел.

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

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

  7. #27

    По умолчанию

    А вот ты ж пишешь так:
    Код:
    ftrigIsClosed: F_TRIG; //триггер спада
    rtrigIsClosed: F_TRIG; //триггер фронта
    Это не ошибка?

    Про логику - я про этот код говорю:
    Код:
    //если ворота выключены, то остальные сигналы также false
    xgpioButtonEnabled:=xButtonEnabled AND xEnabled;
    xOpen:=xOpen AND xEnabled AND NOT xManual;
    xClose:=xClose AND xEnabled AND NOT xManual;
    Почему у тебя он в начале стоит? Я не весь код смотрел, но не получается ли так, что ты по xEnabled выставил xOpen/xClose в FALSE, а потом поменял их?

  8. #28

    По умолчанию

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    Это не ошибка?
    Ошибка, точно! Поправил! Спасибо!

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    Почему у тебя он в начале стоит? Я не весь код смотрел, но не получается ли так, что ты по xEnabled выставил xOpen/xClose в FALSE, а потом поменял их?
    Не получается.
    А в начале я его поставил потому что именно тут проще всего пресечь разные поползновения, чтобы ФБ не пытался там что-то делать. При этом он отслеживает состояние концевиков, отслеживает движение. То есть как бы не совсем disabled, а только команды не принимает. Ни через ПЛК, ни через другие каналы, т.к. блок управления ворот отключен по этому сигналу. Но ведь ворота можно руками перемещать, вот это отслеживается.

    PS: Правда может при этом работать таймер повтора последней команды и даже подать ее, но эта команда может выполниться только в следующем цикле, в котором ей так же будет присвоен false и ничего не произойдет.

    PPS: Вообще для прозрачности сделаю, чтоб и таймеры просто так не работали, нефиг.
    Последний раз редактировалось turkish945; 02.05.2020 в 00:40.

  9. #29

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    только зачем в коде постоянная избыточность, типа А := А AND Б; ?
    Имеете в виду, что надо заменить на IF и не выполнять операцию каждый цикл? Разве это даст экономию? Просто так красивее, люблю когда компактно.

    Цитата Сообщение от capzap Посмотреть сообщение
    Стоит перечитать про работу таймеров, если они запускаются в теле импульсного условия, то ихним функционалом не воспользоваться
    Где перечитать? В руководстве пользователя практически ничего про них, я ничего противоречащего не нашел. Имеется в виду, если его использовать в условии if .... then? Как тут:
    Код:
    IF tpCMDRepeat.IN AND tpCMDRepeat.ET=tpCMDRepeat.PT THEN
    Что при этом происходит? ФБ таймера не исполняется?

    Цитата Сообщение от capzap Посмотреть сообщение
    Возможно Вы не в курсе, но если использовать в меню галку симуляция, то можно проверить свой код на работоспособность не дожидаясь наличия контроллера
    Да, не знал, попробую, спасибо.

  10. #30

    По умолчанию

    Засрали тему про ООП��

Страница 3 из 5 ПерваяПервая 12345 ПоследняяПоследняя

Похожие темы

  1. Использование УЗС-1
    от Сергей 2909 в разделе Эксплуатация
    Ответов: 0
    Последнее сообщение: 31.05.2018, 07:56
  2. Ответов: 3
    Последнее сообщение: 05.03.2015, 14:01
  3. ПЛК 110, использование RS-232
    от =MiX@$= в разделе ПЛК1хх
    Ответов: 18
    Последнее сообщение: 14.10.2011, 14:26
  4. Использование АС4
    от alex_sinjawin в разделе Сетевые технологии
    Ответов: 2
    Последнее сообщение: 10.11.2009, 18:31
  5. Использование CoDeSys Service Tool (CST).
    от Юрий_1900 в разделе ПЛК1хх
    Ответов: 1
    Последнее сообщение: 03.09.2009, 09:49

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •