Страница 1 из 3 123 ПоследняяПоследняя
Показано с 1 по 10 из 30

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

  1. #1

    Post Модели поведения в CODESYS 2.3

    Как Вы, возможно, знаете PLCOpen разработали документ Creating PLCopen Compliant Libraries, в котором описаны стандартные интерфейсы и поведения функциональных блоков разработанных на языках стандарта МЭК-61131 (всем нам знакомые FBD, CFC, ST и т.д.).
    Не так давно этот документ был переведен на русский язык (доступен по ссылке).

    В стандарте приведены примеры для всех "моделей поведения", но их использование в проекте затруднено т.к. все примеры приведены в виде картинок и текст придется перенабирать вручную.
    В этой теме я буду постепенно выкладывать исходный код ФБ (на языке ST) тех моделей поведения, которые использовал в работе.
    Так Вы сможете просто
    1. скопировать перечисление, содержащее состояния ФБ в Ваш проект;
    2. скопировать "скелет" ФБ;
    3. доработать "скелет" ФБ в соответствии с Вашей задачей (места, которые необходимо доработать под задачу выделил комментариями (* TODO: *)).

    без необходимости перевводить код ФБ вручную.

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

    Итак:
    перечисление, содержащее все состояния ФБ:

    Префикс BM - сокращение от Behavior model (модель поведения)
    Код:
    (*
    Перечисление, содержащее все состояния ФБ
    *)
    TYPE BM_STATES :
    (
    	BM_DORMANT		:= 0, 		(* Ожидание запуска *)
     	BM_EXECUTING		:= 1, 		(* Выполнение операции *)
     	BM_DONE			:= 2, 		(* Завершение операции *)
     	BM_ERROR		:= 3, 		(* Ошибка *)
     	BM_RESETTING		:= 4, 		(* Переинициализация *)
    	BM_ABORTING		:= 5,		(* Прерывание работы ФБ *)
    	BM_ABORTED		:= 6		(* Работа ФБ прервана *)
    );
    END_TYPE


    ETrig
    • Старт по переднему фронту;
    • Нет возможности прерывания до окончания работы блока;
    • Нет ограничения по времени цикла;
    • Нет ограничения по времени выполнения.
    Исходный код:

    Интерфейс ФБ
    Код:
    FUNCTION_BLOCK ETrig
    VAR_INPUT
    	xExecute				: BOOL;
    END_VAR
    VAR_OUTPUT
    	xBusy					: BOOL;
    	xDone					: BOOL;
    	xError					: BOOL;
    END_VAR
    VAR
    	m_eState 				: BM_STATES			:= BM_DORMANT;
    	m_xNeedToChangeState			: BOOL;
    	m_xResetRequest 			: BOOL;
    	m_xIsExecutionDone			: BOOL;
    	m_xIsExecutionFail			: BOOL;
    END_VAR
    Тело ФБ
    Код:
    m_xNeedToChangeState := TRUE;
    WHILE m_xNeedToChangeState DO
     	m_xNeedToChangeState := FALSE;
     	CASE m_eState OF
     		BM_DORMANT:
    			IF xExecute THEN
    				xBusy  := TRUE;
    				m_eState := BM_EXECUTING;
    				m_xNeedToChangeState := TRUE;
    				(* TODO: запомнить состояние остальных входов *)
    			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;
    				m_xNeedToChangeState := TRUE;	
    			ELSIF m_xIsExecutionDone THEN
    				m_eState := BM_DONE;
    				m_xNeedToChangeState := TRUE;
    			END_IF
    		BM_DONE:
    			IF xDone AND (m_xResetRequest OR NOT xExecute) THEN
    			 	 m_eState := BM_RESETTING;
    			 	 m_xNeedToChangeState:= TRUE;
    			ELSE
    				xBusy := FALSE;
    				xDone := TRUE;
    				m_xResetRequest := NOT xExecute;
    				m_xNeedToChangeState:= FALSE;
    			END_IF
    		BM_ERROR:
    			IF xError AND (m_xResetRequest OR NOT xExecute) THEN
    			 	m_eState := BM_RESETTING;
    			 	m_xNeedToChangeState:= TRUE;
    			ELSE
    			 	xBusy := FALSE;
    			 	xError := TRUE;
    			 	m_xResetRequest := NOT xExecute;
    			 	m_xNeedToChangeState:= FALSE;
    			END_IF
    		BM_RESETTING:
    			(* TODO: освобождение ресурсов здесь *)
    			xBusy := FALSE;
    			xDone := FALSE;
    			xError := FALSE;
    			m_eState := BM_DORMANT;
    			m_xNeedToChangeState := m_xResetRequest;
    			m_xResetRequest := FALSE;
    			m_xIsExecutionDone := FALSE;
    			m_xIsExecutionFail := FALSE;
    	END_CASE
    END_WHILE

    ETrigA
    • Старт по переднему фронту;
    • Есть возможность прерывания до окончания работы блока;
    • Нет ограничения по времени цикла;
    • Нет ограничения по времени выполнения.

    Исходный код:

    Интерфейс ФБ
    Код:
    FUNCTION_BLOCK ETrigA
    VAR_INPUT
    	xExecute				: BOOL;
    	xAbort					: BOOL;
    END_VAR
    VAR_OUTPUT
    	xBusy					: BOOL;
    	xDone					: BOOL;
    	xError					: BOOL;
    	xAborted				: BOOL;
    END_VAR
    VAR
    	m_eState 				: BM_STATES			:= BM_DORMANT;
    	m_xNeedToChangeState			: BOOL;
    	m_xResetRequest 			: BOOL;
    	m_xIsExecutionDone			: BOOL;
    	m_xIsExecutionFail			: BOOL;
    	m_xIsAbortingDone			: BOOL;
    	m_xIsAbortingFail			: BOOL;
    END_VAR
    Тело ФБ
    Код:
    m_xNeedToChangeState := TRUE;
    WHILE m_xNeedToChangeState DO
     	m_xNeedToChangeState := FALSE;
     	CASE m_eState OF
     		BM_DORMANT:
    			IF xExecute THEN
    				xBusy  := TRUE;
    				m_eState := BM_EXECUTING;
    				m_xNeedToChangeState := TRUE;
    				(* TODO: запомнить состояние остальных входов *)
    			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;
    				m_xNeedToChangeState := TRUE;	
    			ELSIF m_xIsExecutionDone THEN
    				m_eState := BM_DONE;
    				m_xNeedToChangeState := TRUE;
    			END_IF
    			IF xAbort THEN
    				m_xNeedToChangeState := TRUE;
    				m_eState := BM_ABORTING;
    			END_IF
    		BM_DONE:
    			IF xDone AND (m_xResetRequest OR NOT xExecute) THEN
    			 	 m_eState := BM_RESETTING;
    			 	 m_xNeedToChangeState:= TRUE;
    			ELSE
    				xBusy := FALSE;
    				xDone := TRUE;
    				m_xResetRequest := NOT xExecute;
    				m_xNeedToChangeState:= FALSE;
    			END_IF
    		BM_ERROR:
    			IF xError AND (m_xResetRequest OR NOT xExecute) THEN
    			 	m_eState := BM_RESETTING;
    			 	m_xNeedToChangeState:= TRUE;
    			ELSE
    			 	xBusy := FALSE;
    			 	xError := TRUE;
    			 	m_xResetRequest := NOT xExecute;
    			 	m_xNeedToChangeState:= FALSE;
    			END_IF
    		BM_RESETTING:
    			(* TODO: освобождение ресурсов здесь *)
    			xBusy := FALSE;
    			xDone := FALSE;
    			xError := FALSE;
    			m_eState := BM_DORMANT;
    			m_xNeedToChangeState := m_xResetRequest;
    			m_xResetRequest := FALSE;
    			m_xIsExecutionDone := FALSE;
    			m_xIsExecutionFail := FALSE;
    			m_xIsAbortingDone := FALSE;
    			m_xIsAbortingFail := FALSE;
    		BM_ABORTING:
    			(* TODO:  m_xIsAbortingDone должно стать TRUE, когда прерывание операции выполнено *)
    			m_xIsAbortingDone := TRUE;
    			(* TODO: m_xIsAbortingFail должно стать TRUE, когда возникла ошибка прерывания операции *)
    			m_xIsAbortingFail := FALSE;
    			IF m_xIsAbortingFail THEN
    				m_eState := BM_ERROR;
    				m_xNeedToChangeState := TRUE;	
    			ELSIF m_xIsAbortingDone THEN
    				m_eState := BM_ABORTED;
    				m_xNeedToChangeState:= TRUE;
    			END_IF
    		BM_ABORTED:
    			IF xAborted AND (m_xResetRequest OR (NOT xExecute)) THEN
    				m_eState := BM_RESETTING;
    				m_xNeedToChangeState:= TRUE;
    			ELSE
    				xBusy := FALSE;
    				xAborted := TRUE;
    				m_xResetRequest := NOT xExecute;
    				m_xNeedToChangeState:= FALSE;
    			END_IF
    	END_CASE
    END_WHILE

    P.S. Не смотря на то, что в теме указано "Модели поведения в CODESYS 2.3". Этот же исходный код будет работать и в CODESYS 3.5.

    Заготовка оформления:

    Название модели поведения
    Краткое описание блока
    Исходный код:

    Интерфейс ФБ
    Код:
    
    
    Тело ФБ
    Код:
    
    
    Последний раз редактировалось Евгений Кислов; 13.03.2019 в 19:44.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

    По умолчанию

    не опасно ли всё через while делать и отдавать на использование неподготовленному пользователю
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

  3. #3

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    не опасно ли всё через while делать и отдавать на использование неподготовленному пользователю
    Так реализовано в стандарте.
    Можно реализовать без WHILE, но, в таком случае, выполнение работы ФБ займет как минимум 3 цикла ПЛК (DORMANT -> EXECUTING -> DONE).
    Реализация внутри WHILE позволяет (если задача выполнена уже сейчас) сразу по переднему фронту xExecute перейти на DONE.
    Я выделил места, в которые нужно внести изменения.
    Если неподготовленный пользователь решит менять условия перехода на следующий шаг, а точнее, значение переменной m_xNeedToChangeState, то да, это может привести к "зависанию".
    Но здесь даны ссылки на стандарты не зря. Пользователь, изучивший стандарты, уже не будет неподготовленным. Ведь так?
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

    По умолчанию

    я имел ввиду что неподготовленный пользователь считает документацию для дураков, т.ч. ни кто не будет читать стандарты а захочет сразу применять выложенный код. Я кстати пока не читал документацию, но хотел бы предложить переделать всё это в функцию, а все локальные переменные оформить в UDT структуру и подавать на вход функции через указатель, как мне кажется функция охладит пыл создавать достаточно сложный код

    ЗЫ прочитал, в доках используется REPEAT почему используете WHILE
    Последний раз редактировалось capzap; 08.07.2018 в 18:39.
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

  5. #5

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    я имел ввиду что неподготовленный пользователь считает документацию для дураков, т.ч. ни кто не будет читать стандарты а захочет сразу применять выложенный код. Я кстати пока не читал документацию, но хотел бы предложить переделать всё это в функцию, а все локальные переменные оформить в UDT структуру и подавать на вход функции через указатель, как мне кажется функция охладит пыл создавать достаточно сложный код
    Я не думаю, что неподготовленный пользователь полезет менять то, в чем не понимает.
    Для неподготовленных - четко указано, где и что писать.
    Подготовленные пользователи, наоборот, могут оптимизировать этот "скелет" так, чтобы он более четко соответствовал решаемой задаче.

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

    А решаемую при помощи этого ФБ задачу программист реализует сам, накладывая решение на "скелет".

    Обратите внимание на п.3 списка выше.
    Есть модель поведения, которая позволяет ограничить время, которое ФБ потратит в 1 цикле ПЛК, после чего отложит выполнение на следующий цикл ПЛК (это модели поведения с буквами TL в названии (например, ETrigTl)).
    Т.е. если есть предпосылки для того, что работа ФБ будет сильно увеличивать время цикла ПЛК, нужно будет просто использовать соответствующую модель поведения, и сама модель позаботиться о том, чтобы отложить выполнение при достижении ограничения.
    Пользователю лишь останется написать код так, чтобы при следующем вызове выполнение продолжилось с того же места, на котором было прервано в предыдущем цикле.

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

    Цитата Сообщение от capzap Посмотреть сообщение
    все локальные переменные оформить в UDT структуру
    В данном случае не вижу преимуществ в передаче структуры в функцию и ФБ.
    Заменив переменные ФБ на структуру мы обяжем пользователя работать со структурой в его программе (мониторить xDone, xBusy, изменять xExecute), что на CFC совсем не очевидно.
    По итогу результат будет тем же, но
    Цитата Сообщение от capzap Посмотреть сообщение
    подавать на вход функции через указатель
    новичков это отпугнет.
    Последний раз редактировалось Осинский Алексей; 08.07.2018 в 18:57.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

  6. #6

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    ЗЫ прочитал, в доках используется REPEAT почему используете WHILE
    Мы не используем цикл REPEAT т.к. его использование ухудшает читабельность программы:
    чтобы понять до каких пор будет выполняться цикл нужно пролистать до конца цикла и только потом станет понятно условие выхода.

    Цикл WHILE лишен этого недостатка: условие выхода становится понятным уже на 1й строке.
    Последний раз редактировалось Осинский Алексей; 08.07.2018 в 18:55.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

    По умолчанию

    SysLibFile, SysLibMem, SysLibSocket мы разве не используем ADR(что_то_там) и ни кого не пугает, я бы и эти ФБ закрыл в запароленную библиотеку, а условия переходов между кейсами вывел во входные аргументы. Использование структуры дисциплинирует, быстрее относительно других способов можно увидеть чего и сколько используется
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

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

    По умолчанию

    Цитата Сообщение от Осинский Алексей Посмотреть сообщение
    Мы не используем цикл REPEAT т.к. его использование ухудшает читабельность программы:
    чтобы понять до каких пор будет выполняться цикл нужно пролистать до конца цикла и только потом станет понятно условие выхода.

    Цикл WHILE лишен этого недостатка: условие выхода становится понятным уже на 1й строке.
    не совсем так, переменную мы найдем в while в начале блока, а в repeat в конце блока, а условие выхода нужно искать в теле обоих циклов и чтоб быть уверенным что оно несколько раз не изменяется, в каждом случае надо пролистывать от начала и до конца блока, между ними лишь одна разница repeat один раз но выполниться
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

  9. #9

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    SysLibFile, SysLibMem, SysLibSocket мы разве не используем ADR(что_то_там) и ни кого не пугает, я бы и эти ФБ закрыл в запароленную библиотеку, а условия переходов между кейсами вывел во входные аргументы.
    Используем только потому, что нет другого выхода.
    Вспоминая себя, когда я только-только знакомился с программированием, указатели воспринимались как что-то сверх естественное.
    В то время как простые операции я мог представить себе в голове, то большая часть операций с указателями выглядела как магия.
    Это если не брать во внимание то, что мы (автор функции) никак не можем проверить передают ли нам по указателю те данные, которых мы ожидаем, или случайный набор байт.
    Указатели - мощный инструмент, но, на мой взгляд, их использования стоит избегать там, где для этого существуют другие инструменты.

    Цитата Сообщение от capzap Посмотреть сообщение
    Использование структуры дисциплинирует, быстрее относительно других способов можно увидеть чего и сколько используется
    Хотя мне и ставили в укор то, что я "фанат функций", объективных преимуществ использования набора "структура + функция" против функционального блока в данной ситуации я не вижу.
    Я использую
    1. набор "cтруктура + функция" в тех случаях, когда результат работы 100% будет получен сразу после вызова функции;
      В данном случае структура используется для того, чтобы сократить количество передаваемых функции параметров.
    2. ФБ в тех случаях, когда выполнение задачи предположительно может потребовать более 1 цикла ПЛК и необходимо хранить промежуточные значения.
    Последний раз редактировалось Осинский Алексей; 08.07.2018 в 19:45.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

  10. #10

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    не совсем так, переменную мы найдем в while в начале блока, а в repeat в конце блока, а условие выхода нужно искать в теле обоих циклов и чтоб быть уверенным что оно несколько раз не изменяется, в каждом случае надо пролистывать от начала и до конца блока, между ними лишь одна разница repeat один раз но выполниться
    Мы не используем (за исключением редких случаев) прерывание цикла при помощи CONTINUE и EXIT т.к. это ухудшает читабельность кода (п. 6.5.2 PLCopen Coding Guidelines):
    пробежавшись глазами по телу цикла легко пропустить такой оператор, и сидеть, недоумевая, над программой, в попытках понять, почему этот конкретный участок кода не выполняется.
    А спустя какое-то время увидеть, что перед ним стоял оператор EXIT.

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

    UPD: Из тех же соображений избегаем использования RETURN.
    Последний раз редактировалось Осинский Алексей; 08.07.2018 в 19:40.
    OSCAT.ru читать стандарты и статьи по автоматизации на русском без регистрации и СМС

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

Похожие темы

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

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

Ваши права

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