Not able to understand this S7-code

drspanda

Member
Join Date
Oct 2005
Location
Damanjodi
Posts
155
Dear S7 Experts,

After several attempts I have come to conclusion that I should seek your help...The below is the stl source code.

FC311 calls FC1008 and DB900 is the data block which is passed into FC1008..

I am not able to intrepret the code and the data movement/manuplation in the DB900...and also I am not getting the concept why the programmer is using SLD3 for multiplication by 8.

Advance thanks.


FUNCTION FC 311 : VOID
TITLE =Pusher
VERSION : 0.1


VAR_TEMP
sp_push_time_int : REAL ;
table : ARRAY [0 .. 19 ] OF REAL ;
END_VAR
BEGIN
NETWORK
TITLE =Pusher-Speed_ convert time to valve position (lookUpTable)


A M 0.1;
= L 84.0;
BLD 103;
CALL FC 1008 (
Table := DB 900,
Input := MD 1652,
low := 7.500000e+001,
high := 2.100000e+002,
invert := L 84.0,
output := MD 1644);
NOP 0;
END_FUNCTION


DATA_BLOCK DB 900
TITLE =
VERSION : 0.1



STRUCT
POS_0 : REAL := 7.500000e+001;
POS_05 : REAL := 7.600000e+001;
POS_10 : REAL := 7.700000e+001;
POS_15 : REAL := 7.800000e+001;
POS_20 : REAL := 7.900000e+001;
POS_25 : REAL := 8.100000e+001;
POS_30 : REAL := 8.500000e+001;
POS_35 : REAL := 9.000000e+001;
POS_40 : REAL := 9.900000e+001;
POS_45 : REAL := 1.290000e+002;
POS_50 : REAL := 1.500000e+002;
POS_55 : REAL := 1.800000e+002;
POS_60 : REAL := 2.100000e+002;
POS_65 : REAL := 2.100000e+002;
POS_70 : REAL := 2.100000e+002;
POS_75 : REAL := 2.100000e+002;
POS_80 : REAL := 2.100000e+002;
POS_85 : REAL := 2.100000e+002;
POS_90 : REAL := 2.000000e+003;
POS_95 : REAL := 2.100000e+003;
POS_100 : REAL := 2.100000e+002;
END_STRUCT ;
BEGIN
POS_0 := 7.500000e+001;
POS_05 := 7.600000e+001;
POS_10 := 7.700000e+001;
POS_15 := 7.800000e+001;
POS_20 := 7.900000e+001;
POS_25 := 8.100000e+001;
POS_30 := 8.500000e+001;
POS_35 := 9.000000e+001;
POS_40 := 9.900000e+001;
POS_45 := 1.290000e+002;
POS_50 := 1.500000e+002;
POS_55 := 1.800000e+002;
POS_60 := 2.100000e+002;
POS_65 := 2.100000e+002;
POS_70 := 2.100000e+002;
POS_75 := 2.100000e+002;
POS_80 := 2.100000e+002;
POS_85 := 2.100000e+002;
POS_90 := 2.100000e+002;
POS_95 := 2.100000e+002;
POS_100 := 2.100000e+002;
END_DATA_BLOCK


FUNCTION FC 1008 : VOID
TITLE =
VERSION : 0.1



VAR_INPUT
Table : BLOCK_DB ;
Input : REAL ;
low : REAL ;
high : REAL ;
invert : BOOL ;
END_VAR
VAR_OUTPUT
output : REAL ;
END_VAR
VAR_TEMP
index : INT ;
pointer_min : DINT ;
pointer_max : DINT ;
min : REAL ;
max : REAL ;
input_int : REAL ;
dummy : REAL ;
END_VAR
BEGIN
NETWORK
TITLE =limit imput value


A M 0.1;
= L 26.0;
A L 26.0;
JNB _001;
L #Input;
T #input_int;
_001: NOP 0;
A L 26.0;
A( ;
L #Input;
L #high;
>R ;
) ;
JNB _002;
L #high;
T #input_int;
_002: NOP 0;
A L 26.0;
A( ;
L #Input;
L #low;
<R ;
) ;
JNB _003;
L #low;
T #input_int;
_003: NOP 0;
NETWORK
TITLE =


OPN #Table;

NETWORK
TITLE =
//5*(index-((max-input)/(max-min)))
L 1; //start index
T #index;


loop: L #index; //create pointer
L 4;
*I ;
SLD 3;
T #pointer_max;


L #index; //create pointer+1
L 1;
-I ;
L 4;
*I ;
SLD 3;
T #pointer_min;



//compare
L #input_int;
L DBD [#pointer_max];
<=R ;
JCN inc;


//calc
L DBD [#pointer_max];
L DBD [#pointer_min];
-R ;
L 1.000000e-009; // no div by 0
+R ;
T #dummy;


L DBD [#pointer_max];
L #input_int;
-R ;
L #dummy;
/R ;


L #index;
ITD ;
DTR ;
TAK ;
-R ;
L 5.000000e+000;
*R ;
T #output;
JU end;


inc: L #index;
L 1;
+I ;
T #index;
JU loop;


end: NOP 0;



NETWORK
TITLE =invert output


A #invert;
JCN end1;
L 1.000000e+002;
L #output;
-R ;
T #output;
end1: NOP 0;
END_FUNCTION




 
'also I am not getting the concept why the programmer is using SLD3 for multiplication by 8.'

This is OK if you are confident the result will not overflow.

Its to do with binary.

Shift Left 1 = Multiply by 2
Shift Left 2 = Multiply by 4
Shift Left 3 = Multiply by 8
Shift Left 4 = Multiply by 16
etc.

Example for 8 bits.

0000 0001 = 1
Shift by 1 = 0000 0010 = 2
Shift by 2 = 0000 0100 = 4
Shift by 3 = 0000 1000 = 8
Shift by 4 = 0001 0000 = 16
etc..



edit: :oops: had to edit the Shift, I had accidently left out the 'f' and the then cut and paste, result loads of **** o_O:D
 
Last edited:
I also don't have S7, so looking at the code is awkward, but just noticed, the SLD3 is not multiplying by 8, but setting up a pointer. (Should have guessed really).

Pointer format, 32 bits

mmmm mmmm 0000 0bbb bbbb bbbb bxxx

where:

m = code for data type
0 = not used
b = byte address
x = bit address

so the SLD3 is moving the byte address over to the correct area of the double word.
 
From this point:

Code:
 [color=black]NETWORK
  TITLE =
  //5*(index-((max-input)/(max-min)))
  L 1; //start index
  T #index;
[/color]

Presets index to 1.

Code:
 [color=black]loop: L #index; //create pointer
  L 4; 
  *I ; 
  SLD 3; 
  T #pointer_max;

the loop: part indicates he jumps back to here (as opposed to a LOOP instruction)[/color]

On the first run index =1, therefore 1 * 4 = 4, shift left 3 and stores at pointer max., this will point to byte 4.

Code:
 [color=black]L #index; //create pointer+1
  L 1; 
  -I ; 
  L 4; 
  *I ; 
  SLD 3; 
  T #pointer_min;

Index = 1, therefore 1-1 = 0, 0*4 = 0, after shifting will point to byte 0.

[/color]
Code:
 [color=black]//compare
  L #input_int; 
  L DBD [#pointer_max]; 
  <=R ; 
  JCN inc;

This is comparing the input against DBD4[/color]

If the input is NOT less than or equal to DBD4, it will jump to label inc.

Code:
 [color=black]//calc
  L DBD [#pointer_max]; 
  L DBD [#pointer_min]; 
  -R ; 
  L 1.000000e-009; // no div by 0
  +R ; 
  T #dummy; [/color]
  
  [color=black]L DBD [#pointer_max]; 
  L #input_int; 
  -R ; 
  L #dummy; 
  /R ; [/color]
  [color=black]
[/color]

Subtract DBD0 from DBD4 and adds 1 (edit: sorry not 1, but a very small number) (=dummy), he then subtracts the INPUT from DBD4 and divides by the dummy value.

Code:
 [color=black]L #index; 
  ITD ; 
  DTR ; 
  TAK ; 
  -R ; 
  L 5.000000e+000; 
  *R ; 
  T #output; 
  JU end;[/color]
 
   [color=black]
[/color]

Then he takes the INDEX value and converts from Integer to Double Integer (ITD), then from Double Integer to real (DTR).

TAK swaps the ACCU’s around, so the modified INDEX goes to ACCU2 and the previous calc value returns to ACCU 1.

He then subtracts the index value from the previous calc and multiples by 0.5.

Then transfers it to the output.

Had he jumped to inc after the earlier compare, he increments INDEX and goes back to loop.

There’s a little bit at the end where he inverts the output if required.


I don’t know if I missed it but it looks as if it could go in an eternal loop! If the comparison never allows the program to flow through.
 
Last edited:
Am I missing simple thing?

Dear PeterW,

I am not able to understand why on the first scan #pointer_max contains/refers to the location DBD4?
#pointer_max should contain 32 and L DBD [#pointer_max] should refer to DBD32...Why it is not so here??

OPN #Table //Data Block
L #index //index =1 on first instance.
L 4
*I
SLD 3
T #pointer_max

Am I missing a simple thing?
 
PeterW said:
I also don't have S7, so looking at the code is awkward, but just noticed, the SLD3 is not multiplying by 8, but setting up a pointer. (Should have guessed really).

Pointer format, 32 bits

mmmm mmmm 0000 0bbb bbbb bbbb bxxx

where:

m = code for data type
0 = not used
b = byte address
x = bit address

so the SLD3 is moving the byte address over to the correct area of the double word.


To answer your question, re-look at this.

The SDL3 is NOT multiplying by 8.

The SLD3 is moving the Number, in the first case 4, to match up with the byte address.

4 = 100 in binary, after SLD3 it = 100000, now match this to the pointer format.

mmmm mmmm 0000 0bbb bbbb bbbb bxxx
0000 0000 0000 0000 0000 0010 0000

Taking just the b's which is the byte address

bbb bbbb bbbb b
000 0000 0010 0

this = byte 4.
 
Thank You Very Much

Dear PeterW,

Thank you very much...now I have understood the concept...

L 4.000000e+000
T DB1.DBD 24

//In this case the 4.0 will be transferred to DB1.DBD 24
//open DB1
OPN DB1
// load decimal 36
L 36
// multiply with 8
SLD 3
// Transfer the result 8x8=64 to MD30.
T MD 30
// Load real number 10.8
L 1.080000e+001
// Transfer to already opened DB1 at memory byte
// location specified by the pointer MD30
T DBD [MD 30]
So When we use square brackets then compiler treats MD30 as a pointer not its value, which is 64....Binary equivalent of 64 is taken and from that, using rules of pointer addressing its value is obtained to be 36.

And finally 10.8 is transferred to DB1.DBD36
 
better late than never...

drspanda said:
SLD 3
// Transfer the result 8x8=64 to MD30.
T MD 30
// Load real number 10.8
L 1.080000e+001
// Transfer to already opened DB1 at memory byte
// location specified by the pointer MD30
T DBD [MD 30]
So When we use square brackets then compiler treats MD30 as a pointer not its value, which is 64....Binary equivalent of 64 is taken and from that, using rules of pointer addressing its value is obtained to be 36.

And finally 10.8 is transferred to DB1.DBD36

I have made a mistake and today when I am refering to my own thread feel to correct it....
SLD 3
// Transfer the result 36x8=288 to MD30.
T MD 30
// Load real number 10.8
L 1.080000e+001
// Transfer to already opened DB1 at memory byte
// location specified by the pointer MD30
T DBD [MD 30]
So When we use square brackets then compiler treats MD30 as a pointer not its value, which is 288....Binary equivalent of 288 is taken [0001_0010_0000]and from that, using rules of pointer addressing its value is obtained to be [0001_0010_0] or simply [100100]....is equivalent to 36.

And finally 10.8 is transferred to DB1.DBD36
 

Similar Topics

Hello, Can any one help me about hot use BSL and BSR in Slc 500. After configuring how to use it to distinguish different products in an assembly...
Replies
3
Views
4,384
I am calling FC4 through which I am just monitoring the input, which if persists for more then 10seconds continuously, will make the output high...
Replies
17
Views
5,116
Dear Experts, I am using Simovert Masterdrive 6ES77032-1EG60-Z connected to S7-400 through CBP2 card 6ES7090-0XX84-0FF5. The problem is I am not...
Replies
2
Views
4,744
I am running CCW 13 trying to upload to a micro 820 vers.12 I get an output message OPC server is unable to load project controller. Please help!
Replies
1
Views
107
Hello, I am still new to PLC programming and I just got this job two year out of school so I don’t remember much. I was given a task were I have...
Replies
1
Views
162
Back
Top Bottom