hey guys,
I'm using a esp32 to communicate with a sensor, im getting a response from the sensor (8 bits).
For example, I get this: FF 03 02 15 28 9F 1E, I then use 0x15 * 256 + 0x28 = (humidity for example)
The last 2 bits are the checksum.
How do I put in the code for the CRC16 to check if everything is correct?
Thanks in advance to anyone that can help
ESP32 CRC16
Re: ESP32 CRC16
According to https://en.wikipedia.org/wiki/Cyclic_redundancy_check there exist ~15 different CRC16 algorithms.
For a start, you could ask google for "python CRC16".
For a start, you could ask google for "python CRC16".
A few hours of debugging might save you from minutes of reading the documentation!
My repositories: https://github.com/karfas
My repositories: https://github.com/karfas
Re: ESP32 CRC16
@AntonioBrito: We had that discussion already at the PM, and I gave you a suitable code for the CRC calculation: Here it is again:
I added as test case the message you gave as example. If you calculate the CRC over the full message including the CRC, you get 0 as result. That is a property of CRC and an easy check for pass. If you omit the last two bytes in the CRC calculation, then you get the CRC from the message. Note, that not the ASCII representation of the message is used, but the binary content. If you receive the ASCII string, you have to convert it first to binary.
But according the the MODBUS spec for messages with CRC, the message is transferred binary.
Code: Select all
PRESET = 0xFFFF
POLYNOMIAL = 0xA001 # bit reverse of 0x8005
def crc16(data):
crc = PRESET
for c in data:
crc = crc ^ c
for j in range(8):
if (crc & 1) == 0:
crc = crc >> 1
else:
crc = crc >> 1
crc = crc ^ POLYNOMIAL
return crc
# test case
data = b'\xFF\x03\x02\x15\x28\x9F\x1E'
crc = crc16(data)
print(hex(crc), len(data))
But according the the MODBUS spec for messages with CRC, the message is transferred binary.
Re: ESP32 CRC16
Another implementation uses a pre-compiled table, which is faster, since that table case to be created only once.
Code: Select all
PRESET = 0xFFFF
POLYNOMIAL = 0xA001 # bit reverse of 0x8005
def _initial(c):
crc = 0
for j in range(8):
if (crc ^ c) & 0x1:
crc = (crc >> 1) ^ POLYNOMIAL
else:
crc = crc >> 1
c = c >> 1
return crc
import array
_tab = array.array("H", [_initial(i) for i in range(256)])
def crc16t(str):
crc = PRESET
for c in str:
crc = (crc >> 8) ^ _tab[(crc ^ c) & 0xff]
return crc
data = b'\xFF\x03\x02\x15\x28\x9F\x1E'
crc = crc16t(data)
print(hex(crc), len(data))
Re: ESP32 CRC16
A slightly simplified version of the table approach, which also prints the table for comparison:
Everything is properly documented in the modbus spec. See: https://www.modbustools.com/modbus.html
The direct calculation can also be written slighly clearer as:
If you compare the two implementations you'll see, that the table is created by calculating the CRC over each single byte in the range 0 - 0xff in the code line:
Code: Select all
# --------------------------------------------------------
# Table based implementation
PRESET = 0xFFFF
POLYNOMIAL = 0xA001 # bit reverse of 0x8005
# create a single entry to the CRC table
def _initial(c):
crc = c
for j in range(8):
if crc & 0x01:
crc = (crc >> 1) ^ POLYNOMIAL
else:
crc = crc >> 1
return crc
# Create the table
import array
_tab = array.array("H", [_initial(i) for i in range(256)])
# Checkum calculation
def crc16t(str):
crc = PRESET
for c in str:
crc = (crc >> 8) ^ _tab[(crc ^ c) & 0xff]
return crc
# Test case
print("\nCRC Table:")
for _ in range(256):
if (_ % 8) == 0:
print()
print("0x%04x " % _tab[_], end="")
print()
data = b'\xFF\x03\x02\x15\x28\x9F\x1E'
crc = crc16t(data)
print("\nCRC Test result: ", hex(crc), len(data))
The direct calculation can also be written slighly clearer as:
Code: Select all
# Direct calculation
PRESET = 0xFFFF
POLYNOMIAL = 0xA001 # bit reverse of 0x8005
def crc16(data):
crc = PRESET
for c in data:
crc = crc ^ c
for j in range(8):
if crc & 0x01:
crc = (crc >> 1) ^ POLYNOMIAL
else:
crc = crc >> 1
return crc
# test case
data = b'\xFF\x03\x02\x15\x28\x9F\x1E'
crc = crc16(data)
print("CRC Test result: ", hex(crc), len(data))
Code: Select all
_tab = array.array("H", [_initial(i) for i in range(256)])
-
- Posts: 7
- Joined: Wed Jul 27, 2022 10:39 am
Re: ESP32 CRC16
thank you Robert I figure it out with your help