CHECKSUM FUNCTION

Anonymous
2018-06-04
2018-06-08
  • Anonymous - 2018-06-04

    Originally created by: silviu_marchidanu

    Hi guys a have a 36 bytes array and I have to calculate the checksum for it, fallowing the manufacture indication.
    Also I have a Function made by somebody else in JAVASCRIPT but I don't really know to converted to codesys ST.

    Known Example 1 in HEX :
    36 Bytes = 00 00 01 EF 00 00 01 00 12 34 00 00 05 13 25 B0 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    Checksum = A6

    Known Example 2 in HEX :
    36 bytes = 00 00 01 EF 00 00 01 00 12 34 56 78 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    Checksum = 6E

    Instructions by manufacture to calculate the checksum also in the attached picture:
    """
    Each bit of a byte coming is XOR with the bit 0 of CRC check register, the result of the XOR is used to change the bit 4 and 3 with a XOR as well then all bits are shifted to the right for the next bit.
    """

    JAVA SCRIPT FUNCTION
    """
    function _byte_xor(chks, byte) {

    var tmp1;
    var tmp2;

    for (i = 0; i < 8 ; i++)
    {
    tmp1 = byte && (0x01 << i); (Mask bit i)
    tmp1 = tmp1 >> i; ( Get it to bit 0)
    tmp2 = chks && 0x01; ( Get checksum bit 0)
    tmp2 = tmp1 ^ tmp2; ( XOR bits 0)
    chks = (chks && 0xFE) && tmp2; ( Put the XOR result in checksum bit 0)
    tmp1 = (chks && 0x08) ^ (tmp2 << 3); ( XOR bits 3)
    chks = (chks && 0xF7) && tmp1; ( Put the XOR result in checksum bit 3)
    tmp1 = (chks && 0x10) ^ (tmp2 << 4); ( XOR Bit 4)
    chks = (chks && 0xEF) && tmp1; ( Put the XOR result in checksum bit 4)
    tmp2 = chks && 0x01; ( Get checksum bit 0)
    tmp2 = tmp2 << 7; ( Move it to bit 7)
    chks = chks >> 1; ( Shift checksum right 1 bit)
    chks = chks && tmp2; ( Rotate calculated bit 0 into bit 7)
    }
    return chks;
    }
    """
    I have tried in a old fashion way by converting the bits in Boolean but it doesn't really work.
    I appreciate your help in advance .

    IMG: 37 Byte Code.jpg

     
  • Lo5tNet - 2018-06-04

    Not sure if this helps but OSCAT has a function called CRC_GEN. If you pass the 32byte array (According to the picture you attached only 32bytes are used in the checksum) into it using the following values I was able to generate a HEX of A6 and 6E for the examples given.

    VAR
        aMessageHex : ARRAY[0..31] OF BYTE := [16#00, 16#00, 16#01, 16#00, 16#12, 16#34, 16#56, 16#78, 16#10, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00];
                                            //[16#00, 16#00, 16#01, 16#00, 16#12, 16#34, 16#00, 16#00, 16#05, 16#13, 16#25, 16#B0, 16#12, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00];
        nPL : INT := 8;
        nPN : DWORD := 46;
        nINIT : DWORD := 5;
        xREV_IN : BOOL := TRUE;
        xREV_OUT : BOOL := FALSE;
        nXOR_OUT : DWORD;
        nGEN : DWORD;
    END_VAR
    nGEN := BASIC.CRC_GEN( PT:= ADR(aMessageHex), 
                                         SIZE:= SIZEOF(aMessageHex), 
                                         PL:= nPL, 
                                         PN:= nPN, 
                                         INIT:= nINIT, 
                                         REV_IN:= xREV_IN, 
                                         REV_OUT:= xREV_OUT, 
                                         XOR_OUT:= nXOR_OUT);
    
     
  • Anonymous - 2018-06-04

    Originally created by: silviu_marchidanu

    I really appreciate your time and effort and I would like to say : THANK YOU VERY MUCH !!!
    I've been looking for a solution for weeks now and you really made my day

    Hope I wont bother to much and wander if you can help me with some additional information .

    I don't really understand why only 32 Bytes are used in the DT: Row ?

    I would really appreciate if you can give me another example with all the 36 bytes as per below formulation as this is actually the format that I need to send out for reporting.
    """
    Byte Value Description
    00 0xE0 Command (LIVE EVENTS)
    01 0x21 Century
    02 0x18 Year
    03 0x05 Month
    04 0x00 Day
    05 0x20 Hour
    06 0x20 Minute
    07 0x02 Event Group Number ( Alarm Partition STATUS)
    08 0x12 Event Sup-group Number (Arm Partition)
    09 0x02 Partition Number ( Partition 2)
    10 0x12 WAGO Given Serial Number digit 1 and 2
    11 0x34 WAGO GivenModule Serial Number digit 3 and 4
    12 0x56 WAGO GivenModule Serial Number digit 5 and 6
    13 0x78 WAGO GivenModule Serial Number digit 7 and 8
    14-35 0x00 N/U
    36 0xXX Checksum Note 1
    """
    Basically this is a code generation in order to send SMS and GPRS data to Me, my family and Security dispatch Company thru a Regular Reporting GPS/GPRS Module Used on the market for the : House Alarm System that I made in WAGO PLC 750 Series fallowing their protocol.

    Hope you will sort me out this time as well.
    I really appreciate your effort and time as I know how much I've been putting in my self and maybe one day Ill be able to help others.
    Cheers !!!

     
  • Lo5tNet - 2018-06-04

    Just to make sure we are clear I am giving you an answer based off of my best guess and previous experience.

    To me the first 4 bytes of the data "00 00 01 EF" in the message are just a definition of where/what to do with the following bytes. This is also said about the 36th byte since it is just a checksum (Making sure all the data is intact and not corrupt). So the message in the data above shows "--" and since it shows "--" for the checksum I strongly believe that in the example message anything with a "--" in the DT row is not counted towards the end checksum.

    An example of doing 36 bytes instead (Using the values you provided) is:

    VAR
        aMessageHex : ARRAY[0..36] OF BYTE := [16#E0, 16#21, 16#18, 16#05, 16#00, 16#20, 16#20, 16#02, 16#12, 16#02, 16#12, 16#34, 16#56, 16#78, 16#00,
                                        16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00,
                                        16#00, 16#00, 16#00, 16#00];    //Bytes 0-35 are the message and byte 36 is the checksum
        nPL : INT := 8;
        nPN : DWORD := 46;
        nINIT : DWORD := 5;
        xREV_IN : BOOL := TRUE;
        xREV_OUT : BOOL := FALSE;
        nXOR_OUT : DWORD;
        nGEN : DWORD;
    END_VAR
    nGEN := BASIC.CRC_GEN( PT:= ADR(aMessageHex), 
                                     SIZE:= SIZEOF(aMessageHex)-1, 
                                     PL:= nPL, 
                                     PN:= nPN, 
                                     INIT:= nINIT, 
                                     REV_IN:= xREV_IN, 
                                     REV_OUT:= xREV_OUT, 
                                     XOR_OUT:= nXOR_OUT);
                                     
    aMessageHex[SIZEOF(aMessageHex)-1] := DWORD_TO_BYTE(nGEN);
    

    The end result is a checksum value of 108 OR 6C in hex. Hopefully this checks out against your javascript function.

     
  • Anonymous - 2018-06-05

    Originally created by: silviu_marchidanu

    Thank you very much for your help , I really appreciate it.
    I'm one of those guys that likes to understand the process behind not just copy the code provided .
    How did you get the parameters right :
    nPL : INT := 8;
    nPN : DWORD := 46;
    nINIT : DWORD := 5;

    I have looked on the manual provided by OSCAT library and is not a regular known CRC but there is an online calculator , did you use that one ?
    Thanks again and hope not asking to much again.

     
  • Lo5tNet - 2018-06-05

    nPL was used for 8bits (size of the checksum value that is coming across in the message)

    nPN and nINIT were setup in a loop that stopped once both of your examples checksum matched. Without more examples it is hard to be certain that those are the right parameters but since they both matched it is a good start.

     
  • Anonymous - 2018-06-07

    Originally created by: silviu_marchidanu

    Thank you very much for your reply again.
    I have managed to get the first checsum working based on your indications and it checks out on other DATA as well.
    Now I'm facing a different type of checksum which is for all the 36 bytes and from what I have discovered with the ONLINE CHECK SUM CALCULATOR " https://www.scadacore.com/tools/program ... alculator/ " that is a NORMAL CheckSum8 Modulo 256 , Sum of Bytes % 256 .
    Can I use the same OSCAT CRC_GEN or there is another way ?
    Example below :
    No1:
    e0 14 12 06 07 16 05 01 01 00 00 00 00 00 00 49 6e 74 72 61 72 65 20 20 20 20 20 20 20 20 20 00 00 00 00 00
    Checksum 25 ( HEX )
    No2 :
    e0 14 12 06 07 16 05 00 01 00 00 00 00 00 00 49 6e 74 72 61 72 65 20 20 20 20 20 20 20 20 20 00 00 00 00 00
    Checksum : 24 (HEX)

    Thanks again.

     
  • Anonymous - 2018-06-08

    Originally created by: silviu_marchidanu

    I managed to get the final 8 bit Modulo Checksum calculation for the 35 bytes as per below :

    FUNCTION_BLOCK CALC_CRC
    VAR_INPUT
    aMessageIN : ARRAY [0..36] OF BYTE ; ( BYTES TO BE CALCULATED / EXCEPT BYTE 36 - checksum)
    END_VAR
    VAR_OUTPUT
    aMessageOUT : ARRAY [0..36] OF BYTE ; ( COMPLETE ARRAY INCLUDING CHECKSUM)
    END_VAR


    VAR
    i: INT:=0;
    ByteSUM: DWORD;
    checksumWord: DWORD;
    END_VAR

    ByteSUM:=0;
    FOR i := 0 TO 35 DO
    ByteSUM := ByteSUM + aMessageIN[i];
    END_FOR
    checksumWord := ByteSUM MOD 256;
    (checksumBYTE:= INT_TO_BYTE (checksumINT);)
    aMessageOUT:=aMessageIN;
    aMessageOUT[SIZEOF(aMessageIN)-1] := DWORD_TO_BYTE(checksumWord);

     
  • Lo5tNet - 2018-06-08

    Glad you got it working.

     

Log in to post a comment.