Если это не поможет, свяжитесь с изготовителем ПЛКCoDeSys V2.310-123Приложение J: Ошибки и предупреждения компилятора3601″<name> is a reserved variable name»Имя данной переменной зарезервировано генератором кода, измените его.3610″ ‘<Name>’ is not supported»Данное свойство не поддерживается в установленной целевой системе.3611″The given compile directory ‘<name>’ is invalid»В ‚Project’ ‚Options’ ‚Directories’ задана несуществующая директория для файлов компилятора.3612″Maximum number of POUs (<number>) exceeded! Compile is aborted.»В проекте используется слишком много POU.
Измените максимум POU в Target Settings / MemoryLayout.3613″Build canceled»Компиляция прервана пользователем.3614″Project must contain a POU named ‘<name>’ (main routine) or a taskconfiguration»Создайте главный POU (т.е. PLC_PRG) или задайте конфигурацию задач.3615″<Name> (main routine) must be of type program»Главный POU (т.е. PLC_PRG) должен иметь тип программа.3616″Programs musn’t be implemented in external libraries»Проект, который предполагается сохранить как внешнюю библиотеку? содержит программы.
Они небудут доступны в библиотеке.3617″Out of memory»Увеличьте размер виртуальной памяти вашего компьютера.CoDeSys V2.310-124Приложение J: Ошибки и предупреждения компилятора3618″BitAccess not supported in current code generator!»Битовый доступ не поддерживается генератором кода данной целевой системы.3619″Object file ‘<name>’ and library ‘<name>’ have different versions!»Убедитесь, что файлы *.lib и *.obj resp. *.hex соответствуют одной версии библиотеки.
Проверьте даты создания этих файлов.3620″The POU ‘<name>’ must not be present inside a library»Вы пытаетесь сохранить библиотеку в формате версии 2.1. В этой версии библиотека не может содержать PLC_PRG, удалите или переименуйте его.3621″Cannot write compile file ‘<name>'»Вероятнее всего, в директории, указанной для файлов компилятора, уже имеется файл с таким именем, имеющий атрибут «Только чтение «. Удалите данный файл либо измените ему права доступа.3622″The symbol file ‘<name>’ could not be created»Вероятнее всего, в директории, указанной для символьных файлов (обычно это директория проекта),уже имеется файл с таким именем, имеющий атрибут «Только чтение «.
Удалите данный файл либоизмените ему права доступа.3623″Cannot write boot project file ‘<name>'»Вероятнее всего, в директории, указанной для загрузочных файлов (специфичных для целевой платформы), уже имеется файл с таким именем, имеющий атрибут «Только чтение «. Удалите данный файллибо измените ему права доступа.3624″Target setting <targetsetting1>=<set value> not compatible with <targetsetting2>=<set value>»Проверьте и исправьте данные установки в диалоге Targetsettings dialogs (вкладка Resources). Если онинедоступны для редактирования, то обратитесь к изготовителю контроллера.3700» POU with name ‘<name>’ is already in library ‘<name>'»Имя POU проекта уже использовано в библиотеке, измените его.CoDeSys V2.310-125Приложение J: Ошибки и предупреждения компилятора3701″Name used in interface is not identical with POU Name»Используйте команду ‘Project’ ‘Rename object’ для изменения памяти POU в организаторе объектовлибо измените имя в окне объявления POU.
Имя POU следует за одним из ключевых слов: PROGRAM, FUNCTION или FUNCTIONBLOCK.3702″Overflow of identifier list»Не более 100 идентификаторов могут быть использованы при объявлении одной переменной.3703″Duplicate definition of identifier ‘<Name>'»Убедитесь, что только один идентификатор ‘<Name>’ присутствует в разделе объявлений POU.3704″data recursion: «<POU 0> -> <POU 1> -> .. -> <POU 0>»»Применен не допустимый вызов экземпляром функционального блока самого себя.3705″<Name>: VAR_IN_OUT in Top-Level-POU not allowed, if there is no Task-Configuration»Создайте конфигурацию задач или убедитесь, что переменные VAR_IN_OUT не используются вPLC_PRG.3720″Address expected after ‘AT'»После ключевого слова AT должен быть указан корректный адрес.3721″Only ‘VAR’ and ‘VAR_GLOBAL’ can be located to addresses»Поместите объявление в область VAR или VAR_GLOBAL.3722″Only ‘BOOL’ variables allowed on bit addresses»Только переменные типа BOOL могут адресовать биты.
Измените адрес или тип переменной.3726″Constants can not be laid on direct addresses»Константы нельзя располагать по прямым адресам.CoDeSys V2.310-126Приложение J: Ошибки и предупреждения компилятора3727″No array declaration allowed on this address»Объявление может быть произведено по указанному адресу. Измените адрес.3728″Invalid address: ‘<address>'»Указанный адрес не определен для заданной конфигурации ПЛК. Измените адрес или конфигурациюПЛК.3729″Invalid type ‘<name>’ at address: ‘<Name>’ «Переменная данного типа не может быть размещена по указанному адресу.
Например: адрес AT%IB1:WORD; не допустим, если включено выравнивание по четным адресам. Данная ошибка можетвозникнуть при попытке разместить массив по недопустимому прямому адресу.3740″Invalid type: ‘<Name>’ «Ошибка в типе данных объявления.3741″Expecting type specification»Ключевое слово или оператор использован вместо типа данных3742″Enumeration value expected»В определении перечисления пропущен идентификатор после скобки либо разделитель.3743″Integer number expected»Перечисления можно инициализировать только целыми значениями (INT).3744″Enum constant ‘<name>’ already defined»Проверьте соблюдение следующих правил при объявлении перечислений:•Все значения в одном перечислении должны быть уникальны.•Во всех глобальных перечислениях все значения должны быть уникальны.•Во всех локальных перечислениях все значения должны быть уникальны.CoDeSys V2.310-127Приложение J: Ошибки и предупреждения компилятора3745″Subranges are only allowed on Integers!»Переменные с ограниченным диапазоном образуются только на целочисленных типах.3746″Subrange ‘<name>’ is not compatible with Type ‘<name>'»Один из пределов диапазона выходит за область значений базового типа.3747″unknown string length: ‘<name>'»Для определения длины строки используется ошибочная константа.3748″More than three dimensions are not allowed for arrays»Нельзя использовать массивы с размерностью более трех.
Используйте ARRAY OF ARRAY при необходимости.3749″lower bound ‘<name>’ not defined»Не задана константа, определяющая нижнюю границу диапазона.3750″upper bound ‘<name>’ not defined»Не задана константа, определяющая верхнюю границу диапазона.3751″Invalid string length ‘<number of characters>'»Заданный размер строки превышает допустимый в данной целевой системе.3752“More than 9 dimensions are not allowed for nested arrays»Массив может быть 1- 2- или 3-мерный. Размерность можно еще увеличить путем вложений массивов(например, «arr: ARRAY [0..2,0..2,0..2] OF ARRAY [0..2,0..2,0..2] OF ARRAY [0..2,0..2,0..2, 0..2] OFDINT».
Максимальная размерность не должна превышать 9. Данная ошибка говорит о превышенииэтого ограничения. Уменьшите вложенность массивов.3760″Error in initial value»CoDeSys V2.310-128Приложение J: Ошибки и предупреждения компилятораИспользуйте для инициализации значение, совместимое с типом переменной. Изменяя объявление,воспользуйтесь диалогом объявлений переменных (Shift/F2 или ‘Edit»Autodeclare’).3761″‘VAR_IN_OUT’ variables must not have an initial value.»Удалите инициализацию в объявлении переменной VAR_IN_OUT.3780″‘VAR’, ‘VAR_INPUT’, ‘VAR_OUTPUT’ or ‘VAR_IN_OUT’ expected»В следующей за определением имени POU строке должно быть одно из перечисленных ключевыхслов.3781″‘END_VAR’ or identifier expected»Введите корректное определение END_VAR в данной строке окна объявлений.3782″Unexpected end»В разделе объявлений: добавьте ключевое слово END_VAR в конце раздела.В разделе кода: добавьте инструкцию, заканчивающую команду (например, END_IF).3783″END_STRUCT’ or identifier expected»Проверьте правильность окончания определения типа.3784″The current target doesn’t support attribute <attribute name>»Данная целевая система не поддерживает переменные такого типа (например, RETAIN, PERSISTENT)3800″The global variables need too much memory.
Increase the available memory in the project options.»Увеличьте число сегментов в опциях диалога Project’ ‚Options’ ‚Build’.3801″The variable ‘<Name>’ is too big. (<size> byte)»Переменная использует тип, занимающий более одного сегментаРазмер сегмента определяется настройкой целевой платформы. Если вы не нашли этого параметра вопциях памяти, свяжитесь с изготовителем ПЛК.CoDeSys V2.310-129Приложение J: Ошибки и предупреждения компилятора3802″Out of retain memory. Variable ‘<name>’, <number> bytes.»Израсходована вся память Retain переменных.
Обновлено: 29.01.2023
I am currently working on ABB PLC, I tried to upload the program from PLC but I cann’t make it. Now I got the backup program which have number of errors. The errors are
Error4268:RECIPE(32):Expression expected.
Error4052:RECIPE(32):»must be a declared instance of function block’ADDSUB’
Please help me on this. How to remove this error?
Lifetime Supporting Member
Join Date: Apr 2004
Location: Israel
Posts: 615
Can you upload the code?
Which PLC are you using?
Member
Join Date: Nov 2011
Location: Aurangabad
Posts: 9
I am using CPU PM571, with CD522, DC522, AX521 modules.
Code is attached here with
Member
Join Date: Dec 2012
Location: Koprivnica, HR
Posts: 418
Quote:
Originally Posted by kam
Error4268:RECIPE(32):Expression expected.
Error4052:RECIPE(32):»must be a declared instance of function block’ADDSUB’
Please help me on this. How to remove this error?
First error was probably due to forgotten semicolon at the end or = instead of :=
Second error: you forgot to declare function block instance as variable:
balash |
View Public Profile |
Find More Posts by balash |
Member
Join Date: Nov 2011
Location: Aurangabad
Posts: 9
I checked program many times, we have given all necessary punctuation marks. Also we have declared each function block.
For ex. TRAVERS_MTR: AC500_REAL_AO;
SPOOLADD: ADDSUB;
Attached Files
Program.zip (40.2 KB, 17 views)
Member
Join Date: Dec 2012
Location: Koprivnica, HR
Posts: 418
well i can’t really much compile cause i have codesys integrated with control builder, and i miss lots of your custom libraries and PLC conf but.
if i am not wrong i think you forgot to name the instance of «addsub» box in rung 32. every functionblock box must have instance that is name of the functionblock box.
that would solve one problem i guess.
not much help with second problem cause i’m cripled without conf and libs needed.
balash |
View Public Profile |
Find More Posts by balash |
Member
Join Date: Nov 2011
Location: Aurangabad
Posts: 9
Thanks for your reply.
I have resolved all the errors by following steps.
1. If you observe the PLC configuration you won’t found CD522 module, so to insert this module I upgraded my CoDeSys.
2. The programmer have declared the Function Blocks by some variable name, but forgot to give that variable name to certain block.
For ex. in OUTPUT (11) he used AC500_REAL_AO, but didn’t give the variable name to this function block, but he declared this block by ‘LEFT SPOOLER3’. So I give the same name to function block. and Bingo.
But not while going online I am going through a error. I have attached this for reference.
Читайте также:
- Плач ярославны что значит выражение
- Я в курсе выражение
- Живет же горстка людей откуда фраза
- Примером применения нормативного подхода в макроэкономическом анализе являются высказывания что
- В жизни шура человеку должно повезти три раза откуда фраза
|
#1 |
Member
Join Date: Nov 2011 Location: Aurangabad Posts: 9 |
Need help on ABB (CoDeSys) errors Hi all, I am currently working on ABB PLC, I tried to upload the program from PLC but I cann’t make it. Now I got the backup program which have number of errors. The errors are Error4268:RECIPE(32):Expression expected. Thank you |
|
|
#2 |
Lifetime Supporting Member
Join Date: Apr 2004 Location: Israel Posts: 616 |
Hi Kam. Can you upload the code? Which PLC are you using? (8{)} (: .) |
|
|
#3 |
Member
Join Date: Nov 2011 Location: Aurangabad Posts: 9 |
I am using CPU PM571, with CD522, DC522, AX521 modules. Code is attached here with |
|
|
#4 |
Member
Join Date: Dec 2012 Location: Koprivnica, HR Posts: 418 |
Quote:
Originally Posted by kam Hi all, Error4268:RECIPE(32):Expression expected. First error was probably due to forgotten semicolon at the end or = instead of := Second error: you forgot to declare function block instance as variable:
|
|
|
#5 |
Member
Join Date: Nov 2011 Location: Aurangabad Posts: 9 |
Hi balash, I checked program many times, we have given all necessary punctuation marks. Also we have declared each function block. For ex. TRAVERS_MTR: AC500_REAL_AO; and so on… |
|
|
#6 |
Member
Join Date: Dec 2012 Location: Koprivnica, HR Posts: 418 |
well i can’t really much compile cause i have codesys integrated with control builder, and i miss lots of your custom libraries and PLC conf but… that would solve one problem i guess… not much help with second problem cause i’m cripled without conf and libs needed… |
|
|
#7 |
Member
Join Date: Nov 2011 Location: Aurangabad Posts: 9 |
Hi balash, Thanks for your reply. I have resolved all the errors by following steps. 1. If you observe the PLC configuration you won’t found CD522 module, so to insert this module I upgraded my CoDeSys. 2. The programmer have declared the Function Blocks by some variable name, but forgot to give that variable name to certain block. But not while going online I am going through a error. I have attached this for reference. |
|
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
1 |
|
14.05.2015, 22:11. Показов 10633. Ответов 10
Добрый день.
__________________ 0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
14.05.2015, 22:11 |
Ответы с готовыми решениями: Внутреняя ошибка связи или нет связи с удалённым сервером Ошибка связи Ошибка связи. Ошибка связи 10 |
91 / 86 / 12 Регистрация: 08.08.2013 Сообщений: 667 |
|
14.05.2015, 23:01 |
2 |
На вкладке «онлайн» галочка «Режим эмуляции» стоит? 0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
14.05.2015, 23:31 [ТС] |
3 |
Спасибо, заработало!! Добавлено через 13 минут 0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
14.05.2015, 23:59 [ТС] |
4 |
Или просто вход А = выход В Миниатюры
0 |
Почетный модератор 28037 / 15768 / 981 Регистрация: 15.09.2009 Сообщений: 67,753 Записей в блоге: 78 |
|
15.05.2015, 08:29 |
5 |
онлайн — логин 0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:48 [ТС] |
6 |
Совершенно верно, уважаемый. Но как увидеть изменение значений выходов? 0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:55 [ТС] |
7 |
Вот Миниатюры
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:56 [ТС] |
8 |
Вход А изменяю, выход В не меняется… 0 |
Почетный модератор 28037 / 15768 / 981 Регистрация: 15.09.2009 Сообщений: 67,753 Записей в блоге: 78 |
|
15.05.2015, 08:57 |
9 |
не нужно. двойной щелчок — ctrl+F7 1 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 09:20 [ТС] |
10 |
O my god, заработалааа! Спасибо! Добавлено через 12 минут 0 |
91 / 86 / 12 Регистрация: 08.08.2013 Сообщений: 667 |
|
15.05.2015, 10:06 |
11 |
сверху, там где объявляются переменные типа ton1:ton; 0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
15.05.2015, 10:06 |
Помогаю со студенческими работами здесь CodeSYs v 2.3.9.43 Codesys ошибка в связи с базой WAIT на CODESYS 2.3 Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 11 |
Продолжаем повествование о прагма-выражениях, которые были описаны в обзорной статье. Напомню что условные прагмы влияют на генерацию кода во время прекомпиляции и компиляции, но не во время исполнения программы. С помощью условных прагм вы влияете, учитывается ли код реализации при компиляции. Например, вы можете сделать это зависимым от того, объявлена ли определенная переменная, существует ли определенный функциональный блок и т.д.
Прагма {define}
Имеет синтаксис:
{define <identifier> <string>}
Задает какой либо идентификатор, который в последствии будет использоваться. Стоит помнить про область видимости. Данный идентификатор будет виден только в пределах того места где он был определен прагмой {define}.
Определение возможно только в разделе кода.
Чтобы было понятнее приложу скриншоты объявления и результаты выполнения.
Если вы заметили, то там еще есть флаги для идентификаторов С и D, С объявлен в глобальных данных, а D в POU программа, где мы и вызываем этот FB.
Прагма {undefine}
Оператор {define} идентификатора <identifier> отменяется, и с этого момента идентификатор снова становится неопределенным. Прагма игнорируется, если указанный идентификатор вообще не определен.
Рассмотрим несколько идентификаторов.
В результате выполнения все хорошо скомпилировалось и все биты были взведены.
Теперь мы немного усложним данные директивы.
Логика здесь в следующем. Если нет C, то определяем идентификатор D.
Прагмы для условной компиляции
Назначение условных прагм - повлиять на генерацию кода в процессе пре-компиляции или в процессе компиляции. Язык реализации ST поддерживает эти прагмы. Это как раз те условия, что мы писали выше. Единственное, что в блоке {IF} есть специальные операторы, которые позволяют нам гибко контролировать условия компиляции.
Оператор defined(<identifier>)
Этот оператор приводит к тому, что выражению присваивается значение ИСТИНА. Требование состоит в том, чтобы идентификатор <identifier> был определен с помощью инструкции {define} и не определялся снова после этого с помощью инструкции {undefine}; в противном случае возвращается ЛОЖЬ.
Примером этому служит все что было выше.
Оператор defined (variable: variable)
Этот оператор приводит к тому, что выражению присваивается значение ИСТИНА, если переменная объявлена в текущей области; в противном случае возвращается ЛОЖЬ.
Если мы возьмем и напишем следующий код:
И попытаемся скомпилировать данную программу, то получим сообщение:
Следует только объявить данную переменную, как все скомпилируется без сообщения и переменной rSum будет присвоено значение 5.
Оператор defined (type: identifire)
Возвращает TRUE когда у нас есть объявленная переменная с соответствующим пользовательским типом данных.
Например: Нам требуется понять есть ли в данном функциональном блоке переменная с каким-то определенным пользовательским типом.
В исходном коде у нас есть и данный тип и прагма условие и какие-то действия.
Никогда не присваивайте значения каким-то объявленным переменным во время прагма выражений для условной компиляции если вы не полностью осознаете последствия.
При выполнении кода у нас будет присвоено значение равное 45.
В то же время стоит помнить
Прагма выражения чувствительны к регистру
И если type вдруг изменится на TYPE то мы получим ошибку
А теперь почему не стоит инициализировать значения переменных при проверки типов. Допустим если мы все оставим как у меня, то может получится следующая ошибка.
Компилятор нам разумеется сообщит об ошибке, но не всегда, особенно если пользовательские типы совпадут.
Оператор defined (pou: <pou name> )
Условный оператор возвращает TRUE если есть FB или Action с таким именем.
Вопрос. Какое значение будет у переменной xInit в следующем примере:
Когда я только начал разбираться, то был уверен, что xInit будет FALSE, однако:
Весь фокус заключался в том, что у меня в проекте есть POU TCPLogic. Так что данное условие удобно применять при проверки целостности. а все ли мы подтянули из нужных нам библиотек.
Оператор defined (task: <identifire)
Возвращает True если мы имеем task с нужным именем.
Рассмотрим список моих задач
В нем есть ровно две задачи. Одна основная другая на визуализацию. В FB я создам условие, при котором, если будет отсутствовать в проекте необходимый TASK, переменная xError станет True.
Так как TASK с идентификатором MainTask1 у меня нет, то мы получили ошибку.
Оператор defined (IsSimulationMode)
Возвращает True, Когда мы находимся в режиме симуляции(эмуляции).
Ну тут даже не нужен пример.
Оператор defined (IsLittleEndian)
Наверно самая нужная прагма, которая позволяет нам правильно представлять данные.
Итог
В данной статье я описал половину доступных прагма операторов для условных выражений. В следующий раз у нас будет остаток и еще чуть чуть про пользовательские прагма-выражения, т.к. они очень нужны. Это всего лишь теоретический материал. Найдете ли вы ему практическое применение неизвестно, но я убежден, что каждый должен отлично знать инструмент на котором работает.
Как я могу выбросить стандартные системные исключения (и, если возможно, создать собственные исключения и выбросить их тоже).
Самое простое, что приходит в голову, — это просто разделить переменную на ноль, но в лучшем случае это просто уловка.
Я нашел упоминания о функции AppGenerateException
в библиотеке CmpApp
, но не могу найти для нее ни документации, ни примеров. Может ли кто-нибудь указать мне на какую-то документацию по этому поводу?
1 ответ
Лучший ответ
Из любопытства я проверил AppGenerateException
и убедился, что он работает. Получил некоторую помощь от этой справочной страницы Codesys .
Я по-прежнему считаю, что это не лучший способ добиться того, что вам нужно, но он может сработать.
К сожалению, у меня 64-битная система, а TRY..CATCH пока не работает в других, кроме 32-битных систем, насколько мне известно, поэтому я не смог проверить отлов.
Добавьте следующие библиотеки:
- CmpApp
- SysExcept
Тогда кажется, что следующий код работает. Установите для ThrowErr
значение true, чтобы получить системное исключение.
PROGRAM PRG_TestThrow
VAR CONSTANT
MY_PRIVATE_EXCEPTION : DWORD := 32001;
END_VAR
VAR
ThrowErr : BOOL; //Set this to TRUE to throw an error
//The next two are for getting App instance
_pApp : POINTER TO CmpApp.APPLICATION;
_Result : SysExcept.SysTypes.RTS_IEC_RESULT;
END_VAR
//Get App instance
_pApp := AppGetCurrent(pResult := ADR(_Result));
IF ThrowErr THEN
ThrowErr := FALSE;
IF _pApp <> 0 THEN
//Throw divide by zero exception
AppGenerateException(pApp:=_pApp, ulException:=RtsExceptions.RTSEXCPT_DIVIDEBYZERO);
//You could use probably any available number as your own custom exception.
//For example the following works BUT not sure if it's ok to this.
//AppGenerateException(pApp:=_pApp, ulException:=MY_PRIVATE_EXCEPTION);
//See RtsExceptions type for available exception codes.
//For my Codesys version, it has largest exception number of 0x2000 so all larger number are free (for now...)
END_IF
END_IF
Кажется, что можно использовать любой пользовательский код исключения, например:
AppGenerateException(pApp:=_pApp, ulException:=MY_PRIVATE_EXCEPTION);
Но это не задокументировано, поэтому я буду осторожен.
1
Quirzo
4 Июн 2020 в 08:48
Если это не поможет, свяжитесь с изготовителем ПЛКCoDeSys V2.310-123Приложение J: Ошибки и предупреждения компилятора3601″<name> is a reserved variable name»Имя данной переменной зарезервировано генератором кода, измените его.3610″ ‘<Name>’ is not supported»Данное свойство не поддерживается в установленной целевой системе.3611″The given compile directory ‘<name>’ is invalid»В ‚Project’ ‚Options’ ‚Directories’ задана несуществующая директория для файлов компилятора.3612″Maximum number of POUs (<number>) exceeded! Compile is aborted.»В проекте используется слишком много POU.
Измените максимум POU в Target Settings / MemoryLayout.3613″Build canceled»Компиляция прервана пользователем.3614″Project must contain a POU named ‘<name>’ (main routine) or a taskconfiguration»Создайте главный POU (т.е. PLC_PRG) или задайте конфигурацию задач.3615″<Name> (main routine) must be of type program»Главный POU (т.е. PLC_PRG) должен иметь тип программа.3616″Programs musn’t be implemented in external libraries»Проект, который предполагается сохранить как внешнюю библиотеку? содержит программы.
Они небудут доступны в библиотеке.3617″Out of memory»Увеличьте размер виртуальной памяти вашего компьютера.CoDeSys V2.310-124Приложение J: Ошибки и предупреждения компилятора3618″BitAccess not supported in current code generator!»Битовый доступ не поддерживается генератором кода данной целевой системы.3619″Object file ‘<name>’ and library ‘<name>’ have different versions!»Убедитесь, что файлы *.lib и *.obj resp. *.hex соответствуют одной версии библиотеки.
Проверьте даты создания этих файлов.3620″The POU ‘<name>’ must not be present inside a library»Вы пытаетесь сохранить библиотеку в формате версии 2.1. В этой версии библиотека не может содержать PLC_PRG, удалите или переименуйте его.3621″Cannot write compile file ‘<name>’»Вероятнее всего, в директории, указанной для файлов компилятора, уже имеется файл с таким именем, имеющий атрибут «Только чтение «. Удалите данный файл либо измените ему права доступа.3622″The symbol file ‘<name>’ could not be created»Вероятнее всего, в директории, указанной для символьных файлов (обычно это директория проекта),уже имеется файл с таким именем, имеющий атрибут «Только чтение «.
Удалите данный файл либоизмените ему права доступа.3623″Cannot write boot project file ‘<name>’»Вероятнее всего, в директории, указанной для загрузочных файлов (специфичных для целевой платформы), уже имеется файл с таким именем, имеющий атрибут «Только чтение «. Удалите данный файллибо измените ему права доступа.3624″Target setting <targetsetting1>=<set value> not compatible with <targetsetting2>=<set value>»Проверьте и исправьте данные установки в диалоге Targetsettings dialogs (вкладка Resources). Если онинедоступны для редактирования, то обратитесь к изготовителю контроллера.3700» POU with name ‘<name>’ is already in library ‘<name>’»Имя POU проекта уже использовано в библиотеке, измените его.CoDeSys V2.310-125Приложение J: Ошибки и предупреждения компилятора3701″Name used in interface is not identical with POU Name»Используйте команду ‘Project’ ‘Rename object’ для изменения памяти POU в организаторе объектовлибо измените имя в окне объявления POU.
Имя POU следует за одним из ключевых слов: PROGRAM, FUNCTION или FUNCTIONBLOCK.3702″Overflow of identifier list»Не более 100 идентификаторов могут быть использованы при объявлении одной переменной.3703″Duplicate definition of identifier ‘<Name>’»Убедитесь, что только один идентификатор ‘<Name>’ присутствует в разделе объявлений POU.3704″data recursion: «<POU 0> -> <POU 1> -> .. -> <POU 0>»»Применен не допустимый вызов экземпляром функционального блока самого себя.3705″<Name>: VAR_IN_OUT in Top-Level-POU not allowed, if there is no Task-Configuration»Создайте конфигурацию задач или убедитесь, что переменные VAR_IN_OUT не используются вPLC_PRG.3720″Address expected after ‘AT’»После ключевого слова AT должен быть указан корректный адрес.3721″Only ‘VAR’ and ‘VAR_GLOBAL’ can be located to addresses»Поместите объявление в область VAR или VAR_GLOBAL.3722″Only ‘BOOL’ variables allowed on bit addresses»Только переменные типа BOOL могут адресовать биты.
Измените адрес или тип переменной.3726″Constants can not be laid on direct addresses»Константы нельзя располагать по прямым адресам.CoDeSys V2.310-126Приложение J: Ошибки и предупреждения компилятора3727″No array declaration allowed on this address»Объявление может быть произведено по указанному адресу. Измените адрес.3728″Invalid address: ‘<address>’»Указанный адрес не определен для заданной конфигурации ПЛК. Измените адрес или конфигурациюПЛК.3729″Invalid type ‘<name>’ at address: ‘<Name>’ «Переменная данного типа не может быть размещена по указанному адресу.
Например: адрес AT%IB1:WORD; не допустим, если включено выравнивание по четным адресам. Данная ошибка можетвозникнуть при попытке разместить массив по недопустимому прямому адресу.3740″Invalid type: ‘<Name>’ «Ошибка в типе данных объявления.3741″Expecting type specification»Ключевое слово или оператор использован вместо типа данных3742″Enumeration value expected»В определении перечисления пропущен идентификатор после скобки либо разделитель.3743″Integer number expected»Перечисления можно инициализировать только целыми значениями (INT).3744″Enum constant ‘<name>’ already defined»Проверьте соблюдение следующих правил при объявлении перечислений:•Все значения в одном перечислении должны быть уникальны.•Во всех глобальных перечислениях все значения должны быть уникальны.•Во всех локальных перечислениях все значения должны быть уникальны.CoDeSys V2.310-127Приложение J: Ошибки и предупреждения компилятора3745″Subranges are only allowed on Integers!»Переменные с ограниченным диапазоном образуются только на целочисленных типах.3746″Subrange ‘<name>’ is not compatible with Type ‘<name>’»Один из пределов диапазона выходит за область значений базового типа.3747″unknown string length: ‘<name>’»Для определения длины строки используется ошибочная константа.3748″More than three dimensions are not allowed for arrays»Нельзя использовать массивы с размерностью более трех.
Используйте ARRAY OF ARRAY при необходимости.3749″lower bound ‘<name>’ not defined»Не задана константа, определяющая нижнюю границу диапазона.3750″upper bound ‘<name>’ not defined»Не задана константа, определяющая верхнюю границу диапазона.3751″Invalid string length ‘<number of characters>’»Заданный размер строки превышает допустимый в данной целевой системе.3752“More than 9 dimensions are not allowed for nested arrays»Массив может быть 1- 2- или 3-мерный. Размерность можно еще увеличить путем вложений массивов(например, «arr: ARRAY [0..2,0..2,0..2] OF ARRAY [0..2,0..2,0..2] OF ARRAY [0..2,0..2,0..2, 0..2] OFDINT».
Максимальная размерность не должна превышать 9. Данная ошибка говорит о превышенииэтого ограничения. Уменьшите вложенность массивов.3760″Error in initial value»CoDeSys V2.310-128Приложение J: Ошибки и предупреждения компилятораИспользуйте для инициализации значение, совместимое с типом переменной. Изменяя объявление,воспользуйтесь диалогом объявлений переменных (Shift/F2 или ‘Edit»Autodeclare’).3761″‘VAR_IN_OUT’ variables must not have an initial value.»Удалите инициализацию в объявлении переменной VAR_IN_OUT.3780″‘VAR’, ‘VAR_INPUT’, ‘VAR_OUTPUT’ or ‘VAR_IN_OUT’ expected»В следующей за определением имени POU строке должно быть одно из перечисленных ключевыхслов.3781″‘END_VAR’ or identifier expected»Введите корректное определение END_VAR в данной строке окна объявлений.3782″Unexpected end»В разделе объявлений: добавьте ключевое слово END_VAR в конце раздела.В разделе кода: добавьте инструкцию, заканчивающую команду (например, END_IF).3783″END_STRUCT’ or identifier expected»Проверьте правильность окончания определения типа.3784″The current target doesn’t support attribute <attribute name>»Данная целевая система не поддерживает переменные такого типа (например, RETAIN, PERSISTENT)3800″The global variables need too much memory.
Increase the available memory in the project options.»Увеличьте число сегментов в опциях диалога Project’ ‚Options’ ‚Build’.3801″The variable ‘<Name>’ is too big. (<size> byte)»Переменная использует тип, занимающий более одного сегментаРазмер сегмента определяется настройкой целевой платформы. Если вы не нашли этого параметра вопциях памяти, свяжитесь с изготовителем ПЛК.CoDeSys V2.310-129Приложение J: Ошибки и предупреждения компилятора3802″Out of retain memory. Variable ‘<name>’, <number> bytes.»Израсходована вся память Retain переменных.
kobrik писал(а):
Михайло писал(а):
1. Проверь, поддерживают ли контроллеры протокол Modbus TCP.В даташитах обоих контроллеров указано что поддерживается Modbus TCP. Я впрочем уже использовал этот протокол для соединения по ОРС. Для меня сейчас загадка, как будет правильно сделать это в Овен.
Пробуй!
kobrik писал(а):
Михайло писал(а):2. Как ты думаешь, имеет ли значение, какой из контроллеров будет клиентом, а какой — сервером? Применительно к нашей задаче автоматизации, конечно.
Да имеет. Т.к. основная программа будет в Сиеменсе, который будет запрашивать данные у ПЛК110.
Действительно, имеет значение, но не настолько, чтобы совсем критично. На самом деле можно настроить обмен по обеим схемам: «Сименс — клиент» и «Сименс — сервер». По схеме «Сименс — сервер» Овен будет запрашивать входные значения для ПИД-регулятора у Сименса, а затем записывать в память Сименса выход ПИД-регулятора. То есть все будет работать.
Но все же логичнее клиентом делать тот узел, который является наиболее важным в системе. Что значит «важным»? Ну это тот узел, который управляет общим процессом. Дело в том, что клиент в отличие от сервера может произвольно приостанавливать обмен, определять ошибки обмена, изменять частоту запросов. Если сетевой кабель между клиентом и сервером оборвался, то такой случай можно обрабатывать в клиенте по определенной программе, например, можно зажечь светодиод, остановить обмен на 30 секунд, затем попробовать сделать один запрос, затем — через каждые 5 минут, через 1 час попыток связи включить сирену и т.д.
kobrik писал(а):
Михайло писал(а):3. Вопрос посложнее: могут ли контроллеры одновременно совмещать функции клиента и сервера? Например, контроллер S7-1200 пишет в память ПЛК110, а ПЛК110 в свою очередь пишет в память S7-1200.
Думаю могут, если правильно распределить адресацию и использовать отдельные блоки Мастер-Слейв.
Фишка в том, что протоколы TCP/IP обеспечивают логическое разделение нескольких разных соединений, то есть по одному кабелю Ethernet можно работать по нескольким протоколам одновременно и они не будут путаться. Главное, чтобы все эти протоколы поддерживали TCP/IP (протоколы-надстройки над TCP/IP). Если пытаться разбираться в TCP/IP, то там довольно сложная организация данных (стек TCP/IP, программные порты и т.д.). Главное для себя выяснить те свойства, которые придаются протоколам, которые поддерживают TCP/IP.
Свойства:
1. Адресация осуществляется через IP-адреса. Для сравнения: есть еще более простая, но негибкая адресация по MAC-адресам.
2. Можно создавать разветвленные Ethernet-сети с коммутаторами, маршрутизаторами.
3. Не нужно контролировать контрольную сумму (это уже делает TCP)
4. Можно совмещать несколько протоколов в одном «проводе». Например, можно работать по Modbus TCP и предоставлять веб-интерфейс. Также можно совместить два совершенно разных Modbus-соединения и они не запутаются друг с другом.
Может я сейчас еще какие-то свойства забыл упомянуть…
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
1 |
|
14.05.2015, 22:11. Показов 10946. Ответов 10
Добрый день.
__________________
0 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
14.05.2015, 22:11 |
Ответы с готовыми решениями: Внутреняя ошибка связи или нет связи с удалённым сервером Ошибка связи Ошибка связи. Ошибка связи 10 |
91 / 86 / 12 Регистрация: 08.08.2013 Сообщений: 667 |
|
14.05.2015, 23:01 |
2 |
На вкладке «онлайн» галочка «Режим эмуляции» стоит?
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
14.05.2015, 23:31 [ТС] |
3 |
Спасибо, заработало!! Добавлено через 13 минут
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
14.05.2015, 23:59 [ТС] |
4 |
Или просто вход А = выход В Миниатюры
0 |
Почетный модератор 28037 / 15768 / 981 Регистрация: 15.09.2009 Сообщений: 67,753 Записей в блоге: 78 |
|
15.05.2015, 08:29 |
5 |
онлайн — логин
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:48 [ТС] |
6 |
Совершенно верно, уважаемый. Но как увидеть изменение значений выходов?
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:55 [ТС] |
7 |
Вот Миниатюры
0 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 08:56 [ТС] |
8 |
Вход А изменяю, выход В не меняется…
0 |
Почетный модератор 28037 / 15768 / 981 Регистрация: 15.09.2009 Сообщений: 67,753 Записей в блоге: 78 |
|
15.05.2015, 08:57 |
9 |
не нужно. двойной щелчок — ctrl+F7
1 |
0 / 0 / 0 Регистрация: 14.05.2015 Сообщений: 7 |
|
15.05.2015, 09:20 [ТС] |
10 |
O my god, заработалааа! Спасибо! Добавлено через 12 минут
0 |
91 / 86 / 12 Регистрация: 08.08.2013 Сообщений: 667 |
|
15.05.2015, 10:06 |
11 |
сверху, там где объявляются переменные типа ton1:ton;
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
15.05.2015, 10:06 |
Помогаю со студенческими работами здесь CodeSYs v 2.3.9.43 Codesys ошибка в связи с базой WAIT на CODESYS 2.3 Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 11 |
Время прочтения
8 мин
Просмотры 8.8K
Введение
За время работы инженером-программистом ПЛК очень часто в ходе разработки находились не самые очевидные, но довольно простые и красивые решения как типовых, так и специализированных задач. В этой статье хочу поделиться опытом и рассказать как сделать разработку под ПЛК приятнее и эффективнее.
Об опыте автора
Опыт работы с ПЛК: 3 года.
Разработка под ПЛК: Beckhoff CX series, SE Modicon M221, WAGO 750 series.
Среды разработки: TwinCAT 3, EcoStruxure Machine Expert-Basic, CODESYS V2.3.
Основная часть опыта приходится на ST+TwinCAT 3, который базируется на CODESYS и IEC 61131.
Статью решил написать так как покидаю OT и перехожу в мир IT. Хочется поделится опытом, чтобы эти 3 года не прошли даром.
Среда разработки
Если часто приходиться комментировать части кода — то узнайте какое сочетание клавиш позволит вам это сделать, это сэкономит много времени. В TwinCAT XAE Shell для комментирования выделенного кода: Ctrl+K+C и Ctrl+K+U для расскомментирования.
Обезвредьте кнопку Stop, чтобы случайно не остановить ПЛК, иногда такое случайное нажатие может привести к нежелательным последствиям. В TwinCAT XAE Shell можно выбрать какие кнопки выводить на toolbar. После локальной отладки программы рекомендую скрыть кнопку остановки ПЛК.
Structured Text
STRING vs WSTRING
В TwinCAT 3 есть возможность использовать Unicode строки. Они могут пригодиться, если необходимо передовать специфические символы, но без необходимости лучше не использовать WSTRING.
STRING |
WSTRING |
|
Format |
ASCII |
Unicode |
Size of character |
BYTE (1 byte) |
WORD (2 bytes) |
Terminator |
Null character |
0 |
Date and time
Почти в любом проекте необходимо знать точное время, вычислять временные интервалы. Часто работа с временем и датами доставляет много проблем и боли. Для себя я нашёл решение, уверен, оно упростит многим жизнь.
F_GetSystemTime() (Функция из модуля Tc2_System)
Эта функция может быть использована для считывания метки времени операционной системы. Временная метка представляет собой 64-разрядное целое значение с точностью до 100 нс. Помимо прочего, его можно использовать для синхронизации задач или измерения времени. Одна единица соответствует 100 нс. Время представляет собой количество интервалов в 100 нс с 1 января 1601 года.
Хранятся отметки в переменных типа ULINT. Зная всё это мы можем без труда рассчитывать интервалы времени с точностью до 100нс! Нужно просто найти разность между отметками.
К сожалению, стандартных функций для преобразования отметки в тип DATETYPE я не нашёл, поэтому пришлось реализовать такую функцию самостоятельно:
(*
:Description: Convert time since 1 January 1601 in 100 ns to DATE_AND_TIME (Преобразует время с 1 Января 1601 года в 100 нс в DATE_AND_TIME)
:Usability: Convert timestamp to datetime
:Note: check then nSystemType more then 01.01.1970 00:00:00
Version history:
Kozhemaykin E. A. | Creating | 16.08.2021;
*)
FUNCTION F_SystemTimeToDT : DT
VAR CONSTANT
SECONDS_BETWEEN_1601_AND_1970 : ULINT := 11_644_473_600;
END_VAR
VAR_INPUT
nSystemTime : ULINT; // One unit is 100 ns since 1 January 1601
END_VAR
VAR
nSeconds : ULINT;
END_VAR
nSeconds := (nSystemTime / 10_000_000) - SECONDS_BETWEEN_1601_AND_1970;
F_SystemTimeToDT := ULINT_TO_DT(nSeconds);
Как видно из кода, сложность заключалась в расчёте интервала между начальным отсчётом системного времени ПЛК и типа DATETIME.
Функция для получения текущей даты/времени в формате DATETIME
(*
:Description: Return datetime now in format DATE_AND_TIME (DT)
:Usability: For getting datetime now in format DATE_AND_TIME (DT)
Version history:
Kozhemaykin E. A. | Creating | 16.08.2021;
*)
FUNCTION F_DateTimeNow : DT
F_DateTimeNow := F_SystemTimeToDT(F_GetSystemTime());
Функция для получения прошедшего времени в формате TIME
(*
:Description: Time passed since tStart (Прошло времени c tStart)
:Usability: If need check how long time past
Version history:
Kozhemaykin E. A. | Creating | 16.08.2021;
*)
FUNCTION F_TimePassed : TIME
VAR_INPUT
tStart: ULINT; (* Время начала в 100нс от 01.01.1601,
текущее время в данном формате предоставляет функция F_GetSystemTime()*)
END_VAR
F_TimePassed := ULINT_TO_TIME((F_GetSystemTime() - tStart) / 10000);
Числовые константы
Большинство документаций по обмену по промышленным протоколам содержит шестнадцатиричные адреса регистров, номера функций, обозначения комманд и т.д. Для битовых операций необходимо представлять числа в двоичном виде. Чтобы эффективно решать задачи, где приходиться отходить от десятичной системы счисления необходимо знать о возможности задания константных чисел заданного типа в заданной системе счисления.
В общем виде задание числовой константы выглядит так:
{datetype}#{numeral system}#value
Пример: DINT#16#A1
Числовые значения могут быть двоичными числами, восьмеричными числами, десятичными числами или шестнадцатеричными числами. Если целое значение не является десятичным числом, его основание должно быть записано перед целочисленной константой, за которой следует символ хэша (#). Для шестнадцатеричных чисел цифры для чисел от 10 до 15, как обычно, представлены буквами A-F.
Типом этих числовых значений может быть BYTE, WORD, DWORD, SINT, USINT, INT, UINT, DINT, UDINT, REAL или LREAL.
ANY type
В языках программирования со статической типизацией довольно сложно делать универсальные функции/функциональные блоки. Когда мне поставили задачу собирать и анализировать различные данные, я решил, что копировать функциональные блоки и изменять в них только тип входного значения — не лучший вариант. Тогда появилась идея приводить все типы к одному и по объективным причинам это тип LREAL.
При реализации функции или метода вы можете объявлять входные данные (VAR_INPUT) как переменные с типом данных ANY. Далее вы можете получить указатель на значение, тип данных и размер переданной на этот вход переменной.
Структура типа данных ANY
TYPE AnyType :
STRUCT
// the type of the actual parameter
typeclass : __SYSTEM.TYPE_CLASS ;
// the pointer to the actual parameter
pvalue : POINTER TO BYTE;
// the size of the data, to which the pointer points
diSize : DINT;
END_STRUCT
END_TYPE
Кроме типа ANY существуют также дочерние типы:
Хочу обратить внимание что на вход типа ANY не может быть подана константа, поэтому в некоторых случаях придётся создавать дополнительную переменную.
Зная про этот тип мне удалось реализовать функцию, которая приводила данные разных типов к LREAL.
Функция по преобразованию числовых типов в LREAL
(*
:Description: Convert ANY_NUM and ANY_BIT to LREAL
:Usability: For development universal functions
:Note:
Valid types is:
ANY_NUM:
- ANY_REAL: REAL, LREAL
- ANY_INT: USINT, UINT, UDINT, ULINT, SINT, INT, DINT, LINT
ANY_BIT:
- BYTE, WORD, DWORD, LWORD
Version history:
Kozhemaykin E. A. | Creating | 01.06.2021;
Kozhemaykin E. A. | {CLASS_TO_LREAL -> TO_LREAL | 03.11.2021;
*)
FUNCTION F_AnyNumToLREAL : LREAL
VAR_INPUT
AnyNum: ANY; // Variable for converting, need have address
END_VAR
VAR
pReal : POINTER TO REAL; // pointer to a variable of the type REAL
pLReal : POINTER TO LREAL; // pointer to a variable of the type LREAL
pUSInt : POINTER TO USINT; // pointer to a variable of the type USInt
pUInt : POINTER TO UINT; // pointer to a variable of the type UInt
pUDInt : POINTER TO UDINT; // pointer to a variable of the type UDInt
pULInt : POINTER TO ULINT; // pointer to a variable of the type ULInt
pSInt : POINTER TO SINT; // pointer to a variable of the type SInt
pInt : POINTER TO INT; // pointer to a variable of the type Int
pDInt : POINTER TO DINT; // pointer to a variable of the type DInt
pLInt : POINTER TO LINT; // pointer to a variable of the type LInt
pByte : POINTER TO BYTE; // pointer to a variable of the type Byte
pWord : POINTER TO WORD; // pointer to a variable of the type Word
pDWord : POINTER TO DWORD; // pointer to a variable of the type DWord
pLWord : POINTER TO LWORD; // pointer to a variable of the type LWord
END_VAR
VAR_OUTPUT
OrginalType: __SYSTEM.TYPE_CLASS;
bInvalidType: BOOL := FALSE;
END_VAR
// Real numbers
IF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_REAL) THEN
pReal := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_REAL;
F_AnyNumToLREAL := TO_LREAL(pReal^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_LREAL) THEN
pLReal := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_LREAL;
F_AnyNumToLREAL := pLReal^;
// Bit's numbers
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_BYTE) THEN
pByte := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_BYTE;
F_AnyNumToLREAL := TO_LREAL(pByte^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_WORD) THEN
pWord := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_WORD;
F_AnyNumToLREAL := TO_LREAL(pWord^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_DWORD) THEN
pDWord := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_DWORD;
F_AnyNumToLREAL := TO_LREAL(pDWord^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_LWORD) THEN
pLWord := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_LWORD;
F_AnyNumToLREAL := TO_LREAL(pLWord^);
// Unsigned integers
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_USINT) THEN
pUSInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_USINT;
F_AnyNumToLREAL := TO_LREAL(pUSInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_UINT) THEN
pUInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_UINT;
F_AnyNumToLREAL := TO_LREAL(pUInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_UDINT) THEN
pUDInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_UDINT;
F_AnyNumToLREAL := TO_LREAL(pUDInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_ULINT) THEN
pULInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_ULINT;
F_AnyNumToLREAL := TO_LREAL(pULInt^);
// Signed integers
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_SINT) THEN
pSInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_SINT;
F_AnyNumToLREAL := TO_LREAL(pSInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_INT) THEN
pInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_INT;
F_AnyNumToLREAL := TO_LREAL(pInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_DINT) THEN
pDInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_DINT;
F_AnyNumToLREAL := TO_LREAL(pDInt^);
ELSIF (AnyNum.TypeClass = __SYSTEM.TYPE_CLASS.TYPE_LINT) THEN
pLInt := AnyNum.pValue;
OrginalType := __SYSTEM.TYPE_CLASS.TYPE_LINT;
F_AnyNumToLREAL := TO_LREAL(pLInt^);
//Invalid type
ELSE
F_AnyNumToLREAL := 0;
bInvalidType := TRUE;
END_IF
REFERENCE
Все знают про указатели (POINTER) и связанные с ними проблемы, так вот многие из них можно избежать, если использовать ссылки(REFERENCE):
-
Ссылки проще в использовании: ссылку не нужно разыменовывать (с помощью ^), чтобы получить доступ к содержимому объекта, на который ссылается ссылка.
-
Более чистый синтаксис для передачи значений: Если вход является ссылкой, то нет необходимости писать ADDR(value).
-
В отличие от указателей, для ссылок компилятор проверяет типы данных при передаче значений.
Стоит отметить, что не всегда ссылкой можно заменить указатель, но когда это возможно, то сделайте это.
Pragmas
Инструкции pragma влияют на свойства переменных, относящихся к процессу компиляции или предкомпиляции. Не поленитесь просмотреть возможности каждого типа pragmas — обязательно найдёте что-то полезное для своего проекта.
Типы pragmas:
-
Message pragmas
-
Attribute pragmas
-
Conditional pragmas
-
Region pragma
-
Pragmas for warning suppression
Union
Union — тип структуры, который позволяет представлять значение в разных типах данных. Данная структура полезна при отладке кода а также при обработке входных значений.
В случае, если нужно обращаться к битам, то это можно сделать через точку. Но у этого способа я вижу огромный недостаток: нет возможности итерироваться по битам. Если нужно разобрать переменную на байты или по 16-бит или другим сложным образом, то вместо написания сложных функций попробуйте сначала сделать это с помощью Union.
SEL, MIN, MAX, LIMIT
Многим программистам ПЛК часто не хватает синтаксического сахара, которого много в других языках программирования. На примере функции SEL хочется показать, что возможно этот «сахар» в виде тернарного оператора не особо нужен.
Если вам нужно выбрать значение в зависимости от условия, выможете сделать это в одну строку:
value := SEL(condition, if false, if true);
Если вам нужно ограничить значение сверху и/или снизу, это также можно сделать в одну строку:
value := MIN(value, max_limit);
value := MAX(value, min_limit);
or
value := LIMIT(min_limit, value, max_limit);
Многие функции и операторы, которых нам не хватает уже написаны — нужно только поискать.
Заключение
В статье описано,то на что лично мне захотелось обратить внимание (ООП решил не трогать). Буду рад если мой опыт принесёт кому-то пользу. Попрошу при использовании предоставленных функций оставлять продолжать version history.
Делитесь своим опытом в комментариях. Чтобы быть в курсе событий и общаться с коллегами предлагаю перейти по ссылкам: тг-канал proPLC, тг-чат proPLC.