Страница 2 из 3 ПерваяПервая 123 ПоследняяПоследняя
Показано с 11 по 20 из 30

Тема: Модели поведения в CODESYS 2.3

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

    По умолчанию

    на счет структур конечно не настаиваю, мне удобно за счет того что в тиа портале это тоже что и блок данных

    легко пропустить такой оператор
    так это равнозначно относиться как к while так и к repeat, только из-за того чтоб кто то не на косячил с условиями перед while Вы вынуждены присваивать переменной TRUE
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  2. #12

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    так это равнозначно относиться как к while так и к repeat, только из-за того чтоб кто то не на косячил с условиями перед while Вы вынуждены присваивать переменной TRUE
    Если накосячить с условиями - то WHILE совсем не выполниться (и понятно, где искать проблему: в условии входа в цикл),
    если же в теле цикла есть оператор, прерывающий выполнение, то программа войдет в цикл, но до места, которое Вы хотите отладить не дойдет (и, если внутри цикла много кода, будет сложно понять, куда смотреть).
    Тут Вы можете сказать, что
    • функции должны быть макисмально аскетичны,
    • не должны содержать больше 2х уровней вложенности
    • и т.д.

    тогда их будет легко отладить.
    Со всем вышеперечисленным я соглашусь.

    Но бывают ситуации, когда этим приходиться пренебрегать в связи с ограничениями.
    Например В ПЛК63\ПЛК73 есть ограничение на 256 POU и в больших проектах в это ограничение легко упереться.
    Приходиться функции делать больше.

    К примеру, я переписал цикл из тела ETrig, ориентировав его на использование оператора оператора EXIT:
    Код:
    WHILE TRUE DO
     	CASE m_eState OF
     		BM_DORMANT:
    			IF xExecute THEN
    				xBusy  := TRUE;
    				m_eState := BM_EXECUTING;
    				(* TODO: запомнить состояние остальных входов *)
    			ELSE
    				EXIT;
    			END_IF
    		BM_EXECUTING:
    			(* TODO: m_xIsExecutionDone должно стать TRUE, когда выполнение операции завершено успешно *)
    			m_xIsExecutionDone := TRUE;
    			(* TODO: m_xIsExecutionFail должно стать TRUE, когда возникла ошибка выполнения операции *)
    			m_xIsExecutionFail := FALSE;
    			IF m_xIsExecutionFail THEN
    				m_eState := BM_ERROR;
    			ELSIF m_xIsExecutionDone THEN
    				m_eState := BM_DONE;
    				; (*ЗДЕСЬ ДОЛЖНО БЫТЬ ELSE EXIT *)
    			END_IF
    		BM_DONE:
    			IF xDone AND (m_xResetRequest OR NOT xExecute) THEN
    			 	 m_eState := BM_RESETTING;
    			ELSE
    				xBusy := FALSE;
    				xDone := TRUE;
    				m_xResetRequest := NOT xExecute;
    				EXIT;
    			END_IF
    		BM_ERROR:
    			IF xError AND (m_xResetRequest OR NOT xExecute) THEN
    			 	m_eState := BM_RESETTING;
    			ELSE
    			 	xBusy := FALSE;
    			 	xError := TRUE;
    			 	m_xResetRequest := NOT xExecute;
    			 	EXIT;
    			END_IF
    		BM_RESETTING:
    			(* TODO: освобождение ресурсов здесь *)
    			xBusy := FALSE;
    			xDone := FALSE;
    			xError := FALSE;
    			m_eState := BM_DORMANT;
    			m_xResetRequest := FALSE;
    			m_xIsExecutionDone := FALSE;
    			m_xIsExecutionFail := FALSE;
    			EXIT;
    	END_CASE
    END_WHILE
    Работать он должен точно так же, как в 1м посте темы (но я не проверял т.к. думаю, что для понимания идеи его работоспособность не важна).
    Допустим, есть проект. ПЛК перезагружается на вызове этого ФБ.
    Я открываю код, и вижу:
    Код:
    WHILE TRUE DO
    бесконечный цикл внутри ФБ для ПЛК.

    Пишу письмо: "Так мол, и так, у Вас бесконечный цикл вот в этом ФБ."
    Приходит ответ: "Нет там ничего бесконечного. Раньше работало, а теперь, вот, перестало".
    Волосы на моей голове поднимаются дыбом с мыслью "Ну как так? Не могло это работать".
    Начинаю изучать внимательно, ставлю точки останова, прощелкиваю в пошаговой отладке.
    Вижу:
    1. ага, с этого шага выход через EXIT, с этого есть, а вот с этого шага как должно выходить?
      А, EXIT потеряли.
    2. или, для разнообразия, проблема вообще не в самом цикле, а на шаге RESETTING есть запись по некорректному указателю.



    Я, конечно, утрирую. Но такая ситуация вполне могла возникнуть.

    С другой стороны:
    Получаю программу, ПЛК все так же перезагружается на вызове ФБ, но реализован так, как в 1м посте
    Код:
    m_xNeedToChangeState := TRUE;
    WHILE m_xNeedToChangeState DO
    Первая мысль: где-то внутри цикла переменная m_xNeedToChangeState не изменяется на FALSE.
    Пробегаю, смотрю, нет, все хорошо, меняется на FALSE везде, где должна.
    Начинаю искать проблему в других местах.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

    По умолчанию

    http://www.owen.ru/forum/showthread....l=1#post282567

    ни чего не понял, в обоих случаях исследуете код тела цикла, только в первом варианте красочно расписываете как всё плохо, а во втором зачем то сделали свой REPEAT, хотя если в теле такие же проблемы как и в первом варианте то разницы между обеими вариантами нет
    Теперь если использовать REPEAT и перед ним принудительно переменной присваивать FALSE то код выполниться один раз, если не активировать условие цикличности внутри тела, а если это будет функция, то и фальш присваивать не обязательно.
    И к тому же такие способы диагностики некорректного кода больше подходят к чужому коду а не собственному, вот пользуясь случаем хочу спросить про Вашу подпись, какими тестами пользуетесь в КДС, мне например не встречались, сам я только записывал нужные значения в фифо
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  4. #14
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,224

    По умолчанию

    Цитата Сообщение от Осинский Алексей Посмотреть сообщение
    Если я правильно понял, то на графических языках "функция + структура" отображается как ФБ?
    Я слышал о том, что при программировании этих контроллеров используется подход "функция + структура", но этого не знал.

    На сколько мне известно, там и работа с указателями по другому устроена.
    Не просто число (адрес ячейки памяти), а структура (область памяти, адрес ячейки памяти, тип доступа к памяти...). На сколько я понимаю, эта дополнительная информация позволяет проконтролировать то, что нам не подсунут просто набор байт вместо нужной структуры?
    я не использую графические языки ни там ни там уже достаточно давно. Для меня проще в плане того, что если переносить код из_в я просто обычной заменой меняю обозначение указателя в КДС на решетку в TIA, ну конечно подправив еще несколько вещей, это касается функций заменяющих ФБ, зато экземпляры одинаково смотрятся в обоих средах
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  5. #15

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    И к тому же такие способы диагностики некорректного кода больше подходят к чужому коду а не собственному
    В первую очередь - да. По работе, иногда, приходится читать чужой код.
    Но и свой, написанный давно, код можно сходу не разобрать. Не знаю, как у Вас, но у меня с течением времени подход к проектированию меняется. Иногда смотрю на свой код 3-6 летней давности, и думаю, "зачем так написал? можно же было вот-так... и было бы лучше, быстрее, понятнее (ненужное зачеркнуть)".

    Цитата Сообщение от capzap Посмотреть сообщение
    Вот пользуясь случаем хочу спросить про Вашу подпись, какими тестами пользуетесь в КДС, мне например не встречались, сам я только записывал нужные значения в фифо
    Для тестирования модулей (ФБ, функций) на текущий момент использую самописные тесты.
    и для CDS2 и для CDS3 подход схожий (ниже тестируется некий ФБ для управления прожектором):
    1) Объявляю структуру, содержащую желаемые значения входов и выходов тестируемого ФБ
    Скрытый текст:

    Код:
    TYPE SpotlightTest :
    STRUCT
    	eDirection				: SPOTLIGHT_DIRECTION;
    	eSensorsState				: END_SENSOR;
    	xNeedToTurnOn				: BOOL;
    	eCurrentDirection			: SPOTLIGHT_DIRECTION;
    	xIsTurnedOn				: BOOL;
    	xIsMoving				: BOOL;
    	xDirectionChanged			: BOOL;
    END_STRUCT
    END_TYPE

    2) Реализую функцию, назначение которой:
    2.1) Установить значения входов;
    2.2) Вызвать тестируемый ФБ;
    2.3) Сравнить значения выходов с ожидаемыми;
    2.4) Вернуть TRUE, если состояние выходов ФБ равно ожидаемому, иначе вернуть FALSE и записать сообщение в лог с сообщением о том почему тест провален
    Скрытый текст:

    Интерфейс
    Код:
    (*
    Задает состояние входов ФБ типа prv_FastOutPulseGenerator по адресу pfbFopgToTest.
    Вызывает его и проверяет состояние выходов.
    Если состояние выходов не соответствует ожиданию - добавляет запись в лог.
    Возвращает TRUE, если состояние выходов соответствовало ожиданию.
    FALSE во всех остальных случаях
    *)
    FUNCTION AssertSpotlightOutputs : BOOL
    VAR_INPUT
    	sModuleName				: TestMessage;		(* Название теста *)
    	pfbSpotlightToTest			: POINTER TO Spotlight;
    	stTestToExecute				: SpotlightTest;
    END_VAR
    Реализация:
    Код:
    AssertSpotlightOutputs := FALSE;
    IF pfbSpotlightToTest = 0 THEN
    	AddMessageToTestLog ('AssertSpotlightOutputs', 'Некорректный указатель на ФБ');
    ELSE
    
    	pfbSpotlightToTest^.eSensorsState := stTestToExecute.eSensorsState;
    	MoveSpotlightToDirection (pfbSpotlightToTest, stTestToExecute.eDirection);
    	pfbSpotlightToTest^.xNeedToTurnOn := stTestToExecute.xNeedToTurnOn;
    
    	pfbSpotlightToTest^();
    
    	IF pfbSpotlightToTest^.xIsTurnedOn <> stTestToExecute.xIsTurnedOn THEN
    		AddMessageToTestLog (sModuleName, 'Некорректное состояние xIsTurnedOn');
    	ELSIF pfbSpotlightToTest^.eMoveDirection <> stTestToExecute.eCurrentDirection THEN
    		AddMessageToTestLog (sModuleName, 'Некорректное состояние eMoveDirection');
    	ELSIF pfbSpotlightToTest^.xIsTurnedOn <> stTestToExecute.xIsTurnedOn THEN
    		AddMessageToTestLog (sModuleName, 'Некорректное состояние xIsTurnedOn');
    	ELSIF pfbSpotlightToTest^.xIsMoving <> stTestToExecute.xIsMoving THEN
    		AddMessageToTestLog (sModuleName, 'Некорректное состояние xIsMoving');
    	ELSIF pfbSpotlightToTest^.xDirectionChanged <> stTestToExecute.xDirectionChanged THEN
    		AddMessageToTestLog (sModuleName, 'Некорректное состояние xDirectionChanged');
    	ELSE
    		AssertSpotlightOutputs := TRUE;
    	END_IF
    END_IF

    3) Пишу ФБ-тесты (1 ФБ - 1 тестируемая концепция), в которых
    3.1) массив структур SpotlightTest заполнен в соответствии с тем, что хочу протестировать
    3.2) Происходит последовательный вызов функции из п.2 и передача ей необходимого теста и ФБ
    Интерфейс ФБ примерно следующий::

    Код:
    VAR_OUTPUT
    	xDone					: BOOL;
    	xBusy					: BOOL;
    	xPassed					: BOOL;
    	xFailed					: BOOL;
    END_VAR
    VAR CONSTANT
    	m_c_sModuleName			: TestMessage					:= 'Spotlight.EndPositionTest';
    	m_c_usiTestStepsCount		: USINT						:= 9;
    	m_c_astSteps			: ARRAY [1..m_c_usiTestStepsCount] OF SpotlightTest :=
    		(eDirection := DIRECTION_TOPLEFT, xIsMoving	:= TRUE, xDirectionChanged := TRUE, eCurrentDirection := DIRECTION_TOPLEFT),
    ....

    Ну а наполнение, думаю, понятно.

    4) Дело за малым - вызывать тесты по очереди.

    Для CODESYS 3.5 разрабатываю библиотеку, чтобы уменьшить количество написанной вручную обвязки.
    Но, пока что, она не на той стадии готовности, когда ее можно показывать людям.

    А для тестирования проекта в целом использую Process Simulator (ПО бесплатно, с открытым исходным кодом).
    Такая мини-скада, основная задача которой эмулировать поведение исполнительных механизмов.
    Есть возможность писать свои скрипты на C#.
    Все никак руки не дойдут до написания статьи на эту тему.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

  6. #16

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    я не использую графические языки ни там ни там уже достаточно давно. Для меня проще в плане того, что если переносить код из_в я просто обычной заменой меняю обозначение указателя в КДС на решетку в TIA, ну конечно подправив еще несколько вещей, это касается функций заменяющих ФБ, зато экземпляры одинаково смотрятся в обоих средах
    У меня статистика, примерно, такая:
    1) В CDS 2.3 PLC_PRG на CFC т.к. хорошо видно все ли входы-выходы привязаны (в 3.5 на ST т.к. в основном использую методы/property для передачи параметров, а на CFC это болезненный процесс);
    2) 10% SFC (там, где четко прослеживаются отдельные состояния и понятны все переходы между состояниями. Модели поведения тоже на SFC раньше "писал", сейчас модели поведения реализую на ST);
    3) 90% ST.
    Последний раз редактировалось Осинский Алексей; 09.07.2018 в 00:13.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

  7. #17

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    ни чего не понял, в обоих случаях исследуете код тела цикла, только в первом варианте красочно расписываете как всё плохо, а во втором зачем то сделали свой REPEAT, хотя если в теле такие же проблемы как и в первом варианте то разницы между обеими вариантами нет
    В варианте с переменной в условии четко видно, на что обращать внимание: где эта переменная меняется.
    В варианте только с EXIT'ами может быть не очевидно, что из этого цикла вообще есть выход.
    Если бы я реализовал вариант и с переменной и с EXIT'ами стало бы совсем не очевидно: в условии видно, что выход произойдет по значению переменной, но при детальном разборе оказывается, что есть еще некие условия выхода.

    Но, как мы и проговорили выше, все это, в основном, актуально для "чужого" кода. Если код читает только автор - то тут вопросов нет.

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

  8. #18

    По умолчанию

    Цитата Сообщение от Осинский Алексей Посмотреть сообщение
    В "модели поведения" основная идея в том, что по интерфейсу ФБ можно быстро понять как этот ФБ работает:
    1. работа по уровню, или по переднему фронту;
    2. есть ли возможность прервать работу блока;
    3. есть ли возможность ограничить время цикла блока;
    4. есть ли возможность задать таймаут работы блока;
    А можно небольшое объяснение?
    По пунктам 2,3,4 какое то понимание есть, а вот по 1 пункту... Понятно как это работает, непонятно как применить. В каких случаях следует использовать логику по уровню, а в каких по фронту?

    Спасибо.

  9. #19

    По умолчанию

    Цитата Сообщение от Салихов Ильдар Посмотреть сообщение
    А можно небольшое объяснение?
    По пунктам 2,3,4 какое то понимание есть, а вот по 1 пункту... Понятно как это работает, непонятно как применить. В каких случаях следует использовать логику по уровню, а в каких по фронту?

    Спасибо.
    Цитата Сообщение от Осинский Алексей Посмотреть сообщение
    Не так давно этот документ был переведен на русский язык (доступен по ссылке).
    Не смотрели документ по ссылке выше?

    Если вкратце, то
    • ФБ с работой "по уровню" выполняет некую задачу до тех пор, пока на входе xEnable присутствует высокий уровень сигнала (например, утюг, поддерживает температуру до тех пор, пока включен в розетку);
    • ФБ с работой "по фронту" начинает выполнение некой задачи по переднему фронту сигнала xExecute и до тех пор, пока задача не будет выполнена (например, стиральная машина: программу выбрали, кнопку нажали, закончит стирку - пропищит).

    Какая модель Вам поможет для решения конкретной задачи - предстоит определить Вам.
    Не смотря на написанное в списке выше я могу себе представить как
    нагреватель, работающий по фронту (например, плавный набор температуры и выдержка в течение некоторого времени)
    так и
    стиральную машину, работающую по уровню (нажали кнопку - стирает, нажали еще раз - прекратила стирать).
    Последний раз редактировалось Осинский Алексей; 09.07.2018 в 09:17.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

  10. #20

    По умолчанию

    Ильдар, пока писал о нагреватель, работающий по фронту, сообразил что мы с Вами уже общались соседней теме.
    Вам не подошло решение, которое я там предложил?
    Или подошло и Вы "для себя" разбираетесь?
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

Похожие темы

  1. Ответов: 2
    Последнее сообщение: 02.03.2021, 00:31
  2. Термопара 125 модели
    от Wladislaw в разделе Подбор Оборудования
    Ответов: 1
    Последнее сообщение: 17.07.2017, 13:35
  3. Замена модели в проекте
    от CEkip в разделе Программируемые реле
    Ответов: 11
    Последнее сообщение: 16.01.2015, 20:04

Метки этой темы

Ваши права

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