Moacir Ferreira
Moacir Ferreira

Reputation: 51

Calculating CRC16 in Python for modbus

Firstly, sorry! I am a beginner...

I got the following byte sequence on a modbus: "01 04 08 00 00 00 09 00 00 00 00 f8 0c". The CRC on bold on this byte sequence is correct. However, to check/create the CRC I have to follow the device especs that states:

The error checking must be done using a 16 bit CRC implemented as two 8 bit bytes. The CRC is appended to the frame as the last field. The low order byte of the CRC is appended first, followed by the high order byte. Thus, the CRC high order byte is the last byte to be sent in the frame. The polynomial value used to generate the CRC must be 0xA001.

Now, how can I check the CRC using crcmod? My code is:

import crcmod
crc16 = crcmod.mkCrcFun(0x1A001, rev=True, initCrc=0xFFFF, xorOut=0x0000)
print crc16("0104080000000900000000".decode("hex"))

I tried everything but I can't get the "f8 0C" that is correct on the byte sequence...

Upvotes: 3

Views: 9636

Answers (3)

rams
rams

Reputation: 51

A simple implementation of the MODBUS CRC without any additional lib:

def modbusCrc(msg:str) -> int:
    crc = 0xFFFF
    for n in range(len(msg)):
        crc ^= msg[n]
        for i in range(8):
            if crc & 1:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc

msg = bytes.fromhex("0104080000000900000000")
crc = modbusCrc(msg)
print("0x%04X"%(crc))            

ba = crc.to_bytes(2, byteorder='little')
print("%02X %02X"%(ba[0], ba[1]))

The output is:

0x0CF8
F8 0C

Upvotes: 5

Ben
Ben

Reputation: 1291

Modbus shortcut, if not diving into the CRC detail

from pymodbus.utilities import computeCRC

Upvotes: -1

Mark Adler
Mark Adler

Reputation: 112219

Use 0x18005 instead of 0x1A001.

Upvotes: 1

Related Questions