Our Sixteen LV Digital Inputs 8-Layer Stackable HAT for Raspberry Pi can act as a Modbus device in a MODBUS RTU network over RS485.
This blog will describe a practical example for this use case, using Raspberry PI with Two Serial Ports RS485 and RS232 Stackable HAT for Raspberry Pi as a MODBUS Master
Setup the Master
1) Enable the serial port on Raspberry:
- Open a console and type sudo raspi-config
- Select Interface Options
- Serial Port
- No shell over the serial port must be selected
- Enable serial port hardware
- The summary looks like this.
- Finish the setup and restart the Raspberry if it asks.
2) Install pymodbus library:
- Open a terminal and type sudo pip install pymodbus
Setup the device
The default settings for the 16-LV-Digital Inputs card are: Modbus enabled, serial 38400/8/N/1, Modbus device address 1. This setting allows you to use the card as a Modbus device without making any changes but you can change the settings as follows:
- Install the 16inpind CLI by following the instructions in the readme.
- Connect the Sixteen LV Digital Inputs HAT to a Raspberry Pi 2x20 pin connector.
- Set up the card serial port and Modbus parameters by running the 16inpind command. type 16inpind -h cfg485wr for the online help of the command. Let's say we want to communicate with the device at 38400 bits per second, one stop bit, no parity, the Modbus address to be 1, and there are no dipswitches turned on, we will type the following command: 16inpind 0 cfg485wr 1 1 38400 1 0
Even though the online help is clear, I need to remind you that the Modbus address is the result of the parameter set by the 16inpind command plus the value of the stack-level switches. This way you can change the Modbus address just by changing the dipswitches.
After the settings are done, the card can be disconnected from the Raspberry Pi.
Testing
Once the wiring has been made between Two Serials and Sixteen LV Digital inputs RS485 ports respecting the pin marking (connect A to A, B to B, and GND to GND) and the cards are powered, you can start the testing.
Here is a Python script that can be used :
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# Configure Modbus client
client = ModbusClient(
method='rtu',
port='/dev/ttyS0', # Replace with your serial port
baudrate=38400, # Match the card's baud rate
parity='N',
stopbits=1,
bytesize=8,
timeout=1
)
# Connect to the device
if client.connect():
print("Connected to Modbus device.")
# Replace `slave_id` and `discrete_input` with the specific addresses
slave_id = 1 # Modbus ID of your input card
discrete_input = 0 # Starting discrete input address
try:
#Read 16 discrete inputs
response = client.read_discrete_inputs(discrete_input, count=16, unit=slave_id)
if response.isError():
print(f"Error reading inputs: {response}")
else:
print(f"Input states 1..16: {response.bits}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
client.close()
else:
print("Failed to connect to Modbus device.")
Here is an example of the output of the script when input 1 is energized:
Please refer to the MODBUS.md file for the list of the registers and future updates of the address structure.