thiagoralves
Hi all,

I just updated OpenPLC v3 code to support special functions. These are values related to internal PLC status and data. Currently only two special functions are implemented: current time (RTC) and number of scan cycles executed. These functions are located in memory at address %ML1024 onwards. To be more specific:

%ML1024   ->   Current time in seconds since Epoch

%ML1025   ->   Number of scan cycles executed since the runtime started

%ML1026   ->   Slave Devices communication error counter

Attached is a simple program that works with the current time special function. The program turns the lamp on if the current time is greater than 15:06pm on Nov, 1st, 2018.

Just keep in mind that this program will fail if you don't update your OpenPLC v3 installation with the newer code. On Windows, to update just run "Rebase OpenPLC" from start menu. On other systems you will have to manually update following the installation instructions again.
Quote 2 0
supremesports
Very cool, I had it controlled from AdvancedHMI, but it would be great since now it will be standalone 😃 
Quote 0 0
supremesports
How the DT variable type works?

Is there a way to get this into independent variables like current year, month, day, hour, minute and seconds?

Thanks 😃
Quote 0 0
supremesports
Also, it takes the current time from the system it is installed on? So it will take DST, timezone, etc. into account???
Quote 0 0
thiagoralves
Wow, a lot of questions! 😃 So, DT stand for Date-Time, which means that DT variables hold both the date and the time together. You can get individual portions of the datetime by using the conversion blocks. You can google about IEC 61131-3 conversion of datetime variables to check some examples. But basically, you can use DT to TOD block to get just the time of the day from the DT variable. Then from that you can continue converting to get just the day, just the time, etc...

About time zone stuff, that was tricky, but I believe I implemented it right. The special function gets the system time including time zone and daylight savings configuration, and does the proper adjustments that are needed. So, OpenPLC should get the right time as long as your system time is correct.
Quote 0 0
supremesports
Thank you very much, I'll try this out, it's very interesting. As I said in another post, I implement a very sophisticated Home automation at my house, and I want this to work well. Your work and help is much appreciated!!!
Quote 0 0
thiagoralves
So, turns out that conversion goes down to time of the day and date. Getting individual numbers for day, month, year, etc is tricky since there aren't any ready to use blocks to do that. I've tried to implement this directly on the PLC program using PLC language. It works well for time (it can accurately break out the right hour, minute and second), but it is not working 100% for the date. Sometimes it gets the wrong month number or the wrong day number. But at least it is a start. I'm attaching here my program with the algorithm to calculate the year, month, day, hour, minute and second of a DT (datetime) variable.
Quote 2 0
supremesports
To whoever interested in getting it all separated, here's a code I generated quickly tonight... You have to setup few constants in the function block such as timezone. Also, the DST detection is programmed as per North American rules that are currently active and might need to be re-coded later whenever the rules may be changed. I hope someone will be happy to have this 🙂
DISCLAIMER : Code has been tested with many different input Epoch input dates and times and seems to work fine as of now. This code with will be heavily used and tested in my home automation project and if I ever get issues, I'll update the code and post it back.

I also have a sunclock function that is already made and I could eventually throw in if you ever need to control a lamp with a sun event (sunset, sunrise, etc.). I need to convert it into a function block, let me know if someone is interested.

EDIT : Removed the old version of the code as there was an issue with the time, thiagoralves had a better implementation of the time
Quote 0 0
supremesports
Oops, I just realized that you posted something and I reworked everything from scratch ðŸ˜®

I think that together we'll get something good as the time is not working good for me but the date seems perfect... ÃƒÂ°Ã…¸ËœÅ  I'll check to integrate your time part with my date part and see if it's better...
In fact, my time is good, but it does skip few seconds due to rounding in REAL values... I see that you worked it all in ULINT which is a good idea...
Quote 0 0
supremesports
Everything works good now, your time function is perfect. For the date formula you used, I got some problem with it few weeks ago and I wasn't able to figure it out, so I switched to another formula that I adapted and it is implemented in my version of the code. But for the time formula, since it's already in seconds, I think you were right to use it directly.

Here's a pretty much final version, but as I said, date WILL need to be monitored...

EDIT : Corrected a little bug 2018-11-02 10:44PM EDT
EDIT : Corrected a little bug 2018-11-03 00:14AM EDT
Quote 0 0
thiagoralves
Nice coding supremesports! I just have a few little suggestions for your functionBlock. First, instead of receiving as input the OpenPLC current time from %ML1024, it is better to receive a standard DT variable. The reason for that is because %ML1024 is not a true unix timestamp. The unix timestamp is calculated based on the UTC time, but OpenPLC %ML1024 has a "modified" timestamp that takes into consideration the current timezone, DST, etc. So, in my opinion, the best way is to convert %ML1024 to DT using the regular ULINT_TO_DT block and have everything operate based on DT variables. Another reason to have DT variables as input is because it is a lot easier to format fixed dates this way (using for example DT#2018-05-09-13:29:20), in case the block gets a fixed date as input. Well, in general, since IEC 61131-3 supports DT variables, it just makes a lot more sense to me to use them instead of a big timestamp non-sense number.

The other silly suggestion I have is just to rename DOW and DST to DayOfWeek and DaylightSavings. It makes it easier for beginners.
Quote 1 0
supremesports
As per thiagoralves suggestions, code simplification and few bugs fixed in the original date and time management. Also added the leap year management directly into the MonthDays[1..12] array, otherwise it was causing issues on the February 29th of a leap year.

Also, as promised, I included the SunClock as a function block for the benefit of everyone. I spent many hours/days to get it working properly because of PLCOpenEditor being very picky about variable types (can't work with different types in a same equation). It was still a nice challenge and I'm happy to provide it to you; I really hope it will help someone...

For the SunClock, inside the function block, there's few constants to set such as timezone, latitude and longitude of your specific location. I picked a small town in Quebec, Canada to test it and compared to a simple google search of current sunset, sunrise, etc. and it is mostly within a minute of difference. Two reasons to this:
1 - Google search doesn't know the exact location of the computer when making a search for this type of information and approximate up to 60 miles (100km) around. In either direction, it impacts the solar time of day
2 - The formula used is a simple version of the real which is very complicated to implement in this type of controller and it would be over killed as we don't want to send a rocket in space, don't we?
2a - Exact formula, good luck : https://www.nrel.gov/docs/fy08osti/34302.pdf.
2b - If you want to trigger some events in regard to sun (e.g.: turn ON a light at sunset), it will work perfectly. If you want to use it as a sun tracker for solar panels, this is NOT the algorithm you need.

As you can see from below image in the Radzio modbus nodes
10-12 Date : 2018/11/3
13-15 Time : 22h49m15s
16 So I was also getting 2249 as military time
17 We're Saturday, so day of week is 6,
18 The 1 is for DST active (consequently, it will turn to zero in few hours)
19 The 0 is for leap year (would be 1 if it we were in a leap year).

SunClock information as per the little town north in Quebec, Canada
20 Dawn time : 7h06
21 Sunrise time : 7h39
22 Solar noon time : 12h32
23 Sunset time : 17h26
24 Dusk time : 17h59
25 Solar midnight time : 00h32

TestRTC3.jpg
Quote 2 0
tim292stro
Interesting, I had adapted some code for AutoIt to do something like this based on code from NOAA.  Later I converted it from AutoIt to Perl as I moved my building/home automation to Linux from Windows Server.

Do you have registers in your code that can pull out the azimuth and elevation of the sun relative to you?  I use this data for setting the open angle of blinds so that direct sunlight doesn't over heat a room.

Questions:
  • Would you find any utility in outputting the sun's position?
  • What algorithm are you using for determining dawn/dusk?
  • Are you outputting edges (digital IO) only or time values?
For my tool chain, I latched on to "legal" definitions (as in, defined by U.S. Law) like: sunset and sunrise like you did, but I also used the other terms: Noon Transit, Midnight Transit, Civil Twilight, Nautical Twilight, Astronomical Twilight.  For each of the events, not only is a time value available for each step, I generate a fraction of the period so that I can tie into dimmers or color mixers with an algorithmically derived value.

For example the duration between sunset and the end of civil twilight causes a ramp from 0-100% on my outdoor lighting dimmers, with a roof mounted analog ambient light detector as an override (~>500lux=0%, ~5lux=100%).  This system also accounts for early weather related darkness, with a clock based backup for liability coverage.
Quote 0 0
PLCMercenary
The OSCAT library for Codesys, which is a free IEC61131-3 hardware independent IDE and runtime.. however its made by 3S and it has some things that are non-free. anyway OSCAT library its open source, its implemented in IEC61131-3 LAD or ST. There is a HUGE section of date and time functions, including sunrise, sunset, daylight hours per day, lunar cycles, azimuth. heliocentric alignment offsets. all that fun stuff. I would give that a look if there are functions that you need. They  might even import with minimal modification. 

@thiagoralves This is a good move to get added.. Accurate time is critically important to many network and data store and forward security protocols. If using amazon AWS IOT, a full second differential in expected packet headers will start throwing out connection alerts 
Quote 0 0
thiagoralves
This is very good to know! I’ll take a look at OSCAT and try to integrate the library on OpenPLC
Quote 0 0