S7-300 Date Time

smakdown61

Member
Join Date
Aug 2009
Location
NC
Posts
90
I'm attempting to call the date time function so I can clear my runtime counts at certain shift times. I've attached what my code looks like when I call the date time and convert to integer. The second picture is what ends up in the DB.

When I took these pictures it was 2:50PM. The numbers seem to be going to the wrong spots in the DB...

Date_Time.jpg Date_Time2.JPG
 
Nope - the numbers you are loading from the local data area are being transferred to the DB. This snippet of code needs to be thrown in the bin - you should not refer to the absolute address of a local data variable.
 
Nope - the numbers you are loading from the local data area are being transferred to the DB. This snippet of code needs to be thrown in the bin - you should not refer to the absolute address of a local data variable.

Hmm. Actually found this example on this forum if I remember right lol. What would be a better way to code this?
 
Post your source code instead of the screen image. We will be able to see what is wrong and can then correct it.
 
FUNCTION FC 28 : VOID
TITLE =
VERSION : 0.1


VAR_TEMP
Return : INT ;
ReadCurrentTime : DATE_AND_TIME ;
Minute_Decimal : REAL ;
Runtime_Real : REAL ;
OEE_Temp : REAL ;
END_VAR
BEGIN
NETWORK
TITLE =

CALL SFC 1 (//Call SFC 1, "Read System Clock"
RET_VAL := #Return,
CDT := #ReadCurrentTime);


//***************************
//Load each byte of #ReadCurrentTime and transfer
//them to data bytes. This wouldn't be
//absolutely necessary, but it's nice to go online
//with the block and see what the current time is.
//Use the Siemens Help to see the "Date and Time"
//format to see why I have to SLW12 and SRW12 on LB7.
//***************************
L LB 0;
BTI ;
T DB501.DBW 0;
L LB 1;
BTI ;
T DB501.DBW 2;
L LB 2;
BTI ;
T DB501.DBW 4;
L LB 3;
BTI ;
T DB501.DBW 6;
L LB 4;
BTI ;
T DB501.DBW 8;
L LB 5;
BTI ;
T DB501.DBW 10;
L LB 6;
BTI ;
T DB501.DBW 12;
L LB 7;
SLW 12;
SRW 12;
T DB501.DBW 14;


//***************************
//Siemens uses the BCD format in the Date And Time,
//so I have to use the BTI instruction to convert
//it to an integer. In this section, I check to see
//if it is 600 hours (6AM) OR 1800 hours (6PM) . If it is not, then I don't jump
//to label "rst", and I end the block.
//***************************


NETWORK
TITLE =

A( ;
A( ;
L DB501.DBW 6;
L 6;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 0;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 0;
==I ;
) ;
O ;
A( ;
L DB501.DBW 6;
L 18;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 0;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 0;
==I ;
) ;
) ;
AN DB501.DBX 16.0;
JC RST;
NETWORK
TITLE =

RST: A( ;
A( ;
A( ;
L DB502.DBW 2;
T DB502.DBD 4;
SET ;
SAVE ;
CLR ;
A BR;
) ;
JNB _001;
L DB502.DBW 0;
T DB502.DBD 8;
SET ;
SAVE ;
CLR ;
_001: A BR;
) ;
JNB _002;
L 6.000000e+001;
L DB502.DBD 4;
/R ;
T #Minute_Decimal;
AN OV;
SAVE ;
CLR ;
_002: A BR;
) ;
JNB _003;
L #Minute_Decimal;
L DB502.DBD 8;
+R ;
T #Runtime_Real;
AN OV;
SAVE ;
CLR ;
_003: A BR;
JC RST1;
NETWORK
TITLE =ResetComplete

RST1: A( ;
A( ;
A( ;
A( ;
A( ;
L #Runtime_Real;
L 1.200000e+001;
/R ;
T #OEE_Temp;
AN OV;
SAVE ;
CLR ;
A BR;
) ;
JNB _004;
L #OEE_Temp;
L 1.000000e+002;
*R ;
T DB500.DBD 164;
AN OV;
SAVE ;
CLR ;
_004: A BR;
) ;
JNB _005;
L DB502.DBW 0;
T DB500.DBW 28;
SET ;
SAVE ;
CLR ;
_005: A BR;
) ;
JNB _006;
L DB502.DBW 2;
T DB500.DBW 30;
SET ;
SAVE ;
CLR ;
_006: A BR;
) ;
JNB _007;
L 0;
T DB502.DBW 0;
SET ;
SAVE ;
CLR ;
_007: A BR;
) ;
JNB _008;
L 0;
T DB502.DBW 2;
SET ;
SAVE ;
CLR ;
_008: A BR;
= DB501.DBX 16.0;
END_FUNCTION
 
Good job - as expected all is obvious now you have posted the code. The code was written assuming the ReadCurrentTime variable was the first declaration in the temp data area, hence the accesses to LB 0 for the year, LB1 for the month etc.
Wherever you got this code from didn't highlight the fact that you either had to declare ReadCurrentTime as the first temp variable, or, if you declared it elsewhere then you needed to change the LB addresses to match your declaration entry. In your example, ReadCurrentTime starts at LB2 so all the LB addresses need to be adjusted by +2 to work correctly.
As you can imagine, there must be a better way than having to manually keep track of the address of the local variable....

Of course you could simply swap the entries in the temp area and make ReadCurrentTime the first entry - all will be happy but I'm sure you would prefer a method that isn't so cumbersome.

Before giving you the alternative please confirm that you understand what is going here....

fc28.JPG
 
Last edited:
Here's one alternative using statement list and an address register to access the separate bytes of the date and time.
I've chopped down your FC to just show the relevant processing.

Code:
FUNCTION FC 280 : VOID
TITLE =
VERSION : 0.1

VAR_TEMP
  Return : INT ; 
  ReadCurrentTime : DATE_AND_TIME ; 
  Minute_Decimal : REAL ; 
  Runtime_Real : REAL ; 
  OEE_Temp : REAL ; 
END_VAR
BEGIN
NETWORK
TITLE =
      CALL SFC    1 (//Call SFC 1, "Read System Clock"
           RET_VAL                  := #Return,
           CDT                      := #ReadCurrentTime);
//..
//To access the individual bytes of the ReadCurrentTime variable we use an address register.
//Using an address register allows you to point the address register at the base address of an area
//and then access data at given offsets within that area.
//The offset is specified in pointer format, P#1.0 means offset by 1 byte
//(P#0.1 means offset by one bit)
//..
//Using the address register to point to the address of a named variable means that you do not have to
//be concerned about absolute address of the named variable - you are free to modify the temp area by adding
//or removing variables - S7 automatically ensures that the correct address is generated
//..
//
      LAR1  P##ReadCurrentTime; //address register 1 (AR1) points to the base address of Readcurrenttime
      L     B [AR1,P#0.0]; //Year at byte offset 0
      BTI   ; 
      T     DB501.DBW    0; 
      L     B [AR1,P#1.0]; //Month at byte offset 1
      BTI   ; 
      T     DB501.DBW    2; 
      L     B [AR1,P#2.0]; //Day at byte offset 2
      BTI   ; 
      T     DB501.DBW    4; 
      L     B [AR1,P#3.0]; //Hour at byte offset 3
      BTI   ; 
      T     DB501.DBW    6; 
      L     B [AR1,P#4.0]; //Minute at byte offset 4
      BTI   ; 
      T     DB501.DBW    8; 
      L     B [AR1,P#5.0]; //etc
      BTI   ; 
      T     DB501.DBW   10; 
      L     B [AR1,P#6.0]; //etc
      BTI   ; 
      T     DB501.DBW   12; 
      L     B [AR1,P#7.0]; 
      SLW   12; 
      SRW   12; 
      T     DB501.DBW   14; 
END_FUNCTION
 
Another alternative is to write a small FC that allows you to access data which is offset from a base address. You can then use this function and keep the main processing in ladder.

fc281.JPG
 
So the date and time seem to be working now which is great. In my code, I'm basically looking for a specific time to occur in which I want to jump to the next label and move my runtime data to the historian block, then clear runtime data. I have tried changing the time its looking for many times now but it doesn't seem to be executing the steps in the networks following the date/time network. Code:

UNCTION FC 28 : VOID
TITLE =
VERSION : 0.1


VAR_TEMP
Return : INT ;
ReadCurrentTime : DATE_AND_TIME ;
Minute_Decimal : REAL ;
Runtime_Real : REAL ;
OEE_Temp : REAL ;
END_VAR
BEGIN
NETWORK
TITLE =

CALL SFC 1 (//Call SFC 1, "Read System Clock"
RET_VAL := #Return,
CDT := #ReadCurrentTime);


//***************************
//Load each byte of #ReadCurrentTime and transfer
//them to data bytes. This wouldn't be
//absolutely necessary, but it's nice to go online
//with the block and see what the current time is.
//Use the Siemens Help to see the "Date and Time"
//format to see why I have to SLW12 and SRW12 on LB7.
//***************************
L LB 2;
BTI ;
T DB501.DBW 0;
L LB 3;
BTI ;
T DB501.DBW 2;
L LB 4;
BTI ;
T DB501.DBW 4;
L LB 5;
BTI ;
T DB501.DBW 6;
L LB 6;
BTI ;
T DB501.DBW 8;
L LB 7;
BTI ;
T DB501.DBW 10;
L LB 8;
BTI ;
T DB501.DBW 12;
L LB 9;
SLW 12;
SRW 12;
T DB501.DBW 14;


//***************************
//Siemens uses the BCD format in the Date And Time,
//so I have to use the BTI instruction to convert
//it to an integer. In this section, I check to see
//if it is 600 hours (6AM) OR 1800 hours (6PM) . If it is not, then I don't jump
//to label "rst", and I end the block.
//***************************


NETWORK
TITLE =

A( ;
A( ;
L DB501.DBW 6;
L 9;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 5;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 0;
==I ;
) ;
O ;
A( ;
L DB501.DBW 6;
L 18;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 0;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 0;
==I ;
) ;
) ;
AN DB501.DBX 16.0;
JC RST;
BEU ;
NETWORK
TITLE =

RST: A( ;
A( ;
A( ;
L DB502.DBW 2;
T DB502.DBD 4;
SET ;
SAVE ;
CLR ;
A BR;
) ;
JNB _001;
L DB502.DBW 0;
T DB502.DBD 8;
SET ;
SAVE ;
CLR ;
_001: A BR;
) ;
JNB _002;
L 6.000000e+001;
L DB502.DBD 4;
/R ;
T #Minute_Decimal;
AN OV;
SAVE ;
CLR ;
_002: A BR;
) ;
JNB _003;
L #Minute_Decimal;
L DB502.DBD 8;
+R ;
T #Runtime_Real;
AN OV;
SAVE ;
CLR ;
_003: A BR;
JC RST1;
NETWORK
TITLE =ResetComplete

RST1: A( ;
A( ;
A( ;
A( ;
A( ;
L #Runtime_Real;
L 1.200000e+001;
/R ;
T #OEE_Temp;
AN OV;
SAVE ;
CLR ;
A BR;
) ;
JNB _004;
L #OEE_Temp;
L 1.000000e+002;
*R ;
T DB500.DBD 164;
AN OV;
SAVE ;
CLR ;
_004: A BR;
) ;
JNB _005;
L DB502.DBW 0;
T DB500.DBW 28;
SET ;
SAVE ;
CLR ;
_005: A BR;
) ;
JNB _006;
L DB502.DBW 2;
T DB500.DBW 30;
SET ;
SAVE ;
CLR ;
_006: A BR;
) ;
JNB _007;
L 0;
T DB502.DBW 0;
SET ;
SAVE ;
CLR ;
_007: A BR;
) ;
JNB _008;
L 0;
T DB502.DBW 2;
SET ;
SAVE ;
CLR ;
_008: A BR;
= DB501.DBX 16.0;
END_FUNCTION
 
Have you looked at the implementation I posted to your previous query ?

http://www.plctalk.net/qanda/showthread.php?t=56185&highlight=FC8

Yeah that's definitely a viable option, however I think I am close to getting the original method to work. I noticed on network 3, the program is getting stuck at the divide real function (see in pic). Thats keeping the rest of the rung and the rung below from executing. Here is the latest source code:

FUNCTION FC 28 : VOID
TITLE =
VERSION : 0.1


VAR_TEMP
Return : INT ;
ReadCurrentTime : DATE_AND_TIME ;
Minute_Decimal : REAL ;
Runtime_Real : REAL ;
OEE_Temp : REAL ;
END_VAR
BEGIN
NETWORK
TITLE =

CALL SFC 1 (//Call SFC 1, "Read System Clock"
RET_VAL := #Return,
CDT := #ReadCurrentTime);


//***************************
//Load each byte of #ReadCurrentTime and transfer
//them to data bytes. This wouldn't be
//absolutely necessary, but it's nice to go online
//with the block and see what the current time is.
//Use the Siemens Help to see the "Date and Time"
//format to see why I have to SLW12 and SRW12 on LB7.
//***************************
L LB 2;
BTI ;
T DB501.DBW 0;
L LB 3;
BTI ;
T DB501.DBW 2;
L LB 4;
BTI ;
T DB501.DBW 4;
L LB 5;
BTI ;
T DB501.DBW 6;
L LB 6;
BTI ;
T DB501.DBW 8;
L LB 7;
BTI ;
T DB501.DBW 10;
L LB 8;
BTI ;
T DB501.DBW 12;
L LB 9;
SLW 12;
SRW 12;
T DB501.DBW 14;


//***************************
//Siemens uses the BCD format in the Date And Time,
//so I have to use the BTI instruction to convert
//it to an integer. In this section, I check to see
//if it is 600 hours (6AM) OR 1800 hours (6PM) . If it is not, then I don't jump
//to label "rst", and I end the block.
//***************************


NETWORK
TITLE =

A( ;
A( ;
L DB501.DBW 6;
L 10;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 13;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 30;
==I ;
) ;
O ;
A( ;
L DB501.DBW 6;
L 18;
==I ;
) ;
A( ;
L DB501.DBW 8;
L 0;
==I ;
) ;
A( ;
L DB501.DBW 10;
L 0;
==I ;
) ;
) ;
AN DB501.DBX 16.0;
O ;
AN DB501.DBX 16.0;
A M 2.1;
= M 2.1;
NETWORK
TITLE =

A( ;
A( ;
A( ;
A M 2.1;
JNB _001;
L DB502.DBW 2;
T DB502.DBD 4;
SET ;
SAVE ;
CLR ;
_001: A BR;
) ;
JNB _002;
L DB502.DBW 0;
T DB502.DBD 8;
SET ;
SAVE ;
CLR ;
_002: A BR;
) ;
JNB _003;
L DB502.DBD 4;
L 6.000000e+001;
/R ;
T #Minute_Decimal;
AN OV;
SAVE ;
CLR ;
_003: A BR;
) ;
JNB _004;
L #Minute_Decimal;
L DB502.DBD 8;
+R ;
T #Runtime_Real;
AN OV;
SAVE ;
CLR ;
_004: A BR;
= M 2.2;
NETWORK
TITLE =ResetComplete

A( ;
A( ;
A( ;
A( ;
A( ;
A M 2.2;
JNB _005;
L #Runtime_Real;
L 1.200000e+001;
/R ;
T #OEE_Temp;
AN OV;
SAVE ;
CLR ;
_005: A BR;
) ;
JNB _006;
L #OEE_Temp;
L 1.000000e+002;
*R ;
T DB500.DBD 164;
AN OV;
SAVE ;
CLR ;
_006: A BR;
) ;
JNB _007;
L DB502.DBW 0;
T DB500.DBW 28;
SET ;
SAVE ;
CLR ;
_007: A BR;
) ;
JNB _008;
L DB502.DBW 2;
T DB500.DBW 30;
SET ;
SAVE ;
CLR ;
_008: A BR;
) ;
JNB _009;
L 0;
T DB502.DBW 0;
SET ;
SAVE ;
CLR ;
_009: A BR;
) ;
JNB _00a;
L 0;
T DB502.DBW 2;
SET ;
SAVE ;
CLR ;
_00a: A BR;
= DB501.DBX 16.0;
END_FUNCTION

s7_pic1.jpg
 
I was just about to post......

A move of an INT variable to a REAL variable does not convert the int to a real, it copies the 16 bits of the INT variable, fills the top 16 bits with zeros and then copies the resultant 32 bits to the real variable.

To convert an INT to REAL you have to first convert the INT to DINT, then convert DINT to REAL. Use the conversions, not MOVE
 

Similar Topics

I set the Date and Time of the S7 300 PLC equal to that of my PG. But after a few days I found that the date and time were not what they should...
Replies
0
Views
1,916
Hi Guys. Is it possible to read out the automatic calculated PN update time in a S7-300? In most cases we use the "automatic calculated update...
Replies
0
Views
1,257
Ok then guys after a lot of looking around for an answer on this subject i feel very dizzy and amazed it appears so hard to be able to create a...
Replies
18
Views
14,969
Dear All, i want to know how we Date and Time set and Change from HMI MP277 use Wincc Flexible.PLC is S7 300 CPU 315 2-DP.i use SFC0,SFC1 but...
Replies
4
Views
5,714
Hello I have simple home automation made with Siemens S7-300 series. It consist of CPU 315-2 DP, Digital inputs (321),outputs (322), relays and...
Replies
1
Views
2,342
Back
Top Bottom