How to put four bytes into a DWORD

fabiospark
2008-02-29
2013-01-12
  • fabiospark - 2008-02-29

    With a Wago ethernet PLC (750 841) and an RS485 interface, I'm reading values from a modbus register of an instrument through the Modbus master function I found in the Wago application notes.

    The value I'm reading is a 32 bit type (two words, four bytes) and it is sent back in a four bytes array as follows:

    Array[1] = MSB (word 1)

    Array[2] = LSB (word 1)

    Array[3] = MSB (word 2)

    Array[4] = LSB (word 2)

    My questions are, with Codesys:

    a) how can I put the four bytes array into a single DWORD?

    b) will I have to use a type conversion (can't see an "array to dword" one) or to write some lines of code?

    c) is there a simpler way that, in my noobieness, I can't see but it's there?

    Thanks.

     

    Related

    Talk.ru: 1
    Talk.ru: 2
    Talk.ru: 3

  • ndzied1 - 2008-03-01

    I usually do this kind of thing with overlapping marker addresses (I'm pretty sure Wago supports marker addressing).

    The idea is to define multiple things at the same address. If you know anything about C programming it is like a union.

    So, if you have to swap hi, low I would do the following:

    B0 AT %MB0: BYTE;
    B1 AT %MB1: BYTE;
    B2 AT %MB2: BYTE;
    B3 AT %MB3: BYTE;
    DW1 AT %MDW0: DWORD;
    

    Then in the code (ST), do:

    B0 := Array[2];
    B1 := Array[1];
    B2 := Array[4];
    B3 := Array[3];
    

    When you access DW1, it will have the parts of the Array stuffed into it.

    Note that the order of my reversals may not match what your modbus is putting into the bytes but I know this kind of thing works. There may be other ways to do this but it's what makes the most sense in my head....

     

    Related

    Talk.ru: 1
    Talk.ru: 2
    Talk.ru: 3

  • fabiospark - 2008-03-01

    Thanks. That worked.

    Only differences are on the variable addressing (%MD0) with no "W" and the correct reversal is 4,3,2,1 instead of your 2,1,4,3.

    Now let me ask another one, please.

    I have to deal with 4 slaves and read just once from each of them.

    Is it possible to create four similar POUs, each one with one Modbus master function pointing to a different slave, and put four calls in the PLC_PRG master section?

    I mean, will the serial port resource be shared correctly provided that only one Mod Mas function should be active at a time?

    Will I have to use something more than just calls like this:

    Slave1_prg()

    Slave2_prg()

    Slave3_prg()

    Slave4_prg()

    ?

    Thanks again for the attention.

     
  • Uwe - 2008-03-03

    Hello fabiospark,

    i think it doesn't work.

    You may have only one instance for each serial module.

    If you have more than one instance, you have to

    synchronize this instances by yourself.

    It isn't easy .

    I think the best way is to use only one instance with different jobs.

    Please see the attached example.

    In this example are two jobs in a list and this jobs are executed in turns.

    You can simple modify this example up to many jobs.

    Uwe

    modbusmaster_multi.pro [47.41 KiB]

     
  • Rolf-Geisler - 2008-03-03

    Another way is to use the free library BinUtils at http://www.geisler-controls.de. There is the function PutByte_DW to patch a byte into a DWORD resp. ExtractByte_DW to read a byte out of a DWORD. The code is prett easy:

    var
    Β  Byte0 : BYTE;
    Β  Byte1 : BYTE;
    Β  Byte2 : BYTE;
    Β  Byte3 : BYTE;
    Β  ADWord : DWORD;
    
    ADWord := PutByte_DW (ADWord, 0, Byte0);
    ADWord := PutByte_DW (ADWord, 1, Byte1);
    ADWord := PutByte_DW (ADWord, 2, Byte2);
    ADWord := PutByte_DW (ADWord, 3, Byte3);
    

    Interface of the functions is commented in English, but PDF documentation is in German only

    Have success

    Rolf

     
  • hugo - 2008-03-12

    yes shure the solutions above will work, but a good library will give you a solution that is much faster in terms of performance

    in the open source libraray at w www.oscat.de w you will find the following code for the job

    DWord_of_Byte := SHL(SHL(SHL(B3,8) OR B2,8) OR B1,8) OR B0;

    this is a much faster solution while B? are the respective bytes

     
  • hugo - 2008-03-12

    sorry the smilies are the right hand brackets

     
  • Aditya Prabowo - 2013-01-11

    Dear editor,

    Hi all! Thanks a lot in advance for giving me such a nice opportunity in viewing all threads. Anyway, nowadays I end up with this conversion issue. Currently I'm trying to build an application using Wago 750-881 with CoDeSys v2.3. I'm still newbie with these two-systems.

    Direct to the issue, is it possible for me to convert two-bytes into single one-word. What I already tried with the code is as listed below:

    VARIABLES DECLARATION

    VAR_INPUT
    BYTE10 AT %MB10: BYTE;
    BYTE11 AT %MB11: BYTE;
    END_VAR

    VAR_OUTPUT
    WORD10 AT %MW10: WORD;
    END_VAR

    LOGIC (IL)

    LD BYTE10
    ST BYTE10
    LD BYTE11
    ST BYTE11
    LD WORD10
    ST WORD10

    Thank you in advance whether any of guys could help me with this issue. Have a nice day!

     
  • shooter - 2013-01-11

    have a look at hugo answer or

    outword := shl(mbyte11),8) or mbyte10;

    btw the post was very old
    and yes oscat lib is great.

     
  • Aditya Prabowo - 2013-01-11

    Hi, Shooter!

    Thanks a lot for your comments. But any way for my case is I'd like to combine %MB10 as LSByte with %MB11 as MSByte. And in the end I'd like to read a whole %MW10. I think my case is related to data-order bytes.

    After I see through, http://www.sps-forum.de/showthread.php/ ... te-in-word , for my case, logic becomes as listed below:

    FUNCTION_BLOCK FBXX_ST_WORD_OSCAT

    VAR_INPUT
    BYTE10: BYTE;
    BYTE11: BYTE;
    END_VAR

    VAR_OUTPUT
    WORD10: DWORD;
    END_VAR

    VAR
    ( outword := SHL(mbyte11),8) OR mbyte10; )
    mbyte10 AT %MB10: BYTE;
    mbyte11 AT %MB11: BYTE;
    mword10 AT %MW10: WORD;
    END_VAR


    mbyte10:=BYTE10;
    mbyte11:=BYTE11;
    ( mword10:=SHL(mbyte11,8) OR mbyte10; )
    mword10:=SHL(BYTE_TO_WORD(mbyte11),8)+BYTE_TO_WORD(mbyte10);
    WORD10:=mword10;

    Thanks once again for your hints, shooter!

    Best regards,
    Aditya Prabowo
    Jakarta, ID

    IMG: test_2bytes_to_word.png

     
  • shooter - 2013-01-11

    remarks:
    FUNCTION_BLOCK FBXX_ST_WORD_OSCAT


    VAR_INPUT
    BYTE10: BYTE;
    BYTE11: BYTE;
    END_VAR

    VAR_OUTPUT
    WORD10: WORD;
    END_VAR


    WORD10:=SHL(BYTE_TO_WORD(byte11),8)+BYTE_TO_WORD(byte10);

    do not put MarkerVAR in function blocks but always in GLOBAL_VAR
    (to prevent double definition)

     
  • Aditya Prabowo - 2013-01-12

    Hi Shooter,

    Thanks for the advice. I will look into that further.

    Best regards,
    Aditya Prabowo
    Jakarta, ID

     

Log in to post a comment.