/*
TUF-2000M User Manual 
 
40
 01    03       00    00     00    0A           C5      CD     (hex) 
Unit  Function   start  REG   Numbers of REGs     Check-sum 
While under the MODBUS-ASCII format, the command could be 
:01030000000AF2(CR and LF) 

*/

Modbus CRC calculator

paste the codes into the box below. It works out the CRC as each byte is added. If it includes the CRC,( CRC-low, CRC-H ) should get a 0x00 if all is okay.

Examples: 
0x01,0x03,0x00,0x02,0x00,0x02,        0x65,0xCB
0x01,0x03,0x04,0x01,0xe6,0xff,0x9f,   0x1b,0xA0
output

https://how2electronics.com/modbus-rtu-with-raspberry-pi-pico-micropython/

def calculate_crc(frame):
    crc = 0xFFFF
    for pos in frame:
        crc ^= pos
        for _ in range(8):
            if crc & 0x0001:
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return crc
 
def construct_modbus_request(address, function, start_high, start_low, count_high, count_low):
    frame = [address, function, start_high, start_low, count_high, count_low]
    crc = calculate_crc(frame)
    frame.append(crc & 0xFF)         # CRC low byte
    frame.append((crc >> 8) & 0xFF)  # CRC high byte
    return bytes(frame)


CRC16/MODBUS
x¹⁶ + x¹⁵ + x² + 1
16	0x8005	0xFFFF	0x0000	true	true	Used in Modbus industrial protocol

uint16_t calc(uint8_t *packet, uint8_t size)
{
    uint16_t crc_polynome = 0xa001;
    uint16_t crc = 0xffff;
    for (uint8_t j = 0; j < size; j++)
    {
        crc ^= packet[j];
        for (uint8_t i = 0; i < 8; i++)
        {
            if (crc & 0x1)
            {
                crc >>= 1; 
                crc ^= crc_polynome;
            } 
            else 
            { 
                crc >>= 1;
            }
        }
    }
    return crc;
}

Address Code	Function Code	Initial Address	Data Length	Check Code Low	Check Code High
0x01	0x03	0x00 0x02	0x00 0x02	0xC4	0x08
Response Frame (hexadecimal): (For example, the temperature is -9.7°C and the humidity is 48.6%RH)

Address Code	Function Code	Number of Valid Bytes	Humidity Value	Temperature Value	Check Code Low	Check Code High
0x01	0x03	0x04	0x01 E6	0xFF 0x9F	0x1B	0xA0


/*
uint16_t calc(uint8_t *packet, uint8_t size)
{
    uint16_t crc_polynome = 0xa001;
    uint16_t crc = 0xffff;
    for (uint8_t j = 0; j < size; j++)
    {
        crc ^= packet[j];
        for (uint8_t i = 0; i < 8; i++)
        {
            if (crc & 0x1)
            {
                crc >>= 1; 
                crc ^= crc_polynome;
            } 
            else 
            { 
                crc >>= 1;
            }
        }
    }
    return crc;
}
*/