121
Technical support / Re:week number
« on: January 09, 2018, 08:00:23 PM »
I am glad that you have a good working algorithm.
As a suggestion, there are more direct ways to determine if something can be divided by 4 without a remainder.
Your code sample:
'PUT DATE IN M$
M$ = STR$(DATE[1])
'DIVIDE YEAR NUMBER BY 4
M# =VAL(M$)/4.0
'PUT NUMBER INTO STRING
N$ = STR$(M#)
'PUT FIRST DECIMAL PLACE INTO O$
O$ = MID$(N$,6,1)
'IF DECIMAL IS ZERO, THEN SET LEAP YEAR
IF VAL(O$) = O THEN
SETIO LEAP_YEAR
ELSE CLRIO LEAP_YEAR
ENDIF
[/color]
Could probably be written in a much more direct way using the modulo (MOD) operator:
If (DATE[1] MOD 4)
ClrIO LEAP_YEAR
else
SetIO LEAP_YEAR
endif
[/color]
I'm certain that you are aware that your algorithm for determining leap year is not technically correct as it will fail on some years that are divisible by 100.
The only other thing that you should give a little bit of thought to is the accessing of the DATE[] and TIME[] registers. The issue is that you access these registers multiple times in your algorithm. The values in these registers are updated by PLC low-level firmware and it is possible for the register values to change between the first and last access that your CF makes to these registers. For the DATE[] registers these changes tend to happen at the last second of the day. The worst case is on the last day of the year 31-12-2018 the registers will update to 1-1-2019 and it is possible for your PLC software to read a mixture of the old and new date as the registers are updated one at a time.
One approach is to use the SETSYSTEM 253,0 to shut down updates of the RTC registers, read all of the DATE[] registers and store the values, store them in DM[] and then use the SETSYSTEM 253,1 statement to turn back on the RTC registers.
Another approach is to NOT access the DATE[] registers around midnight.
Best regards,
Gary D*ckinson
As a suggestion, there are more direct ways to determine if something can be divided by 4 without a remainder.
Your code sample:
'PUT DATE IN M$
M$ = STR$(DATE[1])
'DIVIDE YEAR NUMBER BY 4
M# =VAL(M$)/4.0
'PUT NUMBER INTO STRING
N$ = STR$(M#)
'PUT FIRST DECIMAL PLACE INTO O$
O$ = MID$(N$,6,1)
'IF DECIMAL IS ZERO, THEN SET LEAP YEAR
IF VAL(O$) = O THEN
SETIO LEAP_YEAR
ELSE CLRIO LEAP_YEAR
ENDIF
[/color]
Could probably be written in a much more direct way using the modulo (MOD) operator:
If (DATE[1] MOD 4)
ClrIO LEAP_YEAR
else
SetIO LEAP_YEAR
endif
[/color]
I'm certain that you are aware that your algorithm for determining leap year is not technically correct as it will fail on some years that are divisible by 100.
The only other thing that you should give a little bit of thought to is the accessing of the DATE[] and TIME[] registers. The issue is that you access these registers multiple times in your algorithm. The values in these registers are updated by PLC low-level firmware and it is possible for the register values to change between the first and last access that your CF makes to these registers. For the DATE[] registers these changes tend to happen at the last second of the day. The worst case is on the last day of the year 31-12-2018 the registers will update to 1-1-2019 and it is possible for your PLC software to read a mixture of the old and new date as the registers are updated one at a time.
One approach is to use the SETSYSTEM 253,0 to shut down updates of the RTC registers, read all of the DATE[] registers and store the values, store them in DM[] and then use the SETSYSTEM 253,1 statement to turn back on the RTC registers.
Another approach is to NOT access the DATE[] registers around midnight.
Best regards,
Gary D*ckinson