Internet PLC Forum
General => Technical support => Topic started by: tobor0216 on July 17, 2009, 03:12:34 AM
-
I am trying to turn a I/O off at a certian time, and turn it back on at a certian time. My code is below. The controller does not either clear or set the I/O at the specified time.
If Time[1] and Time[2] => 800 then
Clrio XXXX
Clrio YYYY
Endif
If Time[1] and Time[2] => 1600 then
Setio XXXX
Setio YYYY
Endif
-
TIME[1] and TIME[2] are two different variables. You can't combine them the way you did. Try:
IF TIME[1] >= 8 AND TIME[2] >= 0 THEN
.....
ENDIF
But actually if I interpret what you want correctly, your code would be accomplished as follow:
IF TIME[1] >= 8 AND TIME[1] <= 16
CLRIO XXXX
CLRIO YYYY
ELSE
SETIO XXXX
CLRIO YYYY
ENDIF
TIME[2] and TIME[3] are not required if all you want is the define the time period that the IO are to be set.
-
I tried what is listed below, and am still having problems. First problem is when the RTC reaches 7:59:59, it rools over to 7:59:00 and then continues counting to 7:59;59, at this point the RTC jumps to 8:01:00.
Secondly the IO's are not being cleard at the 8:00:00 mark. Below is the code I am using. I added the TIME[2] event to try and make this work, but no luck.
IF (TIME[1] >=08 AND time[2] =01 and TIME[1] <=16 and Time[2] =01)
CLRIO PWR_TV
CLRIO PWR_COMP
Else
SETIO PWR_TV
SETIO PWR_COMP
ENDIF
-
This is the code that I use to manage 8 time clock events.
I store the start and stop times in the DM[] array. The use of the DM[] array allowed me to make the stop/start times easily changeale (not hard coded). In fact, I actually store the stop/start times in EEPROM and copy the values from EEPROM into DM[1..17] on start up.
The 8 relays that are affected by the routine are in sequential order are relays #17 through #24. These 8 relays are accessed using the setbit and clrbit.
In this example I am only worried about starting and stopping things with a resolution of 1 minute so I only look at time[1] and time[2]. This routine is called every 30 seconds to ensure that I don't miss an event (Nyquest limit).
If you need to make your time clock accurate to 1 second, then you will need to take time[3] into account. You will need to call your routine at least twice each second.
Please note that I use ">=" and "<" to compare my stop/start times against the current time and do not use "=". This ensures that if the PLC is started (or reset) in the middle of a start/stop time period that the outputs (relays) will be set/cleared correctly and not have to wait 24 hrs for the exact "start time".
Please also note that I worry about start/stop events that span midnight (00:00:00) so that these events are handled correctly.
'TimeChk - Called periodically to manage relays 17..23
'Relays are set on/off based on the current time and the
'stop/start times stored in dm[1..17]
'
t=time[1]*100+time[2] ' t is current time in scaled minutes
n=1 ' index into dm[] for start/stop pairs
for i = 0 to 7 ' each relay
if dm[n]<=dm[n+1]
'ON period does not span midnight
if (t>=dm[n]) and (t<dm[n+1])
setbit RELAY[2],i
else
clrbit RELAY[2],i
endif
else
'ON period spans midnight
if (t>=dm[n+1]) and (t<dm[n])
clrbit RELAY[2],i
else
setbit RELAY[2],i
endif
endif
n=n+2 ' next stop/start pair
next
-
I tried what is listed below, and am still having problems. First problem is when the RTC reaches 7:59:59, it rools over to 7:59:00 and then continues counting to 7:59;59, at this point the RTC jumps to 8:01:00.
Secondly the IO's are not being cleard at the 8:00:00 mark. Below is the code I am using. I added the TIME[2] event to try and make this work, but no luck.
IF (TIME[1] >=08 AND time[2] =01 and TIME[1] <=16 and Time[2] =01)
CLRIO PWR_TV
CLRIO PWR_COMP
Else
SETIO PWR_TV
SETIO PWR_COMP
ENDIF
It seems like there is a bug in the F-series RTC when crossing the hour mark, i.e. from xx:59:59 to (xx+1):0:0. I was able to repeat what you described about 7:59:59 becoming 7:59:00 and the next minute it become 8:01:00. All other minute cross-overs work fine. We will report this to the R&D and get this fixed in future. However, you should be able to still control your event using the hour digit only comparison with a 1 minute delay. Alternatively, you can do the following comparison:
IF (TIME[1] = 7 AND TIME[2]=59 AND TIME[3] >=55) OR TIME[1]=8
SETIO XXX
ENDIF
You can check this function every 1s to ensure that the IO XXX will be turned ON from 7:59:55 onwards and include 8:xx:xx.
-
Gary,
Thanks for the code. I am not sure how to fit it into my routine, as I am trying to turn to outputs (PWR_TV and PWR_COMP) off at 08:00 and back on at 16:00 pm. Both outputs will be on over midnight.
-
I can clear the IO's at 08:00 am, but I can not set them at 16:00. Or the other way around.
-
Here is the code I am using
IF (TIME[1] >=7 AND TIME[2]=59 ) OR (TIME[1] <=15 AND TIME[2]=59) then
CLRIO PWR_COMP
Else
Setio PWR_COMP
Endif
-
Thanks Gary. Gary's routine of converting the TIME[1] and TIME[2] data into scaled minutes and checking for crossing of midnight should work very well for this application. We will try to construct a sample .PC6 program to demonstrate the method and will post it later for download.
-
I use this code for controlling lighting events and multiple pumps for a salt water aquarium. I can supply other bits of the code if this would be useful
It is possible that tobor0216 is seeing a real problem.
My experience with physical RTCs (used on old PC mother boards or your MX-RTC) HAVE problems with roll over events. With these RTCs the problem shows up like this:
AT 23:59:59 it was possible to read the time as 23:00:00 if your read the hours register first and the RTC updated the seconds and minutes register before one was able to read them. This problem happens because:
- The HR:MM:SS registers were linked such that the overflow of seconds from XX:XX:59 to XX:XX:00 results in a ripple carry into the minutes register and the minutes register carried into the hours regsiter.
- Each register HR:MM:SS required a separate 8 bit (or multiple 4 bit) access by the CPU.
- There was no mechanism to hold (synchronize) the registers so that the CPU could read all 3 of them and ensure that an ripple did not occur between the access of the first register and the last.
One firmware mechanism to cope with this problem was to read all three registers twice and then compare the values. If there were any differences then assume that a register was updated and reading until two successive reads of the compelee register set gave the same results.
I bring up this issue as
- I have not exhaustively tested the TIME[] mechanism in your PLCs.
- There is no documented interlock mechanism in TLBASIC to ensure that if I read TIME[1], TIME[2] and TIME[3] that there will be no rollover between access to the the HR, MIN and SEC registers.
-
Gary - Thanks for bringing up potential issues with rollover. I think as long as the event is timed to the minute resolution (instead of the second) your routine would work well. However, your valuable feedback could be helpful for future design.
A demo .PC6 program based on your code fragment has just been posted at the following web page.
http://www.tri-plc.com/trilogi/RTCAppByGDK.zip
You can simply include the program into your own codes and then all you need to do is to use the relay contacts #17 to #24 as flags to either turn ON/OFF outputs or trigger custom functions to perform required tasks.
-
I did a simple test with the T100MD+ PLC to see if it is possible to access TIME[1], TIME[2] and TIME[3] and "See"an invalid time.
The short answer is YES. The same problem will occur with DATE[].
I used the following custom function to test the RTC and the online monitoring to examine the contents of the DM[] array:
' Set RTC to 23:59:59
TIME[1]=23
TIME[2]=59
TIME[3]=59
' Read all time registers quickly and store results in DM[]
for i = 1 to 3999 step 3
DM[i+0] = TIME[1]
DM[i+1] = TIME[2]
DM[i+2] = TIME[3]
NEXT
' Hunt through DM[] looking for rollover event.
' I points at change in time array
'
for i = 3 to 3999 step 3
if DM = 0
return
endif
next
With this simple test, I have observed the following transition in the time registers:
23:59:59 -> 23:59:00
and on some occasions
23:59:59 -> to 23:00:00
What I never observed was a clean transition from
23:59:59 to 00:00:00 !!!
Because there is no mechanism in ensure that all 3 TIME[] registers can be accessed without the possibility of a roll over event, I would strongly suggest the following approach:
' this code accesses the TIME[] registers and returns
' with DM[1] = Hours, DM[2] = Minutes and DM[3] = seconds
'
' DM[4..6] are used as scratch registers
'
while 1
for i = 1 to 3 ' read time registers quickly
DM = TIME
next
for i = 4 to 6 ' read them a 2nd time
DM = TIME
next
if (DM[1] = DM[4]) AND (DM[2] = DM[5]) AND (DM[3] = DM[6])
return ' good read, you are done
endif
' if you are here, then a roll over occurred...
'
' Read all the registers again...
'
endwhile
-
One more note.
As there is no mechanism to stop the PLC firmware from updating the RTC registers during Reads of TIME[] and DATE[] there is no mechanism to prevent the PLC firmware from changing the underlining registers during write access to the TIME[] and DATE[] registers.
I suggest that if one is trying to set the RTC time and date via TLBASIC , then one should re-read all of the registers to see that the PLC time and date registers actually got set to the values that you intended.
I hope I don't make you guys too crazy,
Gary D.
-
The early suggestion on how to avoid mis-reading the TIME[] was not tested. This code has been tested:
'Read RTC - code to access time of day registers and return CORRECT values
' in the following variables:
' DM[301] TIME[1], RTC Hours
' DM[302] TIME[2], RTC Minutes
' DM[303] TIME[3], RTC Seconds
while 1
' read all TIME[] registers, one time
'
DM[301] = TIME[1]
DM[302] = TIME[2]
DM[303] = TIME[3]
' re-read the TIME[] register and verify that they did not change
' from the previous set. The whole point of this exercise is to
' detect and discard erronous readings that can occur becuase the PLC
' firmware is constanly updating these register. It is possible to
' observe the following transisitons:
'
' 23:59:59 -> 23:59:00 -> 23:00:00 -> 00:00:00
'
if ((DM[301]=TIME[1]) AND (DM[302]=TIME[2]) AND (DM[303]=TIME[3]))
return ' time is correct, no invalid transisitons
endif
' If we are here then there was a roll over between the reads of the
' TIME[] registers...so try it again
'
endwhile
-
I tried what is listed below, and am still having problems. First problem is when the RTC reaches 7:59:59, it rools over to 7:59:00 and then continues counting to 7:59;59, at this point the RTC jumps to 8:01:00.
Secondly the IO's are not being cleard at the 8:00:00 mark. Below is the code I am using. I added the TIME[2] event to try and make this work, but no luck.
IF (TIME[1] >=08 AND time[2] =01 and TIME[1] <=16 and Time[2] =01)
CLRIO PWR_TV
CLRIO PWR_COMP
Else
SETIO PWR_TV
SETIO PWR_COMP
ENDIF
It seems like there is a bug in the F-series RTC when crossing the hour mark, i.e. from xx:59:59 to (xx+1):0:0. I was able to repeat what you described about 7:59:59 becoming 7:59:00 and the next minute it become 8:01:00. All other minute cross-overs work fine. We will report this to the R&D and get this fixed in future. However, you should be able to still control your event using the hour digit only comparison with a 1 minute delay. Alternatively, you can do the following comparison:
IF (TIME[1] = 7 AND TIME[2]=59 AND TIME[3] >=55) OR TIME[1]=8
SETIO XXX
ENDIF
You can check this function every 1s to ensure that the IO XXX will be turned ON from 7:59:55 onwards and include 8:xx:xx.
On further test, we notice that when the RTC on the F-series PLC runs on its own it actually rolls over properly from xx:59:59 to (xx+1):00:00. However, if the user sets the TIME[2] variable manually to 59, then for some reason it disturbed the RTC internal register and it will roll over from xx:59:59 to (xx):59:00 and in the next minute it becomes (xx+1):01:00. The internal RTC still maintains the clock accurately but only the roll over from xx:59:59 behave oddly. However, if you power down the PLC after setting the RTC (even with TIME[2] set to 59) then the RTC will behave properly and roll over. So the bug in the firmware relates only to how it handles a modification of the TIME[] variable but does not affect its actual operation.
In other words, the RTC on F-series PLC should work properly to trigger the time-based events at precisely the correct time once the RTC has been set up and running normally. It just make testing it a bit awkard when you try to manually set the TIME[2] variable to 59 and it doesn't roll over correctly in the next minute. So to test the program behavior after setting the TIME[2] variable, please cycle the power to the PLC so that the RTC will run properly.