petera спасибо, так заработало. Видимо что-то не так делал сперва.
А вопрос по поводу как правильно делать через конфигуратор задач остается... можно ли передавать параметры в программу и возвращать обратно и как правильно это делать ?
Вид для печати
petera спасибо, так заработало. Видимо что-то не так делал сперва.
А вопрос по поводу как правильно делать через конфигуратор задач остается... можно ли передавать параметры в программу и возвращать обратно и как правильно это делать ?
Например, как было сказано выше, через глобальные переменные.
Вложение 14074 Вложение 14075
Здесь X и IN глобальные переменные для передачи значений в циклическую программу. А результат ее работы в главной программе берется путем обращения к переменной "А" по имени PRG2.А, хотя ее тоже можно было сделать глобальной.
Странно, вроде вчера через глобальные делал точно так же, и не заработало, видать спал уже, сейчас набросал пример и все вроде как завелось.
Может как-то влиять, что я переменную из Modbus сразу назначил глобальной ?
Ну и вот для примера, разница подсчета видна. В первом случае в другой программе с таймером.
Во втором случае вызов каждую секунду из конфигуратора задач. В начале пути опрос через конфигуратор опережает. но значения повторяются, а дальше видно, что значения во втором случае выше. Переменная kwt и kwt1.
Смущает эта фраза. Переменная из модбас сама по себе глобальная без назначений.Цитата:
что я переменную из Modbus сразу назначил глобальной ?
Ретайн это то, что объявлено как ретайн + область ioЦитата:
Глобальные переменные вроде являются Retain или нет ?
Имхо, для большей точности и здравого смысла расчеты нужно делать только в момент прихода ))).Цитата:
беря данные из однофазного мультиметра считать киловатт_часы и значения были близки к показаниям счетчик
Интеграл := интеграл + значение*dt. Остальное время можно курить бамбук.
1. Любые объявления переменных в конфигурации, в том числе и в модуле Modbus, являются глобальными по умолчанию. Т.е. их не нужно объявлять глобальными где-либо еще.
2. В эмуляции будет так, как Вы и описываете, разница будет постепенно увеличиваться. При загрузке в ПЛК разницы быть не должно. Возможна разница только на значение одного вычисления из-за асинхронного вызова подпрограмм.
ЗЫ. К стати в примере из http://www.owen.ru/forum/showthread....l=1#post143814
Ошибка должно быть так
Код:TM(in:=NOT TM.q, pt:=t#1s);
IF NOT TM.q THEN
A:=A+IN/X;
END_IF
Валенок и как понять, что случился "приход" ? если отталкиваться, что читаю по modbus
petera на последней картинке IF TM.Q Then и работает, если поставить IF NOT то считаться будет в течение всей секунды, разве нет ?
Цитата:
как понять, что случился "приход" ?
Если переживаете про постоянное значение (на реальном процессе никогда не будет, для эмуляции пойдет) - прикрутите таймерКод:var
pre : real;
приход : bool;
приход := ai <> pre; //Косвенный, но верный. Если юзаете через б-ки то там факт прихода напрямую
pre := ai;
PSКод:var
t : ton := (pt :=заведомо больше цикла опроса);
t(in:= not приход);
приход:=ai <> pre or t.q;
pre:=ai;
if приход then
интеграл := интеграл + ai * time_to_real(time() - t) / 1000;
t := time();
end_if
И, кстати, отсутствие прихода - косвенный признак обрыва связи с модулем
Код:var
connect : tof := (in:= true, pt := 3..10 циклов опроса);
connect(); //игнорим на старте - ведь еще не успели связатся
connect.in := приход;
if not connect.q then
..
end_if
Валенок спасибо, попробую и по приходу. Просто правильнее в любом случае делить на период опроса, иначе мы не кВт часы получим, а что-то эфемерное...
Ведь приход может быть как раньше секунды, так и позже секунды и как тогда программировать время ?
Суть. кВт час = (при опросе раз в секунду) мощность(в кВт)/3600
Хотя наверное 3600 можно превратить в переменную, зависящую от времени опроса, только формула будет посложнее.
Имеете ввиду FLOW_METER ?
это ПОУ вроде наоборот, из производительности получает суммирующее значение
Сама суть ошибочная.
"(при опросе раз в секунду) мощность(в кВт)/3600" - так Вы мгновенную мощность получите, а не количество потребляемой энергии.
Ведь само определение
«кВт⋅ч» (мощность, умноженная на время). Написание «кВт/ч» (киловатт в час), часто употребляемое во многих СМИ и даже иногда в официальных документах, неправильно. Такое обозначение соответствует изменению мощности в единицу времени (что обычно никого не интересует), но никак не количеству энергии.
Ежели все таки хотите использовать ежесекундные значения мощности, то код программы, вызываемой раз в секунду должен быть не такой как у Вас
kwt:=kwt+(IN/3600000);
а такой
summa:=summa+IN;
kwt:=summa/3600000;
petera вы написали две одинаковых формулы, только по разному считающих.
если сделать по приходу, то вместо 3600 необходимо ввести и расчет периода. данные будут еще точнее и потом делить на 1000, так как прибор дает в Вт, а нам надо в кВт.
типа *1/период расчитанный относительно 1 часа
Между приходами - неизвестность. Вычислять что либо при неизвестности - рукоблудие. Реальность - приход данных.Цитата:
Ведь приход может быть как раньше секунды, так и позже секунды и как тогда программировать время ?
Так расчет времени я Вам и предложил.Цитата:
если сделать по приходу, то вместо 3600 необходимо ввести и расчет периода. данные будут еще точнее и потом делить на 1000, так как прибор дает в Вт, а нам надо в кВт.
S Ai * dt, где dt = time() - t
Кстати, странно, что никто не предложил трапеции для максимально достижимой точности в данном железе.
Код:if pre <> ai then
интеграл := интеграл + (pre + ai) / 2 * time_to_real(time()-t) / 1000;
pre := ai;
t := time();
end_if
Замерил сегодня показания счетчика и ПЛК при использовании таймера опроса раз в 1 с в программе. За 2 часа набегает разница в 0,08 сотых кВт часа.
За сутки набежит примерно 1 кВт час, за месяц соответственно 30. Многовато.
Буду пробовать следующие варианты.
Погрешность лучше описывать в %.Цитата:
разница в 0,08 сотых кВт часа.
"За сутки набежит примерно 1 кВт час" - это 0 на Красноярской ГЭС
И начните хотя бы с погрешности самого МЭ.
Валенок погрешность МЭ +- 0,5% вроде
Соврал, по активной мощности +- 1 %
Решил использовать ET таймера, а не time(), которое дает время от начала запуска. Единственное, может не правильный сброс таймера ???Код:PROGRAM Kwt_hours
VAR
kwt_summ: REAL;
kwt: REAL;
prihod: BOOL;
tm: TON;
END_VAR
TM(in:=NOT tm.q, pt:=t#1.5S);
prihod:=kwt <> activeP OR tm.Q;
kwt:=activeP;
IF prihod THEN
kwt_summ:=kwt_summ+kwt/(3600/(TIME_TO_REAL(tm.et)/1000))/1000;
tm.IN:=FALSE;
END_IF
Кстати в примерах t: ton и тут же time_to_real(time()-t) - что же тут t ?
Вопрос по циклу ПЛК.
выставил когда-то мин 10 мс, на данный момент по статистики выполнение в 100 мкс - 9-10, свободно из расчета 1 мкс - 9ххх (так понимаю в районе 9 мс).
Свободное время учитывается во времени цикла ?, то есть программа отработала за 1 мс , 9 мс курит и начинается новый цикл ?
очепятка. Пусть будет t0 : time;Цитата:
что же тут t
Да. Новый цикл начинает по окончанию текущего, но не ранее МинЦЦитата:
то есть программа отработала за 1 мс , 9 мс курит и начинается новый цикл ?
В IF таймер надо явно сбрасывать tm(in:=false), иначе фигня какая-то получается периодом
И тогда нет смыcла в "not tm.q", просто true
Валенок с таймером сообразил, просто делал сброс чуть по другому.
Так а как коррелируется тогда time_to_real(time() - t0) вот здесь
интеграл := интеграл + ai * time_to_real(time() - t0) / 1000;
t := time();
К соотношению часа ?
приход стал равен 1, мы считали время и отняли 0 (самый первый опрос) и потом запомнили время в переменной t0. И что у нас в расчете за первый опрос, если ПЛК не перегружался ? или такого косяка не должно быть при обновлении программы или просто вносит необходимость выполнять перезапуск ?
Ну и все равно необходимо вычислять соотношение периода опроса к часу. если раз в секунду опрос, то это 1/3600, если 0,5 с то 1/7200 и т.д.
Глупый вопрос, опрос переменной из Modbus контроллер выполняет только в начале/конце цикла основной программы ?
И еще один, таймер ведь будет сброшен физически только на следующем цикле программы ?
Если таймер это TON, то я подразумевал подсчет при срабатывании таймера. Т.е. каждую секунду производится сложение.
Таймер должен сбросится при проходе цикла через его инициализацию, т.е. TM(in:=NOT TM.q, pt:=t#1s);Цитата:
И еще один, таймер ведь будет сброшен физически только на следующем цикле программы ?
P.S.
Уже прочитал))
P.P.S.
Кстати, по поводу цикла контроллера.
Был объект - упаковщик.
Необходимо было по метке на пленке, тормозить саму пленку.
В теории все просто - увидел метку послал сигнал на тормоз, пленка остановилась.
Так вот ПЛК110 постоянно останавливал пленку в разных местах (+-1см), хотя программа была из одной строки, и в теории цикл всегда одинаковый, метка видится хорошо, но остановка плавала.
Бились над этим долго, перешли на схему от Итальянцев, с использованием реле для остановки - все стало тютелька в тютелюку. (Но остановкой уже заведует реле, а не ПЛК)
Непомню уже с чем было связано, но я сперва проверяю условие на выход таймера, а после него само выполнение таймера (про ton говорю, др. не пользуюсь)
Вот и я думаю, что все же лучше опрашивать через конфигуратор задач строго раз в секунду, все же от накопления погрешности от цикла программы избавляемся.
Программу надо писать так, чтобы результаты её исполнения не зависели от равномерности и периодичности её вызова (в разумных пределах). Вы хотите лечить симптомы, на мой взгляд.Цитата:
я думаю, что все же лучше опрашивать через конфигуратор задач строго раз в секунду, все же от накопления погрешности от цикла программы избавляемся.
Yegor программа будет со временем расти. Мне вот интересно, таймеры в CDS являются системными или работают строго по циклам программы ? они вообще учитывают время перекура цикла ?
Так вот и интересно, насколько влияет опрос вызова таймера в каждом цикле.
Таймеры никак не привязаны к циклам. Например ton поднимается при вызове, но не ранее чем прошло заданный интервал времени. Не ранее.
Минц 100мс, ton.pt 150мс => Отработка ton через 200мс. При этом в ET будет [U]150.[/U
Так как проверять не хочется, то при
период:=time()-t0;
t0:=time();
период не зависит от PT таймера.
Блин, перезалил удаленно программу, на всякий случай сделал "Создание загрузочного проекта" и ресетнул ПЛК. Оба модуля ввода отвалились :(
Питание передернуть смогу только приехав домой. Вопрос, вылечить удаленно можно ?
Валенок может немного не так выражаюсь.
Вот пример. Минц=10 мс
Есть команды ТМ(in:=true, pt:=t#1s)
и есть условие IF TM.Q Then
бла-бла-бла
TM(in:=false)
End_if
Когда сбросится в данном случае таймер ? - сразу ?, а запустится он когда ? - только на чтении строки ТМ(in:=true, pt:=t#1s) ?, то есть между сбросом и запуском пройдет целый цикл ?
А как же WHILE TRUE DO ; END_WHILE без записи в загрузочный проект? Собака гавкнет — питание передёрнется.Цитата:
Питание передернуть смогу только приехав домой.
Yegor а подробнее можно, а то ниче непонятно :) то, что речь о watch_dog понимаю, но как использовать ?
Например если по какой-то причине модуль висит с аварией на борту, а перегрузка будет только у ПЛК, а модули висят по питанию паралельно ? Добавлять реле по питанию на всё ?
Оба модуля настроены через конфигуратор.
Да. Если ловить наиболее строгие интервалы ton'ом, нужно делать
[CODE]t(in:=true,..., et => период);
if t.q or ... B then
t(in:=false);
t(in:=true); //здесь же !!!
..
end_if
Но все это фигня если учесть заявленную точность + оцифровка до 1с
Валенок спасибо.
Новая программа каким-то образом не соответствует опросу модулей ? конфигурацию при этом не менял. Переменные в программе вроде тоже не менял. Чудеса...
Действительно, МЭ висел с ошибкой связи, 8АС только индикатор питания. Перезагрузка ПЛК ни к чему не приводила.
Не должно же такого быть ?
Вопрос по датчикам. Вот есть датчики, показания с них прыгают, например датчик 0-10В, смотришь по программе 2,33-2,38-2,42-2,35 и так далее.
То же с датчиком 4-20 мА, 8,36-8,43-8,35 ну и в том же духе...
Как бы их фиксировать, чтобы они не скакали ? Увеличивать время опроса не предлагать, так как все равно не помогает.
Есть какие-то библы для "выравнивания" показаний датчиков ?
а фильтрация не помогает?
capzap так а что делает фильтрация ? сократит количество скачков или она иначе работает ?
Постоянная времени для эспоненциального фильтра
Ограничение скорости изменения измеряемого сигнала (пиковый фильтр)
Имеется ввиду поиграться с настройками этих параметров ?
конечно надо всё попробовать, ведь неизвестно же в чем характер помехи
Добрый день!
Как в CFC или ST сделать следующее:
1. Если значение с аналогового входа меньше определенной уставки в течение некоторого времени (единицы секунд, точность не важна), то выполнить определенное действие, при этом нужно не блокировать основной поток, т.е. "получить значение со входа, подождать 10 секунд, опять получить значение", а в это время контроллер более ничем не занят не подходит.
2. Чем и как считать время наработки (логической единицы на одном из входов)?
Заранее спасибо за ответы!