Доброго времени суток. прошу помоши в следующем деянии:
Необходимо обнулять переменную, типа real, в 00:00 каждый день, первого числа каждого месяца так же в 00:00, и первого января каждого года в 00:00, буду премного благодарен за помощь в этом вопросе.
PS. На WinCC SP3, проделывал такое скриптами, а вот в CDS сделать как ума не приложу.
23.03.2017, 11:31
capzap
можно вопрос в чем отличие первого января от первого числа каждого месяца, про каждый день даже спрашивать не буду
по вопросу, добавляете библиотеку работы с временем, считывате показания с часов реального времени, сравниваете с нужными датами, по выполнению условия сбрасываете переменную
23.03.2017, 11:37
Алексей87
Ну отличия принципиального конечно нет, согласен, просто описал алгоритм, а по поводы "Сравнивать с нужными датами", это э какая простыня то получится расписанная, 12 месяцев, и черт его знает сколько лет, или я чего то не понимаю?
23.03.2017, 11:41
melky
а у вас так много 1-х чисел для создания простыни ? вот просто каждый день у вас пятница, 13-ое прямо...
00:00 И 1-ое число, вот и все сравнения.
Ой, достаточно каждый день 00:00 часов, если еще каждый день...
23.03.2017, 11:44
capzap
так вот по этому у меня и был сперва вопрос. С ТЗ сперва разберитесь,что нужно, если каждый день в полночь обнулять, то и ловите наступление события, смены дня и состояние часов, минут, секунд равными нулю. Вы же писали что в скриптах все это проделываете легко, здесь то чего понапридумывали про портянку
23.03.2017, 11:59
Алексей87
Вложений: 1
Скрипт был прост до безобразия и настройки на выполнения скрипта задавались в настройках триггера. См вложение. Как в CDS сделать еще раз повторюсь не понимаю.Вложение 30202
23.03.2017, 12:14
melky
PROGRAM get_time
VAR CONSTANT
nulldt: SystemTimeDate; (*нужна для обнуления*)
END_VAR
VAR_IN_OUT
Sys_Time: SysTime64;
TimeAndDate: SystemTimeDate;
END_VAR
VAR
GetTime: CurTimeEx;
END_VAR
Вроде есть же в примерах.. Ну и вызывайте это из основной программы.
PROGRAM PLC_PRG
VAR
syst: SysTime64;
tmd: SystemTimeDate;
END_VAR
get_time(Sys_Time:=syst , TimeAndDate:=tmd ); (так кажется, просто у меня это на CFC)
ну а дальше
second := tmd.Second
и так далее
23.03.2017, 12:22
petera
Вложений: 1
Цитата:
Сообщение от Алексей87
Ну отличия принципиального конечно нет, согласен, просто описал алгоритм, а по поводы "Сравнивать с нужными датами", это э какая простыня то получится расписанная, 12 месяцев, и черт его знает сколько лет, или я чего то не понимаю?
Все довольна просто будет, если перейти к переменным DATE
1.
Делаем функцию, которая преобразовывает дату ПЛК(год,месяц,день) в DATE
FUNCTION CurDATE:
Код:
FUNCTION CurDATE : DATE
VAR
CurTimeExInst: CurTimeEx;
CurSystemTimeDate: SystemTimeDate;
CurSysTime64: SysTime64;
year: INT;
second: INT;
day: INT;
hour: INT;
minute: INT;
month: INT;
count: INT;
END_VAR
CurTimeExInst(TimeDate := CurSystemTimeDate, SystemTime := CurSysTime64);
year :=CurSystemTimeDate.Year;
month :=CurSystemTimeDate.Month;
day :=CurSystemTimeDate.Day;
hour :=CurSystemTimeDate.Hour;
minute :=CurSystemTimeDate.Minute;
second :=CurSystemTimeDate.Second;
(*------------------------------------------------------------------------*)
(*Вычислить дату с учетом високосных лет*)
IF month > 2 THEN
count := (month - 1) * 30;
IF month > 7 THEN count := count + SHR(month - 3,1);
ELSE count := count + SHR(month - 4,1); END_IF;
(* проверить на високосный год и добавить один день если год високосный *)
IF SHL(year,14) = 0 THEN count := count + 1; END_IF;
ELSE
count := (month - 1) * 31;
END_IF;
CurDATE:=DWORD_TO_DATE((INT_TO_DWORD(count + day - 1)
+ SHR(INT_TO_DWORD(year) * 1461 - 2878169, 2)) * 86400);
2.
Берем из OSCAT, с некоторой модификацией функцию DAY_OF_MONTH
FUNCTION DAY_OF_MONTH:
Код:
FUNCTION DAY_OF_MONTH : INT
VAR_INPUT
IDATE : DATE;
END_VAR
VAR
leap: INT;
MTH_OFS: ARRAY [1..12] OF INT := 0,31,59,90,120,151,181,212,243,273,304,334;
LEAP_OF_DATE: BOOL;
END_VAR
LEAP_OF_DATE := SHL(((DATE_TO_DWORD(idate) + 43200) / 31557600), 30) = 16#80000000;
(* calculate the day in the year *)
DAY_OF_MONTH := DAY_OF_YEAR(idate);
(* leap will be set to one for a leap year *)
leap := BOOL_TO_INT(LEAP_OF_DATE);
(* if leap year deduct one from the days of the year *)
DAY_OF_MONTH := DAY_OF_MONTH - leap;
(* search if we are in month december to march ? *)
IF DAY_OF_MONTH > MTH_OFS[9] THEN
IF DAY_OF_MONTH > MTH_OFS[11] THEN
IF DAY_OF_MONTH > mth_ofs[12] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[12];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[11];
END_IF;
ELSE
IF DAY_OF_MONTH > mth_ofs[10] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[10];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[9];
END_IF;
END_IF;
ELSIF DAY_OF_MONTH > MTH_OFS[5] THEN
IF DAY_OF_MONTH > MTH_OFS[7] THEN
IF DAY_OF_MONTH > mth_ofs[8] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[8];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[7];
END_IF;
ELSE
IF DAY_OF_MONTH > mth_ofs[6] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[6];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[5];
END_IF;
END_IF;
ELSIF DAY_OF_MONTH > MTH_OFS[3] THEN
IF DAY_OF_MONTH > MTH_OFS[4] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[4];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[3];
END_IF;
ELSE
(* since now we must be in february or january we need to add leap again *)
DAY_OF_MONTH := DAY_OF_MONTH + leap;
IF DAY_OF_MONTH > MTH_OFS[2] THEN DAY_OF_MONTH := DAY_OF_MONTH - mth_ofs[2]; END_IF;
(* since nothing was true before, day_of_month must already be good *)
END_IF;
3. Для FUNCTION DAY_OF_MONTH нужна еще одна функция из OSCAT
Скрытый текст:
Код:
FUNCTION DAY_OF_YEAR : INT
VAR_INPUT
IDATE : DATE;
END_VAR
DAY_OF_YEAR := UDINT_TO_INT((DATE_TO_UDINT(idate) / UDINT#86400) MOD UDINT#1461);
IF DAY_OF_YEAR > 729 THEN
IF DAY_OF_YEAR > 1095 THEN DAY_OF_YEAR := DAY_OF_YEAR - 1095; ELSE DAY_OF_YEAR := DAY_OF_YEAR - 729; END_IF;
ELSIF DAY_OF_YEAR > 364 THEN
DAY_OF_YEAR := DAY_OF_YEAR - 364;
ELSE
DAY_OF_YEAR := DAY_OF_YEAR + 1;
END_IF;
Все довольна просто будет, если перейти к переменным DATE
1.
Делаем функцию, которая преобразовывает дату ПЛК(год,месяц,день) в DATE
FUNCTION CurDATE:
Код:
FUNCTION CurDATE : DATE
VAR
CurTimeExInst: CurTimeEx;
CurSystemTimeDate: SystemTimeDate;
CurSysTime64: SysTime64;
year: INT;
second: INT;
day: INT;
hour: INT;
minute: INT;
month: INT;
count: INT;
END_VAR
CurTimeExInst(TimeDate := CurSystemTimeDate, SystemTime := CurSysTime64);
year :=CurSystemTimeDate.Year;
month :=CurSystemTimeDate.Month;
day :=CurSystemTimeDate.Day;
hour :=CurSystemTimeDate.Hour;
minute :=CurSystemTimeDate.Minute;
second :=CurSystemTimeDate.Second;
(*------------------------------------------------------------------------*)
(*Вычислить дату с учетом високосных лет*)
IF month > 2 THEN
count := (month - 1) * 30;
IF month > 7 THEN count := count + SHR(month - 3,1);
ELSE count := count + SHR(month - 4,1); END_IF;
(* проверить на високосный год и добавить один день если год високосный *)
IF SHL(year,14) = 0 THEN count := count + 1; END_IF;
ELSE
count := (month - 1) * 31;
END_IF;
CurDATE:=DWORD_TO_DATE((INT_TO_DWORD(count + day - 1)
+ SHR(INT_TO_DWORD(year) * 1461 - 2878169, 2)) * 86400);
2.
Берем из OSCAT, с некоторой модификацией функцию DAY_OF_MONTH
FUNCTION DAY_OF_MONTH:
Код:
FUNCTION DAY_OF_MONTH : INT
VAR_INPUT
IDATE : DATE;
END_VAR
VAR
leap: INT;
MTH_OFS: ARRAY [1..12] OF INT := 0,31,59,90,120,151,181,212,243,273,304,334;
LEAP_OF_DATE: BOOL;
END_VAR
LEAP_OF_DATE := SHL(((DATE_TO_DWORD(idate) + 43200) / 31557600), 30) = 16#80000000;
(* calculate the day in the year *)
DAY_OF_MONTH := DAY_OF_YEAR(idate);
(* leap will be set to one for a leap year *)
leap := BOOL_TO_INT(LEAP_OF_DATE);
(* if leap year deduct one from the days of the year *)
DAY_OF_MONTH := DAY_OF_MONTH - leap;
(* search if we are in month december to march ? *)
IF DAY_OF_MONTH > MTH_OFS[9] THEN
IF DAY_OF_MONTH > MTH_OFS[11] THEN
IF DAY_OF_MONTH > mth_ofs[12] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[12];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[11];
END_IF;
ELSE
IF DAY_OF_MONTH > mth_ofs[10] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[10];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[9];
END_IF;
END_IF;
ELSIF DAY_OF_MONTH > MTH_OFS[5] THEN
IF DAY_OF_MONTH > MTH_OFS[7] THEN
IF DAY_OF_MONTH > mth_ofs[8] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[8];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[7];
END_IF;
ELSE
IF DAY_OF_MONTH > mth_ofs[6] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[6];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[5];
END_IF;
END_IF;
ELSIF DAY_OF_MONTH > MTH_OFS[3] THEN
IF DAY_OF_MONTH > MTH_OFS[4] THEN
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[4];
ELSE
DAY_OF_MONTH := DAY_OF_MONTH - MTH_OFS[3];
END_IF;
ELSE
(* since now we must be in february or january we need to add leap again *)
DAY_OF_MONTH := DAY_OF_MONTH + leap;
IF DAY_OF_MONTH > MTH_OFS[2] THEN DAY_OF_MONTH := DAY_OF_MONTH - mth_ofs[2]; END_IF;
(* since nothing was true before, day_of_month must already be good *)
END_IF;
3. Для FUNCTION DAY_OF_MONTH нужна еще одна функция из OSCAT
Скрытый текст:
Код:
FUNCTION DAY_OF_YEAR : INT
VAR_INPUT
IDATE : DATE;
END_VAR
DAY_OF_YEAR := UDINT_TO_INT((DATE_TO_UDINT(idate) / UDINT#86400) MOD UDINT#1461);
IF DAY_OF_YEAR > 729 THEN
IF DAY_OF_YEAR > 1095 THEN DAY_OF_YEAR := DAY_OF_YEAR - 1095; ELSE DAY_OF_YEAR := DAY_OF_YEAR - 729; END_IF;
ELSIF DAY_OF_YEAR > 364 THEN
DAY_OF_YEAR := DAY_OF_YEAR - 364;
ELSE
DAY_OF_YEAR := DAY_OF_YEAR + 1;
END_IF;