Data Conversion

aljack
2010-07-13
2012-08-20
  • aljack - 2010-07-13

    My CoDeSys Version: 2.3.9.19

    Is it possible to convert numeric data string into floating point data?Is it possible to convert ASCII data string into binary, decimal or hexadecimal?


    What I tried but doesn't work:
    1-
    Put my value data string variable at the input of STRING_TO_REAL function block converter.
    And then, I get an output variable that I applied to the modbus holding register AT %MW0 : REAL;
    But even the output variable of the funtion block don’t give the same output data as the string number?
    The converter is not appropriate.
    See the results for some of my test:
    STRING TO REAL = Crap data (4649.0304 =to real= 3.459821e-05)
    STRING TO LREAL = Unconfigurable function block
    STRING TO WORD = Data without the decimal value (4649.0304 =to word= 4649)
    STRING TO INT = Data without the decimal value (4649.0304 =to int= 4649)
    For ASCII character = 0 or a none significant number data like 5, 8 …

    2-
    I put my value data string variable directly at the modbus holding register AT %MW0 : REAL;
    But the build program didn’t take it. It ask for variable declaration or wrong syntax errors.

    3-
    Also tried the STRING_TO_ASCIIBYTE function block. The output data isn’t recognizable.


    Tell me at least if it is possible to make any type of data string conversion...

    Thank you very much!

     
  • Anonymous - 2010-07-13

    Originally created by: Bernhard Werner

    Hello aljack,

    I don't understand your problem:

    realvar := STRING_TO_REAL('4649.0304');

    this works fine on my targets. Only the number of digits is a little bit higher than
    REAL-resolution. So the result is 4649.03.

    What plc do you use?
    What exactly is your test code?

    Bernhard

     
  • JAPIB

    JAPIB - 2010-07-13

    Hello.
    J think you can't write this : ;
    %MW0 is a word format (16 bits), and it can be declare AS INT, Word, but not as a REAL.
    To store a REAL you must use a double word (32 bits), %MDxx.

    To convert ASCII, you must have a look to OSCAT library (http://www.oscat.de/). Oscat lbrairies are a real gold mine !

    JAPIB

     
  • Nitrozin - 2010-07-14

    hi,

    for Modbus communication you have to declare global variables
    VAR_GLOBAL
    RealVar1 AT %MW0 : REAL;
    RealVar2 AT %MW2 : REAL;
    END_VAR

    Nitro

     
  • Ralph Holz - 2010-07-14

    Joel Salut,

    c'est intéressant, vous utilisez OSCAT, vous êtes un fan de cette. Bien que la documentation est disponible uniquement en allemand. Je pense qu'il est temps que cette bibliothèque est utile de document dans d'autres langues. Si donc la confiance dans sa langue à se traduire mais s'il vous plaît vous inscrire à OSCAT. Le monde a besoin de cette bibliothèque.

    Salut
    Ralph

    Now for all the others. this was a verry sepcial service to my french friend Joel. But ist is also the request for all those who are able to translate the Oscat-Library-documentation to your own language please do it and send it to OSCAT. The world really needs this library.

    Regards Ralph

     
  • aljack - 2010-07-14

    Bernhard Werner hat geschrieben:
    Hello aljack,
    I don't understand your problem:
    realvar := STRING_TO_REAL('4649.0304');
    this works fine on my targets. Only the number of digits is a little bit higher than
    REAL-resolution. So the result is 4649.03.
    What plc do you use?
    What exactly is your test code?
    Bernhard

    Hello Bernhard,

    My PLC: WAGO 750-843
    My test code is in function block: See my attached program

    So I use specials functions blocks from Wago online library to read the data from my external device (GPS over NMEA183 protocol).
    I'm able to receive, read and see the data from this device and I apply it to the input of a STRING_TO_REAL converter.
    The data is a string 200% sure.
    Everything goes right until the output convertion of the STRING_TO_REAL don't show what it supposed to.
    The data from the device meaning: 46 Degree 49 Minutes 0304 Secondes
    The data string form look like this: 4649.0304
    The input of converter look like: 4649.0304
    The output of the converter: weird blinking and changing none stable data range like this 3.459821e-05 to 529846

    Strangely I apply the same input string to a STRING_TO_WORD converter for test purpose and the ouput data convert correctly all the integer value (4649.0304 --> 4649).

    Could you tell me if it is possible to seperate data from the string sample (4649.0304).
    Then I could make lots of separate conversion in a WORD var!
    Else I must find the trouble into the REAL conversion.

    thank you very much!

    Network_Project_10 07 14 AJ 09h16.pro [57.64 KiB]

     
  • aljack - 2010-07-14

    Nitrozin hat geschrieben:
    hi,
    for Modbus communication you have to declare variables
    VAR_GLOBAL
    RealVar1 AT %MW0 : REAL;
    RealVar2 AT %MW2 : REAL;
    END_VAR
    Nitro

    Hello Nitrozin,

    Yess you are totally right!
    I have already done this kind of link for my Modbus variable.
    But even if this configuration is ok, the output of the converter don't seems to do his job.

    Thank you!

     
  • aljack - 2010-07-14

    JAPIB hat geschrieben:
    Hello.
    J think you can't write this : ;
    %MW0 is a word format (16 bits), and it can be declare AS INT, Word, but not as a REAL.
    To store a REAL you must use a double word (32 bits), %MDxx.
    To convert ASCII, you must have a look to OSCAT library (http://www.oscat.de/). Oscat lbrairies are a real gold mine !
    JAPIB

    Hello JAPIB,

    I'm agree with you for the memory location data lenght, but even if I change the %MW0 for a %MD0 it change anything. The STRING input data is still convert into a weird REAL output.
    Example :
    One of my input STRING data is very simple: 2.0
    The STRING_TO_REAL convertion give an REAL output of: 52 and then 3276852 and then 1.052508e+009
    The output oscillate between these three values?
    Why I don't know?


    About the ASCII convert I will take a look on OSCAT if I want to learn some German even if I'm a french Canadian. Actually I'm ok, I found yesterday a function block call STRING_TO_ASCIIBYTE, this block convert an ASCII character into decimal value.
    Example: W => => => 87 in decimal (see ASCII table on the web)

    You could find this function block in the library of CoDeSys. At Standard.lib/String_Function/STRING_TO_ASCIIBYTE

    Thanks!

     
  • Uwe - 2010-07-15

    Hello aljack,

    i think your problem is a bug inside the firmware of the 843.
    I hope this bug will be solved with the next firmware release.

    Until the next firmware release please try to use the follow workaround

    Try to replace the call of the functionblock NMEA_RECEIVE
    to the last network inside your PLC_PRG and please
    don't ask me why ...
    but i think it works

    Uwe

     
  • aljack - 2010-07-23

    Hello everyone,

    I finally found my problem, about the floating point data string conversion...
    My PLC provider (WAGO) tell me this: Our PLC is only a 32 bit PLC. The HMI may give the same result unless its got a new processor that has 64 bit capabilities. We are releasing a new version of PLC later this year. I will be interested to see if it will have the LREAL variable for 64 bit real vars.

    That's why the String To Real give me crap data!
    So I created a personalised funtion block to make the decimal floating point conversion possible.

    Fist I took all the data seperately and concatenate it into one Integer string value.
    Then I converted the Integer value into a Word value.
    Yes I still don't have my floating point value that's why I created a devisor value to divide the integer value by the divisor when I'll read the data into my HMI (Human Machine Interface).
    The devisor value is automatically refresh with the quanties of number after the dot.

    See what my funtion block programmation look like!:


    FUNCTION_BLOCK GPS_DECIMAL_STRING_TO_INTERGER_WORD

    VAR_INPUT
    sSTRING_IN:STRING;
    END_VAR
    VAR_OUTPUT
    wINTEGER_WORD:WORD;
    wDIVISOR:WORD;
    END_VAR
    VAR
    DOT_POS: WORD;
    STR_LEN:WORD;

    BEFORE_DOT:STRING;
    AFTER_DOT:STRING;
    INTEGER_STRING:STRING;
    INTEGER_WORD:WORD;
    
    VARIABLE:WORD;
    

    END_VAR


    STR_LEN:= LEN(sSTRING_IN);
    ( Store the lenght of the string into STR_LEN variable)

    DOT_POS:= FIND(sSTRING_IN, '.');
    ( Search the position of the ' x ' x character from left to right and send the numeric position into DOT_POS variable )

    BEFORE_DOT:=LEFT(sSTRING_IN, (DOT_POS-1));
    ( Store all the digits before the dot, into the BEFORE_DOT variable)

    AFTER_DOT:=RIGHT(sSTRING_IN, (STR_LEN - DOT_POS));
    ( Store all the digits after the dot, into the AFTER_DOT variable)

    INTEGER_STRING := CONCAT (BEFORE_DOT, AFTER_DOT);
    ( Take the before and after dot value and put them together into one integer string)

    wINTEGER_WORD:= STRING_TO_WORD(INTEGER_STRING);
    ( Convert the integer string into WORD )

    VARIABLE:=(STR_LEN - DOT_POS); (The VARIABLE store the number of zero necessary to create the wDIVISOR output.)
    IF VARIABLE=1 ( The divisor output is use by the HMI user to take the interger data from the register and do a )
    THEN wDIVISOR:=(10); ( mathematical operation to recover the original decimal data. )
    ELSIF VARIABLE=2 ( Here in this case if the VARIABLE = 2 it means the integer number gets 2 number after the dot)
    THEN wDIVISOR:=(100); ( then the user will do the math with the 100 divisor to recover 2 number after the dot. )
    ELSIF VARIABLE=3 ( If the floating point number isn't always the same, the output divisor adjuste automatically)
    THEN wDIVISOR:=(1000); ( until 6 number after the dot. )
    ELSIF VARIABLE=4
    THEN wDIVISOR:=(10000);
    ELSIF VARIABLE=5
    THEN wDIVISOR:=(10000);
    ELSIF VARIABLE=6
    THEN wDIVISOR:=(10000);
    END_IF


    Summary example:
    sSTRING_IN:STRING = 589.251
    DOT_POS: WORD; = 4
    STR_LEN:WORD; = 7
    BEFORE_DOT:STRING; = 589
    AFTER_DOT:STRING; = 251
    INTEGER_STRING:STRING; = 589251
    INTEGER_WORD:WORD; = 589251
    VARIABLE:WORD; = 3
    wINTEGER_WORD:WORD; = 589251
    wDIVISOR:WORD; = 1000

    HMI script: [ wINTEGER_WORD / wDIVISOR ] = [ 589251 / 1000 ] = 589.251

    I send those data to my HMI with modbus so i've put each data into a modbus register like this:
    wINTEGER_WORD:=GLL_LAT_DEG;
    GLL_LAT_DEG AT %MW0:WORD;
    ( This uses %MW0 because it is a WORD value (16bits), MODBUS Holding Reg 12289 or 412289 )
    ///////////////////////////
    So that's it for the convertion hope it help!
    I also found the utilities of string manipulation with function LEN, LEFT, RIGHT, MID, CONCAT, INSERT
    see Codesys Help for more info on this function.

    Thanks everybody to tried help me!

     
  • shooter - 2010-07-27

    i would stay in string or in dword why all this real is needed?
    cut it and put a dot in between. with real conversion you are losing the fine data.

     
  • balajimct - 2012-08-20

    we have written a code to convert the scientific real to normal real with constant number of digits

    If you want the code you can send me email to the below id
    e balajimct@gmail.com e

     
  • shooter - 2012-08-20

    this post is two years old, however if you like to give it to the group i would like it.

     

Log in to post a comment.