S7 code optimizing...

Borte

Member
Join Date
Feb 2004
Location
Norway
Posts
238
Hello guys!

I have a question about efficient plc code.

I have created a simple block for converting a double integer to a string (array of chars not a true string) but I still think the code is inefficient.
I know the code are repeating so I could use a loop insted of rewriting the same code 7 times but I figured that the extra code needed to create the loop would add even more code being executed each scan.

So do anyone in here have any ideas about what I could do to make this more efficient?

Here's the code:
Code:
FUNCTION FC 6 : VOID
TITLE = TestBlock 
STANDARD
VERSION : 1.0


VAR_INPUT
  Integer : DINT ;  
END_VAR
VAR_OUTPUT
  Text : ARRAY  [1 .. 7 ] OF CHAR ; 
END_VAR
VAR_TEMP
  BCD : DWORD ; 
END_VAR
BEGIN
NETWORK
TITLE =

// Create BCD Code
      LAR1  P##BCD; 
      L     #Integer; 
      DTB   ; 
      T     #BCD; 
      LAR1  P##BCD; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#0.0]; 
      L     B#16#F; 
      AD    ; 
      L     B#16#30; 
      OW    ; 
      T     #Text[1]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#1.0]; 
      L     B#16#F0; 
      AD    ; 
      SRW   4; 
      L     B#16#30; 
      OW    ; 
      T     #Text[2]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#1.0]; 
      L     B#16#F; 
      AD    ; 
      L     B#16#30; 
      OW    ; 
      T     #Text[3]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#2.0]; 
      L     B#16#F0; 
      AD    ; 
      SRW   4; 
      L     B#16#30; 
      OW    ; 
      T     #Text[4]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#2.0]; 
      L     B#16#F; 
      AD    ; 
      L     B#16#30; 
      OW    ; 
      T     #Text[5]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#3.0]; 
      L     B#16#F0; 
      AD    ; 
      SRW   4; 
      L     B#16#30; 
      OW    ; 
      T     #Text[6]; 

// Transfer character
      LAR1  P##BCD; 
      L     LB [AR1,P#3.0]; 
      L     B#16#F; 
      AD    ; 
      L     B#16#30; 
      OW    ; 
      T     #Text[7]; 

      SET   ; 
      SAVE  ; 
END_FUNCTION
 
You don't need to do the conversion stuff on each character. You are already working with bytes, so deal with the characters directly. And, since you aren't changing AR1 each time, you only have to do "LAR1 P##BCD" once. For instance:

// Transfer character
LAR1 P##BCD

L #Integer;
DTB ;
T #BCD;

L LB [AR1,P#0.0];
INC 48
T #Text[1];

L LB [AR1,P#1.0];
INC 48
T #Text[2];

L LB [AR1,P#2.0];
INC 48
T #Text[3];

L LB [AR1,P#3.0];
INC 48
T #Text[4];

I didn't test it, but I think it's ok.

edit- I forgot to mention this: If you are always dealing with four characters from a dint, you would be able to condence it further by working directly with 32 bit instructions, but it would be almost as many instructions when you were finished.
 
Last edited:
Note: You really need 11 characters for a DINT whose value is in the range
+2,147,483,647 to -2,147,483,648 The code you have written will therefore only be useful for a limited range of DINT's
 
I didn't catch that he would be using up to seven characters.


Borte, in that case you will have to add a couple of steps. You will have to break up the number into four-byte sections by dividing by 10000 and doing the above operations twice. I've got a printer that prints values between 1 and 50,000,000 and that's what I had to do too.

In any event, it's a good decision to scrap Siemens strings and deal directly with CHARs. It's much simpler.
 
Thanks for the replys...

SimonGoldsworthy you wrote:
Note: You really need 11 characters for a DINT whose value is in the range
+2,147,483,647 to -2,147,483,648 The code you have written will therefore only be useful for a limited range of DINT's
I'm not limited to 7 characters, I can use as many as required. The only thing limiting it is the DTB command
Got this from the STL help:
The BCD number can be in the range of "-9,999,999" to "+9,999,999". If the number is out of the permissible range, then the status bits OV and OS are set to 1.

S7Guy you wrote:
You don't need to do the conversion stuff on each character. You are already working with bytes, so deal with the characters directly. And, since you aren't changing AR1 each time, you only have to do "LAR1 P##BCD" once
Why do I not need to do the conversion on each character? After using the DTB command the byte will contain two characters. Bit 0-3 is the first char and 4 - 7 will the the other one.
I also tried to remove the LAR1... from each section but then it didn't read the bytes. I was not able to figure out why though...

Cheers
Borte
 
Here's my code for converting dints to an array of chars running in a 300/400 series processor. I have only coded this for positive numbers (negative numbers require a bit more thinking about so I've left them out for this post).
Judicial use of the accumulators is all that is required. (I put the number to be converted in MD900 and then monitor the instance DB to test this function, it's not in exactly the same form as Borte original)

Code:
 FUNCTION_BLOCK FB 2
TITLE =
VERSION : 0.1 
 
VAR
X1 : DINT ; 
X2 : DINT ; 
Y1 : DINT ; 
Result : ARRAY [1 .. 11 ] OF CHAR ; 
END_VAR
BEGIN
NETWORK
TITLE =convert positive dint to array of chars with a plus sign
	 L	 MD 900; 
	 T	 #Y1; 
	 L	 #Y1; 
	 L	 L#10000000; 
	 MOD ; 
	 T	 #X1; // 0 to 9,999,999 part
	 L	 #Y1; 
	 TAK ; 
	 -D	; 
	 L	 L#10000000; 
	 /D	; 
	 T	 #X2; // 10's of millions part
NETWORK
TITLE =
	 L	 #X1; 
	 DTB ; 
	 T	 #X1; 
	 PUSH ; 
NETWORK
TITLE =
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[1]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ;
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[2]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[3]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[4]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[5]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[6]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[7]; 
NETWORK
TITLE =
	 L	 #X2; 
	 DTB ; 
	 T	 #X2; 
	 PUSH ; 
NETWORK
TITLE =
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[8]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[9]; 
	 TAK ; 
	 SRD 4; 
	 PUSH ; 
 
	 AD	DW#16#F; 
	 +	 48; 
	 T	 #Result[10]; 
	 TAK ; 
	 SRD 4; 
 
	 L	 '+'; 
	 T	 #Result[11]; 
END_FUNCTION_BLOCK
 
Last edited:
Thanks Simon!

I have used your code to modify my function so it works like a charm now, the only problem is that I don't want leading zeros... Any idea about how to get rid of that?

BTW: Any easy way of converting Real to text? I have been looking at this and found this to be more complex. I know I can use thw standard function for it, but I want to write a more efficient code (more suited for my needs).

Cheers
Borte
 
Last edited:
To remove leading zero's, here's the pseudo code outline. Note that you need to take care if the number is actually zero, what do you want the result to look like ? ('+0' for example)

If Result[10] equals '0' then
Begin
Result[11]:=NULL;
Result[10]:='+';
End
else
Exit

If Result[9] equals '0' then
Begin
Result[10]:=NULL;
Result[9]:='+';
End
else
Exit

...etc

Re-floating point to chars....I'd use the supplied functions !
 
I was hoping that I could just do some thing easy in the code itself insted of doing a compare at the end since this adds a lot of code.

But I guess I have to go the long road....

Thanks again!

Cheers
Borte
 

Similar Topics

First time posting to PLCtalk so be gentle with me. We just got done working on shortening a Mobile Spreader and the company has asked us to look...
Replies
6
Views
2,357
Hi All, Someone at work has put a PLC system on my desk, that's just been taken off an idle production line. He said "It's an S7 PLC. We don't...
Replies
3
Views
80
hello, I'm a student and for my final grade I have to repare a sepro robot. the only problem I have for now is that i have an error code 3...
Replies
0
Views
35
I received an email from a student with the following code attached. This is supposed to control a floodgate system, and supposed to be written...
Replies
23
Views
778
I have a machine which is undergoing upgradation. As part of the process two SEW drives are being replaced., existing Gen B with new Gen C. The...
Replies
3
Views
193
Back
Top Bottom