Просмотр полной версии : ФБ сохранения показаний на ST с энергонезависимостью.
Всем доброго времени суток, разрабатываю блок для подсчета показаний
с импульсного счетчика на ST. Общие показания сохраняются спокойно и после отключения питания остаются,
но временные показания (сутки, час, месяц, год) слетают после отключения питания.
С чем может быть связан сброс? Программу прилагаю.
Прибор: ПР200-24.2.2.0
З.Ы.: смею высказать свою теорию, что из-за несовпадения даты с сохраненной в локальные переменные блока при повторной подаче питания.
kondor3000
27.12.2023, 17:26
Всем доброго времени суток, разрабатываю блок для подсчета показаний
с импульсного счетчика на ST. Общие показания сохраняются спокойно и после отключения питания остаются,
но временные показания (сутки, час, месяц, год) слетают после отключения питания.
С чем может быть связан сброс? Программу прилагаю.
Прибор: ПР200-24.2.2.0
З.Ы.: смею высказать свою теорию, что из-за несовпадения даты с сохраненной в локальные переменные блока при повторной подаче питания.
Вы же сами всё обнуляете, например кусок кода
if i_nowDay <> l_day then
l_FlowDay := 0; // Зачем здесь обнуление?
l_day := i_nowDay;
end_if
Сначала присваиваете l_FlowDay := i_FlowDay; а потом в коде обнуляете l_FlowDay := 0; // Зачем здесь обнуление? И так везде
kondor3000, Это сравнение числа дня входной переменной с локальной, если не совпадает(по логике происходит на след. день в 00:00), l_FlowDay - переменная с данными по самому потоку (Поток день, дословно) становится равна нулю и считается заново. Аналогичные операции проделываются с годом, часом и месяцем
Вы же сами всё обнуляете, например кусок кода
if i_nowDay <> l_day then
l_FlowDay := 0; // Зачем здесь обнуление?
l_day := i_nowDay;
end_if
Сначала присваиваете l_FlowDay := i_FlowDay; а потом в коде обнуляете l_FlowDay := 0; // Зачем здесь обнуление? И так везде
Кусок кода с вычислениями расходов:
if i_Imp = TRUE then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
Кусок кода со сравнениями переменных дат и времени для сброса когда надо:
if i_nowDay <> l_day then
l_FlowDay := 0;
l_day := i_nowDay;
end_if
if i_nowHour <> l_hour then
l_FlowHour := 0;
l_hour := i_nowHour;
end_if
if i_nowMonth <> l_month then
l_FlowMonth := 0;
l_month := i_nowMonth;
end_if
if i_nowYear <> l_year then
l_FlowYear := 0;
l_year := i_nowYear;
end_if
И каждый цикл программы в сравнениях(и просто в коде) происходит перезапись локальных переменных (которые, как я слышал, энергонезависимые).
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
В таблице переменных все с галочкой на энергонезависимость, но оно все равно сбрасывается
P.S.: все переменные с i_ - входные, l_ - локальные, а выходные без префикса. Но да, комментариев в коде я оставил мало
kondor3000
28.12.2023, 08:36
Просто закомментируйте на время кусок кода с обнулением и проверьте, будут ли сохраняться расходы, при перезагрузке по питанию.
Возможно надо ввести таймер на несколько секунд, чтобы не обнулялось при подаче питания.
Просто закомментируйте на время кусок кода с обнулением и проверьте, будут ли сохраняться расходы, при перезагрузке по питанию.
Возможно надо ввести таймер на несколько секунд, чтобы не обнулялось при подаче питания.
Да, вы правы, если исключить из условия обнуление, он не сбрасывается при перезапуске питания. Как понимаю, задержку на включение действий условия на ST тоже надо сделать.
TON из оф. видео подойдет же?
https://www.youtube.com/watch?v=agJTfeRnfy4
AlexCrane
28.12.2023, 09:42
Да, вы правы, если исключить из условия обнуление, он не сбрасывается при перезапуске питания. Как понимаю, задержку на включение действий условия на ST тоже надо сделать.
TON из оф. видео подойдет же?
https://www.youtube.com/watch?v=agJTfeRnfy4
Может проще выполнение всего блока отложить на один цикл после включения питания
Может проще выполнение всего блока отложить на один цикл после включения питания
Не совсем понимаю, как это реализовать. Поставить линии задержки на все выходные переменные?
Не совсем понимаю, как это реализовать. Поставить линии задержки на все выходные переменные?
Еще один вход сделать - разрешение работы
Просто закомментируйте на время кусок кода с обнулением и проверьте, будут ли сохраняться расходы, при перезагрузке по питанию.
Возможно надо ввести таймер на несколько секунд, чтобы не обнулялось при подаче питания.
Переписал ТОН из оф. ролика. Переменная теперь просто сбрасывается с задержкой таймера после включения.
Делал условие для выключения таймера, тоже не помогает
function_block Flowmeter //имя функционального блока.
var_input //объявление входных переменных
i_Imp: bool; //переменная считывания переднего фронта импульса
i_ImpMass: real; //переменна цены импульса
i_Flow: real; //Общий поток
i_FlowYear: real; //Годовой поток
i_FlowMonth: real; //Поток за месяц
i_FlowDay: real; //Поток за день
i_FlowHour: real; //Поток за час
i_nowYear: udint; //Текущий год
i_nowMonth: udint; //Текущий месяц
i_nowDay: udint; //Текущий день
i_nowHour: udint; //Текущий час
i_nowMinute: udint; //Текущая минута
i_nowSecond: udint; //Текущая секунда
end_var
var_output //объявление выходных переменных
Flow: real;
FlowDay: real;
FlowHour: real;
FlowMonth: real;
FlowYear: real;
ImpMass: real;
end_var
var //объявление локальных переменных
TON: TON_FB;
TON_Q: BOOL;
l_Flow: real;
l_FlowDay: real;
l_FlowHour: real;
l_FlowMonth: real;
l_FlowYear: real;
l_year: udint;
l_month: udint;
l_day: udint;
l_hour: udint;
l_minute: udint;
l_second: udint;
l_impMass: real;
end_var
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
if i_Imp = TRUE then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
//Тут на поток за день сделал попытку с таймером
if i_nowDay <> l_day then
TON(IN := true, PT:= 5,SEC := i_nowSecond, Q => TON_Q);
if TON_Q then
l_day := i_nowDay;
l_FlowDay := 0;
end_if
else
TON(IN := false);
end_if
if i_nowHour <> l_hour then
l_hour := i_nowHour;
//l_FlowHour := 0;
end_if
if i_nowMonth <> l_month then
l_month := i_nowMonth;
//l_FlowMonth := 0;
end_if
if i_nowYear <> l_year then
l_year := i_nowYear;
//l_FlowYear := 0;
end_if
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
end_function_block
AlexCrane
28.12.2023, 10:01
Не совсем понимаю, как это реализовать. Поставить линии задержки на все выходные переменные?
Примерно так, но это не точно...
Еще один вход сделать - разрешение работы
И завести на него 1 с линией задержки, верно?
AlexCrane
28.12.2023, 10:06
И завести на него 1 с линией задержки, верно?
Нужно проверить хватит ли одного цикла
МихаилГл
28.12.2023, 10:10
Таймер (in:= not (стартовый не энергонезависимый бит), pt:= T#5s)
if Таймер.Q then
стартовать программу;
стартовый не энергонезависимый бит:= 1;
end_if
Нужно проверить хватит ли одного цикла
Поставил и сделал в блоке:
IF разрешение работать = 1
(Основной код фб)
END_IF
После перезапуска он вообще стопится, даже цена импульса из энергонезависимости не подгружается
Таймер (in:= not (стартовый не энергонезависимый бит), pt:= T#5s)
if Таймер.Q then
стартовать программу;
стартовый не энергонезависимый бит:= 1;
end_if
Сделал, отвалилась запись входных переменных (цены импульса)
FUNCTION_BLOCK Flowmeter // имя функционального блока.
VAR_INPUT // объявление входных переменных
i_Work: BOOL; // разрешение на работу
i_Imp: BOOL; // переменная считывания переднего фронта импульса
i_ImpMass: REAL; // переменна цены импульса
i_Flow: REAL; // Общий поток
i_FlowYear: REAL; // Годовой поток
i_FlowMonth: REAL; // Поток за месяц
i_FlowDay: REAL; // Поток за день
i_FlowHour: REAL; // Поток за час
i_nowYear: UDINT; // Текущий год
i_nowMonth: UDINT; // Текущий месяц
i_nowDay: UDINT; // Текущий день
i_nowHour: UDINT; // Текущий час
i_nowMinute: UDINT; // Текущая минута
i_nowSecond: UDINT; // Текущая секунда
END_VAR
VAR_OUTPUT // объявление выходных переменных
Flow: REAL;
FlowDay: REAL;
FlowHour: REAL;
FlowMonth: REAL;
FlowYear: REAL;
ImpMass: REAL;
Work: BOOL;
END_VAR
VAR // объявление локальных переменных
TON: TON_FB;
TON_Q: BOOL;
l_Flow: REAL;
l_FlowDay: REAL;
l_FlowHour: REAL;
l_FlowMonth: REAL;
l_FlowYear: REAL;
l_year: UDINT;
l_month: UDINT;
l_day: UDINT;
l_hour: UDINT;
l_minute: UDINT;
l_second: UDINT;
l_impMass: REAL;
END_VAR
TON(IN := NOT(i_Work), PT := 5, Q => TON_Q);
IF TON_Q THEN
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass := 100;
IF i_Imp = TRUE THEN
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
END_IF
IF i_nowDay <> l_day THEN
l_day := i_nowDay;
l_FlowDay := 0;
END_IF
IF i_nowHour <> l_hour THEN
l_hour := i_nowHour;
// l_FlowHour := 0;
END_IF
IF i_nowMonth <> l_month THEN
l_month := i_nowMonth;
// l_FlowMonth := 0;
END_IF
IF i_nowYear <> l_year THEN
l_year := i_nowYear;
// l_FlowYear := 0;
END_IF
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
Work := true;
END_IF
END_FUNCTION_BLOCK
Код с записями переменных делал и внутри условия и вне, без изменений.
Как считаете, будет ли работать, если начать сравнение с конкретными числами:
например:
ЕСЛИ час = 00 И минута = 00 и СЕКУНДА = 00
поток день = 0
КОНЕЦ ЕСЛИ
P.S.: Так действительно значение сохраняется
Только вот, боюсь, с показаниями за месяц это работать не будет, ибо у нас бывает 28, 29, 30, 31 день в месяце. Ну и 365-366 дней в году)
МихаилГл
28.12.2023, 10:41
Почему:
Work := true;
i_Work
Вы не выходите из этого if при таком условии...
И
l_FlowDay := 0; не закомментировали... Внимательнее...
Почему:
Work := true;
i_Work
Вы не выходите из этого if при таком условии...
к i_Work и Work привязана одна и та же переменная, просто i_Work - входная, Work - выходная
Или будет лучше сделать локальную переменную, которая принимается от входной и записывает выходную?
l_FlowDay := 0; не закомментировали... Внимательнее...
Так я и пишу ФБ, чтобы сделать потоки за определенное кол-во времени, если не обнулять - будет просто общий поток(а он работает нормально)
Суть такая:
Программа считает целый день воду и, как только наступают след. сутки, она сбрасывает показания в 0 и считает заново (суточный/месячный/годовой расход).
Если в сутках у нас только 24, то сделать самое просто сравнение времени с нулями еще можно. Но вот с месяцами и годами так не выйдет, ибо всегда разное, поэтому просто каждый цикл смотрим и сравниваем текущие входные числа с локальными, если не равно, то перезаписать локальную и сбросить счетчик
МихаилГл
28.12.2023, 10:52
к i_Work и Work привязана одна и та же переменная, просто i_Work - входная, Work - выходная
Или будет лучше сделать локальную переменную, которая принимается от входной и записывает выходную?
Локальная энергоЗАВИСИМАЯ... А так вы не выходите из условия и обнуляете все... А если будет одна, то код выполнится один раз по истечении 5 секунд и все, и снова только после перезагрузки...
Не две, а ОДНА...
PS ошибся с энергозависимостью... Вы меня запутали совсем
Локальная энергоЗАВИСИМАЯ... А так вы не выходите из условия и обнуляете все... А если будет одна, то код выполнится один раз по истечении 5 секунд и все, и снова только после перезагрузки...
Не две, а ОДНА...
PS ошибся с энергозависимостью... Вы меня запутали совсем
Поменял все ворки эти, результата все равно не дает, не дает программе стартовать
Честно говоря, я вообще не понимаю причины сброса после отвала питания. Если идет сравнение годов, то он в любом случае не поменялся(по логике).
А так ощущение, что часы очень сильно подтупливают и сначала дают какую-нибудь дату 00.00.00 00:00
МихаилГл
28.12.2023, 11:00
Скиньте последний код... Гляну. Я уже совсем запутался чего вы хотите...
Скиньте последний код... Гляну. Я уже совсем запутался чего вы хотите...
FUNCTION_BLOCK Flowmeter // имя функционального блока.
VAR_INPUT // объявление входных переменных
i_Work: BOOL; // разрешение на работу
i_Imp: BOOL; // переменная считывания переднего фронта импульса
i_ImpMass: REAL; // переменна цены импульса
i_Flow: REAL; // Общий поток
i_FlowYear: REAL; // Годовой поток
i_FlowMonth: REAL; // Поток за месяц
i_FlowDay: REAL; // Поток за день
i_FlowHour: REAL; // Поток за час
i_nowYear: UDINT; // Текущий год
i_nowMonth: UDINT; // Текущий месяц
i_nowDay: UDINT; // Текущий день
i_nowHour: UDINT; // Текущий час
i_nowMinute: UDINT; // Текущая минута
i_nowSecond: UDINT; // Текущая секунда
END_VAR
VAR_OUTPUT // объявление выходных переменных
Flow: REAL;
FlowDay: REAL;
FlowHour: REAL;
FlowMonth: REAL;
FlowYear: REAL;
ImpMass: REAL;
Work: BOOL;
END_VAR
VAR // объявление локальных переменных
TON: TON_FB;
TON_Q: BOOL;
l_Flow: REAL;
l_FlowDay: REAL;
l_FlowHour: REAL;
l_FlowMonth: REAL;
l_FlowYear: REAL;
l_year: UDINT;
l_month: UDINT;
l_day: UDINT;
l_hour: UDINT;
l_minute: UDINT;
l_second: UDINT;
l_impMass: REAL;
END_VAR
TON(IN := NOT(i_Work), PT := 5, Q => TON_Q);
IF TON_Q THEN
//запись входных переменных в локальные
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass := 100;
//блок вычисления показаний воды
IF i_Imp = TRUE THEN
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
END_IF
//сравнение дня показаний за день. Сравнение <> не работает, сравнение с нулями работает
IF i_nowHour = 00 AND i_nowMinute = 00 AND i_nowSecond = 00 THEN
l_day := i_nowDay;
l_FlowDay := 0;
END_IF
//Часовые показания
IF i_nowHour <> l_hour THEN
l_hour := i_nowHour;
l_FlowHour := 0;
END_IF
//месячные показания
IF i_nowMonth <> l_month THEN
l_month := i_nowMonth;
l_FlowMonth := 0;
END_IF
//годовые показания
IF i_nowYear <> l_year THEN
l_year := i_nowYear;
l_FlowYear := 0;
END_IF
//запись из локальных переменных в выходные
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
i_Work := true;
END_IF
END_FUNCTION_BLOCK
МихаилГл
28.12.2023, 11:07
Таймер (in:= not (стартовый не энергонезависимый бит), pt:= T#5s)
if Таймер.Q then
стартовать программу;
стартовый не энергонезависимый бит:= 1;
end_if
Поменял все ворки эти, результата все равно не дает, не дает программе стартовать
Честно говоря, я вообще не понимаю причины сброса после отвала питания. Если идет сравнение годов, то он в любом случае не поменялся(по логике).
А так ощущение, что часы очень сильно подтупливают и сначала дают какую-нибудь дату 00.00.00 00:00
Я вот это предлагал вообще в начале запуска программы поставить. Т.е. программа не считает вообще, пока плк не проработает 5 секунд. А там можно на ст не ФБ писать, а не основную программу?
Короче, нужен исходник...
МихаилГл
28.12.2023, 11:07
А как вы в этот код заходите я сам придумать должен? У вас ошибка до...
Я вот это предлагал вообще в начале запуска программы поставить. Т.е. программа не считает вообще, пока плк не проработает 5 секунд. А там можно на ст не ФБ писать, а не основную программу?
Короче, нужен исходник...
Исходник прилагаю.
Просто на вход разрешения работы ФБ кинуть таймер на пять секунд?
А как вы в этот код заходите я сам придумать должен? У вас ошибка до...
Честно говоря, ничего не понял. Может вы про Codesys ST говорите?
Но вот проект с ФБ
МихаилГл
28.12.2023, 11:43
Честно говоря, ничего не понял. Может вы про Codesys ST говорите?
Но вот проект с ФБ
Вот как сделать задержку на запуск подсчетов при первом запуске...
Дальше сами... Но если я пойму что вы хотите дальше, может продолжим... Наверное после НГ)
С i_Work и Work вы правы, я просто с ФБ редко связываюсь.
Вот как сделать задержку на запуск подсчетов при первом запуске...
Дальше сами... Но если я пойму что вы хотите дальше, может продолжим... Наверное после НГ)
С i_Work и Work вы правы, я просто с ФБ редко связываюсь.
Почему-то при задержке ФБ перестает считать, хотя все срабатывает (смотрю по цене импульса).
Пока сделал с тупым сравнением на равенство дат и времени (но если ПРку рубанет в эти нужные моменты, боюсь, она не сбросит показания).
Попробую еще связаться с этой проблемой к ОВЕНовцам, может они что-то подскажут)
Если получится вывести идеальный вариант ФБ, отпишусь в теме
МихаилГл
28.12.2023, 12:03
Почему-то при задержке ФБ перестает считать, хотя все срабатывает (смотрю по цене импульса).
Пока сделал с тупым сравнением на равенство дат и времени (но если ПРку рубанет в эти нужные моменты, боюсь, она не сбросит показания).
Попробую еще связаться с этой проблемой к ОВЕНовцам, может они что-то подскажут)
Если получится вывести идеальный вариант ФБ, отпишусь в теме
Потому что у вас похоже используются переменные из этого ФБ в основном коде (не смотрел внимательно), а он (ФБ) начнет работать только после 5 секунд после подачи питания.
FUNCTION_BLOCK Flowmeter // имя функционального блока.
VAR_INPUT // объявление входных переменных
i_Work: BOOL; // разрешение на работу
i_Imp: BOOL; // переменная считывания переднего фронта импульса
i_ImpMass: REAL; // переменна цены импульса
i_Flow: REAL; // Общий поток
i_FlowYear: REAL; // Годовой поток
i_FlowMonth: REAL; // Поток за месяц
i_FlowDay: REAL; // Поток за день
i_FlowHour: REAL; // Поток за час
i_nowYear: UDINT; // Текущий год
i_nowMonth: UDINT; // Текущий месяц
i_nowDay: UDINT; // Текущий день
i_nowHour: UDINT; // Текущий час
i_nowMinute: UDINT; // Текущая минута
i_nowSecond: UDINT; // Текущая секунда
END_VAR
VAR_OUTPUT // объявление выходных переменных
Flow: REAL;
FlowDay: REAL;
FlowHour: REAL;
FlowMonth: REAL;
FlowYear: REAL;
ImpMass: REAL;
Work: BOOL;
END_VAR
VAR // объявление локальных переменных
TON: TON_FB;
TON_Q: BOOL;
l_Flow: REAL;
l_FlowDay: REAL;
l_FlowHour: REAL;
l_FlowMonth: REAL;
l_FlowYear: REAL;
l_year: UDINT;
l_month: UDINT;
l_day: UDINT;
l_hour: UDINT;
l_minute: UDINT;
l_second: UDINT;
l_impMass: REAL;
END_VAR
TON(IN := NOT(i_Work), PT := 5, Q => TON_Q);
IF TON_Q THEN
//запись входных переменных в локальные
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass := 100;
//блок вычисления показаний воды
IF i_Imp = TRUE THEN
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
END_IF
//сравнение дня показаний за день. Сравнение <> не работает, сравнение с нулями работает
IF i_nowHour = 00 AND i_nowMinute = 00 AND i_nowSecond = 00 THEN
l_day := i_nowDay;
l_FlowDay := 0;
END_IF
//Часовые показания
IF i_nowHour <> l_hour THEN
l_hour := i_nowHour;
l_FlowHour := 0;
END_IF
//месячные показания
IF i_nowMonth <> l_month THEN
l_month := i_nowMonth;
l_FlowMonth := 0;
END_IF
//годовые показания
IF i_nowYear <> l_year THEN
l_year := i_nowYear;
l_FlowYear := 0;
END_IF
//запись из локальных переменных в выходные
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
i_Work := true;
END_IF
END_FUNCTION_BLOCK
Вы запись входных и выходных переменных выведите из под условия разрешения работы - они должны всегда выполняться
Но это не поможет - у вас локальное время не сохраняется, поэтому после перезагрузки все и сбрасывается. Поэтому как-то так
Чтение входных данных
if РАЗРЕШИТЬ then
здесь считаем
else
запись текущего времени в локальные переменные
end_if
Запись выходных данных
Вы запись входных и выходных переменных выведите из под условия разрешения работы - они должны всегда выполняться
Но это не поможет - у вас локальное время не сохраняется, поэтому после перезагрузки все и сбрасывается. Поэтому как-то так
Чтение входных данных
if РАЗРЕШИТЬ then
здесь считаем
else
запись текущего времени в локальные переменные
end_if
Запись выходных данных
Тоже делал, и сейчас еще раз перепроверил, не работает
AlexCrane
28.12.2023, 13:54
Переменные l_hour, l_month и др. на выход блока и через энергонезависимую переменную обратно на входы, видимо только так
Тоже делал, и сейчас еще раз перепроверил, не работает
Вот, проверил, не сбрасывает
function_block Flowmeter //имя функционального блока.
var_input //объявление входных переменных
bEn: bool;
i_Imp: bool; //переменная считывания переднего фронта импульса
i_ImpMass: real; //переменна цены импульса
i_Flow: real; //Общий поток
i_FlowYear: real; //Годовой поток
i_FlowMonth: real; //Поток за месяц
i_FlowDay: real; //Поток за день
i_FlowHour: real; //Поток за час
i_nowYear: udint; //Текущий год
i_nowMonth: udint; //Текущий месяц
i_nowDay: udint; //Текущий день
i_nowHour: udint; //Текущий час
i_nowMinute: udint; //Текущая минута
i_nowSecond: udint; //Текущая секунда
end_var
var_output //объявление выходных переменных
Flow: real;
FlowDay: real;
FlowHour: real;
FlowMonth: real;
FlowYear: real;
ImpMass: real;
end_var
var //объявление локальных переменных
l_Flow: real;
l_FlowDay: real;
l_FlowHour: real;
l_FlowMonth: real;
l_FlowYear: real;
l_year: udint;
l_month: udint;
l_day: udint;
l_hour: udint;
l_minute: udint;
l_second: udint;
l_impMass: real;
end_var
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
if bEn then
if i_Imp = TRUE then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
if i_nowDay <> l_day then
l_FlowDay := 0;
l_day := i_nowDay;
end_if
if i_nowHour <> l_hour then
l_FlowHour := 0;
l_hour := i_nowHour;
end_if
if i_nowMonth <> l_month then
l_FlowMonth := 0;
l_month := i_nowMonth;
end_if
if i_nowYear <> l_year then
l_FlowYear := 0;
l_year := i_nowYear;
end_if
else
l_year := i_nowYear;
l_month := i_nowMonth;
l_day := i_nowDay;
l_hour := i_nowHour;
end_if
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
end_function_block
72684
Но, есть нюанс - если перерыв питания придется на стык часа, дня и т.д., то не сбросится.
Здесь надо по другому делать
Вот, проверил, не сбрасывает
function_block Flowmeter //имя функционального блока.
var_input //объявление входных переменных
bEn: bool;
i_Imp: bool; //переменная считывания переднего фронта импульса
i_ImpMass: real; //переменна цены импульса
i_Flow: real; //Общий поток
i_FlowYear: real; //Годовой поток
i_FlowMonth: real; //Поток за месяц
i_FlowDay: real; //Поток за день
i_FlowHour: real; //Поток за час
i_nowYear: udint; //Текущий год
i_nowMonth: udint; //Текущий месяц
i_nowDay: udint; //Текущий день
i_nowHour: udint; //Текущий час
i_nowMinute: udint; //Текущая минута
i_nowSecond: udint; //Текущая секунда
end_var
var_output //объявление выходных переменных
Flow: real;
FlowDay: real;
FlowHour: real;
FlowMonth: real;
FlowYear: real;
ImpMass: real;
end_var
var //объявление локальных переменных
l_Flow: real;
l_FlowDay: real;
l_FlowHour: real;
l_FlowMonth: real;
l_FlowYear: real;
l_year: udint;
l_month: udint;
l_day: udint;
l_hour: udint;
l_minute: udint;
l_second: udint;
l_impMass: real;
end_var
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
if bEn then
if i_Imp = TRUE then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
if i_nowDay <> l_day then
l_FlowDay := 0;
l_day := i_nowDay;
end_if
if i_nowHour <> l_hour then
l_FlowHour := 0;
l_hour := i_nowHour;
end_if
if i_nowMonth <> l_month then
l_FlowMonth := 0;
l_month := i_nowMonth;
end_if
if i_nowYear <> l_year then
l_FlowYear := 0;
l_year := i_nowYear;
end_if
else
l_year := i_nowYear;
l_month := i_nowMonth;
l_day := i_nowDay;
l_hour := i_nowHour;
end_if
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
end_function_block
72684
Но, есть нюанс - если перерыв питания придется на стык часа, дня и т.д., то не сбросится.
Здесь надо по другому делать
Вероятность просадки по питанию в стыки крайне мала, как мне кажется, но не равна нулю, к сожалению. Спасибо большое за предложенное решение :)
А по-другому, это как? Вернее, с какого ракурса смотреть на решение задачи?
kondor3000
28.12.2023, 14:55
Короче прошлое время всегда равно 0, поэтому всё будет сбрасываться. Сделал инициализацию времени при включении. Всё стало работать.
Короче прошлое время всегда равно 0, поэтому всё будет сбрасываться. Сделал инициализацию времени при включении. Всё стало работать.
Спасибо большое за решение, что-то совсем запутался с этой энергонезависимостью того-сего, не подумал насчет инициализации
МихаилГл
28.12.2023, 15:24
Спасибо большое за решение, что-то совсем запутался с этой энергонезависимостью того-сего, не подумал насчет инициализации
Двоишник)...
Двоишник)...
Не двоечник, а веб-разработчик :D
Где вообще можно посмотреть, какие переменные в каких соусах энергонезависимые?
Руководство по OL штудировать?
Вероятность просадки по питанию в стыки крайне мала, как мне кажется, но не равна нулю, к сожалению. Спасибо большое за предложенное решение :)
А по-другому, это как? Вернее, с какого ракурса смотреть на решение задачи?
Ну, вот так можно
function_block Flowmeter //имя функционального блока.
var_input //объявление входных переменных
i_Imp: bool; //переменная считывания переднего фронта импульса
i_ImpMass: real; //переменна цены импульса
i_Flow: real; //Общий поток
i_FlowYear: real; //Годовой поток
i_FlowMonth: real; //Поток за месяц
i_FlowDay: real; //Поток за день
i_FlowHour: real; //Поток за час
i_nowYear: udint; //Текущий год
i_nowMonth: udint; //Текущий месяц
i_nowDay: udint; //Текущий день
i_nowHour: udint; //Текущий час
i_nowMinute: udint; //Текущая минута
i_nowSecond: udint; //Текущая секунда
in_Time: udint;
end_var
var_output //объявление выходных переменных
Flow: real;
FlowDay: real;
FlowHour: real;
FlowMonth: real;
FlowYear: real;
ImpMass: real;
out_Time: udint;
end_var
var //объявление локальных переменных
l_Flow: real;
l_FlowDay: real;
l_FlowHour: real;
l_FlowMonth: real;
l_FlowYear: real;
l_year: udint;
l_month: udint;
l_day: udint;
l_hour: udint;
l_minute: udint;
l_second: udint;
l_impMass: real;
end_var
l_year := in_Time mod 100;
l_month := (in_Time / 100) mod 100;
l_day := (in_Time / 10000) mod 100;
l_hour := in_Time / 1000000;
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
if i_Imp then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
if i_nowDay <> l_day then
l_FlowDay := 0;
end_if
if i_nowHour <> l_hour then
l_FlowHour := 0;
end_if
if i_nowMonth <> l_month then
l_FlowMonth := 0;
end_if
if i_nowYear <> l_year then
l_FlowYear := 0;
end_if
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
out_Time := i_nowHour * 1000000 + i_nowDay * 10000 + i_nowMonth * 100 + i_nowYear;
end_function_block
Ну, вот так можно
function_block Flowmeter //имя функционального блока.
var_input //объявление входных переменных
i_Imp: bool; //переменная считывания переднего фронта импульса
i_ImpMass: real; //переменна цены импульса
i_Flow: real; //Общий поток
i_FlowYear: real; //Годовой поток
i_FlowMonth: real; //Поток за месяц
i_FlowDay: real; //Поток за день
i_FlowHour: real; //Поток за час
i_nowYear: udint; //Текущий год
i_nowMonth: udint; //Текущий месяц
i_nowDay: udint; //Текущий день
i_nowHour: udint; //Текущий час
i_nowMinute: udint; //Текущая минута
i_nowSecond: udint; //Текущая секунда
in_Time: udint;
end_var
var_output //объявление выходных переменных
Flow: real;
FlowDay: real;
FlowHour: real;
FlowMonth: real;
FlowYear: real;
ImpMass: real;
out_Time: udint;
end_var
var //объявление локальных переменных
l_Flow: real;
l_FlowDay: real;
l_FlowHour: real;
l_FlowMonth: real;
l_FlowYear: real;
l_year: udint;
l_month: udint;
l_day: udint;
l_hour: udint;
l_minute: udint;
l_second: udint;
l_impMass: real;
end_var
l_year := in_Time mod 100;
l_month := (in_Time / 100) mod 100;
l_day := (in_Time / 10000) mod 100;
l_hour := in_Time / 1000000;
l_Flow := i_Flow;
l_FlowYear := i_FlowYear;
l_FlowMonth := i_FlowMonth;
l_FlowDay := i_FlowDay;
l_FlowHour := i_FlowHour;
l_impMass:= i_ImpMass;
if i_Imp then
l_flow := l_Flow + ((1 / 1000) * i_ImpMass);
l_FlowDay := l_FlowDay + ((1 / 1000) * i_ImpMass);
l_FlowHour := l_FlowHour + ((1 / 1000) * i_ImpMass);
l_FlowMonth := l_FlowMonth + ((1 / 1000) * i_ImpMass);
l_FlowYear := l_FlowYear + ((1 / 1000) * i_ImpMass);
end_if
if i_nowDay <> l_day then
l_FlowDay := 0;
end_if
if i_nowHour <> l_hour then
l_FlowHour := 0;
end_if
if i_nowMonth <> l_month then
l_FlowMonth := 0;
end_if
if i_nowYear <> l_year then
l_FlowYear := 0;
end_if
ImpMass := l_impMass;
Flow := l_Flow;
FlowHour := l_FlowHour;
FlowDay := l_FlowDay;
FlowMonth := l_FlowMonth;
FlowYear := l_FlowYear;
out_Time := i_nowHour * 1000000 + i_nowDay * 10000 + i_nowMonth * 100 + i_nowYear;
end_function_block
Перевод всего времени в UNIX c последующим вытаскиванием дат?
Перевод всего времени в UNIX?
Мне лень писать на ST перевод из юникса в дату, поэтому просто упаковал. А так, да, по хорошему на вход надо подавать дату в юникс формате, и входов меньше будет
В, общем, вроде так надо. Ведь нам надо еще синхронизировать импульсы и приращение времени, чтобы при рассогласовании не было погрешности
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot