Просмотр полной версии : Функциональные блоки на языке ST
МихаилГл
14.05.2024, 04:46
Я так понимаю, что ваше предположение оказалось невереым. Потому что нету никакой разницы откуда вызывать ST код если на входе одни и те же данные.
См. сообщение выше. Мое другое предположение об незамеченной ошибке в коде было отвергнуто:
https://owen.ru/forum/showthread.php?t=38239&page=49&p=436815&viewfull=1#post436815
https://owen.ru/forum/showthread.php?t=38239&page=49&p=436824&viewfull=1#post436824
А с тем предположением я солидарен :-) Я просто так акцентируюсь на однозначности выполнения ST кода, чтобы не читать потом тут консперологические теории.
МихаилГл
15.05.2024, 06:52
А с тем предположением я солидарен :-) Я просто так акцентируюсь на однозначности выполнения ST кода, чтобы не читать потом тут консперологические теории.
Конспирология пошла после... Ну уже не актуально, ошибки найдены, код как сообщили работает. Но я подумаю над своей теорией...
desperadoes
22.05.2024, 10:17
Добрый день!
Подскажите как пользоваться вызовом системных функций и ФБ внутри ФД на ST. Что то у меня не получается. Пишу в области Var SYS.Blink, выскакивает подсказка , и что дальше? Не пойму как привязаться к входам выходам. А если попробовать вызвать в области выполнения кода, то она не доступна.
Добрый день!
Подскажите как пользоваться вызовом системных функций и ФБ внутри ФД на ST. Что то у меня не получается. Пишу в области Var SYS.Blink, выскакивает подсказка , и что дальше? Не пойму как привязаться к входам выходам. А если попробовать вызвать в области выполнения кода, то она не доступна.
В объявлении пишите
fbMyBlink: SYS.Blink;
В вызове
fbMyBlink(I:= ...значения входных параметров);
desperadoes
22.05.2024, 10:39
В объявлении пишите
fbMyBlink: SYS.Blink;
В вызове
fbMyBlink(I:= ...значения входных параметров);
Спасибо!
А есть информация по отладке ФБ на ST. Я так понимаю ее сейчас нет. Придвидится ли? Очень бы хотелось))
Денисов Максим Сергеевич
22.05.2024, 10:51
Спасибо!
А есть информация по отладке ФБ на ST. Я так понимаю ее сейчас нет. Придвидится ли? Очень бы хотелось))
Симуляция в редакторе ST уже в разработке)
desperadoes
22.05.2024, 11:07
Симуляция в редакторе ST уже в разработке)
Спасибо, это хорошая новость.
Можно тогда еще вопрос, раз уже все тут собрались. Сейчас сделал такую штуку. Проверяю сохранение моточасов в энергонезависимой памяти. Т.е. Включил отладку включил мотор, смотрю как насчитываются моточасы. Потом отключил отладку, выключил ПР103. Через 5 мин включил, пытаюсь подключиться онлайн, чтобы посмотреть сохранились ли данные. А он мне пишет "Программа не совпадает с ПР103. Загрузите программу". Собственно вопрос, это потому что отличаются счетчики? И как с этим жить, не хочется приехать на объект, и стереть им там все данные чтобы просто подключится онлайн))
Денисов Максим Сергеевич
23.05.2024, 08:07
Спасибо, это хорошая новость.
Можно тогда еще вопрос, раз уже все тут собрались. Сейчас сделал такую штуку. Проверяю сохранение моточасов в энергонезависимой памяти. Т.е. Включил отладку включил мотор, смотрю как насчитываются моточасы. Потом отключил отладку, выключил ПР103. Через 5 мин включил, пытаюсь подключиться онлайн, чтобы посмотреть сохранились ли данные. А он мне пишет "Программа не совпадает с ПР103. Загрузите программу". Собственно вопрос, это потому что отличаются счетчики? И как с этим жить, не хочется приехать на объект, и стереть им там все данные чтобы просто подключится онлайн))
Пришлите ваш проект на почту soft@owen.ru, проверим, звучит как баг
Добрый день. Прошу помощи, несколько дней уже ломаю голову, не пойму как решить проблему.
Описание: Управление осуществляется с помощью одного входа на который заведен gsm-модуль и дублирующая кнопка (по месту). Необходимо при первом нажатии активировать выход Q1, при втором, выход Q2. И так поочередно. Т.е. если сигнал поступил, всегда активен только один выход, если не вышло время и не сработал концевик. Задан интервал времени 40сек, на работу выходов, за это время должны сработать один из датчиков (концевики) и сбросить сигнал, повторным нажатием на кнопку возможно активировать только тот выход, на который не сработал датчик.
Сделал первый вариант, вроде бы все работало, но увеличил скорость работы двигателя и заготовка пролетела концевик, не сбросив цикл, а таймер еще не вышел, в общем последствия не очень!
76006
Переключение выходов сделал в макросе через D триггер с отрицанием одного из выхода. Второй вариант сделал так же через D триггер на каждый выход и вроде бы все хорошо. выхода переключаются, концевики сбрасывают цикл и таймеры. Но, при активации выхода Q1 и входа I2 происходит переключение на выход Q2 и ни как не могу это победить, концевики должны делать полный сброс с выходов
76007
МихаилГл
24.05.2024, 11:08
Добавь rs триггеры
Добрый день! Плдскажите пожалуста: вот написан ФБ на ST, перенес его на холст и подключил переменные. Решил его отредактировать - отредактировал но изминения не появляются в ФБ размещённом на холсте. Приходиться его удалять и вновь перетаскивать на холст и по новой подключать переменные. Есть ли вариант чтобы изминения появлялись уже в блоке размещённом на холсте без предварительного удаления первой версии?
Добрый день! Плдскажите пожалуста: вот написан ФБ на ST, перенес его на холст и подключил переменные. Решил его отредактировать - отредактировал но изминения не появляются в ФБ размещённом на холсте. Приходиться его удалять и вновь перетаскивать на холст и по новой подключать переменные. Есть ли вариант чтобы изминения появлялись уже в блоке размещённом на холсте без предварительного удаления первой версии?
Значит подключенные переменные никуда не ведут
kondor3000
25.05.2024, 11:56
Добрый день! Плдскажите пожалуста: вот написан ФБ на ST, перенес его на холст и подключил переменные. Решил его отредактировать - отредактировал но изминения не появляются в ФБ размещённом на холсте. Приходиться его удалять и вновь перетаскивать на холст и по новой подключать переменные. Есть ли вариант чтобы изминения появлялись уже в блоке размещённом на холсте без предварительного удаления первой версии?
Если подключена на выход, хотя бы одна энергонезависимая переменная (или выход ПР), при изменении ФБ он становится красным с ошибкой, 76035
что блок модифицирован, ПКМ мыши обновляете ФБ и ошибка пропадает, ничего по новой не подключая.
Вот смотрите реальный пример.Выход ФБ должен быть типа BOOL но по невнимательности сделал ег целочисленым. Перетаскиваю,,хромой,, ФБ на холст и пытаюсь соединить выход ФБ с логичиским ИЛИ. Естествено ЛОДЖИК говорит что это сделать не возможно без преобразования. Я начинаю редактировать,,хромой ,,ФБ, исправля. его выход на BOOL. Возврощаюсь на холст но в там изминения не произошли, выход остался целочисленным. Я его сношу и вставляю по новому , тогда все в порядке, но приходиться по новому его комутировать на холсте. Вот так
Если подключена на выход, хотя бы одна энергонезависимая переменная (или выход ПР), при изменении ФБ он становится красным с ошибкой, 76035
что блок модифицирован, ПКМ мыши обновляете ФБ и ошибка пропадает, ничего по новой не подключая.
Вот А у меня такого пункта нет ОБНОВИТТЬ, только Редактировать_Удалить_Копировать_Вставить_Свойства . Лоджик скачал час назад с офиц сайта, может обновить сам лоджик?
kondor3000
25.05.2024, 12:06
Вот смотрите реальный пример.Выход ФБ должен быть типа BOOL но по невнимательности сделал ег целочисленым. Перетаскиваю,,хромой,, ФБ на холст и пытаюсь соединить выход ФБ с логичиским ИЛИ. Естествено ЛОДЖИК говорит что это сделать не возможно без преобразования. Я начинаю редактировать,,хромой ,,ФБ, исправля. его выход на BOOL. Возврощаюсь на холст но в там изминения не произошли, выход остался целочисленным. Я его сношу и вставляю по новому , тогда все в порядке, но приходиться по новому его комутировать на холсте. Вот так
В данном случае вы ещё не подключили все выходы, удалить и по новой поставить будет быстрее. Кроме того вы сами сделали ошибку и наказаны за это)))
kondor3000
25.05.2024, 12:08
Вот А у меня такого пункта нет ОБНОВИТТЬ, только Редактировать_Удалить_Копировать_Вставить_Свойства . Лоджик скачал час назад с офиц сайта, может обновить сам лоджик?
Обновите, только от имени установщика. Если ставил Админ, то и обновлять надо от Админа.
Если подключена на выход, хотя бы одна энергонезависимая переменная (или выход ПР), при изменении ФБ он становится красным с ошибкой, 76035
что блок модифицирован, ПКМ мыши обновляете ФБ и ошибка пропадает, ничего по новой не подключая.
Все спасибо добрый человек за подсказку, внес изминения в ФБ и все произошло как Вы сказали, только почемуто этот механизм не работал ранее что и подвигло меня за эти посты:o
SCOwenUfa
29.05.2024, 09:21
Коллеги, здравствуйте!
Примите ещё пожелание к редактору ST:
Хотелось бы видеть подсветку всех обращений к переменной или функциональному блоку при её выделении в тексте программы (аналогично функции "Перейти к месту использования", только сразу в тексте программы).
Например, как это выглядит в Codesys:
в строке 2 выделен вызов ФБ tofBeepOFF и в 6-й строке подсвечено обращение к выходу этого ФБ
76099
Денисов Максим Сергеевич
29.05.2024, 13:54
Предложение хорошее, добавили себе в бэклог
программист_с_паяльником
06.06.2024, 19:43
Здравствуйте, вчера обновился до вер. 2.7.350.0.
В принципе, это неудобство было и ранее - ST-ФБ или ST-функция, расположенные на холсте, после редакции не просятся обновиться. Попытки сделать это через обновление всех встречающихся мест использования также результатов не дает. Поэтому приходится стирать на холсте и ставить его из панели справа. Соответственно, все входы/выходы по новой нужно накидывать. Не проверял однозначно, должен ли для этого быть подключен девайс. Во всяком случае, когда прибор не подключен, имею что имею. В остальном все вроде норм.
P.S. А так конечно хотелось, чтобы ST в OwenLogic был побогаче - не хватает много )), что может язык.
Здравствуйте, вчера обновился до вер. 2.7.350.0.
В принципе, это неудобство было и ранее - ST-ФБ или ST-функция, расположенные на холсте, после редакции не просятся обновиться. Попытки сделать это через обновление всех встречающихся мест использования также результатов не дает. Поэтому приходится стирать на холсте и ставить его из панели справа. Соответственно, все входы/выходы по новой нужно накидывать. Не проверял однозначно, должен ли для этого быть подключен девайс. Во всяком случае, когда прибор не подключен, имею что имею. В остальном все вроде норм.
P.S. А так конечно хотелось, чтобы ST в OwenLogic был побогаче - не хватает много )), что может язык.
Х.З. У меня просят
76347
Здравствуйте, вчера обновился до вер. 2.7.350.0.
В принципе, это неудобство было и ранее - ST-ФБ или ST-функция, расположенные на холсте, после редакции не просятся обновиться. Попытки сделать это через обновление всех встречающихся мест использования также результатов не дает. Поэтому приходится стирать на холсте и ставить его из панели справа. Соответственно, все входы/выходы по новой нужно накидывать. Не проверял однозначно, должен ли для этого быть подключен девайс. Во всяком случае, когда прибор не подключен, имею что имею. В остальном все вроде норм.
P.S. А так конечно хотелось, чтобы ST в OwenLogic был побогаче - не хватает много )), что может язык.
Подключите выход изменённого ФБ или функции к дискретному выходу ПР - и этот ФБ или функция сразу-же запросит обновление
kondor3000
06.06.2024, 20:18
Здравствуйте, вчера обновился до вер. 2.7.350.0.
В принципе, это неудобство было и ранее - ST-ФБ или ST-функция, расположенные на холсте, после редакции не просятся обновиться. Попытки сделать это через обновление всех встречающихся мест использования также результатов не дает. Поэтому приходится стирать на холсте и ставить его из панели справа. Соответственно, все входы/выходы по новой нужно накидывать. Не проверял однозначно, должен ли для этого быть подключен девайс. Во всяком случае, когда прибор не подключен, имею что имею. В остальном все вроде норм.
P.S. А так конечно хотелось, чтобы ST в OwenLogic был побогаче - не хватает много )), что может язык.
На предыдущей странице ответ со скрином https://owen.ru/forum/showthread.php?t=38239&page=52#514
программист_с_паяльником
06.06.2024, 20:33
Спасибо. Заработало. ))
программист_с_паяльником
06.06.2024, 20:34
Нак предыдущей странице ответ со скрином https://owen.ru/forum/showthread.php?t=38239&page=52#514
Спасибо. Заработало.
программист_с_паяльником
06.06.2024, 20:36
Подключите выход изменённого ФБ или функции к дискретному выходу ПР - и этот ФБ или функция сразу-же запросит обновление
Спасибо. Да. Соединился с дискретным выходом.
Блин, уже миллион раз обсуждали, что если блок не участвует в алгоритме, то лоджик его игнорирует
sad_dimon
14.06.2024, 01:06
Приветствую. Не понял можно ли в функциональном блоке указать переменную как константу? Если да ,то как правильно ее объявить?
Приветствую. Не понял можно ли в функциональном блоке указать переменную как константу? Если да ,то как правильно ее объявить?
Как константу нельзя, но вы можете инициализировать переменную значением по-умолчанию
a : udint := 325;
Приветствую. Не понял можно ли в функциональном блоке указать переменную как константу? Если да ,то как правильно ее объявить?
Подай на вход ФБ константу, вот и все дела.
А вот и небольшой косячок на ST: слово constant не является зарезервированным, но редактор почему-то его выделяет как служебное и, при этом, обрабатывает как переменную
76571
А вот и небольшой косячок на ST: слово constant не является зарезервированным, но редактор почему-то его выделяет как служебное и, при этом, обрабатывает как переменную
76571
И какой в этом криминал ?
И какой в этом криминал ?
форматирование неверное
Добрый день.
Допустим, в ФБ, написанном на ST, я объявляю и затем в тексте кода вызываю системный блок RTRIG. Понятно, что это детектор переднего фронта, который при высоком уровне на входе формирует на выходе импульс длительностью в один цикл.
Код в ST выполняется построчно. Вопрос: внутри моего ФБ какую длительность будет иметь этот импульс - до конца кода ФБ или до момента, когда выполнение снова дойдёт до этой строки с вызовом детектора, то есть сделает полный круг? Или другими словами, насколько важно, в каком месте кода вызывается этот детектор?
kondor3000
14.06.2024, 20:14
Добрый день.
Допустим, в ФБ, написанном на ST, я объявляю и затем в тексте кода вызываю системный блок RTRIG. Понятно, что это детектор переднего фронта, который при высоком уровне на входе формирует на выходе импульс длительностью в один цикл.
Код в ST выполняется построчно. Вопрос: внутри моего ФБ какую длительность будет иметь этот импульс - до конца кода ФБ или до момента, когда выполнение снова дойдёт до этой строки с вызовом детектора, то есть сделает полный круг? Или другими словами, насколько важно, в каком месте кода вызывается этот детектор?
Когда сделает полный круг, то есть полный цикл ПР. Естественно, важно где стоит R_TRIG, сработает он в этом цикле или в начале следующего.
Добрый день.
Допустим, в ФБ, написанном на ST, я объявляю и затем в тексте кода вызываю системный блок RTRIG. Понятно, что это детектор переднего фронта, который при высоком уровне на входе формирует на выходе импульс длительностью в один цикл.
Код в ST выполняется построчно. Вопрос: внутри моего ФБ какую длительность будет иметь этот импульс - до конца кода ФБ или до момента, когда выполнение снова дойдёт до этой строки с вызовом детектора, то есть сделает полный круг? Или другими словами, насколько важно, в каком месте кода вызывается этот детектор?
Сразу ПОСЛЕ вызова RTRIG с 1 на входе вы получите 1 на выходе, и она будет там до повторного вызова RTRIG
Спасибо вам!
Ну, если полный круг, то важность места размещения детектора внутри кода сильно падает. ))) Вот если бы импульс действовал только до конца текста...
Благодарю, очень помогли.
Спасибо вам!
Ну, если полный круг, то важность места размещения детектора внутри кода сильно падает. ))) Вот если бы импульс действовал только до конца текста...
Ну, так, размещаете вызов RTRIG самым первым и он будет действовать только до конца текста
Спасибо, уже понял принцип работы. Мне нужно было именно уяснить принцип. Я имел в виду, что если бы импульс действовал только до конца текста, то на код, расположенный выше вызова, он бы не влиял. В этом случае место расположения имело бы большое значение. Ну а поскольку импульс работает полный круг, так тут и обсуждать уже нечего, по сути. Где ни размести, результат будет один. В моей программе, по крайней мере.
МихаилГл
15.06.2024, 03:41
Я всегда думал что до окончания подпрограммы триггер работает... Может в лоджике и не так...
Надо проверить, поставить до и после условие сравнения и суммирование переменной и по ней определиться.
Я всегда думал что до окончания подпрограммы триггер работает... Может в лоджике и не так...
Надо проверить, поставить до и после условие сравнения и суммирование переменной и по ней определиться.
Функциональный блок работает только в момент его вызова. Все остальное время мы пользуемся результатом его работы.
Например
var_input //объявление входных переменных
E : bool;
end_var
var_output //объявление выходных переменных
Q : bool;
end_var
var //объявление локальных переменных
RTrig : SYS.RTRIG;
end_var
RTrig.I := E;
if not RTrig.Q then RТrig(); end_if
Q := RTrig.Q;
Здесь триггер взведется по фронту Е и останется таким навсегда (ну, или пока мы его где-нибудь в другом месте опять не вызовем)
МихаилГл
15.06.2024, 14:49
Функциональный блок работает только в момент его вызова. Все остальное время мы пользуемся результатом его работы.
Например
var_input //объявление входных переменных
E : bool;
end_var
var_output //объявление выходных переменных
Q : bool;
end_var
var //объявление локальных переменных
RTrig : SYS.RTRIG;
end_var
RTrig.I := E;
if not RTrig.Q then RТrig(); end_if
Q := RTrig.Q;
Здесь триггер взведется по фронту Е и останется таким навсегда (ну, или пока мы его где-нибудь в другом месте опять не вызовем)
Был грешен... Вы мне открыли глаза.
Проверил на codesys 3.5, выход триггера остаётся взведенным до его повторного вызова. Я всегда думал, что он работает до окончания цикла программы/подпрограммы. Т.е. по циклу программы он сбросится только когда снова в него упрется...
Или я знал это раньше, или не знал и забыл)
Надо это всё переосмыслить. Так знал я это или нет...
Камрады-новички (я без иронии). Я вот вас читаю и понимаю, что надо у себя на сайте, что ли, написать простую статью о том, чем Функциональнй Блок от Функции отличается... Прям этот вопрос заново возник у кучи народа на форуме.
МихаилГл
16.06.2024, 10:31
Камрады-новички (я без иронии). Я вот вас читаю и понимаю, что надо у себя на сайте, что ли, написать простую статью о том, чем Функциональнй Блок от Функции отличается... Прям этот вопрос заново возник у кучи народа на форуме.
А я и правда думал, что триггер возведён до конца цикла именно подпрограммы. Везде на диаграммах указан период работы - цикл. Но этот цикл не до окончания подпрограммы, а до того места, пока код в программе опять не увидит этот триггер.
Да, я туп оказался. Позор на мои седины.
А я и правда думал, что триггер возведён до конца цикла именно подпрограммы. Везде на диаграммах указан период работы - цикл. Но этот цикл не до окончания подпрограммы, а до того места, пока код в программе опять не увидит этот триггер.
Да, я туп оказался. Позор на мои седины.
А я всегда выдумываю всякие эксперименты с кодом, если в чем-то сомневаюсь или недопонимаю. Такие баги в башке иногда вылавливаю - ужас!
А я и правда думал, что триггер возведён до конца цикла именно подпрограммы. Ну, если по серьёзному, без шуточек, то мнемонически можно запомнить, что во всей программе/задаче ПЛК цикл - это всё-всё целиком. Причём сначала считываются входы, обрабатывается программа, потом выдаются значения на выходы.
Наверное когда-нибудь я про это напишу всё же, так как сам тупил: думал что FB - автономны, и какой-нибудь таймер сам по себе будет считать, если его не вызывать в коде
sad_dimon
17.06.2024, 16:45
А вот и небольшой косячок на ST: слово constant не является зарезервированным, но редактор почему-то его выделяет как служебное и, при этом, обрабатывает как переменную
76571
Да, это немного сбивает с толку
Да, это немного сбивает с толку Скорее всего константы появятся в будущем. Поэтому слово зарезервировано.
Ну, если по серьёзному, без шуточек, то мнемонически можно запомнить, что во всей программе/задаче ПЛК цикл - это всё-всё целиком. Причём сначала считываются входы, обрабатывается программа, потом выдаются значения на выходы.
Наверное когда-нибудь я про это напишу всё же, так как сам тупил: думал что FB - автономны, и какой-нибудь таймер сам по себе будет считать, если его не вызывать в коде
Вообще, для понимания лучше всего написать, например, тот же RTRIG, с моего вопроса о котором этот разговор начался, самому. И тогда вопросов никаких не остаётся. Сразу видно, что он просто не может по другому отработать. Если бы я это сделал сразу, одним глупым вопросом здесь было бы меньше. ))
hawkey Да. Согласен. Только я душнила и долгострой. Идея классная, но напишу, наверное, через месяц, когда всем, кому интересно, будет нафиг не нужно =)
Добрый день.
Системная функция Get_Time возвращает значение переменной, содержащей время, прошедшее с момента включения прибора, в миллисекундах. Переменная четырёхбайтовая. Что происходит с её значением, если прибор находится во включённом состоянии более 50 дней? Обнуляется и начинает новый круг?
4 байта = 32 бита = 4294967295 сек = 136 лет (примерно)
Да, но в справке сказано, что время в миллисекундах, не в секундах.
Да, но в справке сказано, что время в миллисекундах, не в секундах.
Обнуляется и начинает новый круг.
Для расчета интервалов времени это не имеет значения если используется целочисленная арифметика.
Обнуляется и начинает новый круг.
Для расчета интервалов времени это не имеет значения если используется целочисленная арифметика.
Если в момент обнуления будет работать таймер, написанный с помощью этой функции, в котором, допустим, сравниваются два значения, полученные от неё, разве не нарушит это обнуление его работу?
Если в момент обнуления будет работать таймер, написанный с помощью этой функции, в котором, допустим, сравниваются два значения, полученные от неё, разве не нарушит это обнуление его работу?
Смотря что мы сравниваем. Если продолжительность, т.е. разницу между конечным временем и начальным, то не нарушит (если продолжительность меньше 50 дней)
76725
Смотря что мы сравниваем. Если продолжительность, т.е. разницу между конечным временем и начальным, то не нарушит (если продолжительность меньше 50 дней)
76725
Ok, благодарю, именно это и хотел знать.
Только я душнила и долгострой. Идея классная, но напишу, наверное, через месяц, когда всем, кому интересно, будет нафиг не нужно
Камрады! Я тут ночку посидел, не спя, и написал пост про, который говорил: https://cs-cs.net/funkciya-fun-i-funkcionalniy-blok-fb-codesys-owenlogic
Это пост про Функции и Функциональные блоки. Описал я то, как они работают, как создавать, как вызывать. И некоторые приёмы для CodeSys (для OwenLogic не подойдут).
Если кому полезно - читайте на здоровье!
Подскажите, а работают ли в st функции PUTBIT и EXTRACT? И не планируется ли добавить логические операции с целыми числами? (пр. 5 AND 3 = 1; 5 OR 3 = 7)
Подскажите, а работают ли в st функции PUTBIT и EXTRACT? И не планируется ли добавить логические операции с целыми числами? (пр. 5 AND 3 = 1; 5 OR 3 = 7)
Логические с целочисленными обещали сделать.
К битам целого обращайтесь через точку:
udiVar.x (x - номер бита от 0 до 31)
Логические с целочисленными обещали сделать.
К битам целого обращайтесь через точку:
udiVar.x (x - номер бита от 0 до 31)
Спасибо за информацию! Ждём обновления!
Констант еще нехватает.
инициируйте переменные
Попробовал. Не вариант. case не работает с переменными.
Хотелось состояниям автомата дать осмысленные названия, а не просто числа.
Попробовал. Не вариант. case не работает с переменными.
Хотелось состояниям автомата дать осмысленные названия, а не просто числа.
Ну, не знаю, по мне состояния лучше осмысливать через комментарии
case N of
0: // Инициализация
Res := false;
Q := 0;
1: // Шаг вправо
Res := true;
Q := 1;
2: // Шаг влево
Res := true;
Q := 2;
3: // Растрел
Res := true;
Q := 3;
end_case
Ну, не знаю, по мне состояния лучше осмысливать через комментарии
case N of
0: // Инициализация
Res := false;
Q := 0;
1: // Шаг вправо
Res := true;
Q := 1;
2: // Шаг влево
Res := true;
Q := 2;
3: // Растрел
Res := true;
Q := 3;
end_case
Не, именованые константы/перечисления - очень удобны для таких вещей.
Например, если бы мне надо было вставить в код выше состояние "Прыжок на месте" - то не пришлось бы перенумеровывать все состояния ниже внутри кода, достаточно поправить константы.
Жаль что в OL это не поддержано (хотя бы константы)
Не, именованые константы/перечисления - очень удобны для таких вещей.
Например, если бы мне надо было вставить в код выше состояние "Прыжок на месте" - то не пришлось бы перенумеровывать все состояния ниже внутри кода, достаточно поправить константы.
Жаль что в OL это не поддержано (хотя бы константы)
утверждаете что так не работает?
case N of
3: // Растрел
Res := true;
Q := 3;
2: // Шаг влево
Res := true;
Q := 2;
0: // Инициализация
Res := false;
Q := 0;
1: // Шаг вправо
Res := true;
Q := 1;
end_case
утверждаете что так не работает?
case N of
3: // Растрел
Res := true;
Q := 3;
2: // Шаг влево
Res := true;
Q := 2;
0: // Инициализация
Res := false;
Q := 0;
1: // Шаг вправо
Res := true;
Q := 1;
end_case
Нет конечно (хотя кривой порядок сам по себе может сделать неудобным восприятие).
Это же не единственный вариант их использования, например могло быть так "N > 3 AND N < 10"
Нет конечно (хотя кривой порядок сам по себе может сделать неудобным восприятие).
предлагалось вообще не воспринимать цифры, а вдумчиво вчитываться в коммент к кейсу
Это же не единственный вариант их использования, например могло быть так "N > 3 AND N < 10"
чем это предложение отличается от простой переменной? Константа удобна тем что запись в неё вызовет скорее всего ошибку компилятора, а так её спокойно заменяет обычная переменная, где это возможно в зависимости от среды разработки
Не. Не надо играться с магическими числами. Лучше константы. И ещё и для границ массивов.
Не, именованые константы/перечисления - очень удобны для таких вещей.
Например, если бы мне надо было вставить в код выше состояние "Прыжок на месте" - то не пришлось бы перенумеровывать все состояния ниже внутри кода, достаточно поправить константы.
Жаль что в OL это не поддержано (хотя бы константы)
Перечисления, структуры и константы удобны в больших программах, когда в разных блоках нужно использовать унифицированные значения. В Лоджике же блоки на ST - это, все-таки локальные самодостаточные макросы. Не думаю, что ST в Лоджике перерастет во что-то большее - для этого, думаю, надо заново всю среду разработки переписывать
программа может быть несложной, но из полсотни шагов. И ни какое комментирование, особенно на пнр, не заменит автоматическую перенумерацию которая пофакту будет при использовании констант/перечислений. Особенно при куче ветвлений.
Александр_004
12.08.2024, 12:06
Добрый день!
Подскажите пожалуйста, почему при изменении переменной udisel оператор if не переключает выходы?
Необходимо что бы выход Start кратковременно менял значение при изменении udisel для работы Rise_fall.
//область кода
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false ;
if (udiSel >= 0) or (udiSel <= 1) then
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
Start := true ;
ELSIF udiSel >= 2 THEN
Start := false ;
ELSIF (udiSel >= 2) or (udiSel <=7) then
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
Start := true ;
ELSIF udiSel >= 8 THEN
Start := false ;
end_if
end_function_block
udiSel >= 0 захватывает весь диапазон значений udiSel
наверно хотели написать что-то типа (udiSel >= 0) AND (udiSel <= 1) ?
попробуйте CASE - наверное будет проще
Добрый день!
Подскажите пожалуйста, почему при изменении переменной udisel оператор if не переключает выходы?
Необходимо что бы выход Start кратковременно менял значение при изменении udisel для работы Rise_fall.
//область кода
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false ;
if (udiSel >= 0) or (udiSel <= 1) then
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
Start := true ;
ELSIF udiSel >= 2 THEN
Start := false ;
ELSIF (udiSel >= 2) or (udiSel <=7) then
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
Start := true ;
ELSIF udiSel >= 8 THEN
Start := false ;
end_if
end_function_block
Answer | Phind Instant Model
В вашем коде есть несколько моментов, которые могут привести к тому, что оператор if не переключает выходы так, как вы ожидаете. Давайте разберемся с ними подробнее:
Проблема с логикой условий
Ваш код содержит несколько блоков ELSIF, каждый из которых проверяет различные диапазоны значений udiSel. Однако, последовательность этих условий и их формулировка могут приводить к непредвиденному поведению. В частности, если udiSel находится в диапазоне от 2 до 7 включительно, то выполняется только первый блок ELSIF, который устанавливает Start в true, но не обновляет значения xOut1, xOut2, и xOut3. Это происходит потому, что после выполнения первого условия, остальные условия не проверяются из-за использования ключевого слова ELSIF.
Чтобы исправить это, вам нужно либо объединить условия, чтобы они корректно перекрывались, либо использовать отдельные операторы if для каждого условия, чтобы каждое из них могло быть проверено независимо.
Использование OR вместо >=
Вы используете оператор or (or) для проверки диапазонов значений udiSel. Это может привести к тому, что одно из условий будет истинным даже если udiSel находится вне этого диапазона. Например, (udiSel >= 0) or (udiSel <= 1) будет истинным для любого значения udiSel, поскольку хотя бы одно из условий всегда выполняется. Возможно, вы хотели использовать оператор and (and), чтобы оба условия должны выполняться одновременно.
Рекомендации по исправлению
Пересмотрите логику условий: Убедитесь, что условия корректно перекрывают все возможные значения udiSel и что нет случайных истинностей из-за неправильного использования операторов or или and.
Используйте отдельные операторы if для каждого блока: Это позволит каждому блоку условий быть проверенным независимо, избегая проблем с перекрытием.
Проверьте логику установки Start: Убедитесь, что установка Start в false соответствует вашим требованиям и не мешает правильной работе системы.
Пример исправленного кода:
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false;
if (udiSel >= 0) and (udiSel <= 1) then
begin
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
Start := true;
end
else if udiSel >= 2 and udiSel < 8 then
begin
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
Start := true;
end
else if udiSel >= 8 then
begin
Start := false;
end;
так ответила бездушная машина, вдруг угадала
Добрый день!
Подскажите пожалуйста, почему при изменении переменной udisel оператор if не переключает выходы?
Необходимо что бы выход Start кратковременно менял значение при изменении udisel для работы Rise_fall.
//область кода
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false ;
if (udiSel >= 0) or (udiSel <= 1) then
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
Start := true ;
ELSIF udiSel >= 2 THEN
Start := false ;
ELSIF (udiSel >= 2) or (udiSel <=7) then
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
Start := true ;
ELSIF udiSel >= 8 THEN
Start := false ;
end_if
end_function_block
А можно поинтересоваться, как вы именно хотите моргать переменной Start? При каждом изменении udiSel взвести на один цикл или сбросить на один цикл?
И да, у вас тут несколько ошибок
1. if (udiSel >= 0) or (udiSel <= 1) then - сразу отбрасывает все остальные сравнения, наверное, вы хотели if (udiSel = 0) or (udiSel = 1)
2. ELSIF udiSel >= 2 THEN - отбрасывает следующее сравнение, вероятно здесь вы пытались моргнуть
3. ELSIF (udiSel >= 2) or (udiSel <=7) then - отбрасывает следующее сравнение, тут, наверное ELSIF (udiSel >= 2) and (udiSel <=7)
4. ELSIF udiSel >= 8 THEN - как бы лишний, потому что вначале вы уже сбросили переменную Start
Александр_004
12.08.2024, 12:57
Да, мне нужно при каждом изменении значения udiSel, на один цикл изменять выход Start. Спасибо за поправки
С поправками выше, стало работать, переключает. Но как кратковременно менять значение выхода Start (bool) в цикле программы? При переключении выходов должен сбросится регулятор подключенный к данным выходам.
kondor3000
12.08.2024, 13:26
Да, мне нужно при каждом изменении значения udiSel, на один цикл изменять выход Start. Спасибо за поправки
С поправками выше, стало работать, переключает. Но как кратковременно менять значение выхода Start (bool) в цикле программы? При переключении выходов должен сбросится регулятор подключенный к данным выходам.
Для этого можно использовать код R_Trig, включение выхода на 1 цикл, где In и Q вход и выход
var //объявление локальных переменныx
R:bool; //локальная переменная с типом данных bool
end_var
Q:=In and not R;
R:=In;
Да, мне нужно при каждом изменении значения udiSel, на один цикл изменять выход Start. Спасибо за поправки
С поправками выше, стало работать, переключает. Но как кратковременно менять значение выхода Start (bool) в цикле программы? При переключении выходов должен сбросится регулятор подключенный к данным выходам.
Еще раз хочу уточнить.
У вас первый этап занимает два шага, второй этап - 6 шагов. Вы хотите моргнуть при изменении шага (udiSel) или изменении этапа (выходы)? И как моргнуть - кратковременно сбросить переменную Start или кратковременно взвести ее?
Александр_004
12.08.2024, 14:18
Какие еще есть варианты отключить выход на короткий промежуток времени при смене значения на входе? Возможно ли после каждого оператора If поставить условие отключения выхода, к примеру на 1 мс?
Моргнуть при изменении этапа, кратковременно выключить выход (сбросить Start).
kondor3000
12.08.2024, 14:38
Какие еще есть варианты отключить выход на короткий промежуток времени при смене значения на входе? Возможно ли после каждого оператора If поставить условие отключения выхода, к примеру на 1 мс?
Моргнуть при изменении этапа, кратковременно выключить выход (сбросить Start).
Дописать код в конце и добавить переменную udiSel_ в VAR
if udiSel<> udiSel_ then
Start:=false;
udiSel_:=udiSel;
else Start:=True;
end_if
Александр_004
12.08.2024, 14:43
Дописать код в конце и добавить переменную udiSel_ в VAR
if udiSel<> udiSel_ then
Start:=false;
udiSel_:=udiSel;
else Start:=True;
end_if
Спасибо! Работает!
kondor3000
12.08.2024, 14:48
Спасибо! Работает!
Вообще, всё делается гораздо проще на шаговом автомате CASE, тут есть несколько примеров, везде где есть шаги или переключения режимов, только в вашем случае без таймера шагов https://owen.ru/forum/showthread.php?t=37203&page=9&p=429061#81
Александр_004
12.08.2024, 15:36
При использовании кода:
f udiSel<> udiSel_ then
Start:=false;
udiSel_:=udiSel;
else Start:=True;
end_if
Происходит сброс выхода при каждом изменении переменной udiSel. Case и If у меня дают одинаковые результаты. Как сделать сброс после этапа выполнения? Переменная udiSel меняется от 2 до 7, при этом сброс выхода делать не нужно, так как происходит регулирование в заданном диапазоне.
//область кода
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false;
CASE udiSel OF
0..1:
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
2..7:
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
8..14:
xOut1 := IN2_7max;
xOut2 := IN8_14max;
xOut3 := D8_14;
END_CASE
if udiSel <> udiSel_ then
Start := false;
udiSel_:= udiSel;
else Start := True;
end_if
END_FUNCTION_BLOCK
77972
Александр_004
12.08.2024, 16:49
Селектор работает, но выход не сбрасывается.
//область кода
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
//Start := false;
if (udiSel >= 0) and (udiSel <= 1) then
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
end_if
if (udiSel<>udiSel_) and ((udiSel=0) or (udiSel=1)) then
Start := false;
udiSel_:= udiSel;
else Start := True;
udiSel_:= udiSel;
end_if
if (udiSel >= 2) and (udiSel <= 7) then
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
end_if
if (udiSel<>udiSel_) and ((udiSel=2) or (udiSel=7)) then
Start := false;
udiSel_:= udiSel;
else Start := True;
udiSel_:= udiSel;
end_if
if (udiSel >= 8) and (udiSel <= 14) then
xOut1 := IN2_7max;
xOut2 := IN8_14max ;
xOut3 := D2_7;
end_if
if (udiSel<>udiSel_) and ((udiSel=8) or (udiSel=14)) then
Start := false;
udiSel_:= udiSel;
else Start := True;
udiSel_:= udiSel;
end_if
end_function_block
[QUOTE=Александр_004;443640]Селектор работает, но выход не сбрасывается.
А если так
var
flag : udint;
end_var
xOut1 := 0;
xOut2 := 0;
xOut3 := 0;
Start := false;
case udiSel of
0, 1:
xOut1 := IN0_0;
xOut2 := IN0_1max;
xOut3 := D0_1;
Start := true;
flag := 0;
2..7:
if flag = 1 then
xOut1 := IN0_1max;
xOut2 := IN2_7max;
xOut3 := D2_7;
Start := true;
else
flag := 1;
end_if
8..14:
if flag = 2 then
xOut1 := IN2_7max;
xOut2 := IN8_14max;
xOut3 := D8_14;
Start := true;
else
flag := 2;
end_if
end_case
end_function_block
kondor3000
12.08.2024, 17:55
Селектор работает, но выход не сбрасывается.
Не надо кусками делить, сброс должен быть в конце кода
if (udiSel<>udiSel_) and ((udiSel=2) or (udiSel=7) or (udiSel=8) or (udiSel=14)) then
Start := false;
udiSel_:= udiSel;
else Start := True;
udiSel_:= udiSel;
end_if
end_function_block
Александр_004
12.08.2024, 19:12
Спасибо за помощь! Оба варианта работают
viktor1974
28.08.2024, 15:24
Добрый день! Как можно в OwenLogic взять текущее состояние отсчета времени в таймере TON, красным оно идет и визуално видно, но в выходах его нет?
kondor3000
28.08.2024, 15:59
Добрый день! Как можно в OwenLogic взять текущее состояние отсчета времени в таймере TON, красным оно идет и визуално видно, но в выходах его нет?
Зачем вы в несколько тем пишите? Уже ответил вам тут https://owen.ru/forum/showthread.php?t=9398&page=795&p=444648#post444648
viktor1974
29.08.2024, 21:59
подумал, что не туда написа:oл
sergey_gln
10.09.2024, 09:37
Добрый день!
Делаю проект на ПР205. Возникла потребность вывести на экранчик ПРки давление от вакуумметра в "научном" формате.
Для вычисления мантиссы и десятичного порядка решил написать ФБ на ST. Логичнее использовать функцию, но функция на ST в OWENLogic имеет только один выход, а нужно три.
Код ФБ на картинке (булевская fbstart не используется).
78546
Ошибок не выдает, симуляция запускается. Но в режиме симуляции у ФБ не отображаются никакие значения - ни у выходов, ни у входов. Если к входу ФБ floatNum подключить отдельную входную переменную (регистр Modbus), то в симуляции OwenLogic не позволяет ввести значение этой переменной.
А все выходные переменные блока, если их добавить в окно просмотра, показывают нули.
78543
Для проверки добавил в проект штатный ФБ "Счетчик прямого счета" из библиотеки Owen - та же картина.
78544
С чем может быть связано такое поведение?
P.S.: Среда OWENLogic 2.7.354.0.
Добрый день!
С чем может быть связано такое поведение?
P.S.: Среда OWENLogic 2.7.354.0.
Свяжите выход ФБ с выходом ПР (можно через преобразователь) или выведите его на экран. Без этого ФБ будет игнорироваться компилятором
sergey_gln
10.09.2024, 10:17
Свяжите выход ФБ с выходом ПР (можно через преобразователь) или выведите его на экран. Без этого ФБ будет игнорироваться компилятором
Спасибо!
Вывел выходные переменные на экран, теперь всё отлично работает.
amaterasu
23.09.2024, 17:32
Здравствуйте! нигде не могу найти информацию, В OL есть возможность писать в функциональный блок(Write to FB), я написал ФБ на ST, но не могу обращаться к нему с помощью этой функции, то есть она вообще не появляется в списке ФБ, хотя на холст я его добавил, подскажите с помощью этой функции вообще возможно обратиться к блоку написанному на ST или я что то делаю не так?78809
Здравствуйте! нигде не могу найти информацию, В OL есть возможность писать в функциональный блок(Write to FB), я написал ФБ на ST, но не могу обращаться к нему с помощью этой функции, то есть она вообще не появляется в списке ФБ, хотя на холст я его добавил, подскажите с помощью этой функции вообще возможно обратиться к блоку написанному на ST или я что то делаю не так?
Непонятна цель этих манипуляций.
Что скрывается за фразой "...не могу обращаться к нему с помощью этой функции..."?
amaterasu
23.09.2024, 19:08
я хотел создать массив, для того чтобы не плодить кучу переменных, в каждый элемент которого я бы вводил время стадии, то есть для каждой стадии свой элемент массива в PT таймера, но используя write to fb , мой функциональный блок не появляется в списке, и поэтому у меня вопрос могу ли я вообще использовать write to fb, для фб на ст?
kondor3000
23.09.2024, 19:20
я хотел создать массив, для того чтобы не плодить кучу переменных, в каждый элемент которого я бы вводил время стадии, то есть для каждой стадии свой элемент массива в PT таймера, но используя write to fb , мой функциональный блок не появляется в списке, и поэтому у меня вопрос могу ли я вообще использовать write to fb, для фб на ст?
Write to fb не работает в ФБ, он сделан для макросов.
К ФБ можно обратиться в самом ФБ (вложить блоки один в другой) и только с с помощью входов ФБ.
Глобальные переменные пока в Лоджик не завезли.
amaterasu
23.09.2024, 19:43
большое спасибо
Рогов Алексей
04.12.2024, 11:53
Добрый день!
Уважаемые программисты, нет реле под рукой, такая конструкция жизнеспособна?
function_block R_c //Реверсивный счётчик.
var_input //объявление входных переменных
U : bool; //входная переменная с типом данных bool
D : bool; //входная переменная с типом данных bool
Res : bool; //входная переменная с типом данных bool
N : udint; //входная переменная для значения счетчика после сброса
end_var
var_output //объявление выходных переменных
Q : udint; //выходная переменная с типом данных udint
end_var
var //объявление локальных переменных
CounterValue : udint; //переменная для текущего значения счетчика
RTrig : bool; //переменная для определения переднего фронта на входе «U»
RTrig1 : bool; //переменная для определения переднего фронта на входе «D»
end_var
if Res then
CounterValue := N;
end_if
while U and not RTrig and not Res and CounterValue <100 do
CounterValue := (CounterValue + 1);
RTrig := U;
end_while
if not U and RTrig then
RTrig := false;
end_if
while D and not RTrig1 and not Res and CounterValue > 0 do
CounterValue := (CounterValue - 1);
RTrig1 := D;
end_while
if not D and RTrig1 then
RTrig1 := false;
end_if
Q := CounterValue ;
end_function_block
Добрый!
А чем Вас не устраивает стандартный?
80549
А так, в принципе, - да!
Но я бы сделал так:
function_block CTN
var_input
U, D, R : bool;
N : udint;
end_var
var_output
Q : udint;
end_var
var
UTrig, DTrig : SYS.RTRIG;
init : bool;
end_var
UTrig(I := U); DTrig(I := D);
if UTrig.Q and Q < 100 then Q := Q + 1; end_if
if DTrig.Q and Q > 0 then Q := Q - 1; end_if
if R or not init then Q := N; end_if
init := true;
end_function_block
Добрый день!
Уважаемые программисты, нет реле под рукой, такая конструкция жизнеспособна?
1. А в эмуляторе проверить работу? - если работает, значит жизнеспособна
2. В ST Лоджика уже завезли системные триггеры и счетчики
Добрый!
...Но я бы сделал так:
function_block CTN
var_input
U, D, R : bool;
N : udint;
end_var
var_output
Q : udint;
end_var
var
UTrig, DTrig : SYS.RTRIG;
init : bool;
end_var
UTrig(I := U); DTrig(I := D);
if UTrig.Q and Q < 100 then Q := Q + 1; end_if
if DTrig.Q and Q > 0 then Q := Q - 1; end_if
if R or not init then Q := N; end_if
init := true;
end_function_block
Тогда уж, сразу счетчик использовать, тем более, что в ST он 32-битный
Рогов Алексей
04.12.2024, 13:09
Спасибо! оператор WHILE интересовал. Как факт того, что в блоке счётчика два цикла, а переменная CounterValue одна.
Спасибо! оператор WHILE интересовал. Как факт того, что в блоке счётчика два цикла, а переменная CounterValue одна.
Цикл там у вас, вообще, лишний
lunyov_i
22.12.2024, 07:59
Коллеги!
Рады представить вам Функциональные блоки на текстовом языке ST в Owen Logic:)
Поддержан вызов функции и функционального блока внутри функционального блока;
При вызове ФБ внутри ФБ поддержано обращение к входам и выходам ФБ через точку;
Поддержаны локальные одномерные массивы.
ФБ на ST поддерживают приборы: ПР100(М02), ПР102, ПР200, ПР103, ПР205 и ИПП120.
Данная версия Owen Logic является бета версией!
Скачать Owen Logic 2.4.332(beta) (https://disk.yandex.ru/d/LA3y9k6EziyPzA)
Если в процессе работы с новой версией вы обнаружите баг или у вас есть предложения по развитию ФБ на ST, то можете поделиться в этой теме или прислать на почту soft@owen.ru
UPD (15.08.23):
Выпущена релизная версия Owen Logic 2.4 с ФБ на ST
Это очень здорово. Все "задышало" по-лучше. Скажите, логические операторы для целых типов в дальнейшем возможно cделать в ST? Пока только для типа bool. Иногда просто необходимо разные маски выделить, в FBD это без проблем, а в ST такое невозможно. Или ошибаюсь? Поправьте
kondor3000
22.12.2024, 10:29
Это очень здорово. Все "задышало" по-лучше. Скажите, логические операторы для целых типов в дальнейшем возможно cделать в ST? Пока только для типа bool. Иногда просто необходимо разные маски выделить, в FBD это без проблем, а в ST такое невозможно. Или ошибаюсь? Поправьте
Логические операторы пока только для BOOL, обещали сделать для целых, но никто не запрещал написать функцию самому. Тут есть пример Валенка,
Переключение бит_3++.https://owen.ru/forum/showthread.php?t=26216&page=382#3814
Распаковка и упаковка бит в маску через точку, поддержаны уже сейчас.
Вот, Валенок в свое время вдохновил
Newcomer
24.12.2024, 12:33
Добрый день
Есть ли какая-то возможность сделать энергонезависимой переменную в ФБ на ST ?
Добрый день
Есть ли какая-то возможность сделать энергонезависимой переменную в ФБ на ST ?
Пока - разве что через костыль, привязав её снаружи на отдельный вход и выход блока
Newcomer
24.12.2024, 14:22
Пока - разве что через костыль, привязав её снаружи на отдельный вход и выход блока
Так уже и сделано. Посмотрю что из этого получится.
На самом деле это более правильный путь, делать внешние переменные энергонезависимые. Аналог In_Out и к ним привязываться. Делал такое еще на макросах в FBD. Чтобы целиком FBD не делать энергонезависимым со всеми потрохами.
Подскажите, как запаролить в OWENLogic ФБ, написанный на ST???
Подскажите, как запаролить в OWENLogic ФБ, написанный на ST???
///<Password>Parol</Password>
81133
Я правильно понял, что ДОКУМЕНТИРОВАНИЕ будет работать только после импорта в менеджер компонентов? А это может сделать только ОВЕН?
Я правильно понял, что ДОКУМЕНТИРОВАНИЕ будет работать только после импорта в менеджер компонентов? А это может сделать только ОВЕН?
Вот, можете посмотреть. Пароль 123
Все получилось!!! Спасибо
Простой регулятор для управления регулирующим клапаном в режиме трехпозиционного управления (дискр: открыть/закрыть). Использовал в проектах для ПЛК (в CDS2 и 3) для поддержания уровня воды, температуры, разрежения, давления и т.п. В ПР еще не использовал. Если есть у кого то возможность испытать, то подскажу как настроить.
Тип файла: .fbst
Посмотреть работоспособность можно при помощи эмулятора объекта
https://owen.ru/forum/showthread.php?t=25068&p=447749&viewfull=1#post447749
и тут показывал на примере собственного ПИ-регулятора
https://owen.ru/forum/showthread.php?t=25068&p=447950&viewfull=1#post447950
И ещё интересно описание алгоритма - как формируются импульсы, какие функции и ограничения присутствуют (от взвинчивания интегральной и др.).
Покажу, как свой описывал
https://owen.ru/forum/showthread.php?t=25068&p=430251&viewfull=1#post430251
Ваш ФБ запаролен, нет описания алгоритма, ограничений, связанных с ним. Т.е. ничего не понятно - нет возможности понять назначение и рабочие диапазоны значений входов.
Если бы я начинал работу с Овен ПР и ел, что дадут - ФБ PD_CEkip_v2_ был бы мне полезен, наверное, наряду со множеством других ШИМ от других пользователей или связки PID + RegKZR от Овен.
Мне кажется, что инструменты, предлагаемые другим людям для работы, нужно описывать или так, как показал по ссылкам или даже подробнее, как в моём бложике, чтобы у пользователей было меньше вопросов
https://www.cyberforum.ru/blogs/534277/8438.html
https://www.cyberforum.ru/blogs/534277/8667.html
Это просто критика, надеюсь, будет услышана. Хотел просто проверить работу Вашего ФБ с эмулятором объекта и не смог - описания не хватило.
Эмуляторам не верю ))). Живой объект это другое
Тут другой вопрос есть.
Хочется алгоритм PID написать в виде программы на C#. Примеры PID на C# находил, но вопрос в другом, как написать режим автонастройки ?
Может у кого есть на ST готовый PID с режимом автонастройки ? с ST еще худо бедно на C# переведу. с FBD наверное будет куда сложнее.
Ну вот и хотелось бы написать вариант без патентных прав.
Не вдаваясь в нюансы и в подробности, код Гистерезиса для примера
public class Hysteresis()
{
public bool EN; // входная переменная разрешающая работу программы
public double inCnl;
public double low;
public double high;
public bool mode = true; // По умолчанию нагрев = true, охлаждение = false
public bool Q; // Выход гистерезиса
public ushort cycle; // Задание цикла выполнения программы в мс
public bool terminated = false; // Переменная остановки цикла для остановки программы и(или) для закрытия потока
bool _mode;
public void Run()
{
// Копирование входных переменных во внутренние программы
bool res = false;
do
{
if (EN)
{
// Копирование входных переменных во внутренние в начале цикла программы
_mode = mode;
// Инициализация выходных переменных если требуется.
res = Q; // для возможности задания retain при перезапусках
// тело программы
if (_mode)
{
if (inCnl < low) res = true;
if (inCnl > high) res = false;
}
else
{
if (inCnl < low) res = false;
if (inCnl > high) res = true;
}
// тело программы
// Копирование выходных переменных из внутренних в конце цикла программы, для некоторых необязательно, будут обработаны программой
Q = res;
// Задание времени цикла
Thread.Sleep(cycle);
}
}
while (!terminated);
}
}
Суть, выполнять несколько экземпляров программ из Scada системы с возможностью управления модулями В/В без контроллеров.
Вот PID бы аналогично сделать, но доступный и каким-то образом прикрутить еще автонастройку. Типа запустил на Н-ное время, потом получил в каналах Scada соответствующие коэффициенты. Вбил их в основную программу и запустил на постоянку.
Можно попробовать у ChatGPT алгоритм спросить, или попросить написать :-)
да алгоритм самого PID для C# я находил толи на GIT толи еще где. Тут вопрос больше в сторону автонастройки, ее замутить так же кодом.
да алгоритм самого PID для C# я находил толи на GIT толи еще где. Тут вопрос больше в сторону автонастройки, ее замутить так же кодом.
Если есть желание поразбираться с алгоритмом:
Если есть желание поразбираться с алгоритмом:
Тогда уж, вот
Простой регулятор для управления регулирующим клапаном в режиме трехпозиционного управления (дискр: открыть/закрыть). Использовал в проектах для ПЛК (в CDS2 и 3) для поддержания уровня воды, температуры, разрежения, давления и т.п. В ПР еще не использовал. Если есть у кого то возможность испытать, то подскажу как настроить.
Тип файла: .fbst
Выдалось время и попробовал проверить с эмулятором объекта управления, заодно и описание внимательно прочитал.
Теряюсь с определением названия регулятора. Т.к. на приводе интегрирует, то, если считать выход ПИД эквивалентом положения КЗР, регулятор ближе к ПИ (RU_KP - это Ти, RU_KD - это Кп).
Отличие от моего и от связки PID+RegKZR состоит в
- усечении большого времени импульса до времени пересчёта,
- не накапливании ничтожно малых расчётных импульсов, для одного минимального, т.е. фактическое отсутствие интегрального звена и проявление статической ошибки регулирования пропорционального регулятора (когда рассогласование не позволяет переместить клапан, но уставка так и не достигнута)
- и по этим причинам отсутствует взвинчивание интегральной составляющей. Такое диалектическое поведение - "наши сильные стороны являются продолжением отрицательных черт".
Единственно, поначалу сбивает с толку соотнесение параметров с Кп и Ти "аналогового" ПИД и, соответственно, их первое приближение для начала наладки.
По подобному принципу работает регулятор ТРМ32
D=2.5*K*(E+T*dE)
и незримо в этой формуле параметр S - период пересчёта, а также минимальное время импульса и зона нечувствительности.
Только в ТРМ32 происходит накопление малых импульсов.
В РЭ ТРМ32 есть и рекомендации по подбору параметров.
Работать должно, как и прибор с аналогичным алгоритмом.
Приложу программу с эмуляцией работы для ПР205 - т.к. у него эмулируется дисплей.
SP - уставка
PV - переменная процесса, измеренная на объекте
ПИД - выход ПИД регулятора - заполнение импульса ШИМ, %
Pos - позиция клапана после всех воздействий с учётом люфтов, времени полного хода и прочего, %
Помеха - помеха, приведённая к положению клапана, % (т.е. как бы клапан немного смещается от постороннего воздействия)
Концевые - состояние концевых выключателей
Направление - направление перемещения
Добавлю, что для эксперимента меня интересовало поведение регулятора с учётом существования люфта и даже более - неравномерного люфта. Поэтому там такие значения.
На втором экране - настройки Кп и Тд.
У меня задумка, заливать тестовые программы в ПР и при помощи готовых программ по Modbus получать значения и строить графики. Кажется, это может Owen Configurator, но для новых Windows 10/11.
Поэтому подготовил сетевые переменные, но до графика руки не дошли.
Я уже писал, что эмулятором не верю. Есть конкретные объекты, где все работает. Точность регулирования устраивает. Регулятор не сложный. Ваш регулятор пробовал, так и не смог настроить на объекте. Отказался от него.
В приложении "ТП" - красный тренд это поддерживаемая температура. Есть не стабильность в давлении пара в греющем контуре (светло-фиолетовый тренд) и все прекрасно отрабатывает (голубой тренд - положение клапана РК3). Лишних сработок нет - только по делу )))
Регулятор можно использовать без зоны нечувствительности - эту функцию выполняет параметр "мин. время импульса", чем оно больше, тем больше погрешность регулирования.
Также могу приложить и тренды и по уровню воды и т.п.
Простой регулятор для управления регулирующим клапаном в режиме трехпозиционного управления (дискр: открыть/закрыть). Использовал в проектах для ПЛК (в CDS2 и 3) для поддержания уровня воды, температуры, разрежения, давления и т.п. В ПР еще не использовал. Если есть у кого то возможность испытать, то подскажу как настроить.
Тип файла: .fbst
Тип файла: .fbst - это что ?
Тип файла: .fbst - это что ?
Это сохраненный функциональный блок на ST
А есть еще, *.fst - это функция
Подтягиваются через маню Файл - Импорт из файла
Я уже писал, что эмулятором не верю. Есть конкретные объекты, где все работает. Точность регулирования устраивает. Регулятор не сложный. Ваш регулятор пробовал, так и не смог настроить на объекте. Отказался от него.
К эмуляторам придёте со временем. Пока нет смысла обсуждать. Они требуются для проверки самодельного ФБ, чтобы алгоритм отладить до выхода на объект, а на объекте только подбирать коэффициенты. В рабочей программе эмуляторы не нужны.
Затрудняюсь объяснить причины неудачи с моим регулятором. Не сразу, но настроил его для теплосети, т.е. и лично у меня есть успешный пример. По сходному алгоритму делал и раньше, но там требовалось делать пересчёт интегральной для поддержания выходной мощности ПИД примерно посередине диапазона разрядности числа - лишняя морока.
Хочу для себя сделать вывод трендов на период наладки в какой-нибудь бесплатной программе. Ваши тренды в какой программе построены? Или может посоветовать можете?
МихаилГл
11.01.2025, 19:40
Судя по картинке, это simple scada.
Спасибо. Хочется чего-то простого в настройке - настроить соединение, адрес устройства, регистра, масштаб, период опроса и наслаждаться.
Пока присмотрел, но не проверял
https://github.com/MSoftwaree/modbus-history-chart
https://www.elemer.ru/po/modbus_config.php
до смены компьютера на другой с Windows 10/11 не рассматриваю, но в Owen Configurator будто бы добавили графики (работают только для Win 10/11).
RapidScada. Если надо будет посмотреть графики с масштабированием, то Графики Про. Можно на сайте генерировать бесплатные ключи, если не требуется полноценной работы. Ключи действуют до конца следующих суток.
Здравствуйте , возможно вопрос уже подымался, интересует ПИД регулятор , если он на ST или это не к чему на ST
kondor3000
14.01.2025, 18:05
Здравствуйте , возможно вопрос уже подымался, интересует ПИД регулятор , если он на ST или это не к чему на ST
Здесь пример использования обычного ПИД с сохранением настроек https://owen.ru/forum/showthread.php?t=17974&page=51#505
На форуме выкладывали ПИД и на ST.
Здравствуйте , возможно вопрос уже подымался, интересует ПИД регулятор , если он на ST или это не к чему на ST
Если речь об аналоговом регулировании, то берите из библиотеки компонентов PID_ - он без автонастройки, но для большинства наладчиков это не проблема. При смене платформы не придётся судорожно переделывать с аппаратного, на программный.
С автонастройкой есть аналоговый ПИД, но он аппаратный и доступен не для всех моделей ПР - если ПР его поддерживает, то он будет присутствовать среди макросов проекта.
Если речь о ПИД для 3-позиционного управления без обратной связи по положению привода, то тут я выделяю 2 подхода:
- примерно соответствующий аналоговому регулятору
- просто формирование импульсов, ширина которых меняется по какому-нибудь закону регулирования, иногда похожем на ПИД
Если есть опыт настройки аналоговых регуляторов - берите мой
https://owen.ru/forum/showthread.php?t=25068&p=430251&viewfull=1#post430251
и в сообщении ниже.
Проверял его и на объекте и на эмуляторе
https://owen.ru/forum/showthread.php?t=25068&p=447950&viewfull=1#post447950
Если регулятор должен быть понятным и близким к двухпозиционному - пока значение меньше уставки - давать импульсы открытия, как стало выше - на закрытие, и при этом ширина импульсов меняется от величины рассогласования, то тогда берите любой другой вариант с ШИМ, например, на несколько сообщений выше.
https://owen.ru/forum/showthread.php?t=38239&p=454516&viewfull=1#post454516
или поищите другие варианты.
Тут весь вопрос - в личном опыте ручной настройки регуляторов.
Лично мне ближе аналоговые, поэтому и мой 3-позиционный воспроизводит его поведение. Но его поведение не понятно многим.
Просьба подсказать , у меня простая задача есть датчик температуры , подается на вход ПР , на экране СП 307 оператор выставляет нужную температуру, и предел , дальше происходит нагрев до уставки и разрешение на рабочий цикл
итого 4 Зоны (контура) необходимо вывести и управлять, подскажите пожалуйста по настройке вашего блока , заранее спасибо
kondor3000
10.02.2025, 16:07
Просьба подсказать , у меня простая задача есть датчик температуры , подается на вход ПР , на экране СП 307 оператор выставляет нужную температуру, и предел , дальше происходит нагрев до уставки и разрешение на рабочий цикл
итого 4 Зоны (контура) необходимо вывести и управлять, подскажите пожалуйста по настройке вашего блока , заранее спасибо
Зачем вам ПИД регулятор?
Для вашей задачи подойдёт и простой нагрев до уставки и отключение (включение ).
Просьба подсказать , у меня простая задача есть датчик температуры , подается на вход ПР , на экране СП 307 оператор выставляет нужную температуру, и предел , дальше происходит нагрев до уставки и разрешение на рабочий цикл
итого 4 Зоны (контура) необходимо вывести и управлять, подскажите пожалуйста по настройке вашего блока , заранее спасибо
Если обращение ко мне по поводу макроса ПИ для 3-позиционного управления клапаном, то он ведёт себя точно, как аналоговый. Если аналоговый настраивали - здесь методика та же.
Я, обычно, настраиваю сначала Кр: оцениваю, что при отклонении от уставки Delta нужно принимать меры и полностью открывать клапан. Параметр с такой физической характеристикой называется полоса пропорциональности Xp=1/Кр и должна уже быть знакома по ПИД регуляторам Овен, Siemens и др. После этого умножаю величину на 6 и перевожу обратно к Кр.
Параметр Ти подбираю экспериментом - чем меньше значение Ти, тем быстрее растёт воздействие, чем больше Ти, тем слабее вклад интегральной составляющей в общее дело регулирования.
Например, при отклонении 10 градусов нужно полностью открывать клапан. Хр=10*6=60, Кр=1/Хр=1/60=0,015.
Ти для начала беру 60с=60000мс - не помню, в каких единицах нужно для макроса. Потом подбираю по техпроцессу.
В сообщении выше есть ссылка на готовый пример применения ПИД с эмулятором объекта - можете попробовать "поиграться" с ним. Тем более, что недавно в ПР205 добавили возможность построения графиков - можно в эмуляции смотреть.
pro100user
06.03.2025, 09:02
Очень сильно не хватает точек остановки при отладке функциональных блоков на языке ST. Понятие шага - в Owen Logic - это один цикл контроллера, а было бы очень неплохо, чтобы можно было шагать по коду функционального блока и смотреть, как что изменяется.
Карбофос
10.03.2025, 16:32
Здравствуйте.
Есть ли возможность использовать макросы из "менеджера компонентов" в коде ST?
Здравствуйте.
Есть ли возможность использовать макросы из "менеджера компонентов" в коде ST?
Только если они тоже на ST написаны
Карбофос
11.03.2025, 08:00
Только если они тоже на ST написаны
Беда. Очень странное решение. Есть ли планы по введению возможности использовать любые макросы?
Беда. Очень странное решение. Есть ли планы по введению возможности использовать любые макросы?
Скорее всего мера не странная, а вынужденная.
А какой макрос то нужен?
kondor3000
11.03.2025, 09:45
Беда. Очень странное решение. Есть ли планы по введению возможности использовать любые макросы?
Любой макрос при желании можно переписать на ST. Вопрос нужно ли это? Может у кого то есть готовый уже.
Карбофос
11.03.2025, 13:18
Скорее всего мера не странная, а вынужденная.
А какой макрос то нужен?
Конечно можно, но это все время, которое можно было бы и не тратить, когда вот они, готовые лежат. А теребить постоянно людей с форума тоже не выход.
Вообще, я сейчас не конкретную задачу решаю, а просто нашел время поковырять новый функционал в виде ST - и понимаю, что ему еще очень далеко до совершенства.
А то, что блок на ST нельзя вставить в обычный макрос - вообще жуть, ставит крест на красивом структурированном проекте, все придется пихать в один экран. На презентациях Овен говорит о замене ПЛК63/73 на ПРххх, (в которых вообще не надо задуматься, какой блок на чем написан, вызываешь их друг из друга в произвольном порядке), а тут такое :/.
СергейНовосиб
27.03.2025, 06:25
А то, что блок на ST нельзя вставить в обычный макрос - вообще жуть, ставит крест на красивом структурированном проекте, все придется пихать в один экран. На презентациях Овен говорит о замене ПЛК63/73 на ПРххх, (в которых вообще не надо задуматься, какой блок на чем написан, вызываешь их друг из друга в произвольном порядке), а тут такое :/.
Вопрос разработчикам ОЛ: в планах есть реализовать возможность применения ФБ на ST в макросах?
Интересно как бы выглядел макрос на ST для PT1000 (П)???
Интересно как бы выглядел макрос на ST для PT1000 (П)???
приблизительно как в базовой oscat библиотеке функции TEMP_PT или RES_PT
или так еще
function Solver: real;
var_input
res : real;
end_var
var
W1, W2, W3, W4, W5, W6, W7, W8 : real;
X : real;
end_var
if res < 80.306 or res > 174.016 then
Solver := 3.402824E+38;
else
X := res;
W1 := X * -0.01762491988258928 + 2.2043139613577374;
W2 := X * 0.6400488968662336 + -23.674505917485266;
W3 := X * 0.0031304507906330763 + -16.89945922108154;
W4 := X * 0.018556566294323017 + 0.25613106090327786;
W5 := X * 0.0006476412362364319 + -0.04368540456173019;
W6 := X * -0.017567624863696805 + 1.7862783116150094;
W7 := X * 0.01082710470500994 + -0.6758584965318757;
W8 := X * 0.20777585219031725 + -31.05972211421347;
if W1 <= 0.0 then W1 := 0.0; end_if;
if W2 <= 0.0 then W2 := 0.0; end_if;
if W3 <= 0.0 then W3 := 0.0; end_if;
if W4 <= 0.0 then W4 := 0.0; end_if;
if W5 <= 0.0 then W5 := 0.0; end_if;
if W6 <= 0.0 then W6 := 0.0; end_if;
if W7 <= 0.0 then W7 := 0.0; end_if;
if W8 <= 0.0 then W8 := 0.0; end_if;
Solver := W1 * 2.951575310396745 + W2 * 4.116406053413549 + W3 * -0.5520606526690841 + W4 * -0.0006347054648307377 + W5 * 0.0019590873049887846 + W6 * 2.3390859627862177 + W7 * 0.021819488290564692 + W8 * 0.2417143920895591 + -167.4311587881956;
end_if;
end_function
// score 0.999999622
// 10 103.903
// 20 107.794
// 40 115.541
// 80 130.897
Интересно как бы выглядел макрос на ST для PT1000 (П)???
вот так http://ftp-ow.owen.ru/softupdate/OWEN%20Logic/STFunctions/Example_TempSensor.owle
Сдается мне что capzap не хочет пускать rovki в ST
В компонентах есть такой код
https://ftp-ow.owen.ru/softupdate/OWEN%20Logic/STFunctions/fPt1000.txt
https://ftp-ow.owen.ru/softupdate/OWEN%20Logic/STFunctions/
function fPt1000: Real; // функция для датчика термосопротивления PT1000
var_input //объявление входных переменных
R:Real;
end_var
var //объявление локальных переменных
RtR0: Real;
R0: Real:= 1000;
A: Real:= 0.0039083;
B: Real:= -5.775E-07;
D1: Real:= 255.819;
D2: Real:= 9.14550;
D3: Real:= -2.92363;
D4: Real:= 1.79090;
end_var
//PRG
RtR0:= R/R0;
if R>R0 then
fPt1000:=(pow((A*A-4*B*(1-RtR0)),0.5)-A)/(2*B);
else
fPt1000:=fPol_4((RtR0-1),4,0,D1,D2,D3,D4); //вызов функции "fpol_4"
end_if
end_function
Судя по всему, он опирается на другие функции из тех же компонентов.
Я бы, наверное, попробовал корень квадратный через формулу Ньютона вычислять с ограничением количества итераций.
А полином - без функции, но через схему Горнера, а не так, как в примере.
function fPol_4: Real; //функция вычисления полинома 4й степени
var_input //объявление входных переменных
X : Real;
exp: udint; // степень
D0: Real;
D1: Real;
D2: Real;
D3: Real;
D4: Real;
end_var
var //объявление локальных переменных
i: udint;
d: array [0..4] of Real;
end_var
//PRG
fPol_4:=0;
d[0]:=d0;
d[1]:=d1;
d[2]:=d2;
d[3]:=d3;
d[4]:=d4;
for i := 0 to exp do
fPol_4:=fPol_4 + d[i]*pow(X,udint_to_real(i));
end_for
end_function
Тьфу!..
Стошнило!
Не делайте так!
Про pow поторопился - встроенная функция и корень, наверное, так быстрее извлекать.
Но полином при помощи pow - это позор!
ГОСТ 6651-2009 содержит полиномы и коэффициенты для термопреобразователей сопротивления.
Для платиновых форма зависимости идентичная, но отличаются коэффициенты.
Для Pt1000 (0,00385) они перечислены в исходнике выше.
Для 1000П (0,00391) они равны
R0: Real:= 1000;
A: Real:= 0.0039690;
B: Real:= -5.841E-07;
D1: Real:= 251.903;
D2: Real:= 8.80035;
D3: Real:= -2.91506;
D4: Real:= 1.67611;
Формулы в исходнике соответствуют ГОСТ.
Т.е. заменив коэффициенты на указанные, можно получить макрос для 1000П.
Единственно, я бы заменил вычисление полинома в одну строку и даже без цикла.
function f1000P: real;
var_input
R : real;
end_var
var
RtR0: Real;
R0: Real:= 1000;
A: Real:= 0.0039690;
B: Real:= -5.841E-07;
D1: Real:= 251.903;
D2: Real:= 8.80035;
D3: Real:= -2.91506;
D4: Real:= 1.67611;
end_var
RtR0:= R/R0;
if R>R0 then
f1000P:=(pow((A*A-4*B*(1-RtR0)),0.5)-A)/(2*B);
else
RtR0 := RtR0 - 1;
f1000P := (((((D4 * RtR0) + D3) * RtR0) + D2) * RtR0 + D1) * RtR0;
end_if
end_function
Мдя. Здорово всё так.
0.1...0.2* градуса лоховская точность же.
, дальше происходит нагрев до уставки
не иначе как что-то суперпрецизионное.
Думаю клиент так и задает с суровым лицом
..на экране СП 307 оператор выставляет нужную температуру..
57.4576 *С
Ни 0.0001 градусом меньше
Да ведь и исходное сопротивление - суперпрецизионное. Максимум же 0.000001%.
Грех это не заполиномить.
66666666
13.05.2025, 16:29
вопрос по работе таймеров в функциональных блоках на ST :confused:
создал проект на ПР103, сделал функциональный блок на ST, добавил таймеры TON и TOF, они себя ведут странно в том плане, что в них будто сохраняется отсчет времени, который был начат при предыдущей подаче сигнала на вход. например таймер на 10 сек, подали сигнал на вход, таймер успел отсчитать 5 сек, потом убираем сигнал, при следующей подче сигнала на вход таймер сразу подавал сигнал на выходе.
пересобрал то же самое на блоках, там все нормально, если нет сингала на входе, то таймер сбрасывается.
это потому что у функциональных блоков свои особенности в плане выделения памяти и прочего или чем объяснить такое поведение таймеров на ST?
Покажи код пожалуйста.
Если таймер находится внутри условий типа IF и CASE - то надо уметь его правильно вызывать, чтобы он корректно работал.
Напоминаю мою статью про это (заголовок 7): https://cs-cs.net/funkciya-fun-i-funkcionalniy-blok-fb-codesys-owenlogic#7__fb_ton_tof_tp_blink
Если есть время - прочитай, проверь, так или нет.
Если всё так, как по статье - то тогда лучше писать в ТехПоддержку ОВЕНа.
вопрос по работе таймеров в функциональных блоках на ST :confused:
создал проект на ПР103, сделал функциональный блок на ST, добавил таймеры TON и TOF, они себя ведут странно в том плане, что в них будто сохраняется отсчет времени, который был начат при предыдущей подаче сигнала на вход. например таймер на 10 сек, подали сигнал на вход, таймер успел отсчитать 5 сек, потом убираем сигнал, при следующей подче сигнала на вход таймер сразу подавал сигнал на выходе.
пересобрал то же самое на блоках, там все нормально, если нет сингала на входе, то таймер сбрасывается.
это потому что у функциональных блоков свои особенности в плане выделения памяти и прочего или чем объяснить такое поведение таймеров на ST?
Чтобы отсчёт таймера ТОN сбросился - его надо ВЫЗВАТЬ со значением FALSE на входе (примерно так fbTON(I := FALSE);). Tсли вы вызываете TON только тогда, когда на входе TRUE - вы получите именно такое поведение, как описали (обычно это вызов тамqера внутри IF).
Отсутствие в FBD конструкции "IF" исключает возникновение ошибок такого рода
66666666
13.05.2025, 16:49
да, таймеры внутри условий
function_block PhaseLoadControl
var_input
Current : REAL;
Hight_level : REAL;
Low_level : REAL;
end_var
var_output
Auto1Cmd, Auto2Cmd : BOOL := TRUE; (* Команды управления автоматами *)
end_var
var
TimerOn1, TimerOn2, TimerOff1, TimerOff2 : sys.TON;
T_On, T_Off : TIME := T#5S;
end_var
(* Отключение автоматов, если ток выше Hight_level *)
IF Current > Hight_level THEN
TimerOff1(I := Auto1Cmd, T := T_Off);
IF TimerOff1.Q THEN Auto1Cmd := FALSE; END_IF;
TimerOff2(I := (NOT Auto1Cmd) AND Auto2Cmd AND (Current > Hight_level), T := T_Off);
IF TimerOff2.Q THEN Auto2Cmd := FALSE; END_IF;
END_IF;
(* Включение автоматов, если ток ниже Low_level *)
IF Current < Low_level THEN
TimerOn1(I := NOT Auto1Cmd, T := T_On);
IF TimerOn1.Q THEN Auto1Cmd := TRUE; END_IF;
TimerOn2(I := Auto1Cmd AND NOT Auto2Cmd, T := T_On);
IF TimerOn2.Q THEN Auto2Cmd := TRUE; END_IF;
END_IF;
(* Удержание состояния в диапазоне Low_level-Hight_level *)
IF (Current >= Low_level) AND (Current <= Hight_level) THEN
(* Ничего не делаем, автоматы остаются в текущем состоянии *)
END_IF;
end_function_block
Если в 1-ом условии таймер TimerOff1 еще не сработал, и всё ушло в середину, то таймер как запомнил время старта (и состояние работы), так оно там и осталось. А при возврате в 1-е условие (если Auto1Cmd не упал), таймер смотрит прошедшее время с момента старта в прошлом (а может и позапрошлом (а может поза-поза ..(..))) входе в 1-ое условие.
Вынос из IF типа
TimerOff1(I := (Current > Hight_level) and Auto1Cmd, T := T_Off);
TimerOn1(I := (Current < Low_level) and NOT Auto1Cmd, T := T_On);
Auto1Cmd := not TimerOff1.Q and (Auto1Cmd or TimerOn1.Q);
Аналогично и с другими
да, таймеры внутри условийАга. Оно самое. Причина в этом. Рекомендую мою статью пробежать глазами.
Почему-то, с тех пор как в ПРках появился ST, все темы про вызов таймеров стали снова актуальны...
Почему-то, с тех пор как в ПРках появился ST, все темы про вызов таймеров стали снова актуальны...
С этим всё просто - дешевизна прибора обеспечила массовое применение, а с применением и спрос на программистов - что привело в сферу так называемых "самоучек" без образования (нахватчиков).
Отсюда и запрос на автонастройку ПИД, и разные предложения на введение gcc в языки программирования, и требования пояснить как включить датчик, и неумение читать документацию...
Я не издеваюсь, просто констатирую, что сейчас программируют случайные люди между выполнением монтажных и прочих физических работ, им реально некогда системно учиться, нужно быстрее сдать работу.
66666666
13.05.2025, 21:55
Спасибо всем за ответы, действительно не знал об этой особенности.
Schneider
10.06.2025, 09:00
Побитовые операции типа & | в ST макросах owen logic я так понимаю не поддерживаются?
МихаилГл
10.06.2025, 09:04
Побитовые операции типа & | в ST макросах owen logic я так понимаю не поддерживаются?
Ну можно маску приделать:
bit:= word1 and word2 and mask
Думаю будет работать... Или нет?
Schneider
10.06.2025, 09:07
Ну можно маску приделать:
bit:= word1 and word2 and mask
Думаю будет работать... Или нет?
пишет AND только для булевых переменных
пишет AND только для булевых переменных
можно реализовать самостоятельно
kondor3000
10.06.2025, 09:56
пишет AND только для булевых переменных
Здесь реализованы функции побитового AND и XOR, от Валенок остальные аналогично
https://owen.ru/forum/showthread.php?t=26216&p=447957&viewfull=1#post447957
Вариантов на самом деле полно, каждый делает как ему нравится.
Schneider
10.06.2025, 10:01
можно реализовать самостоятельно
Спасибо. у вас в реализации сдвиг вправо/влево делением/умножением достигается.
но функции SHL, SHR в этой реализации ST все же есть. можно ими было, хотя внутри , наверное, это одинаково работает.
Schneider
10.06.2025, 10:11
Здесь реализованы функции побитового AND и XOR, от Валенок остальные аналогично
https://owen.ru/forum/showthread.php?t=26216&p=447957&viewfull=1#post447957
Вариантов на самом деле полно, каждый делает как ему нравится.
О, накидали то накидали. Спасибо за оперативность.
Впрочем странно, почему те, кто реализовал обращение к биту через точку не реализовал побитовые операции из С
Здравствуйте!
Подскажите, пожалуйста,как соединить два блока с проблемой на изображении (TON3 и CMP1)? 84375
Блок CMP1 написал в ST. Вот код с ST 84376
Пробовал вписать TO_FLOAT в код с помощью ИИ, но постоянно выдаёт ошибку на TO_FLOAT.
Здравствуйте!
Подскажите, пожалуйста,как соединить два блока с проблемой на изображении (TON3 и CMP1)? 84375
Блок CMP1 написал в ST. Вот код с ST 84376
Пробовал вписать TO_FLOAT в код с помощью ИИ, но постоянно выдаёт ошибку на TO_FLOAT.
Какая цель?
Если вы пытаетесь так считать с ФБ TON значение отсчёта времени - то подход изначально неправильный
Цель дать импульс на один из двух выходов в зависимости от времени удержания сигнала на входе. У меня есть готовая схема, но ИИ предложил сделать проще, захотел попробовать. Наткнулся на отсутсвие блока СМР и решил попробовать сделать его с помощью ST. Не сказал бы, что сейчас мне это уритически важно, но на будущее, думаю, будет очень полезно разобраться, в чём дело. Спасибо!
Leo29 у вас сравнение двух аналоговых сигналов. А таймер имеет на выходе bool. Так понимаю вы хотите сравнивать по таймеру сигналы а не на каждом цикле?.
Тогда вам в код ST надо к своему блоку сравнения добавить bool вход EN и написать таким образом, чтобы сравнение происходило по его работе. И уже тогда с таймера на EN заводить выход. Нужно будет постоянное сравнение в цикле программы, просто на EN заведете константу 1 To_Bool
Цель дать импульс на один из двух выходов в зависимости от времени удержания сигнала на входе. У меня есть готовая схема, но ИИ предложил сделать проще, захотел попробовать. Наткнулся на отсутсвие блока СМР и решил попробовать сделать его с помощью ST. Не сказал бы, что сейчас мне это уритически важно, но на будущее, думаю, будет очень полезно разобраться, в чём дело. Спасибо!
Предлагаю так:
84387
Спасибо! Буду пробовать.
А вот мой первый вариант)84388
Leo29 у вас сравнение двух аналоговых сигналов. А таймер имеет на выходе bool. Так понимаю вы хотите сравнивать по таймеру сигналы а не на каждом цикле?.
Тогда вам в код ST надо к своему блоку сравнения добавить bool вход EN и написать таким образом, чтобы сравнение происходило по его работе. И уже тогда с таймера на EN заводить выход. Нужно будет постоянное сравнение в цикле программы, просто на EN заведете константу 1 To_Bool
Спасибо! Попробую
Спасибо! Буду пробовать.
А вот мой первый вариант)84388
Первый импульс после удержания 0,65 сек, второй - еще 0,65 сек. Если длительность сигнала на входе меньше 0,65 сек - импульс. Так и задумано?
Добрый день! Подскажите пожалуста, вот на ST выражениеЖ
if LE_PR AND PUSK OR PUSK_F_RIGT AND NOT L_KONC AND NOT STOP then
MOTOR :=TRUE;
PUSK_F_RIGT:=true;
ELSE
MOTOR :=false;
PUSK_F_RIGT:=false;
end_if;
А это скрин сииммуляцциии его в лоджике
85486
вопрос _почему когда входные переменные:
LE_PR=1 PUSK=1 и L_KONC=1 выходная переменная MOTOR тоже равна 1 хотя условие and not L_KONC должно запрещать выходной переменной MOTOR true? Наверное я чегото с синтаксисом не так написал?
Ответ получил, вопрос снимаеться с повестки.Спасибо kondor3000.
kondor3000
30.08.2025, 11:18
Ответ получил, вопрос снимаеться с повестки.Спасибо kondor3000.
Ответ тут https://owen.ru/forum/showthread.php?t=26216&p=470734&viewfull=1#post470734
Доброго времени суток. Подскажите плз - как сделать, чтобы функции и блоки а язык ST в OL можно было разложить по каталогам. А то все сейчас в куче лежат. Не очень удобно
Доброго времени суток. Подскажите плз - как сделать, чтобы функции и блоки а язык ST в OL можно было разложить по каталогам. А то все сейчас в куче лежат. Не очень удобно
Вставляете в начале функции/ФБ:
///<GroupName>Название каталога</GroupName>
и каталог "Название каталога" появится автоматически с этой функцией/ФБ внутри
Вставляете в начале функции/ФБ:
///<GroupName>Название каталога</GroupName>
и каталог "Название каталога" появится автоматически с этой функцией/ФБ внутри
Спасибо большое
ВСЕМ ПРИВЕТ! устал боротся с собственной безграмотностью, не могу победить код для отправки значиний с плавающей запятой . должно улетать старшим и младшим битом, ругается на intValue AND 65535- не поддерживает UDINT
FUNCTION_BLOCK fbScalePosition
VAR_INPUT
PRO_POS_H : REAL; // Входная позиция (вещественное число)
END_VAR
VAR_OUTPUT
inp_PR0_position_H : UDINT; // Старшие 16 бит результата
inp_PR0_position_L : UDINT; // Младшие 16 бит результата
END_VAR
VAR
scaledValue : REAL; // Промежуточное масштабированное значение
intValue : UDINT; // 32-битное беззнаковое целое для результата
scaledMin : REAL := -10000000.0; // Минимальное значение входного диапазона
scaledMax : REAL := 10000000.0; // Максимальное значение входного диапазона
outputMax : REAL := 4294967295.0; // Максимальное значение выходного диапазона (2^32 - 1)
scaleFactor : REAL; // Коэффициент масштабирования
END_VAR
// Тело функционального блока
scaledValue := PRO_POS_H;
// Ограничение входного значения диапазоном
IF scaledValue < scaledMin THEN
scaledValue := scaledMin;
ELSIF scaledValue > scaledMax THEN
scaledValue := scaledMax;
END_IF;
// Масштабирование входного значения к диапазону 0...4294967295
scaleFactor := outputMax / (scaledMax - scaledMin);
scaledValue := (scaledValue - scaledMin) * scaleFactor;
// Преобразование в целое число
intValue := REAL_TO_UDINT(scaledValue);
// Разделение 32-битного значения на два 16-битных
inp_PR0_position_H := SHR(intValue, 16); // Старшие 16 бит
inp_PR0_position_L := intValue AND 65535; // Младшие 16 бит
END_FUNCTION_BLOCK
kondor3000
16.11.2025, 17:05
ВСЕМ ПРИВЕТ! устал боротся с собственной безграмотностью, не могу победить код для отправки значиний с плавающей запятой . должно улетать старшим и младшим битом, ругается на intValue AND 65535- не поддерживает UDINT
У вас не целое 32 битное, а Float, с ним так не работает.
Здесь выложены ФБ для сборки и разборки Float на DWORD или 2 WORD.
Real_TO_UDINT (DWORD)_ 2 WORD https://owen.ru/forum/showthread.php?t=40405&p=450146&viewfull=1#post450146
А вообще перестановка регистров обычно делается в Мастере, в ПР например, это галка Старшим регистром вперёд.
В панели СП3хх тоже галка есть. В ПЛК1хх это настройка в UMD (Универсал Модбас девайс), настройка Native.
Есть и более простой способ, например для передачи 1 знака после запятой одним регистром, Float умножают на 10 и конвертируют в целое, передают по сети. После приёма целое сначала конвертируют в Float, а потом делят на 10.
То есть передаём 12,3 после умножения и конвертации 123, принимаем, конвертируем и делим 123/10 = 12,3
Для передачи 2 знаков умножаем и делим на 100.
LAGOOPED
19.11.2025, 19:15
Добрый вечер добрый человек kondor. Огромнейшее тебе спасибо за подсказку. Сделал блоки на ST и все цифры встали на место. Ещё раз огромное спасибо.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot