PDA

Просмотр полной версии : Как из ФБ и Ф управлять DO



Barboris
06.08.2012, 17:41
Требуется примерно вот такое (по входу DI1 в течении 1 с включается DO1, отключается или через 1с или если DI2).

TP1(IN:=DI1, PT:=T#1s);
RS1(SET:=TP1.Q, RESET:=(TP1.ET=t#1s OR DI2);
DO1:=RS1.Q;

Таких DO у меня штук 20, я решил сделать функцию , которая будет выбирать какой DO дергать. Примерно вот так:

Function DO_Choice: bool;
Var_input
DO_Num:usint;
end_var

if DO_Num=1 then DO=DO1
...
elseif DO_Num=20 then DO=DO20
end_if

и в программе уже подставлять вместо конкретного DO1 переменную DO которая бы соответствовала правильному выходу плк.

Вопрос - как жестко связать переменную с выходом плк, чтобы такая программа бы заработала?

Yegor
06.08.2012, 19:15
Ваша функция ничего не делает. Для выбора используйте конструкцию CASE.

Не совсем ясно, в какой момент будет выбираться выход. Что должно произойти, если выбор сделан в момент, когда другой выход уже возведён в TRUE и идёт отсчёт таймера с ожиданием DI2? Что такое «правильный выход ПЛК», каким критерием определяется его правильность?

Barboris
06.08.2012, 20:04
Ваша функция ничего не делает. Для выбора используйте конструкцию CASE.

Не совсем ясно, в какой момент будет выбираться выход. Что должно произойти, если выбор сделан в момент, когда другой выход уже возведён в TRUE и идёт отсчёт таймера с ожиданием DI2? Что такое «правильный выход ПЛК», каким критерием определяется его правильность?

Не совсем понимаю, в чем будет разница если использовать CASE.

"Правильный" - выбранный функцией в момент когда функция будет вызвана из ФБ. В принципе в программе будут опрашиваться по очереди все входы и соответственно включаться/выключаться все выходы. Идея была в том, чтобы не писать один и тот же алгоритм 20 раз, а сделать 1 функцию, которую 20 раз вызвать.

Другой выход будет обрабатываться другим экземпляром ФБ, они могут параллельно включаться/выключаться.

Yegor
06.08.2012, 21:12
будут опрашиваться по очереди все входыСогласно вашему описанию, входов там всего два. Оттого и непонятно, как и по какой такой очереди от них должны работать двадцать выходов.

Возможно, подойдёт что-нибудь эдакое:

http://images.devs-on.net/Image/qx5JWuetGVREc34p-CoDeSysUntitled.png

Gans
06.08.2012, 21:26
Здравствуйте, Борис.

Таких DO у меня штук 20, я решил сделать функцию , которая будет выбирать какой DO дергать.
На первый взгляд логично сделать функциональный блок с Вашим алгоритмом. Делаете столько экземпляров сколько нужно и присваиваете входа/выхода которые нужно. Во вложении мой вариант.

Gans
06.08.2012, 21:30
Эх не успел, Егор уже ответил.
У Егора правильнее (за что ему куча плюсиков и лайков), у меня читабелнее :-) Выбирать Борису;)

Barboris
07.08.2012, 14:34
Спасибо за варианты, у меня ближе к варианту Gans.

Я как раз и хотел сделать нужное кол-во ФБ, но хотелось бы не присваивать 20 раз входы и выходы, а только номер от 1 до 20, а с помощью функции автоматически по номеру присваивались нужные входы/выходы.

примерно вот так:

if "включить1(DI_ON)" or "выключить1(DI_OFF)" then SW(1)
elseif "включить2" or "выключить2" then SW(2)
.. так до 20
end.

Function block SW(var_input SW_NUM)
DIDO_Choice(sw_num);
TP1(IN:=DI_ON, PT:=T#1s);
RS1(SET:=TP1.Q, RESET:=(TP1.ET=t#1s OR DI_OFF);
DO:=RS1.Q;
end;

Fuction DIDO_Choice (Var_input: DO_Num:usint; var_output: DI_ON, DI_OFF, DO);
if DO_NUM=1 then DI_ON:=DI1; DI_OFF=DI2; DO:=DO1;
elseif DO_NUM=2 then DI_ON:=DI3; DI_OFF=DI4; DO:=DO2;
elsif.... до 20
end;

Естественно, так работать не будет, потому что изменение переменной DO не заставит включиться выходу DO1, в этом и весь вопрос.

Валенок
07.08.2012, 16:52
Мутность вашей идеи в том, что Вам нужно что-то 20 раз в цикле вызывать с номерами, а внутри этого заниматся перебором номеров до 20 раз. Т.е получается до 200 сравнений за цикл.
А у Егора четко, лаконично и быстро. Сразу понятно что и куда физически привязано. И главное - переносимо без залезания внутрь фб. И сравнений вообще нет.

Yegor
07.08.2012, 19:14
Естественно, так работать не будет, потому что изменение переменной DO не заставит включиться выходу DO1, в этом и весь вопрос.В вашем решении функция-селектор должна возвращать указатель на выход (POINTER TO BOOL). От множественных присваиваний вы этим не избавитесь, т.к. по сути лишь перенесёте их в ту самую функцию. Сложность ради сложности.

Если я правильно понял, то у каждого выхода есть свой набор входов и нет никаких пересечений. В этом случае городить огород точно не стоит.

Barboris
08.08.2012, 11:21
В вашем решении функция-селектор должна возвращать указатель на выход (POINTER TO BOOL). От множественных присваиваний вы этим не избавитесь, т.к. по сути лишь перенесёте их в ту самую функцию. Сложность ради сложности.

Если я правильно понял, то у каждого выхода есть свой набор входов и нет никаких пересечений. В этом случае городить огород точно не стоит.

Поскольку данный ФБ это только одна небольшая часть всего алгоритма работы устройства, то не хотелось бы перегружать основную программу, и хотелось бы чтобы ФБ делал законченную работу, чтобы он самостоятельно включал или выключал нужный выход без дополнительных движений извне.
Про POINTER TO спасибо, буду разбираться.
2Carzap: а с прямыми адресами и наименованиями каналов в конфигураторе у меня не получилось, ведь нужен именно указатель туда, а не прямо они.

Валенок
10.08.2012, 20:20
Да сделайте же промежуточные массивы и обращайтесь по индексу раз приперло

Barboris
11.08.2012, 19:49
Да сделайте же промежуточные массивы и обращайтесь по индексу раз приперло

Вопрос именно в том и заключается, как привязать индекс массива к выходу плк.
Т.е. чтобы при изменении элемента массива включался соотв. выход. И наоборот.

kolyan
11.08.2012, 20:54
Вопрос именно в том и заключается, как привязать индекс массива к выходу плк.
Т.е. чтобы при изменении элемента массива включался соотв. выход. И наоборот.

Во вложении - пример привязки элементов массива входов и массива выходов (20 входов и 20 выходов), соответственно, к входам и выходам ПЛ110-60 (данная модель плк выбрана для примера).
Далее, при написании задачи, можно отслеживать состояние i-го элемента массива входов, и, соответственно, управлять j-м элементом массива выходов, не занимаясь каждый раз многократными повторами и присваиваниями.

P.S. Если честно, то алгоритм самой задачи не совсем ясен.

Barboris
13.08.2012, 10:52
Kolyan, cпасибо за ваш пример. Именно так все конечно работает. А я хотел присваивание делать внутри функции. Или хотя бы ФБ. Пока переделал примерно по методу Yegor - все кроме DO присваивается функцией внутри ФБ, а DO - в основной программе снаружи ФБ (как его выходная переменная (и используется внутри него))

Вот так примерно

http://i40.fastpic.ru/big/2012/0813/cd/c1756842c790ee6b8ba6086e031d5bcd.jpg

Николаев Андрей
14.08.2012, 13:11
Не рекомендую делать управление выходами и работу с входами в функциях и ФБ.
1. Программа становится не переносима, ФБ и Ф не универсальные.
2. Вспомнить потом что и зачем делалось сложно.

Не поленитесь, и создайте в основной программе массив в него записывайте данные из ФБ и из этого массива берите данные для выходов.
В дальнейшем сильно облегчит жизнь.

Casper17
09.08.2019, 07:53
Стоит подобная задача, управлять множеством реле с обратной связью и неким контролем на разрешение включения реле и обрыве. Но в этой теме все примеры, которые выкладывали недоступны((. Как правильно организовать ФБ, передавать каждый раз в него значения входа, выхода и других переменных как параметры, а после ФБ присваивать входы\выходы обращаясь к внутренним переменным ФБ или можно как-то через указатель один раз передать и потом уже использовать в теле ФБ?
Первым способом вроде как работает, я каждый раз в параметры ФБ передаю значения входа, бит ModBus(устанавливается\сбрасывается по команде с ПК) и число(мощность нагрузки), внутри происходит проверка, таймер на включение с интервалом 1с, если после истечение времени на входе не будет сигнала, то выключаем реле. Также проходит проверка на мощность. Проверяется текущая мощность с допустимой, если текущая мощность + мощность реле > допустимой, то мы не включаем реле иначе к текущей + мощность реле. А после отработки ФБ я входу и регистру ModBus присваиваю значения обращаясь к экземпляру ФБ через точку к его внутренним переменным или выходным.
Что посоветуете?

Sulfur
09.08.2019, 08:21
Я делал булевый массив. В ФБ\ПОУ оперировал по индексу. В конце ПЛЦ_ПРГ ставил вызов на собственную ПОУ (проще делать на LD), где массив раскладывается на реальные DO.
На картинке показано упаковка входов в массив и распаковка другого массива на выхода.
43980

Casper17
09.08.2019, 09:53
В LD не силен совсем, мне понятнее будет ST где все операции наглядно видно, что и как происходит. А какая разница, что мы будем после каждого вызова ФБ устанавливать значения выхода, что после всех ФБ установим значения выходов обращаясь выход:=массив[0] и т.д.
В общих чертах у меня сейчас выглядит так:
FB1(in1, mb_bit1, power1);
out1:=FB.output;
mb_bit1:=FB.mb_bit;

FB2(in2, mb_bit2, power);
out2:=FB.output;
mb_bit2:=FB.mb_bit;
И таких вызовов от 40шт, на каждое реле. Мы в ФБ передаем бит из ModBus_slave, значение выхода и некий параметр мощности за который отвечает конкретное реле. И внутри ФБ происходит логика включения и выключения реле с контролем обрыва и мощности.
Это примерный вариант, по памяти, так как весь проект на работе.

Sulfur
09.08.2019, 10:21
Я привел пример своей работы. Задача была обрабатывать в цикле четыре одинаковых процесса, но с разными параметрами для каждого процесса. Причем в одно время должен работать только один процесс, остальные ждать его завершения. Что бы не городить тонны букав на ST я делал свою ПОУ на LD, а в PLC_PRG на ST делается общий контроль всей работы.
В моем случае массивы объявлены глобально, следовательно доступны из любого ФБ\ПОУ как прямо указанному индексу, так и по индексу, в качестве которого работает переменная типа INT.
Вообще, упрощено ФБ работает так - затолкали ему на вход данные>ФБ их прожевал, используя только локальные переменные своего экземпляра, а так же глобальные>выкинул на выход. Используя массивы можно затолкать в цикл FOR (например) свои ФБ, которые используют переменную цикла (глобальная) в качестве индекса, а это сильно сократит количество кода при выполнении большого количества однотипных задач.

Casper17
09.08.2019, 10:32
А если как-то передать указатель на вход, выход один раз каждому экземпляру ФБ и внутри него уже сразу менять состояние, а не после того как ФБ отработал, брать его выходные данные и устанавливать значения входа\выхода.

Sulfur
09.08.2019, 10:40
А смысл? В любом случае ПЛК сначала читает состояние входов, потом выполняет программу, по результатам программы пишет в выхода\регистры, далее цикл повторяется. Не имеет значения в какой момент программы меняется состояние переменной выхода\регистра, физически оно сменится только в конце вышеописанного цикла.