S7-300 SCL program convert string DB to real DB

You dont have any error checking. Maybe it is not a problem if an error goes undetected, but if it is a problem I suggest this:
Set the SCL option that the OK flag must be set.
In code, before writing the resultant REAL value, evaluate OK. Something like this:

Code:
IF OK THEN
  err_flag := FALSE ;
  DB_Number_Real.DD[Address_pointer]:=dwReal;
ELSE
  err_flag := TRUE ;
ENDIF ;
This is an error checking that will take care of most possible errors with the STRING_TO_INT.
 
To simplify your code and use the power of SCL, declare your strings and reals as arrays and pass the arrays to the function. If the reals are actually components of a udt, then pass in the UDT instead.

Code:
FUNCTION FC113 : VOID
VAR_IN_OUT
sData: ARRAY[0..299] OF STRING[7];
rData: ARRAY[0..299] OF REAL;
END_VAR
VAR_TEMP
Decimal : INT;
Length:INT;
iRecipe:INT;
Temper_string:STRING[7];
leftstring:STRING[4];
rightstring:STRING[4];
d_factor:REAL;
temper_real:REAL;
END_VAR
BEGIN
temper_string:='';
FOR iRecipe:=0 TO 299 DO
 temper_string:=sData[iRecipe];
 // Find length for string value
 Length := LEN(S:=temper_string);
 Decimal:=FIND(In1:=temper_string,in2:='.');
 IF decimal>0 THEN
  CASE (length-decimal)OF
   1:d_factor:=10.0;
   2:d_factor:=100.0;
   3:d_factor:=1000.0;
   4:d_factor:=10000.0;
  ELSE: d_factor:=1.0;
  END_CASE;
  //always init temp strings before use
  Leftstring:='';
  RightString:='';
  Leftstring:=LEFT(In:=temper_string,l:=(decimal-1));
  rightstring:=RIGHT(in:=temper_string,l:=(length-decimal));
  temper_real:=DINT_TO_REAL(INT_TO_DINT((STRING_TO_INT(in:=rightstring))))/d_factor;
  temper_real:=temper_real+ STRING_TO_INT(in:=leftstring);
 ELSE
  temper_real:=STRING_TO_INT(in:=temper_string);
 END_IF;
 //Write resultant real
 rData[iRecipe]:=temper_real;
END_FOR; 
End_function
 
Thanks L D[AR2,P#0.0] for the code. But I have to transfer the string DB to real DB to array in order to pass the array to the function. This array will use a lot of memory and I have the other functions running in the same project eat quite a lot of memory in PLC already.

I wonder why the last change of the code, I pass the DB into the function it should work, but it turn out something wrong.
 
Thanks L D[AR2,P#0.0] and JesperMP, I find out the problem is the address and correct the code as following it works fine now. Appreciate!

FUNCTION FC112 : VOID
VAR_INPUT

DB_Number_Real : BLOCK_DB;
DB_number_string: BLOCK_DB;

END_VAR

VAR_TEMP
address_pointer:INT;
Decimal : INT;
Length:INT;
i:INT;
Temper_string:STRING[7];
abData AT Temper_string:ARRAY[1..9] OF BYTE;
leftstring:STRING[4];
rightstring:STRING[4];
d_factor:REAL;
temper_real:REAL;
dwReal AT temper_real:DWORD;
END_VAR
BEGIN

FOR address_pointer:=0 TO 299 DO

//copy string from DB to temp variable
FOR i:=1 TO 9 DO
abData:=DB_number_string.DB[address_pointer*8+i-1];
END_FOR;
// Find length for string value
Length := LEN(S:=temper_string);
Decimal:=FIND(In1:=temper_string,in2:='.');

IF decimal>0 THEN

CASE (length-decimal)of
1:d_factor:=10.0;
2:d_factor:=100.0;
3:d_factor:=1000.0;
4:d_factor:=10000.0;
ELSE: d_factor:=1.0;
END_CASE;
//always init temp strings before use
Leftstring:='';
RightString:='';
Leftstring:=LEFT(In:=temper_string,l:=(decimal-1));
rightstring:=RIGHT(in:=temper_string,l:=(length-decimal));

temper_real:=DINT_TO_REAL(INT_TO_DINT((STRING_TO_INT(in:=rightstring))))/d_factor;
temper_real:=temper_real+ STRING_TO_INT(in:=leftstring);
ELSE
temper_real:=STRING_TO_INT(in:=temper_string);
END_IF;
//Write resultant real
DB_Number_Real.DD[Address_pointer*4]:=dwReal;
END_FOR;
END_FUNCTION
 
But I have to transfer the string DB to real DB to array in order to pass the array to the function. This array will use a lot of memory and I have the other functions running in the same project eat quite a lot of memory in PLC already.

The string DB and real DB all ready exist and take up memory. I am suggesting you redeclare them as arrays so you can pass them to the FC.
 
The reason I use DB instead of Array is because the DB can link to tags in HMI which read the USB memory and dump the data through tags to DB. I am not sure if array can do the same job in HMI. At the beginning, I actually write a script in HMI to convert the string to real instead to do in PLC. Unfortunately, HMI has a unsolvable bugs when such a quantity of data converting (3000 data) the compiler of VB script have some nonsense error. The address in DB is writing wrong. So eventually. I have to done this in PLC
 
Now, the function is working fine. But I have 9 string DBs need to convert to real DBs, when I call more than 4 times this function CPU(315 2NP/DP stop because the cycle time exceeded ! Anyone have clue how to fix it?
 
The reason I use DB instead of Array is because the DB can link to tags in HMI which read the USB memory and dump the data through tags to DB. I am not sure if array can do the same job in HMI. At the beginning, I actually write a script in HMI to convert the string to real instead to do in PLC. Unfortunately, HMI has a unsolvable bugs when such a quantity of data converting (3000 data) the compiler of VB script have some nonsense error. The address in DB is writing wrong. So eventually. I have to done this in PLC

So you dont understand data?
 
JesperMP, I find out the problem is the address and correct the code as following it works fine now
The error checking I recommend is to catch when the STRING contains something that cannot fit your xxx.yyy REAL format.
Since you read a text file (on a flash card I presume), you have no guarantee that the STRINGs contain values that can be interpreted as REALs. I think that the STRING_TO_INT simply returns a 0 when it encounters a STRING that cannot be interpreted as a number. Only you can know if a failed conversion would mean a problem for your machine.

I would as a minimum check if the code catches these STRINGs:
'' (i.e. is empty).
'1234.56' (more integer digits than allowed)
'12.3456' (more fraction digits than allowed)
'123.' (no fractional part)
'.123' (no integer part)
'12a.456' (contains other characters)

A sidenote: Getting the code to work is 90% of the work. Getting the code to work reliably is the other 90% of the work.
 
Last edited:
kind of new hand

These are really just anypointers, but compiler makes all the hard stuff for you for pointing to right place.

Code:
VAR_IN_OUT
sData: ARRAY[0..299] OF STRING[7];
rData: ARRAY[0..299] OF REAL;
END_VAR

If you would make datablock where is data MyRealArray[0..299] and input it to rData when calling for fc, if you would now use in your code rData[6] for example, it would really point to MyRealArray[6].

So, it does not take more space. How have you declared your 300 reals and strings in your datablock now?
 
Now, the function is working fine. But I have 9 string DBs need to convert to real DBs, when I call more than 4 times this function CPU(315 2NP/DP stop because the cycle time exceeded ! Anyone have clue how to fix it?

Spread the processing over several scans using a counter for example.
 
Hello,
Im currently trying to accomplish the same thing as Michaelchenca, but my source data is a string stream over RS232, in the format 123.45,123.67,123.89...etc.
Its 12 real values in text format, divided by comma.
My plan was to utilize the same method as Michaelchenca as soon as I have got the source data into a subString[] like this:
subString[1] = 123.45
subString[2] = 123.67
subString[3] = 123.89
...

My problem is that im stuck and cant figure how to split the source data into separate strings.
PS this is my first time using SCL...:whistle:

Code:
FUNCTION_BLOCK FB1331


VAR_INPUT    
    
strINPUT : STRING;                            //read input string from I/O in Format: 123.45,123.67,123.89...
    
    _str AT strINPUT: STRUCT                  //local variable to ref struct.
    length: BYTE;
    act_length: BYTE;
    str: ARRAY [1..254] OF BYTE;
    END_STRUCT;
        
END_VAR


VAR

    tempTable: ARRAY [1..20] OF STRING;         //Array to hold string values
    tempString : STRING;                        //temporary value to store here 
    i : INT;                                    //Position in the tempTable array
    j : INT;                                    //Number of real values
 stop : INT;                                    //ACTUAL length of input String
    X: BYTE;                                    //Current BYTE
 
END_VAR


VAR_OUTPUT
 
//OUTPUT OF REAL VALUES
OUTPUT : ARRAY [1..20] OF REAL;                 //Output of REAL values

END_VAR


BEGIN

///////////TODO/////////////////////////////////
//1 Iterate through string and find 0-9 and '.'
//2 Iterat through string and find ',' indicating new value
////////////////////////////////////////////////


//1 Iterate through string and find 0-9 and '.'

stop := BYTE_TO_INT(_str.act_length);           //Find actual length of string;
FOR i := 1 TO stop DO;
    X := _str.str[i];                           //Catch current Byte to search in
    
    IF ((BYTE_TO_INT(X) > 47 AND BYTE_TO_INT(X) < 58) OR BYTE_TO_INT(X) = 16#2E) THEN//46 = period (16#2E)
        
        //Build temporary string out of findings
        tempString := CONCAT (IN1:= tempString, IN2 := BYTE_TO_CHAR (_str.str[i]));  

//2 Iterat through STRING AND FIND ',' indicating new value. Write to array and increment j

        IF BYTE_TO_INT(X)=16#2C THEN //44 = comma (16#2C)
            
        j:=j+1; //Increment number of comma
                                                                           
        //Move tempString into temporary array
         tempTable[j] := tempString;
         //Clear tempString
         tempString:='';
         
                //Reset array position if End of String  
                IF i=stop THEN
                j:=0;
                END_IF;       
         END_IF; 
     END_IF;
END_FOR;





END_FUNCTION_BLOCK
 
Last edited:

Similar Topics

I feel like I'm going crazy, new to Siemens, coming from AB, and I cannot get a dang string copied in SCL. This is a S7-300, V16 PLC. I have a...
Replies
10
Views
3,501
How to realize transformation functions : 1/s and 1/(1+s) into SCL inside S7-300
Replies
0
Views
944
Hi. I tryid to make a shiftregister with 31 entry's. the string array are declared in the Static area of the FB. When I run the code its not...
Replies
1
Views
1,280
Looking for some help with an array of strings in SCL. I have an array of 99 string[98] I also have an array of 99 INT My first 4 chars of the...
Replies
9
Views
2,448
I am trying to take several individual CHAR bytes and turn them into a string. The CHAR bytes are located in a DB. I am trying to figure out the...
Replies
4
Views
3,502
Back
Top Bottom