Complex problem in S7, specialists in STL needed

userxyz

Member
Join Date
May 2002
Location
any
Posts
2,768
Something difficult to explain, but I'll try. I have a data buffer where data enters of 4 serially connected devices. DB130 is my buffer, so far so good, data arrives in ASCII.

I get data every 2 seconds in this buffer of adress 1, 2, 3 and 4.
When adress 1, then DB130 has to be transmitted to DB81
When adress 2, then DB130 has to be transmitted to DB82
When adress 3, then DB130 has to be transmitted to DB83
When adress 4, then DB130 has to be transmitted to DB84

Data transmitting:
Code:
	  L	 DB130.DBB   32
	  L	 B#16#6
	  ==I   
	  FP	#MEMBITS._2
	  JCN   NOC
	  L	 #BOX_ADDR
	  L	 80
	  +I	
	  T	 #DoelDB
	  CALL  FC	30
	   BronDB	  :=#REC_DB
	   BronByte	:=32
	   DoelDB	  :=#DoelDB
	   DoelByte	:=32
	   Lengte_Bytes:=35
	   Fout		:=#DB_DB_FLT
	  L	 0
	  T	 DB130.DBB   32
NOC:  NOP   0

FC30:
Code:
	  L	 P##Bron
	  LAR1  
	  L	 P##Doel
	  LAR2  
	  L	 B#16#10
	  T	 LB [AR1,P#0.0]
	  T	 LB [AR2,P#0.0]
	  L	 B#16#2
	  T	 LB [AR1,P#1.0]
	  T	 LB [AR2,P#1.0]
	  L	 #Lengte_Bytes
	  T	 LW [AR1,P#2.0]
	  T	 LW [AR2,P#2.0]
	  L	 #BronDB
	  T	 LW [AR1,P#4.0]
	  L	 #DoelDB
	  T	 LW [AR2,P#4.0]
	  L	 #BronByte
	  SLD   3
	  L	 DW#16#84000000
	  OD	
	  T	 LD [AR1,P#6.0]
	  L	 #DoelByte
	  SLD   3
	  L	 DW#16#84000000
	  OD	
	  T	 LD [AR2,P#6.0]

	  CALL  SFC   20
	   SRCBLK :=#Bron
	   RET_VAL:=#RET
	   DSTBLK :=#Doel

What's my problem:

In monitor I have seen that DB81 gets data from box 3, so, the data is nog given in a good way from DB130 to DB81, 82, 83 or 84.

Could it be my code ?
 
It appears you send 35 bytes from #REC_DB (you don't show where this is).

The offset that you feel is incorrect is #BOX_ADDR, which should be 1, 2, 3 or 4, you dpon't show where that gets calculated either.

Your setting up of the pointers appear correct.

Is this called from a FB or FC, as changing AR2 could be a problem if you have not saved it first.

Thats by the by though, the problem you say if I am correct, is that BOX_ADDR is not correct, you don't show where this comes from.
 
The only problem that is immediately apparent is that when you add the offset (#BronByte) to the start address your code should use +D and not OD. Using OD will limit the number of the offet you can use and still have the code work as desired. Also, you shouldn't need to us LW or LB or LD because AR1 and AR2 are pointing to the variables in local data already.

Try something like this:

LAR1 P##pSourceDB
L W#16#1002 //ANY pointer, type 02 = BYTE
T W [AR1,P#0.0]
L #iNumberOfByte //number of bytes to transfer
T W [AR1,P#2.0]
L 0
L #iSourceDBNumber
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

Nick
 
k

PeterW said:
It appears you send 35 bytes from #REC_DB (you don't show where this is).

The offset that you feel is incorrect is #BOX_ADDR, which should be 1, 2, 3 or 4, you dpon't show where that gets calculated either.

Your setting up of the pointers appear correct.

Is this called from a FB or FC, as changing AR2 could be a problem if you have not saved it first.

Thats by the by though, the problem you say if I am correct, is that BOX_ADDR is not correct, you don't show where this comes from.

Code:
	  L	 #POLL_Time
	  L	 1000
	  *I	
	  T	 #PT_Time
	  AN	#T_bit
	  =	 #T_IN
	  CALL  SFB	4 , DB4
	   IN:=#T_IN
	   PT:=#PT_Time
	   Q :=#T_bit
	   ET:=
	  A	 #T_bit
	  =	 #REQ

Code:
	  A	 #REQ
	  FP	#MEMBITS._1
	  JCN   _1
	  L	 #BOX_ADDR
	  L	 1
	  +I	
	  T	 #BOX_ADDR
_1:   L	 #BOX_ADDR
	  L	 4
	  >I	
	  JCN   _2
	  L	 1
	  T	 #BOX_ADDR
_2:   NOP   0
 
So if I read this right, every x seconds you increment BOX_ADDR.

You say x seconds is actually set as 2 seconds.

So BOX_ADDR = 1 for 2 seconds, then 2 for 2 seconds, etc until 4, then back to 1.

From your original post, I thought from the following that BOX_ADDR was an offset based on the message contents;

'When adress 1, then DB130 has to be transmitted to DB81
When adress 2, then DB130 has to be transmitted to DB82
When adress 3, then DB130 has to be transmitted to DB83
When adress 4, then DB130 has to be transmitted to DB84'

There appears no control on where the data is put, if the second received message is 8 seconds after the first, it will overwrite the first. Also if two messages are received within a second, then again the first can be overwritten.

Why don't you increment BOX_ADDR before the call to FC30, and rotate around 81 to 84, instead of 1 to 4.
 
PeterW said:
So if I read this right, every x seconds you increment BOX_ADDR.

You say x seconds is actually set as 2 seconds.

So BOX_ADDR = 1 for 2 seconds, then 2 for 2 seconds, etc until 4, then back to 1.

From your original post, I thought from the following that BOX_ADDR was an offset based on the message contents;

'When adress 1, then DB130 has to be transmitted to DB81
When adress 2, then DB130 has to be transmitted to DB82
When adress 3, then DB130 has to be transmitted to DB83
When adress 4, then DB130 has to be transmitted to DB84'
Indeed, I change the adresses in that way, and every time the timer elapsed 2s, the req is 1 cycle high. That's how I ask data of box 1, 2, 3 and 4. The command for the data request is 0581, 0582, 0583 and 0584. I want the received data in DB130 of these boxes automatiacally in DB81, DB82, DB83 and 84.

So, the actual data received in DB130 @ the moment of request box 2 for example, then the data from DB130 must be send to DB82...

There appears no control on where the data is put, if the second received message is 8 seconds after the first, it will overwrite the first. Also if two messages are received within a second, then again the first can be overwritten.

Why don't you increment BOX_ADDR before the call to FC30, and rotate around 81 to 84, instead of 1 to 4.

The data may be overwritten every 8s. That's not the problem for me. These are temperatures that I want to read, slow measurements, but that doesn't matter
What I need is the data of box 1 in DB81, the data of box 2 in DB82, etc..
 
As you only have 4 different fixed destinations, you could simplify the code as follows:

A #trigger
JCN Pass
L #Box_Address
L 1
==I
JC D81 //DB81?
TAK
L 2
==I
JC D82 //DB82?
TAK
L 3
==I
JC D83 //DB83?
TAK
L 4
==I
JC D84 //DB84?
JU pass
D81: CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB81.DBX35.0 BYTE 35
JU pass

D83 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB82.DBX35.0 BYTE 35
JU pass

D83 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB83.DBX35.0 BYTE 35
JU pass

D84 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB84.DBX35.0 BYTE 35

pass: NOP 0

This might make it easier to spot any errors elsewhere in the code.

Nick
 
k

ggg.JPG


The first 3 DBW's containing good data. The rest is data of box 3 ??? It's data from another box.

So, there is a mixup of data,

while the data in DB130 enters correctly every 2s.

here is the project if you wanna take a look @ it:

http://download.yousendit.com/EA0FB7CA3B77AFD4
 
...

looks interesting, this is a bit easier then the any pointer also btw

Manglemender said:
As you only have 4 different fixed destinations, you could simplify the code as follows:

A #trigger
JCN Pass
L #Box_Address
L 1
==I
JC D81 //DB81?
TAK
L 2
==I
JC D82 //DB82?
TAK
L 3
==I
JC D83 //DB83?
TAK
L 4
==I
JC D84 //DB84?
JU pass
D81: CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB81.DBX35.0 BYTE 35
JU pass

D83 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB82.DBX35.0 BYTE 35
JU pass

D83 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB83.DBX35.0 BYTE 35
JU pass

D84 : CALL "BLKMOV"
SRCBLK :=P#DB130.DBX35.0 BYTE 35
RET_VAL:=#ret_val
DSTBLK :=P#DB84.DBX35.0 BYTE 35

pass: NOP 0

This might make it easier to spot any errors elsewhere in the code.

Nick
 
I tried this code, but the result remains,

so the any pointer wasn't the problem


Ow, in case you want to know that the 6 means, when a telegram arrives, it always starts with 6 Hex. In this way I can detect when a telegram arrived, I reset it on zero after the data has been transferred to the DB
 
Manglemender said:
As you only have 4 different fixed destinations, you could simplify the code as follows:

A #trigger
JCN Pass
L #Box_Address
L 1
==I
JC D81 //DB81?
TAK
L 2
==I
JC D82 //DB82?
TAK
L 3
==I
JC D83 //DB83?
TAK
L 4
==I
JC D84 //DB84?
JU pass


This might make it easier to spot any errors elsewhere in the code.

Nick

This jump sequence can be done easier:

check out the JL statement (Jump to Labels) in the Help on STL.

Jeebs
 
hey

I FOUND IT !!!

Code:
	  L	 DB130.DBB   65
	  L	 B#16#3
	  ==I   
	  FP	#MEMBITS._2
	  JCN   NOC
	  L	 #BOX_ADDR
	  L	 1
	  ==I   
	  JC	DB81
	  TAK   
	  L	 2
	  ==I   
	  JC	DB82
	  TAK   
	  L	 3
	  ==I   
	  JC	DB83
	  TAK   
	  L	 4
	  ==I   
	  JC	DB84
	  JU	NOC
DB81: CALL  SFC   20
	   SRCBLK :=P#DB130.DBX32.0 BYTE 35
	   RET_VAL:=#ret
	   DSTBLK :=P#DB81.DBX32.0 BYTE 35
	  JU	zer
DB82: CALL  SFC   20
	   SRCBLK :=P#DB130.DBX32.0 BYTE 35
	   RET_VAL:=#ret
	   DSTBLK :=P#DB82.DBX32.0 BYTE 35
	  JU	zer
DB83: CALL  SFC   20
	   SRCBLK :=P#DB130.DBX32.0 BYTE 35
	   RET_VAL:=#ret
	   DSTBLK :=P#DB83.DBX32.0 BYTE 35
	  JU	zer
DB84: CALL  SFC   20
	   SRCBLK :=P#DB130.DBX32.0 BYTE 35
	   RET_VAL:=#ret
	   DSTBLK :=P#DB84.DBX32.0 BYTE 35
zer:  L	 0
	  T	 DB130.DBB   65

I was checking Byte 32, the first byte of the telegram, but I need to check the last byte (65), when that byte is arrived, then the whole telegram is red in the PLC, then I can transfer the data from DB130 to DB81, 82, etc... not sooner...

So I think I made the mistake by checking the first byte, the CPU is much faster then the communication of 9600 bps.

Thanks all for your help, and I like the blockmov better then the Any Pointer BTW, I don't like it, too complex, don't you think ? Or should I use it in this situation ?
 
You could also do the following :

L #BOX_ADDR // is 1,2,3 or 4
L 80 // add 80
+I
T #temp // contains DB nr to open

OPN DB[#temp]

CALL SFC 20
SRCBLK :=P#DB130.DBX32.0 BYTE 35
RET_VAL:=#ret
DSTBLK :=P#DBX32.0 BYTE 35

Only thing .... make sure values can only be 1,2,3 or 4

Eric
 
okay

Okay

aikona said:
You could also do the following :

L #BOX_ADDR // is 1,2,3 or 4
L 80 // add 80
+I
T #temp // contains DB nr to open

OPN DB[#temp]

CALL SFC 20
SRCBLK :=P#DB130.DBX32.0 BYTE 35
RET_VAL:=#ret
DSTBLK :=P#DBX32.0 BYTE 35

Only thing .... make sure values can only be 1,2,3 or 4

Eric
 

Similar Topics

RSLogix 5000 V24 1756-L72 Trying to figure out the best way to solve this problem. TCF = e ˄ 1100(1/298 - 1/T) Where T = °C + 273.15 TCF...
Replies
16
Views
3,875
Yes it's very legacy.. but sometimes it's necessary to use old stuff for fun.. and because it's so much cheaper. Crimson 3.0 had the ability to...
Replies
4
Views
1,607
Hello all, I am fairly new to programming HMI's and am working with Crimson 3.1 for the first time. I am trying to recreate an annunciator of...
Replies
12
Views
6,356
What application in your experience has demanded the most complex PLC program? I suppose I should clarify what manner "complex" I'm asking about...
Replies
37
Views
12,354
I have this complex code tag that returns as a string variable. For some reason it returns the two strings with a ?? between them -- not the...
Replies
2
Views
3,503
Back
Top Bottom