Доброго времени суток. прошу помоши в следующем деянии:
Необходимо обнулять переменную, типа real, в 00:00 каждый день, первого числа каждого месяца так же в 00:00, и первого января каждого года в 00:00, буду премного благодарен за помощь в этом вопросе.
PS. На WinCC SP3, проделывал такое скриптами, а вот в CDS сделать как ума не приложу.
можно вопрос в чем отличие первого января от первого числа каждого месяца, про каждый день даже спрашивать не буду
по вопросу, добавляете библиотеку работы с временем, считывате показания с часов реального времени, сравниваете с нужными датами, по выполнению условия сбрасываете переменную
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
среди успешных людей я не встречала нытиков
Барбара Коркоран
Ну отличия принципиального конечно нет, согласен, просто описал алгоритм, а по поводы "Сравнивать с нужными датами", это э какая простыня то получится расписанная, 12 месяцев, и черт его знает сколько лет, или я чего то не понимаю?
так вот по этому у меня и был сперва вопрос. С ТЗ сперва разберитесь,что нужно, если каждый день в полночь обнулять, то и ловите наступление события, смены дня и состояние часов, минут, секунд равными нулю. Вы же писали что в скриптах все это проделываете легко, здесь то чего понапридумывали про портянку
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
среди успешных людей я не встречала нытиков
Барбара Коркоран
Скрипт был прост до безобразия и настройки на выполнения скрипта задавались в настройках триггера. См вложение. Как в CDS сделать еще раз повторюсь не понимаю.ноль.jpg
PROGRAM get_time
VAR CONSTANT
nulldt: SystemTimeDate; (*нужна для обнуления*)
END_VAR
VAR_IN_OUT
Sys_Time: SysTime64;
TimeAndDate: SystemTimeDate;
END_VAR
VAR
GetTime: CurTimeEx;
END_VAR
Ну отличия принципиального конечно нет, согласен, просто описал алгоритм, а по поводы "Сравнивать с нужными датами", это э какая простыня то получится расписанная, 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;
А дальше все просто, как три пальца... Захват-1.png
Все довольна просто будет, если перейти к переменным 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;
А дальше все просто, как три пальца... Захват-1.png