Author Topic: Time based events  (Read 9028 times)

tobor0216

  • Newbie
  • Posts: 24
  • I'm a llama!
    • View Profile
Time based events
« 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

support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3171
    • View Profile
    • Internet Programmable PLCs
Re:Time based events
« Reply #1 on: July 17, 2009, 01:23:11 PM »
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.
Email: support@triplc.com
Tel: 1-877-TRI-PLCS

tobor0216

  • Newbie
  • Posts: 24
  • I'm a llama!
    • View Profile
Re:Time based events
« Reply #2 on: July 18, 2009, 07:02:14 AM »
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

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Time based events
« Reply #3 on: July 18, 2009, 10:54:02 AM »
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

support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3171
    • View Profile
    • Internet Programmable PLCs
Re:Time based events
« Reply #4 on: July 19, 2009, 08:24:52 AM »
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.
   
Email: support@triplc.com
Tel: 1-877-TRI-PLCS

tobor0216

  • Newbie
  • Posts: 24
  • I'm a llama!
    • View Profile
Re:Time based events
« Reply #5 on: July 19, 2009, 11:38:34 AM »
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.

tobor0216

  • Newbie
  • Posts: 24
  • I'm a llama!
    • View Profile
Re:Time based events
« Reply #6 on: July 19, 2009, 11:40:34 AM »
I can clear the IO's at 08:00 am, but I can not set them at 16:00. Or the other way around.

tobor0216

  • Newbie
  • Posts: 24
  • I'm a llama!
    • View Profile
Re:Time based events
« Reply #7 on: July 19, 2009, 11:46:17 AM »
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

support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3171
    • View Profile
    • Internet Programmable PLCs
Re:Time based events
« Reply #8 on: July 19, 2009, 04:29:06 PM »
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.
Email: support@triplc.com
Tel: 1-877-TRI-PLCS

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Time based events
« Reply #9 on: July 19, 2009, 07:05:57 PM »
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.




support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3171
    • View Profile
    • Internet Programmable PLCs
Re:Time based events
« Reply #10 on: July 20, 2009, 05:47:55 AM »
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.
« Last Edit: July 20, 2009, 05:54:26 AM by support »
Email: support@triplc.com
Tel: 1-877-TRI-PLCS

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Time based events
« Reply #11 on: July 20, 2009, 06:12:02 PM »
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


garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Time based events
« Reply #12 on: July 20, 2009, 06:29:42 PM »
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.

garysdickinson

  • Hero Member
  • Posts: 502
  • Old PLC Coder
    • View Profile
Re:Time based events
« Reply #13 on: July 20, 2009, 08:35:46 PM »
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

support

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3171
    • View Profile
    • Internet Programmable PLCs
Re:Time based events
« Reply #14 on: July 21, 2009, 08:59:08 PM »
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.
« Last Edit: July 22, 2009, 04:07:51 AM by support »
Email: support@triplc.com
Tel: 1-877-TRI-PLCS