Copy UDT data to tempory data

It's example of FB in FB. All variables in VAR section are FB type. When I define instance DB2 for FB2, all FB variables are created automatically. Take into accordance: IN, OUT and IN_OUT variables of this FBs present in DB2. This means you must to keep in mind place occupied by it when create HMI tags.
Code:
FUNCTION_BLOCK "MA2DevDrv"
TITLE =
//This function control MA2 devices in accordance with it's commands.
VERSION : 0.1
 
VAR
ConvToPress2 : "DrvBidirectional"; 
ConvFromPress : "DrvBidirectional"; 
ConvOut : "DrvBidirectional"; 
BattConv : "DrvUnidirectional"; 
BattElev : "DrvUnidirectional"; 
BattConv2 : "DrvUnidirectional"; 
CageConv1 : "DrvBidirectional"; 
CageConv2 : "DrvBidirectional"; 
PackPump : "DrvUnidirectional"; 
PackPumpHeat : "DrvUnidirectional"; 
PressPump : "DrvUnidirectional"; 
BattElevBottom : "DrvUpDown"; 
BattSeparator : "DrvUpDown"; 
BattCageFillStop : "DrvUpDown"; 
ConvOutCylinder : "DrvUpDown"; 
END_VAR
BEGIN
NETWORK
TITLE =
//Most of devices of this area are enabled when system is enabled.
	 A	 "SystemEnabled"; 
	 =	 "DeviceEnabled"; 
NETWORK
TITLE =
//Device work with VFD; command to VFD is sended from corresponding DB field.
	 CALL #ConvToPress2 ;
NETWORK
TITLE =
//Device work with VFD; command to VFD is sended from corresponding DB field.
	 CALL #ConvFromPress ;
NETWORK
TITLE =
	 CALL #ConvOut (
		 qRunForw				 := "pqPackConvForw",
		 qRunBack				 := "pqPackConvBack");
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #BattConv (
		 qRun					 := "pqBattenConv");// Q2.2
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #BattElev (
		 qRun					 := "pqBattenElev");
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #BattConv2 (
		 qRun					 := "pqBattenConv2");
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #CageConv1 (
		 qRunForw				 := "pqBattenCageConv1Forw",
		 qRunBack				 := "pqBattenCageConv1Back");
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #CageConv2 (
		 qRunForw				 := "pqBattenCageConv2Forw",
		 qRunBack				 := "pqBattenCageConv2Back");
NETWORK
TITLE =
	 CALL #PackPumpHeat (
		 qRun					 := "pqPackPumpHeater");// Q3.0
NETWORK
TITLE =
//Next devices are enabled always.
	 SET ; 
	 =	 "DeviceEnabled"; 
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #PackPump (
		 qRun					 := "pqPackPump");// Q2.7
NETWORK
TITLE =
//Because device hasn't attached VFD, command qRun is send directly to 
//corresponding peripheral output.
	 CALL #PressPump (
		 qRun					 := "pqPackPressPump");// Q3.1
NETWORK
TITLE =
//Next devices are enabled when system is enabled.
	 A	 "SystemEnabled"; 
	 =	 "DeviceEnabled"; 
NETWORK
TITLE =
	 CALL #BattElevBottom (
		 qRunUp				 := "pqBatElevBottomOpen",// Q5.6 Open
		 qRunDown				 := "pqBatElevBottomClose");// Q5.7 Close
NETWORK
TITLE =
	 CALL #BattSeparator (
		 qRunUp				 := "pqBatSepUp",// Q6.0 Up
		 qRunDown				 := "pqBatSepDown");// Q6.1 Down
NETWORK
TITLE =
	 CALL #BattCageFillStop (
		 qRunUp				 := "pqBatCageFSNarrow",// Q6.2 Narrow
		 qRunDown				 := "pqBatCageFSWider");// Q6.3 Wider
NETWORK
TITLE =
	 CALL #ConvOutCylinder (
		 qRunUp				 := "pqPackConvUp",// Q6.4 Up
		 qRunDown				 := "pqPackConvDown");// Q6.5 Down
END_FUNCTION_BLOCK
 
Stupid question: If I have an UDT inside the temp. area of my FC. Is there a way to make the any pointer in one line/command.

I want to create the ANY pointer without typing absolute values. Because if I add an temp variable there is a change my pointer is wrong.
 
You can't do it in one line, you need something like this.
Code:
...
VAR_TEMP
pSourceDB : ANY ; 
END_VAR
BEGIN
NETWORK
TITLE =any pointer for source
	 LAR1 P##pSourceDB; 
	 L	 W#16#1002; //specify ANY pointer, type 02 = BYTE
	 T	 W [AR1,P#0.0]; 
	 L	 #iNumberOfBytes; //number of bytes to transfer
	 T	 W [AR1,P#2.0]; 
	 L	 DBNO; //data block to use
	 T	 W [AR1,P#4.0]; 
	 L	 DW#16#84000000; //global data block for area pointer
	 L	 #iSourceByteOffset; 
	 SLD 3; 
	 +D	; 
	 T	 D [AR1,P#6.0]; //start of data block
...
 
If someone checks the following, I haven't done it for a while and have no testing facility. I believe its correct though.


Code:
	 L	 P##source_ANY
	 LAR1 
 
	 L	 W#16#1004				 // 10 = S7, 04 = WORD
	 T	 W [AR1,P#0.0]
	 L	 30
	 T	 W [AR1,P#2.0]
	 L	 0
	 T	 W [AR1,P#4.0]
	 L	 P##IN_UDT
	 T	 D [AR1,P#6.0]
 
	 L	 P##Dest_ANY
	 LAR1 
 
	 L	 W#16#1004				 // 10 = S7, 04 = WORD
	 T	 W [AR1,P#0.0]
	 L	 30
	 T	 W [AR1,P#2.0]
	 L	 0
	 T	 W [AR1,P#4.0]
	 L	 P##TEMP_UDT
	 T	 D [AR1,P#6.0]
	 L	 B#16#87
	 T	 B [AR1,P#6.0]			// Change temp area to previous temp area. 
 
	 CALL "BLKMOV"
	 SRCBLK :=#source_ANY
	 RET_VAL:=#Ret
	 DSTBLK :=#Dest_ANY

Can'r remember if the first part needs moving to previous temp area as well.

I remember someone put a neat example of auto calculating the length of a UDT, which can be run from OB100, so you the length could be a variable, which updates if you alter the UDT length.
 
Last edited:
As I said, long time since I did the above. I've remembered another bit of info.

The input parameter I used was a pointer to the first word of the UDT in the DB, not the UDT itself.

Some of the data held in the DB was memory data, so I did a second block move at the end to return the data.

The TEMP address was a UDT, the IN was a POINTER to a DB.DBW, therefore only the TEMP required the data type changed to 'v' Previous TEMP area (B#16#87).

This of course makes the first part wrong. The IN would be #IN_POINTER and a couple of TEMPs created #DB_Address and #DW_Address.

Code:
L		P##IN_POINTER  // Load pointer to IN pointer to AR1
LAR1
 
L	   W [AR1,P#0.0]
T	   #DB_Address   // Get DB Address
 
L	   W [AR1,P#2.0]
T	   #DW_Address   // Get DW Address
 
L	 P##source_ANY  // Set AR1 to source_ANY
LAR1 
 
	 L	 W#16#1004				 // 10 = S7, 04 = WORD
	 T	 W [AR1,P#0.0]
	 L	 30
	 T	 W [AR1,P#2.0]
	 L		#DB_Address  
T	 W [AR1,P#4.0]
	 L		#DW_Address 
T	 D [AR1,P#6.0]
 

Similar Topics

Hello! I am completely new to PLCs, so I apologize in advance if this is a dumb question. I have a device that sends out its data as a number of...
Replies
5
Views
2,140
I have created a UDT (profile) it consists of 59 elements one of which is a string that contains the name of the profile that can be changed via...
Replies
2
Views
3,477
Hello Inside a FB, I´m trying to transfer a string from a DB to a IN_OUT var that was define as a UDT. The problem is that i can´t determine the...
Replies
4
Views
133
The PLC program I'm monitoring has a UDT of alarm booleans. 36 in total. What I'm trying to do is monitor a few rungs, and also monitor a possible...
Replies
3
Views
1,602
I have a separate program running for user security that i need to interface with existing security within my program. All of the external program...
Replies
1
Views
1,156
Back
Top Bottom