Ummm - what time is it?
I just programmed a timed filtration system, and was very pleased at how simple the code is to handle a simple on/off timer with selectable day-of-the week:
Pretty neat, huh? I coupled that with a simple screen letting the user set start and stop times and select the days to run:
and the lion's share of the job was done.
But there's much more to Unitronics timekeeping than just simple timers. In the forums, there's been some discussion of the difference between RTC and UTC, the use of UTC to do things such as determine long periods of elapsed time, or to store and retrieve date/time values in log files. Let's try to clear up the confusion, shall we?
First, let's look at the different ways that times can be stored in a Unitronics PLC. For starters, there's RTC (Real Time Clock) - that's a collection of five MI registers, in a specific order:
Base + 0: Seconds
Base + 1: Hours and Minutes
Base + 2: Days and Months
Base + 3: Year
Base + 4: Day Of Week
If you point a function block which uses an RTC value at the special register SI30, you'll get the PLC's built-in Real Time Clock value which should be set for the current date and time of day. You can also point these function blocks at any other group of registers, so that you can manipulate time values which are not the current time, but may instead be values which the user has entered, or values stored in a table, or values which the program has saved for some reason.
Now, the main reason to use an RTC value is that it is very familiar - there's not much question in our minds about what the "hours" field means, or what "month" it is. There are several problems with this representation, though - while an RTC date is easy for a human to read, it can be a lot of work for a computer to do calculations solely on RTC values. For example, if we want to find out the difference between two RTC dates, we might find that the month has changed and that the later date has a lower day value than the earlier date, and we wind up having to compare and subtract both days and months - but months have different numbers of days depending on the month _and_ the year (that annoying leap year thing!)
Here's where the UTC value comes in. UTC is a standardized time format which counts the number of seconds elapsed since an "Epoch" value. The Vision series uses an Epoch of Midnight, January 1, 1900 as its starting point, and counts seconds in a 32 bit register moving forward from then. So, for example, 1 AM, January 1, 1900 would have a UTC value of 3600 - 60 minutes of 60 seconds each from the epoch. There are function blocks to convert from RTC register blocks to UTC values, and back again - thus, if you wanted to compare two RTC dates, you would simply convert both values to UTC and subtract the results. That would give you a difference between the dates in seconds, which you could convert to hours, days, or whatever just by dividing by the correct constant (3600 seconds in an hour, 86400 seconds in a day, etc.) It is important to realize that any given time/date value maps one-to-one with a UTC value - thus, 4:14:35 30 March 2004 equals 3,289,608,875 and 3,481,706,253 converts to 12:37:33 1 May 2010. This lets us readily do mathematics and comparisons in the otherwise complicated realm of date handling.
When would we want to actually do this? How about product packaging - I want to tell an ink-jet printer to print an expiration date which is 28 days from today. Doing this on other PLCs can be a nightmare, requiring a stored table of the days per month plus a special rung to add a day on leap years. On the Unitronics, however, we merely convert the system RTC to a UTC value, add 24192 (28 * 24 * 60 * 60) and convert back from UTC to an RTC at a different location. That RTC value then gets formatted and sent to the printer, and we're done - no worrying about rolling over the month or how many days there are in April.
Or maybe we want to time a long value - something long enough that trying to count seconds or minutes with an MI register starts producing inaccurate results due to the fact that the program takes time to scan, and every time you add a pulse, you will be off by a few milliseconds. So all you do is convert RTC to UTC in a "Now" DW register, save that value to a "Start Time" DW register at the beginning of your timing interval, and calculate your elapsed time by subtracting "Start Time" from "Now" - the result will be a doubleword integer value of elapsed seconds, accurate to durations of years. (Note that if the user changes the Real Time Clock setting while you're timing, the time result will be wrong.)
There's more to all of this - things like timer values and date strings in ASCII, but I'll cover some of that in my next post...