PDA

Просмотр полной версии : Существует ли в CoDeSys v.2(v.3) альтернатива #if defined



Вова
02.07.2011, 09:56
Здравствуйте!

В языке Си есть директива #if defined, говорящая препроцессору компилятора, что следующий код нужно компилировать в машинный код (прошивку) или нет, исходя из некоего условия. Пример:
В начале программы

#define a
//#define b
Условие "a" установлено, условие "b" закомментировано.
Далее, где-то в программе

#if defined (a)
ANCON0 = 0b01001100;
#else
ANCON0 = 0b01000011;
#endif
Здесь если установлено условие "а" откомилируется в состав прошивки выделенная красным строка, иначе - выделенная зелёным. Таким образом очень удобно, например, писать код, который будет работать на разных процессорах, описав все различимые вещи в подобных #if defined, а условием выбирая нужный процессор. И смена целевого процессора производится закомментированием всех остальных и выбором одного, то есть пара нажатий кнопок.
Теперь собственно вопрос. Есть ли в кодесис подобная возможность быстрой смены части конфигурации, программы и описания переменных? Т.е., можно ли сделать две альтернативные части конфигурации, скажем, для условия "release" переменные "Right", "Up", "Vertical" и тому подобные сконфигурированы как дискретные входы/выходы ПЛК. А для условия "debug" эти же переменные сконфигурированы как биты входных/выходных переменных подчинённого модуля связи.
Сам вижу решение только в написании двух кусков блоков описания глобальных переменных и закомментирования ненужного целиком. В принципе не намного сложнее чем так, как привык, но это только если касается описания переменных, то есть одного куска. А если нужно по-разному настроить конфигурацию, по-разному написать часть программы, то есть в более общем случае?
В общем, есть какое-либо подобное решение такого вопроса? Спасибо заранее.

PS забыл в названии темы поставить знак вопроса, а отредактировать уже нельзя

Вова
02.07.2011, 10:46
Спасибо, а как это будет выглядеть на st? Графические языки плохо понимаю.

Herzog
02.07.2011, 11:12
Я бы тоже хотел иметь возможность условной компиляции.
Но не для кросплатформенности (такая задача не стоит и никогда не стояла), а для отладки - заменять аппаратные входные сигналы отладочными программными.
А то потом ищи в десятке мест, где вставил дебаговские затычки.

С уважением,
Herzog

Вова
02.07.2011, 21:56
Но не для кросплатформенности (такая задача не стоит и никогда не стояла), а для отладки - заменять аппаратные входные сигналы отладочными программными.
А то потом ищи в десятке мест, где вставил дебаговские затычки.

Кроссплатформенность просто в пример привёл, а так, конечно, тоже нужна именно возможность отладки.

a:=SEL(FLAG_DEBUG,REAL_RightSensor,VIRT_RightSenso r); или POU_FB(in:=SEL(FLAG_DEBUG,REAL_RightSensor,VIRT_Ri ghtSensor));
и т.д.
Честно говоря, ничего не понял. Мне нужно (пока только это), чтобы для каждого символьного имени входа и выхода, используемого в программе, было два объявления, одно вида:

RightSensor AT %IX3.0.0: BOOL; (* реальный вход *)
Другое вида:

RightSensor AT %IW8.0.0.0: BOOL; (* бит входной сетевой переменной, управляемый мастером *)
И чтобы переключать с "реальных" на "виртуальные" входы/выходы можно было "одной кнопкой". А использовать переменные просто:

IF RightSensor THEN...
Без дополнительных сущностей. Такое возможно? Если нет, то всё понятно, и вопрос снимается, но если возможно, то хотелось бы об этом знать, чтобы не изобретать велосипед.

Herzog
03.07.2011, 09:21
вроде я про это и толкую, только вместо if-ов у меня sel, почитайте документациюSel тот же if, только в профиль.

Но условная компиляция имеет гораздо большие возможности.
Например, кусок кода:
#ifdef (флаг-условие А)
... 200 операторов ...
#else
... еще полсотни другого кода ....
#endif
не компилирует одновременно 250 строк, а - в зависимости от условия А - либо первые 200, либо вторые полсотни.

Если же использовать простой if, то Вам может прости не хватить памяти - как для программы, так и для данных. Если Вы отлаживаете запись в retain, то без условной компиляции придется компилировать два набора данных - один истинный, другой отладочный - и объема retain может не хватить.
Так что простые sel и if условную компиляцию не заменяют.

С уважением,
Herzog

Николаев Андрей
03.07.2011, 09:37
Если я все правильно понимаю - ни о какой условной компиляции речи идти не может - в контроллер заливается полностью скомпилированный, машинный код под конкретный тип ЦП.

Herzog
03.07.2011, 10:27
Если я все правильно понимаю - ни о какой условной компиляции речи идти не может - в контроллер заливается полностью скомпилированный, машинный код под конкретный тип ЦП.Вы не правильно поняли.
Условная компиляция подразумевает различные варианты построения программы в соответствии с заданным условием.
Например, PLC работает в системе, используя входные сигналы от внешнего "железа", которого на момент отладки нет. В этом случае можно симитировать внешние сигналы программно, отлаживая другие части программы. Участок кода, выполняющий иммитацию, запускается в компиляцию при задании условной константы (например, #define USB_DEBUG), а когда дело дойдет до реальной отладки на "железе", то условие закоментируется (строка, #define USB_DEBUG комментируется) и компилируется настоящий, а не отладочный код - воспринимающий реальные сигналы со входов.

С уважением,
Herzog

Вова
03.07.2011, 19:18
Вы не правильно поняли.
Условная компиляция подразумевает различные варианты построения программы в соответствии с заданным условием.
Например, PLC работает в системе, используя входные сигналы от внешнего "железа", которого на момент отладки нет. В этом случае можно симитировать внешние сигналы программно, отлаживая другие части программы. Участок кода, выполняющий иммитацию, запускается в компиляцию при задании условной константы (например, #define USB_DEBUG), а когда дело дойдет до реальной отладки на "железе", то условие закоментируется (строка, #define USB_DEBUG комментируется) и компилируется настоящий, а не отладочный код - воспринимающий реальные сигналы со входов.
Совершенно верно. Правильнее было назвать тему "существует ли условная компиляция в кодесис". Странно, что

ни о какой условной компиляции речи идти не может - в контроллер заливается полностью скомпилированный, машинный код под конкретный тип ЦП.

ну да не мне судить стандарты МЭК. Если её нет, придётся извращаться.

Насколько я понял задавшего вопрос, его желание не снимать ПЛК с производства, а через ModbusTCP симитировать входные сигналы если потребуется. Все это будет подаваться с ПК, но не через КДС, поэтому раскоментировать отладочные функции и обратно будет проблематично.
Да, здесь всё верно. Конкретно то, что требуется сейчас, решается-таки относительно просто - в области глобальных переменных целиком комментируется блок либо присвоения реальным входам/выходам переменных "сенсоров" и "выходов", либо блок присвоения этим переменным адресов в области ввода/вывода по TCP. И так как контроллер работает в slave режиме, то переконфигурировать настройки связи не нужно (slave же сам не говорит, если его не спрашивают, поэтому проц в "реальном" режиме отвлекать не будет).
Но вот в случае, когда надо именно менять куски кода в зависимости от отладки/рабочего режима, либо настройки конфигурации, условная компиляция незаменима. Герцог сказал, повторюсь, условная компиляция работает на этапе так сказать прекомпиляции, грубо говоря это то же самое, что закомментировать один кусок кода и раскомментировать другой - скомпилируется только один кусок. Только у условной компиляции намного больше возможностей.
С той же конфигурацией, я вообще не вижу, как можно менять её настройки быстро и "одним махом" кроме как по одному ручками.

Мой же вариант, ПЛК слушает на своем слейв устройстве некий флаг, он всегда FALSE и только при отладке в TRUE. Далее в отличии от IF-ов, SEL можно вставить на вход любого функционального блока, функции и т.п. Причем его входами могут так же выступать блоки и функции, что позволяет уместить отладочный код хоть в 500 строк
Тут снова ничего не понял, нужно курить документацию, пока что спасибо. Но что-то кажется, что это даже не "не совсем то, что нужно", а "совсем не то, что нужно". Но может быть, ошибаюсь, надо почитать про эти SEL.

Herzog
04.07.2011, 09:15
ну да не мне судить стандарты МЭК. Если её нет, придётся извращаться.И здесь более-менее приемлимой альтернативой могло бы стать использование системы контроля версий на уровне исходных текстов.

1. Вы пишете истинный код работающий на "железе", сохраняете его как очередную версию (скажем номер 17).
2. Далее пишите версию в отдельной ветке вариант с отладочным кодом. Сохраняете ее (допустим версия 18). Сохраняете файл различий версий 18 и 17.
3. Долго и нудно отлаживаете в ветке, начинающейся с версии 18, части программы, не связанные с железом (можно, я больше не буду ставить кавычки на этом слове?)
4. Сливаете ветку 18+ с веткой версии 17. Сливаете получившийся файл с файлом различий шага 2 и получаете отлаженный код, готовый к работе на железе.

Преимущество использования СКВ - она выделит Вам все различающиеся места и Вы не забудете ни одно из этих мест, как могло бы быть при редактировании вручную.
Однако все это чисто гипотетически, поскольку сравнения версий на уровне исходных кодов в CodeSys нет (Обсуждалось в этой (http://www.owen.ru/forum/showthread.php?t=10679) теме).
Мне, например, приходится использовать изврат, для использования СКВ типа Tortoise SVN параллельно записывая файл проекта и его исходные коды через макрос.
После чего, поскольку проект не собирается из исходных кодов, вручную (Ctrl-Ins Shift-Ins) вставлять получившийся код в проект.

С уважением,
Herzog

Малышев Олег
04.07.2011, 09:24
В проекте можно исключить из компиляции один POU и включить другой - это конечно не так удобно как ifdef - но работать можно

Herzog
04.07.2011, 10:36
В проекте можно исключить из компиляции один POU и включить другой - это конечно не так удобно как ifdef - но работать можноОчень неудобно.

Если Вы используете переменную, которую нужно исключить в процессе компиляции или заменить на отлаживаемум программную, 40 раз в разных местах программы, то неужели нужно оформлять ее вызов (не функциональные действия, поскольку они разные - все 40 раз, а только вызов!) в виде отдельного ФБ?
Причем после отладки для возвращения к нормальному функционированию - вручную удалять все вызовы ФБ? Впрочем в Вашей идее есть частица рациональности, т.к. отыскивать один ФБ проще - нужно удалить его и затем последовательно по ошибкам компилятора на несуществующий теперь ФБ убрать все ссылки, восстановив наромальную переменную. Муторно правда делать сие вручную.

Но все же заводить специальный ФБ только для вызова переменной - непозволительная роскошь.

С уважением,
Herzog

Игорь Петров
04.07.2011, 11:25
Однако все это чисто гипотетически, поскольку сравнения версий на уровне исходных кодов в CodeSys нет..
Хм, а мы применяем. В ходе отладки пишем на диск Имя_проекта_номер версии. Далее Проект – Сравнить. Удобный инструмент, причем не ограниченный только текстовыми языками (было бы крайне странно для профессиональной МЭК системы). В одной из наших текущих работ рабочая версия фала проекта 47. Удобно что в CoDeSys проект храниться в одном файле. Все версии лежат в отдельной папочке. За 3 сек на любой ноут переносим всю историю и в седло, в поля. Пока, наши прикладники сопротивляются тотальному внедрению СКВ, считают вышеописанный подход ‘ближе к народу’ в глубинке :)

Для СКВ в CoDeSys V2.3 ставится дополнительный платный компонент ENI. Он позволяет интегрироваться с SVN в удобной форме, для текстовых и графических языков без ограничений. Содержит наглядный инструмент для сравнения. В одной базе можно хранить все документы, включая программы Дельфи и др. без всяких извратов.


Условная компиляция в V2.3 есть только на уровне объектов: в глобальных переменных создаем 2 папки с разными наборами объявлений. Проект- Опции - Генератора кода – Исключить объекты – отключаем лишнюю. Для поставленной в этой теме задачи, даже удобнее, ибо переключаемся мышкой, набирать буквы вообще не нужно.

В CoDeSys V3:

{IF defined (variable:bXZ)}
bXZ := TRUE;
{text ''Эта надпись будет показана в окне сообщений компилятора'}
{END_IF}

См. также язык ExST в хелпе и Директивы компилятора.

Herzog
04.07.2011, 15:16
Условная компиляция в V2.3 есть только на уровне объектов: в глобальных переменных создаем 2 папки с разными наборами объявлений. Проект- Опции - Генератора кода – Исключить объекты – отключаем лишнюю.Мало что дает - переключать набор переменных.

Вот я использую какие-то входные данные, поступающие от внешнего железа. Мне важно отладить другой кусок, где они обрабатываются.
Для этого я пишу отладочный программный кусок, где задаю нужные крайние случаи, аварийные комбинации - и отлаживаю их обработку в своей программе. Пишу "генератор поступления сигналов".
Это блок нужно сделать компилируемым по условию на этапе отладки, а далее будут работать настоящие внешние сигналы - если условие компиляции отключить.
Различные наборы данных, как Вы предлагаете, ничем помочь здесь не могут. Дело не в переменных, а в вариациях программного кода.

Ситуация эта типичнейшая. Необходимость ее есть у всех, кто работает с внешним железом, а не собирает из PLC вещь в себе. Почему CodeSys не предусмотрела условной компиляции, инструмента, который есть во всех существующих компиляторах и интегрированных средах разработки - понять не могу.

О неудобстве использовать специализированную СКВ типа ENI в системе, использующей комбинацию PLC и внешнего компи (что является почти стандартным решением большинства практических задач) я уже писал в другой теме.

С уважением,
Herzog

Игорь Петров
05.07.2011, 13:54
Почему CodeSys не предусмотрела условной компиляции, инструмента, который есть во всех существующих компиляторах и интегрированных средах разработки - понять не могу.

О неудобстве использовать специализированную СКВ типа ENI в системе, использующей комбинацию PLC и внешнего компи (что является почти стандартным решением большинства практических задач) я уже писал в другой теме.

Условная компиляция нужна. Это очевидно. Поэтому она сделана в CoDeSys V3. Даже более сильно, чем некоторых популярных компиляторах.

В стандарте МЭК 61131-3 условная компиляция не предусмотрена, как и много чего еще. Совместимость для V2.3 была очень важна. Поэтому самодеятельность недопустима. Есть включение/отключение целых объектов. Полумера с сохранением МЭК совместимости.

В V3 поднимается на уровень выше, чем стандарт МЭК. Тут уже можно импровизировать и даже вводить новые ключевые слова и целые языки программирования.

Про ENI повторю: нет никакой ‘специализированной СКВ типа ENI’. Ставите свой любимый Subversion и к нему же через ENI цепляется CoDeSys. Это шлюз к СКВ, такой же, как Gateway server для портов связи. Полчаса тратим на установку и экономим кучу времени на извратах. Поставить бесплатно я один раз уже предлагал..

-=Vovka=-
15.10.2018, 16:18
Подниму старую тему
А в версии 2.3 есть что-то типа #define?

A.Simonov
18.10.2018, 13:07
Подниму старую тему
А в версии 2.3 есть что-то типа #define?

К сожалению, нет.

capzap
18.10.2018, 13:44
К сожалению, нет.

чёйто? а VAR CONSTANT не подходит разве, спрашивалось же что-то типа

IVM
18.10.2018, 14:05
чёйто? а VAR CONSTANT не подходит разве, спрашивалось же что-то типа

А при чем тут VAR CONSTANT ?

Директива #define определяет идентификатор и последовательность символов, которой будет замещаться данный идентификатор при его обнаружении в тексте программы.

Например, если необходимо использовать TRUE для значения 1, a FALSE для 0 то можно объявить следующие два макроса:

#define TRUE 1
#define FALSE 0

capzap
18.10.2018, 14:27
ну и, напишу я в константах EDINICA : INT := 1; разве слово не заменит целочисленную единицу в формулах?

IVM
18.10.2018, 15:39
ну и, напишу я в константах EDINICA : INT := 1; разве слово не заменит целочисленную единицу в формулах?

У директивы #define более широкие возможности. Здесь почитайте: http://www.c-cpp.ru/books/define

capzap
18.10.2018, 16:06
У директивы #define более широкие возможности. Здесь почитайте: http://www.c-cpp.ru/books/define

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

capzap
19.10.2018, 07:30
Вот один из вариантов моего видения, как можно использовать что то типа define в КДС, например сделать преобразование на своих условиях

-=Vovka=-
19.10.2018, 10:01
А при чем тут VAR CONSTANT ?

Директива #define определяет идентификатор и последовательность символов, которой будет замещаться данный идентификатор при его обнаружении в тексте программы.

Например, если необходимо использовать TRUE для значения 1, a FALSE для 0 то можно объявить следующие два макроса:

#define TRUE 1
#define FALSE 0

Такое определение ST не известно: если в окне переменных написать, то ошибка:
Здесь должно быть: 'VAR', 'VAR_INPUT', 'VAR_OUTPUT' или 'VAR_IN_OUT'
если в теле программы, то:
Требуется ST-выражнение или окончание POU

В догонку, а какой синтаксис определения числа в битовом виде? Типа 0b11001000

Мимоход
19.10.2018, 10:04
Такое определение ST не известно: если в окне переменных написать, то ошибка:
Здесь должно быть: 'VAR', 'VAR_INPUT', 'VAR_OUTPUT' или 'VAR_IN_OUT'
если в теле программы, то:
Требуется ST-выражнение или окончание POU

В догонку, а какой синтаксис определения числа в битовом виде? Типа 0b11001000
2#11001000

а в шестнадцатиричном 16#00CB

-=Vovka=-
19.10.2018, 10:04
У директивы #define более широкие возможности. Здесь почитайте: http://www.c-cpp.ru/books/define

А при чем здесь СИ к языку ST, который больше похож на Паскаль?

-=Vovka=-
19.10.2018, 10:05
2#11001000

А что означает 2 и #

Мимоход
19.10.2018, 10:06
А что означает 2 и #

A:= 2#11001000 -присвоит значение 0b11001000 переменной А

-=Vovka=-
19.10.2018, 10:10
Круто! Никогда б не подумал... :)

-=Vovka=-
19.10.2018, 10:12
2#11001000

а в шестнадцатиричном 16#00CB

Дошло! Число, перед решеткой - система счисления

-=Vovka=-
19.10.2018, 10:27
а зачем думать, когда документация есть
Вот я и не понял написанное в документации:

Обычно при использовании МЭК констант подразумевается наименьший из возможных типов данных. Если нужно точно указать тип константы, применяется префикс типа: <Type>#<Literal>
<Type> указывает необходимый тип. Это может быть: BOOL, SINT, USINT, BYTE, INT, UINT, WORD, DINT, UDINT, DWORD, REAL, LREAL. Тип нужно указывать заглавными буквами.
<Literal> указывает значение константы.
Пример:
var1:=DINT#34;

capzap
19.10.2018, 10:30
Вот я и не понял написанное в документации:

Обычно при использовании МЭК констант подразумевается наименьший из возможных типов данных. Если нужно точно указать тип константы, применяется префикс типа: <Type>#<Literal>
<Type> указывает необходимый тип. Это может быть: BOOL, SINT, USINT, BYTE, INT, UINT, WORD, DINT, UDINT, DWORD, REAL, LREAL. Тип нужно указывать заглавными буквами.
<Literal> указывает значение константы.
Пример:
var1:=DINT#34;

чуть выше этого абзаца всё есть и про решетку и про цифры впереди

-=Vovka=-
19.10.2018, 10:32
допустим я меняю биты в переменной так:

var1 := var1 OR 2#00000001;

мне нужно где-то глобально как-то определить 2#00000001, чтобы писать как-то так:

#define BIT1 2#00000001

var1 := var1 OR BIT1;

-=Vovka=-
19.10.2018, 10:35
чуть выше этого абзаца всё есть и про решетку и про цифры впереди
Спасибо, увидел ;)

capzap
19.10.2018, 10:41
допустим я меняю биты в переменной так:

var1 := var1 OR 2#00000001;

мне нужно где-то глобально как-то определить 2#00000001, чтобы писать как-то так:

#define BIT1 2#00000001

var1 := var1 OR BIT1;
очень рекомендую, помимо документации ознакомиться с тремя библиотеками от oscat.de
на скрине, раз уж у Вас не получается локально объявить константы, показан вариант с глобальными константами и мало того показано как формируется массив при компиляции относительно значения константы

Мимоход
19.10.2018, 10:45
capzap прямо с языка сорвал
39316

-=Vovka=-
19.10.2018, 10:53
capzap, Мимоход, понял, спасибо!

capzap
19.10.2018, 10:56
Такое определение ST не известно: если в окне переменных написать, то ошибка:
Здесь должно быть: 'VAR', 'VAR_INPUT', 'VAR_OUTPUT' или 'VAR_IN_OUT'
если в теле программы, то:
Требуется ST-выражнение или окончание POU

Вы случайно не через нижнее подчеркивание пытались написать VAR CONSTANT

-=Vovka=-
19.10.2018, 11:06
ага, пытался ;)