Search code examples
raspberry-pimodbusminimalmodbus

Modbus Checksum Error using minimalmodbus python library with Waveshare RS485 CAN HAT (B) on Raspberry Pi 3B+


I am trying to use the minimalmodbus library to read register values from an industrial sensor called an ICM by company MP Filtri. I am using the Waveshare RS485 CAN HAT (B) connected on top of a Raspberry Pi 3B+.

When I try to read a register, I get a Checksum error response as follows (username redacted because it contains my family name): Checksum Error

I am using an external 24VDC power source to supply power to both the Waveshare Hat (which powers the Pi) as well as the MP Filtri ICM Sensor. The A and B wires of the sensor are correctly connected to the A and B terminals of "RS485_0" on the Waveshare Hat. The Sensor and the Pi/hat share the same power source and the grounds are connected.

I've configured the Waveshare hat as it shows in the Waveshare wiki under the "Install Libraries" and the "Driver Configuration" sections. Once the driver is configured in /boot/config.txt as described, I can then see the devices have been added to /dev as ttySC0 and ttySC1. Also, I ran the suggested command dmesg | grep -i '\(can\|spi\)' and get the following output: GREP SPI **This is important to note because you will see in the code below, the only baud rate that I can get to return anything is 921600 as it shows in this screenshot for ttySC0 and ttySC1

The Modbus section of the ICM sensor's manual shows the following setup information:

3.1 Modbus Settings

Protocol type RTU (not ASCII)
Data Bits 8
Stop Bits 1
Parity Required, Even
Baud Auto-sensing 1200-115200
Signalling RS485
Node Address 204 (or user set)
3.2 Communications Check
You should be able to read the product ID code from register 0 (from Modbus node address 204). The product ID code is the value 54237 (decimal) or 0xD3DD (hexadecimal).

When writing the Python script to read register 0 from the sensor (Product ID), I used the basic code from the minimalmodbus docs. I also used the Modbus slave address of 4, which is set in the device. The document page above states that address 204 can be used as a permanent address, but an address can also be set in the device that it will respond on as well. I've tried both with the same results, but in the event that more devices are added to the bus at a later date, I am using the salve address set in the device which is 4. The code that I am using in a file called basic.py is as follows:

#!/usr/bin/env python3

import minimalmodbus

instrument = minimalmodbus.Instrument('/dev/ttySC0', 4, debug = True)  # port name, slave address (in decimal)

instrument.serial.baudrate = 921600             # Baud
instrument.serial.bytesize = 8                  # bytesize
instrument.serial.parity   = minimalmodbus.serial.PARITY_EVEN
instrument.serial.stopbits = 1                  # stop bits
instrument.serial.timeout  = 0.5                # seconds
instrument.mode = minimalmodbus.MODE_RTU        # rtu or ascii mode
instrument.clear_buffers_before_each_transaction = True

## Read Product ID From Register 0 ##
prodid = instrument.read_register(0, 0)  # Registernumber, number of decimals
print(prodid)

The response that I receive is a checksum error as shown above and also here again: Checksum Error

Why am I receiving this checksum error message and how do eliminate this error? Also, why is the only baud rate that works 921600? Is that because the base baud of ttySC0 is showing up as this rate?


Solution

  • After trying many different options, baud rates, coding, and multiple exchanges with Waveshare's customer service department, I finally came to a very simple solution to my question.

    The Waveshare RS485 CAN HAT (B) has jumpers on each of the two RS485 channels that enable a 120 ohm resistor by default. Waveshare's customer service suggested trying without the resistors enabled, as they are not always needed on RS-485 communication (according to them). As soon as i removed the jumper, the program responded and I was able to read registers from the sensor.