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

alberth007
2021-04-22
2022-01-11
  • 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!

     
  • Tyro - 2021-04-24

    065536+04096+1*256+182=437

     
    • 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 - 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 - 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 - 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 - 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.