PDA

Просмотр полной версии : Какой синтаксис инициализации массива структур



mikola_wow
12.02.2019, 17:13
ДОБРЫЙ ДЕНЬ.
Нужна помощь в синтаксисе Кодесиса 3.5
Есть структура

TYPE Recept_STRUCT :
STRUCT
name:STRING (50);
ves_shebnja:REAL;
ves_peska:REAL;
ves_cementa:REAL;
ves_voda:REAL;
ves_ximdob:REAL;
time_zames:INT;

END_STRUCT
END_TYPE

Необходимо сделать инициализацию массива стрктур в Retain области.

Инициализация по типу:
arr_recept: ARRAY [0..10] OF Recept_STRUCT :=
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ,
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600) ;

ВЫДАЕТ ОШИБКУ компиляции!
Как это сделать ?
Заранеее спасибо.

Евгений Кислов
12.02.2019, 17:44
Все содержимое надо поместить в квадратные скобки.
[ (инициализация элементов структуры 1), (инициализация элементов структуры 2), ... ];

Jobin
24.12.2019, 01:16
Доброй ночи! На второй день знакомства с CoDeSys 3.5 не нашёл ответа на вопрос
из той же оперы после применения квадратных вот только здесь обнаруженных скобок -

PROGRAM PLC_PRG
VAR
wtpr1: INT := 65;
wtpr2: INT := 78;
wtpr3: INT := 25;
wtpr4: INT := 59;
wt1:INT;
wt2:INT;
wt3:INT;
wt4:INT;
wt: ARRAY [1..4] OF INT:= [wt1,wt2,wt3,wt4];//[wt1:=120,wt2:=56,wt3:=84,wt4:=33]
check:INT;

END_VAR

Компилятор ругается на попытку обратиться к элементу через точку - wt.wt1:=wtpr1;
считает, что wt вообще не структурированная штука. Никаких вариантов синтаксиса
нигде не обнаружил. Может, я слепой - подскажите, чего не хватает, чтобы записывать
значения в массив.

C0018: 'wt.wr1:=wtpr1' is no valid assignment target
C0062: 'wt' не является структурированной переменной

Добавлю после экспериментов. Компилятор не бракует такой вариант
wt[wt4]:=wt4:=wtpr4;
check:=wt[wt4];
и в эмуляторе действительно все четыре значения дружно изменяются, вот только в таблице
эмулятора значения массива wt[n] по нулям. В "Ассистенте ввода" wt[wt4] нет конечно, то есть
это действительно обращение, а не переменная.
И как эти нули понимать?..

krollcbas
24.12.2019, 03:32
Joblin, сложно понять что Вы делаете и зачем так.

Ну объявили переменные. Хорошо, но весь этот замут с инициализацией так делать бы и не стал.
Сделал бы так (пример одной ячейки)


IF NOT INIT THEN
wt[1]:=120;
и.т.д
INIT:=TRUE;
END_IF;

Jobin
24.12.2019, 05:25
Joblin, сложно понять что Вы делаете и зачем так.

))) Так это... разбираюсь с CoDeSys'ом... третий день пошёл.
Выяснял, как ведёт себя массив с переменными. Например, хочу таким образом наработку
нескольких агрегатов контролировать, сохранять и использовать для ротации.
Сама по себе инициализация не нужна в такой задаче.

Ну объявили переменные. Хорошо, но весь этот замут с инициализацией так делать бы и не стал.
Сделал бы так (пример одной ячейки)

Спасибо, этим и продолжу.

Но теперь вопрос именно в том, чему верить - нулям в табличке массива в эмуляторе,
или контрольным переменным, которые вроде честно читают из массива значения -
косяк эмулятора или мой.
Поэтому неуютно )))

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

Jobin
24.12.2019, 15:23
)))

Спасибо! Но пока не укладывается в голове, как в разделе констант
объявить наработку насосов.

Компиляция вроде решена. Доки вроде читал. Вопрос реально
теперь в том - кто неадекватен - я или эмулятор.
Все среды разработки с косяками. Точно знаю.
И я с косяками. Поэтому вопрос - чей косяк -
актуален.

Спасибо. Точку на квадратные скобки
вчера заменил. Работает. Но вопросов меньше не стало.

Jobin
24.12.2019, 16:23
Судя по тому, что сброс как раз и записывает в массив последние значения -
это подразумевает - эмулятор именно на запись в retain намекает.
Вообще вопрос был о дыре в доках по синтаксису 3.5.
И ребусах с эмулятором.

И уж извините - но если чтение всей недодокументации решает
все вопросы - зачем тогда форумы?

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

Jobin
24.12.2019, 16:50
Доки перелопатил прежде чем задать вопрос.
Ткните носом в ответ в доках пенсионера автоматизации -
скажу спасибо!

Перманентное жлобство производителей по части инфы бесит -
типа хочешь купить колбасу - купи весы для каждого сорта этой дряни.
Причём весы именно конкретного производителя.
Вот и весь МЭК.

Jobin
03.01.2020, 14:55
"не чего на зеркало пенять если рожа крива" (орфография автора - capzap)

)))

Спасибо всем ответившим!
Вся возня с записью наработки произвольного числа агрегатов,
сортировкой зафиксированных значений этого массива и нумерацией
агрегатов для последующей ротации по наработке и резервированием
по авариям в результате заняла около сорока строчек вместе с комментариями
и имитацией переменных. И новогоднюю неделю знакомства с нюансами ST на CoDeSys'е...

Serhioromano
07.01.2020, 08:56
Для бушующих поколений. Если при инициализации вы инициируете один и те же значения то можно их инициировать при объявлении самой структуры.



TYPE Recept_STRUCT :
STRUCT
name:STRING (50) :='B100';
ves_shebnja:REAL :=100;
ves_peska:REAL :=200;
ves_cementa:REAL :=300;
ves_voda:REAL :=400;
ves_ximdob:REAL :=500;
time_zames:INT :=600;
END_STRUCT
END_TYPE

Или же если при инициализации массива можно сиользовать групповое назначение.


arr_recept: ARRAY [0..10] OF Recept_STRUCT := [
11(
(name:='B100' , ves_shebnja:=100, ves_peska:=200, ves_cementa:=300, ves_voda:=400, ves_ximdob:=500, time_zames:=600)
)
];

Все подобные тонкости описаны в моей книге по ST :)

RomeoVar
08.07.2021, 13:17
Извините, не в своей теме вопрос: Есть массив структур, делаю инициализацию структур значенями по умолчанию. Хочу чтобы эти значения были защищены от изменения. Возможно ли такое?


TYPE MB_SWORD :
STRUCT
iChannelIndex : INT;
uiDataAddr : UINT;
uiDataCount : UINT := 1;
wData : WORD;
END_STRUCT
END_TYPE


Присвоенное значение хочу защитить от изменения
uiDataCount : UINT := 1;
Можно ли это сделать?

Евгений Кислов
08.07.2021, 13:57
Извините, не в своей теме вопрос: Есть массив структур, делаю инициализацию структур значенями по умолчанию. Хочу чтобы эти значения были защищены от изменения. Возможно ли такое?


TYPE MB_SWORD :
STRUCT
iChannelIndex : INT;
uiDataAddr : UINT;
uiDataCount : UINT := 1;
wData : WORD;
END_STRUCT
END_TYPE


Присвоенное значение хочу защитить от изменения
uiDataCount : UINT := 1;
Можно ли это сделать?

Максимум, что можно сделать:

uiDataCount : UINT(1..1) := 1;

Тогда если ввести любой литерал, кроме 1 - компилятор выдаст ошибку.
Но если вместо литерала присвоить переменную - то ошибок не будет, потому что это не константа, а тип с ограничением диапазона (subrange).

RomeoVar
08.07.2021, 14:11
Спасибо,
Плохо конечно что можно изменить, но терпимо.
А что если рецепт прикрутить? И ограничить значения минимальным/максимальным значением?
И при загрузке заполнять переменные значениями из рецепта

Евгений Кислов
08.07.2021, 14:14
Спасибо,
Плохо конечно что можно изменить, но терпимо.
А что если рецепт прикрутить? И ограничить значения минимальным/максимальным значением?
И при загрузке заполнять переменные значениями из рецепта

Я не думаю, что это усложнение повлияет на ситуацию.

RomeoVar
08.07.2021, 18:24
а как же примеры из оскат, создается структура, создается VAR_GLOBAL CONSTANT и в нем объявляется такой пользовательский тип данных или вопрос не в этом

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

Codesys не дает целостного механизма работы по Modbus если нужно обмениваться достаточно большим количеством переменных. Если использовать таблицу каналов, каждый канал имеет свой индекс, к нему привязана переменная. Если обмен по флагу - нужны задержки и я ХЗ как нормально проверить что все данные записаны (пробовал вешать на циклическую задачу с малым временем вызова - все-равно бывают факты пропуска).
Если использовать "приложение" ModbusChannel вроде все хорошо, НО (огромное такое) в качестве аргумента ModbusChannel принимает iChannelIndex и нужно придумать связку Переменная -> К***** а ее нет. В переменную данные записал но хрен-то я знаю номер канала к которой привязана переменная.
БОлее-менее OwenCommunication, там нет каналов - чисто регистры устройства. Но к переменным нужно привязать адреса регистров, чтоб можно было в цикле отправлять данные и не париться, что я собственно и сделал. Такая вот структура (примерно, прошу не пинать)


TYPE MB_DWORD :
STRUCT
iChannelIndex : INT;
uiDataAddr : UINT;
uiDataCount : UINT := 2;
unData : U_DW2W;
END_STRUCT
END_TYPE


И потом собираю все регистры в Массив устройства (тут уже я подумываю о FB с закрытыми свойствами, но это тож не сильно поможет). И полю uiDataAddr определяю регистр памяти устройства. Но если, случайно, эти значения изменятся.... все сломается...


TYPE ST_SERVO_RW :
STRUCT
wInputSignal: ARRAY[0..7] OF MB_SWORD :=
[
(uiDataAddr := 500),
(uiDataAddr := 501),
(uiDataAddr := 502),
(uiDataAddr := 503),
(uiDataAddr := 504),
(uiDataAddr := 505),
(uiDataAddr := 506),
(uiDataAddr := 507)
];
wdwLevInSignal: MB_DWORD := (uiDataAddr := 508);
wdwOutSignal: MB_DWORD := (uiDataAddr := 510);
wP0_ConMode: MB_SWORD := (uiDataAddr := 0);
wP2_EncTypeRes: MB_SWORD := (uiDataAddr := 2);
wP205_Gear: MB_SWORD := (uiDataAddr := 205);
wP206_Gear: MB_SWORD := (uiDataAddr := 206);
wP225_Gear: MB_SWORD := (uiDataAddr := 225);
wP226_Gear: MB_SWORD := (uiDataAddr := 226);
wP525_Coin: MB_SWORD := (uiDataAddr := 525);
wP700_IntPosP: MB_SWORD := (uiDataAddr := 700);
wP765_IntPosDZT: MB_SWORD := (uiDataAddr := 765);
wP770_IntPosSw: MB_SWORD := (uiDataAddr := 770);
stHoming: HOME_POS_REGS;
stIntPos: ARRAY[0..15] OF INT_POS_REGS :=
[
(unIntPos := (uiDataAddr := 701), wIntPosACDC := (uiDataAddr := 749), wIntPosSPD := (uiDataAddr := 733)),
(unIntPos := (uiDataAddr := 703), wIntPosACDC := (uiDataAddr := 750), wIntPosSPD := (uiDataAddr := 734)),
(unIntPos := (uiDataAddr := 705), wIntPosACDC := (uiDataAddr := 751), wIntPosSPD := (uiDataAddr := 735)),
(unIntPos := (uiDataAddr := 707), wIntPosACDC := (uiDataAddr := 752), wIntPosSPD := (uiDataAddr := 736)),
(unIntPos := (uiDataAddr := 709), wIntPosACDC := (uiDataAddr := 753), wIntPosSPD := (uiDataAddr := 737)),
(unIntPos := (uiDataAddr := 711), wIntPosACDC := (uiDataAddr := 754), wIntPosSPD := (uiDataAddr := 738)),
(unIntPos := (uiDataAddr := 713), wIntPosACDC := (uiDataAddr := 755), wIntPosSPD := (uiDataAddr := 739)),
(unIntPos := (uiDataAddr := 715), wIntPosACDC := (uiDataAddr := 756), wIntPosSPD := (uiDataAddr := 740)),
(unIntPos := (uiDataAddr := 717), wIntPosACDC := (uiDataAddr := 757), wIntPosSPD := (uiDataAddr := 741)),
(unIntPos := (uiDataAddr := 719), wIntPosACDC := (uiDataAddr := 758), wIntPosSPD := (uiDataAddr := 742)),
(unIntPos := (uiDataAddr := 721), wIntPosACDC := (uiDataAddr := 759), wIntPosSPD := (uiDataAddr := 743)),
(unIntPos := (uiDataAddr := 723), wIntPosACDC := (uiDataAddr := 760), wIntPosSPD := (uiDataAddr := 744)),
(unIntPos := (uiDataAddr := 725), wIntPosACDC := (uiDataAddr := 761), wIntPosSPD := (uiDataAddr := 745)),
(unIntPos := (uiDataAddr := 727), wIntPosACDC := (uiDataAddr := 762), wIntPosSPD := (uiDataAddr := 746)),
(unIntPos := (uiDataAddr := 729), wIntPosACDC := (uiDataAddr := 763), wIntPosSPD := (uiDataAddr := 747)),
(unIntPos := (uiDataAddr := 731), wIntPosACDC := (uiDataAddr := 764), wIntPosSPD := (uiDataAddr := 748))

];
END_STRUCT
END_TYPE

RomeoVar
08.07.2021, 18:27
Вот это прикол - мне к-а-н-а-л в сообщении затерли. Оставили только К****:D

Евгений Кислов
08.07.2021, 19:12
Но если, случайно, эти значения изменятся.... все сломается...

Очень странная фраза, на мой взгляд.
Значения могут измениться "случайно" только из-за segfault, но тогда уже маловероятно, что какая-то соломка поможет.
И это не особенность CODESYS - это везде так.

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


Вот это прикол - мне к-а-н-а-л в сообщении затерли. Оставили только К****:D

Это вордфильтр форума так исторически работает.

allozavr
07.09.2022, 07:06
62499
Добрый день. Интересует вопрос о инициализации массива структур. А именно структуры содержащей элементы пользовательского типа (UNION). Когда пытаюсь инициализировать переменную( в Global Variable List обращаясь к ней через точку, как
показано в первой части скриншота, в итоге получаю ошибку синтаксиса. Если объявлять такой массив без инициализации и работать с ним в программе, то все работает.
Во второй части скриншота показал, что общий синтаксис инициализации массива правильный и проблема в типе данных. Подскажите, данная проблема решаема и как можно инициализировать подобный массив (интересует возможность инициализации, именно каждого элемента массива по-отдельности, а не в самой структуре).

Евгений Кислов
07.09.2022, 07:36
62499
Добрый день. Интересует вопрос о инициализации массива структур. А именно структуры содержащей элементы пользовательского типа (UNION). Когда пытаюсь инициализировать переменную( в Global Variable List обращаясь к ней через точку, как
показано в первой части скриншота, в итоге получаю ошибку синтаксиса. Если объявлять такой массив без инициализации и работать с ним в программе, то все работает.
Во второй части скриншота показал, что общий синтаксис инициализации массива правильный и проблема в типе данных. Подскажите, данная проблема решаема и как можно инициализировать подобный массив (интересует возможность инициализации, именно каждого элемента массива по-отдельности, а не в самой структуре).

Добрый день.



xxx_2: ARRAY [0..1] OF AI_Struct := [(a := (rRealValue := 1.0), b := 2.0), (a := (rRealValue := 3.0), b := 4.0)];

allozavr
07.09.2022, 07:42
Добрый день.



xxx_2: ARRAY [0..1] OF AI_Struct := [(a := (rRealValue := 1.0), b := 2.0), (a := (rRealValue := 3.0), b := 4.0)];


Спасибо огромное! Вы случайно не знаете книжку, где описаны нюансы подобные этому?

Евгений Кислов
07.09.2022, 08:01
Спасибо огромное! Вы случайно не знаете книжку, где описаны нюансы подобные этому?

Я не думаю, что все эти варианты в принципе имеет смысл описывать.
Проще в таких случаях воспользоваться редактором инициализации - он автоматически сгенерирует нужное объявление.
См. здесь: https://youtu.be/KjVlFH2lF4k?t=341

allozavr
07.09.2022, 09:48
62502

Я не думаю, что все эти варианты в принципе имеет смысл описывать.
Проще в таких случаях воспользоваться редактором инициализации - он автоматически сгенерирует нужное объявление.
См. здесь: https://youtu.be/KjVlFH2lF4k?t=341

Я имел ввиду касательно синтаксиса в CodeSys, иногда он не очень очевиден. Вот опять столкнулся с проблемой. Пытаюсь обратиться к переменной IN_OUT на языке ST, компилятор выдает ошибку. При обращений к переменной IN_OUT на FBD таких проблем нет.
Может быть знаете, как обратится к переменной IN_OUT в ST.

Евгений Кислов
07.09.2022, 10:03
62502


Я имел ввиду касательно синтаксиса в CodeSys, иногда он не очень очевиден. Вот опять столкнулся с проблемой. Пытаюсь обратиться к переменной IN_OUT на языке ST, компилятор выдает ошибку. При обращений к переменной IN_OUT на FBD таких проблем нет.
Может быть знаете, как обратится к переменной IN_OUT в ST.

Насчет синтаксиса - скоро обновим документ "Первый старт", в нем будет рассмотрено большинство этих нюансов.

По вашему вопросу - обращение к входам, выходам и входам-выходам нужно производить при вызове ФБ:



VarGlobal.AI_FB[1](VAR_AI := VarGlobal.AI_MOD[1]);

e.vavilov81
12.09.2023, 07:08
Доброй ночи! На второй день знакомства с CoDeSys 3.5 не нашёл ответа на вопрос
из той же оперы после применения квадратных вот только здесь обнаруженных скобок -

PROGRAM PLC_PRG
VAR
wtpr1: INT := 65;
wtpr2: INT := 78;
wtpr3: INT := 25;
wtpr4: INT := 59;
wt1:INT;
wt2:INT;
wt3:INT;
wt4:INT;
wt: ARRAY [1..4] OF INT:= [wt1,wt2,wt3,wt4];//[wt1:=120,wt2:=56,wt3:=84,wt4:=33]
check:INT;

END_VAR

Компилятор ругается на попытку обратиться к элементу через точку - wt.wt1:=wtpr1;
считает, что wt вообще не структурированная штука. Никаких вариантов синтаксиса
нигде не обнаружил. Может, я слепой - подскажите, чего не хватает, чтобы записывать
..

просто невнимательность,
если для массива заданы переменные символами wt1, wt2, ...
то запись. "wt.wr1 := ..." ошибочная, массив не содержит в себе wR1 чтобы присвоить ему хоть какое значение :)
wt.wt4 := wtpr4;" - попробуйте, может понравится





C0018: 'wt.wr1:=wtpr1' is no valid assignment target
C0062: 'wt' не является структурированной переменной

Добавлю после экспериментов. Компилятор не бракует такой вариант
wt[wt4]:=wt4:=wtpr4;
check:=wt[wt4];

?..