Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Extract 4 bytes from array of bytes to save in decimal value (int?)

alberth007
2021-04-22
2022-01-11
  • alberth007

    alberth007 - 2021-04-22

    Hello,

    I have a question, maybe easy for you, but I cannot solve it and maybe you can help. I have a sensor that provides me the data in an array of 16 bytes. I need to take the 4 first bytes and save it in an INT value which is a distance value, so I have in the four first bytes [0,0,1,181,..] which is 437 mm that my sensor is displaying I need these 437 into a variable (INT I suppose). How can I do it easily?

    Thanks for your help!

     
  • Singh

    Singh - 2021-04-24

    065536+04096+1*256+182=437

     
    • sgronchi

      sgronchi - 2021-04-26

      You should recheck your coefficients, because 2^16 is not 4096 and 2^24 is not 65536.

      Or just use the PackBytesToDWord function which is more explicative in source code.

       

      Last edit: sgronchi 2021-04-26
  • nothinrandom

    nothinrandom - 2022-01-02

    @alberth007,

    Probably the easiest and most efficient way is to use pointer. Just create a pointer to DWORD since it's 4 bytes. For example:

    // create variable
    pdwValue : POINTER TO DWORD;
    
    // map variable to memory address
    pdwValue := ADR(Application.GVL_IO_LINK.Port1_inputs);
    
    // dereference pointer to get value and operate on it directly
    IF (pdwValue^ > 500) THEN
        // do something
    END_IF
    
    // less efficient way would be to copy value to another variable
    myValue := pdwValue^;
    
     
    • sgronchi

      sgronchi - 2022-01-07

      This works only if you have a big endian machine.
      The easiest way would be using the dedicated functions from CAA Memory.

       
      • nothinrandom

        nothinrandom - 2022-01-11

        Oh good catch! I didn't notice the system endianess. Typically, I would avoid adding additional libraries just to use a single function.

        Let's get back to the basics where packing bytes is simply bit shifting. In this case, the output could be computed via (assuming receiving system is little endian):

        dwOutput := SHL(Application.GVL_IO_LINK.Port1_inputs[4], 24) + SHL(Application.GVL_IO_LINK.Port1_inputs[3], 16) + SHL(Application.GVL_IO_LINK.Port1_inputs[2], 8) + Application.GVL_IO_LINK.Port1_inputs[1];

        Bit shifting is the equivalent of multiplying by orders of 2 (e.g. shift left by 1 means multiply by 2).

         

        Related

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

        • sgronchi

          sgronchi - 2022-01-11

          The focus is on the readability, almost everyone can roll a (de)serialization code.

          A library function which is already made and does everything right and aptly named is way better than something that would be copypasted all over the place and quickly gets messy.

          Besides that, your code is broken on 16-bit processors. Yes, they still exist, run Codesys and continue to be deployed.

           

Log in to post a comment.