Просмотр полной версии : Как передать массив в функциональный блок если зарание не известно сколько элемнтов
Serhioromano
26.03.2017, 16:50
Предположим есть массивы
myArray1 := ARRAY[0..2] OF STRING;
myArray2 := ARRAY[0..10] OF STRING;
myArray3 := ARRAY[0..4] OF STRING;
Конечно же все сложней. Это не строки а структура с многотиповым хранением данных.
Есть так же универсальный функциональный блок который может их обработать. Он просто в цикле походит по каждому элементу и делает свое дело.
Когда я поределяю входную переменную мне надо написать
In := ARRAY[0..2] OF STRING;
И вот тут проблема. я ведь могу туда опустить любой массив а у меня разное количество элементов.
Как мне сделать так что бы можно было передать массив с любым колличеством элементов?
добавляйте а свою структуру некий id, в фб передайте указатель, если у очередного элемента индекс равен нулю, значит массив закончился
Serhioromano
27.03.2017, 07:54
Нет это понятно. Я могу пройти в цикле неопределенное количество элементов. Это не проблема. Как этот массив передать в FB? Ведь мне нужно декларировать переменную входную или локальную и там указвать зарание количество элементов в массиве, так что как я не передавай, входная переменная должна иметь тоже колличество.
массив, это уложенные последовательно в памяти однородные данные, ни какой массив передавать в ФБ я не предлагаю, а рекомендую передавать указатель на тип данных из которых сформирован массив, начиная с начального элемента массива, а далее как угодно, в цикле определяете когда данные закончились или с этим указателем передавайте количество элементов массива. В оскат библиотеке много таких примеров
Когда работал с файлами, там тоже заранее неизвестно сколько и чего записывать надо обычно. Как советует capzap, то просто дать указатель и работать с ним. Также можно передавать и разнородную структуру. Мне было удобно указатель на байт и sizeof структуры, чтобы определить её границы.
Serhioromano
30.03.2017, 03:36
Можно примерчик указателя?
Можно примерчик указателя?
Кусочно-линейная аппроксимация http://www.owen.ru/forum/showthread.php?t=10555&p=220263&viewfull=1#post220263
FUNCTION MyGraf_p : REAL
VAR_INPUT
IN: REAL; (*Входной сигнал*)
pt : POINTER TO ARRAY[0..99] OF Point_GR; (*Массив точек графика, не более 100 пар точек X,Y*)
size : UINT;
END_VAR
VAR
a: INT; (*Начало интервала поиска*)
b: INT; (*Конец интервала поиска*)
N: INT; (*Число точек в графике*)
i: INT;
END_VAR
N:= SHR(size,3)-1; (*Число точек в графике*)
(*Начальные значения интнрвала поиска*)
a:=0;
b:=N-1;
(*Обрезание графика для крайних точек*)
IF IN<=pt^[0].X THEN
MyGraf_p:=pt^[0].Y;
ELSIF IN>=pt^[N-1].X THEN
MyGraf_p:=pt^[N-1].Y;
(*Теперь можно начать поиск*)
ELSE
WHILE (b-a) <> 1 DO (*В конце концов, входной сигнал ТОЧНО попадет между двумя соседними точками X(a) и Х(а+1)*)
i:=(a+b)/2; (*Делим интервал поиска пополам*)
IF IN=pt^[i+1].X THEN (*Может нам повезло, и мы сразу нашли точку? *)
a:=i; b:=i+1; (*Бинго! прекращаем итераций, нечего в пустую молотить :) *)
(*мимо :( ,тогда посмотрим в какую половину интервала попали*)
ELSIF IN>pt^[i].X THEN (*Если входной сигнал больше середины интервала поиска,*)
a:=i; (*то следующий поиск будем делать начиная от середины и до конца массива*)
ELSE (*А если входной сигнал меньше середины интервала поиска,*)
b:=i; (*то следующий поиск будем делать начиная от начала и до середины массива*)
END_IF
(*Таким образом на каждой итерации отбрасываем из поиска заведомо ненужную половину значений
две соседние координаты X(a) и Х(а+1), меду которыми попадает входной сигнал найдем очень быстро
для 8 точек графика нужно не более 3 итераций
при 9..16 точек в графике нужно не более 4 итераций
при 17..32 точек в графике нужно не более 5 итераций
при 33..64 точек в графике нужно не более 6 итераций
при 65..128 точек в графике нужно не более 7 итераций
инфа точная - 100% ;) *)
END_WHILE
(*Теперь самое простое - сделать линейную аппроксимацию по двум точкам ;) *)
MyGraf_p:=pt^[b].Y-(pt^[b].X-IN)*(pt^[b].Y-pt^[a].Y)/(pt^[b].X-pt^[a].X);
END_IF
Сам массив структур передается в функцию через указатель, по этому вызывать ее нужно так
MyGraf_p(IN, ADR(Имя_Массива), SIZEOF(Имя_Массива))
Например
PROGRAM PLC_PRG
VAR
GR: ARRAY [0..49] OF Point_GR:=
(X:=0, Y:=15),(X:=3, Y:=25),(X:=4, Y:=45),(X:=8, Y:=75),(X:=15, Y:=45),
(X:=16, Y:=45),(X:=20, Y:=65),(X:=22, Y:=75),(X:=40, Y:=95),(X:=50, Y:=105),
(X:=110, Y:=15),(X:=120, Y:=25),(X:=130, Y:=45),(X:=140, Y:=75),(X:=150, Y:=45),
(X:=160, Y:=45),(X:=200, Y:=65),(X:=220, Y:=75),(X:=240, Y:=95),(X:=250, Y:=305),
(X:=301, Y:=15),(X:=305, Y:=25),(X:=324, Y:=45),(X:=380, Y:=75),(X:=415, Y:=45),
(X:=416, Y:=45),(X:=420, Y:=65),(X:=422, Y:=75),(X:=440, Y:=495),(X:=450, Y:=505),
(X:=511, Y:=15),(X:=515, Y:=25),(X:=524, Y:=45),(X:=580, Y:=75),(X:=615, Y:=45),
(X:=416, Y:=45),(X:=420, Y:=65),(X:=422, Y:=75),(X:=440, Y:=495),(X:=450, Y:=505),
(X:=621, Y:=15),(X:=625, Y:=25),(X:=634, Y:=45),(X:=680, Y:=75),(X:=695, Y:=45),
(X:=676, Y:=45),(X:=680, Y:=65),(X:=692, Y:=75),(X:=740, Y:=495),(X:=750, Y:=505);
IN: REAL;
OUT: REAL;
END_VAR
(*ВАЖНО!
Таблица должна быть обязательно отсортирована по X в порядке возрастания значений.*)
OUT:=MyGraf_p(IN, ADR(GR), SIZEOF(GR));
Сам массив структур передается в функцию через указатель, по этому вызывать ее нужно так
это не совсем то про что я говорю,указатель на объект, из чего состоит массив, а не указатель на массив
как то так:
FUNCTION_BLOCK FB
VAR_INPUT
In : POINTER TO STRING;
Sz: byte;
END_VAR
VAR
str: STRING;
END_VAR
где то в прграмме:
FB( In := adr( myArray1[0] ), Sz := 2 );
А это где то в теле FB:
можно в цикле от нуля до Sz
str := In^ - это myArray1[0];
In := In + sizeof( str ); (* теперь str := In^ - это myArray1[1]; *)
Владимир Ситников
30.03.2017, 12:45
это не совсем то про что я говорю,указатель на объект, из чего состоит массив, а не указатель на массив
Вот интересно. Вроде, должен быть безопасный язык. А чуть что сразу работа с памятью и адресами.
Была бы возможность передавать статические массивы.
Или это в КДС3 уже сделано?
Была бы возможность передавать статические массивы.
так передавай, хоть по ссылке хоть через указатель. и во втором. в третьем ввобще ссылки есть как сущность )
var_in_out
arr: ARRAY [0..255] OF BYTE; ссылка
end_var
var_in_out
parr: pointer to ARRAY [0..255] OF BYTE; указатель
end_var
кста, не знаю чо будет если в эти переменные скормить массив меньшей длинны. хозяину топика можно былобы проверить )
Евгений Кислов
30.03.2017, 15:46
Была бы возможность передавать статические массивы.[Или это в КДС3 уже сделано?
В КДС3 (начиная с SP8) можно так (естественно, только для VAR_INPUT и VAR_IN_OUT):
30310
Владимир Ситников
30.03.2017, 15:50
так передавай, хоть по ссылке хоть через указатель. и во втором. в третьем ввобще ссылки есть как сущность )
Не понимаю. Разве можно передать массив так, чтобы "на принимающей стороне" компилятор проверял код и сообщал о выходах за границы массива?
кста, не знаю чо будет если в эти переменные скормить массив меньшей длинны. хозяину
Во во. Я и говорю, что в КДС2 нет возможности сделать блок-обработку массива, который мог бы принимать массивы разных размеров и при этом проверялись границы массива на этапе компиляции.
который мог бы принимать массивы разных размеров и при этом проверялись границы массива на этапе компиляции.
как на этапе компиляции можно знать длину переменного массива? )
а вообще массив с переменной длинной в кодесисе можно самому сделать.
Serhioromano
30.03.2017, 17:33
Короче 3 меня массив это анимация фонтана. Каждый элемент массива это струтура кторая хранит время, начальную точку, конечную точку, тип линейности и время паузы по достижении.
На фонтане 3 контура. Например пока один кнтур за 3 цикла поднимает от 0 до 100, другой контур 3 раза поднимает от 0 до 100 за это время. Значит в массиве первого контура один элемент, а в массиве второго контура 3 элемента.
Блок который это обрабатывает один и тот же. Вот в чем проблема. Если я сделал.
pt : POINTER TO ARRAY[0..99] OF Point_GR;
то и передать мне нужно будет массив с [0..99]. А как? ведь у меня разные длинны массива для каждого контура? Мне чтоделать разные копии блоков для этого? Но ведь я всегда могу добавить новые элементы для дополнительных узоров анимации, и что потом переделывать блоки?
Короче сейчас я делал так. Я передаю в блок просто номер программы. Массивы программы я сделал глобальными, а уже в нутри блока я использую CASE что бы обращаться к нужному массиву.
Пока так. Это вроде работает но мне кажется должен быть более элегантный способ решит эту задачу.
Короче 3 меня массив это анимация фонтана. Каждый элемент массива это струтура кторая хранит время, начальную точку, конечную точку, тип линейности и время паузы по достижении.
На фонтане 3 контура. Например пока один кнтур за 3 цикла поднимает от 0 до 100, другой контур 3 раза поднимает от 0 до 100 за это время. Значит в массиве первого контура один элемент, а в массиве второго контура 3 элемента.
Блок который это обрабатывает один и тот же. Вот в чем проблема. Если я сделал.
pt : POINTER TO ARRAY[0..99] OF Point_GR;
то и передать мне нужно будет массив с [0..99]. А как? ведь у меня разные длинны массива для каждого контура? Мне чтоделать разные копии блоков для этого? Но ведь я всегда могу добавить новые элементы для дополнительных узоров анимации, и что потом переделывать блоки?
Как Вы смотрели пример http://www.owen.ru/forum/showthread.php?t=26394&p=242495&viewfull=1#post242495
Сам массив структур передается в функцию через указатель, по этому вызывать ее нужно так
MyGraf_p(IN, ADR(Имя_Массива), SIZEOF(Имя_Массива))
В функции
pt : POINTER TO ARRAY[0..99] OF Point_GR;
Это максимальное количество! Реальное количество определяется при вызове параметром SIZEOF(Имя_Массива)
в моем примере - это первая строка функции
N:= SHR(size,3)-1; (*Число точек в графике*)
В примере есть вызов функции для графиков с разным количеством точек, например 50 точек
VAR
GR: ARRAY [0..49] OF Point_GR:=
(X:=0, Y:=15),(X:=3, Y:=25),(X:=4, Y:=45),(X:=8, Y:=75),(X:=15, Y:=45),
(X:=16, Y:=45),(X:=20, Y:=65),(X:=22, Y:=75),(X:=40, Y:=95),(X:=50, Y:=105),
(X:=110, Y:=15),(X:=120, Y:=25),(X:=130, Y:=45),(X:=140, Y:=75),(X:=150, Y:=45),
(X:=160, Y:=45),(X:=200, Y:=65),(X:=220, Y:=75),(X:=240, Y:=95),(X:=250, Y:=305),
(X:=301, Y:=15),(X:=305, Y:=25),(X:=324, Y:=45),(X:=380, Y:=75),(X:=415, Y:=45),
(X:=416, Y:=45),(X:=420, Y:=65),(X:=422, Y:=75),(X:=440, Y:=495),(X:=450, Y:=505),
(X:=511, Y:=15),(X:=515, Y:=25),(X:=524, Y:=45),(X:=580, Y:=75),(X:=615, Y:=45),
(X:=416, Y:=45),(X:=420, Y:=65),(X:=422, Y:=75),(X:=440, Y:=495),(X:=450, Y:=505),
(X:=621, Y:=15),(X:=625, Y:=25),(X:=634, Y:=45),(X:=680, Y:=75),(X:=695, Y:=45),
(X:=676, Y:=45),(X:=680, Y:=65),(X:=692, Y:=75),(X:=740, Y:=495),(X:=750, Y:=505);
IN: REAL;
OUT: REAL;
END_VAR
Вызов функции
OUT:=MyGraf_p(IN, ADR(GR), SIZEOF(GR));
Serhioromano
31.03.2017, 19:31
А зачем тут вообще массивы ? Может списки ?
Как образуются данные ?
Можно пример списка? Не пойму о чем речь.
Serhioromano
02.04.2017, 15:33
Понятно. Я вообщем то программист. Хотя и вышел и прикладного программирования. В КДС программирую пару лет. Знаю пяток языков.
Но у меня все еще вопрос что такое списки? На что вы ссылаетесь по этим термином? Думаете я не погуглил по теме списков и КДС? Нет, я погуглил, но ни чего не нашел. Этот термин мне ни о чем не говорит уж извините меня. В КДС есть структуры, есть массивы но списков я не нашел.
Приведите пример хоть как декларировать список в ST? Что за тип данных? Или хотя бы скажите английский термен который используется для этого. По слову list ни чего нет.
Если вы ссылаетесь в общем на концепт программирования или метод структоризации, то покажите как его реализовать в среде ST.
Список - это определяемый пользователем тип данных под названием "перечисление". Посмотрите в документации "Руководство пользователя по программированию ПЛК в CODESYS" (файл CoDeSys_V23_RU.pdf стр. 334) на диске, который идет с ПЛК или на сайте Овена.
Serhioromano
04.04.2017, 15:14
Список - это определяемый пользователем тип данных под названием "перечисление". Посмотрите в документации "Руководство пользователя по программированию ПЛК в CODESYS" (файл CoDeSys_V23_RU.pdf стр. 334) на диске, который идет с ПЛК или на сайте Овена.
Спасибо.
Издеваетесь ?
function_block item //элемент списка
var ...
... //данные
var_output
next : dword; //суть - pointer to item;
end_var
-------------
... //творим
пример прогона списка
var
list, //сам список
p : pointer to item; //времянка
------------
p := list;
while p <> 0 do
p^( ..., next => p);
end_while
Спасибо. Речь идет о перечеслениях. Я понял. Не сразу понял что вы называете списком.
К сожалению я не вижу как я могу заменить свой массив "списком". Вот что у меня. Печатаю без копи\вставить так что могут быть ошибки.
TYPE RepCyc STRUCT
from:INT;
to:int;
ease:STRING;
pause:INT;
cycle:INT;
END_STRUCT
Теперь я объявляю глобальную переменную.
VAR
glbAnimationWave: ARRAY[1..5] OR RepCyc := (from:=20, to:=80, ease:='easeInCubic', pause:=2, cycle:=2).......
END_VAR
И так далее. Где каждый элемент массива это задача как себя поведет фонтан от цикла к циклу.
Перечесления же с другой стороны это
Перечисление - это определяемый пользователем тип данных, задающий несколько строковых псевдонимов для числовых констант.
Хотя я понял о чем идет речь в смысле списков, можете мне посоветовать как мне оптимально их использовать в моей задаче?
Serhioromano
06.04.2017, 10:12
Короче вчера все переписал. Спасибо. Поинтеры работают отлично. А вот как в моем случае использовать перечисления или как Валенок написал списки, я так и не понял.
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot