Raspberry Pi Modbus GUI Installation &
Usage Guide
1. Prerequisites
- Raspberry Pi with Ethernet or USB-Ethernet
- Ethernet cable to Liebert IS-Unity card
- Raspberry Pi OS installed
- Python 3.9+ (default in Raspberry Pi OS)
- Monitor/keyboard or SSH access
- Internet connection for setup
2. Network Configuration
Configure Pi’s Ethernet interface to communicate with IS-Unity card at IP 169.254.24.7.
Edit dhcpcd.conf:
sudo nano /etc/dhcpcd.conf
Add at the bottom:
interface eth0
static ip_address=169.254.24.10/16
static routers=0.0.0.0
static domain_name_servers=8.8.8.8
Save and reboot with:
sudo reboot
Test connection:
ping 169.254.24.7
3. Install Required Python Libraries
Update and install:
sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-tk
pip3 install pymodbus
4. Create the Modbus GUI Script
1. Create folder and enter:
mkdir ~/modbus_gui
cd ~/modbus_gui
2. Create Python file:
nano modbus_gui.py
3. Paste the following code:
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
from pymodbus.client import ModbusTcpClient
IP = "169.254.24.7"
PORT = 502
UNIT_ID = 1
client = ModbusTcpClient(IP, port=PORT)
def read_registers():
reg_type = type_var.get()
try:
start = int(start_entry.get())
end = int(end_entry.get())
except ValueError:
messagebox.showerror("Error", "Invalid start/end register")
return
count = end - start + 1
tree.delete(*tree.get_children())
try:
if reg_type == "Input":
rr = client.read_input_registers(start, count, unit=UNIT_ID)
if rr.isError(): raise Exception(rr)
for i, val in enumerate(rr.registers):
tree.insert("", "end", values=(f"R{start+i}", val, "Read-Only"))
elif reg_type == "Holding":
rr = client.read_holding_registers(start, count, unit=UNIT_ID)
if rr.isError(): raise Exception(rr)
for i, val in enumerate(rr.registers):
tree.insert("", "end", values=(f"R{start+i}", val, "Editable"))
elif reg_type == "Coils":
rr = client.read_coils(start, count, unit=UNIT_ID)
if rr.isError(): raise Exception(rr)
for i, val in enumerate(rr.bits):
tree.insert("", "end", values=(f"C{start+i}", int(val), "Editable"))
except Exception as e:
messagebox.showerror("Read Error", str(e))
def write_selected():
selected = tree.selection()
if not selected:
return
reg_type = type_var.get()
for sel in selected:
reg, val, mode = tree.item(sel, "values")
addr = int(reg[1:])
new_val = simpledialog.askinteger("Write Value", f"Enter new value for {reg}:")
if new_val is None:
continue
try:
if reg_type == "Holding":
client.write_register(addr, new_val, unit=UNIT_ID)
elif reg_type == "Coils":
client.write_coil(addr, bool(new_val), unit=UNIT_ID)
tree.item(sel, values=(reg, new_val, mode))
except Exception as e:
messagebox.showerror("Write Error", str(e))
root = tk.Tk()
root.title("Modbus GUI - Select Range")
tk.Label(root, text="Start").grid(row=0, column=0)
start_entry = tk.Entry(root); start_entry.grid(row=0, column=1)
tk.Label(root, text="End").grid(row=0, column=2)
end_entry = tk.Entry(root); end_entry.grid(row=0, column=3)
type_var = tk.StringVar(value="Input")
ttk.Combobox(root, textvariable=type_var, values=["Input","Holding","Coils"]).grid(row=0,
column=4)
tk.Button(root, text="Read", command=read_registers).grid(row=0, column=5)
tk.Button(root, text="Write Selected", command=write_selected).grid(row=0, column=6)
tree = ttk.Treeview(root, columns=("Register", "Value", "Mode"), show="headings")
tree.heading("Register", text="Register")
tree.heading("Value", text="Value")
tree.heading("Mode", text="Mode")
tree.grid(row=1, column=0, columnspan=7, sticky="nsew")
root.mainloop()
5. Run the Application
To run the GUI:
python3 ~/modbus_gui/modbus_gui.py
6. Auto-Start at Boot (Optional)
Create a systemd service:
sudo nano /etc/systemd/system/modbus_gui.service
Add:
[Unit]
Description=Modbus GUI
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/modbus_gui/modbus_gui.py
WorkingDirectory=/home/pi/modbus_gui
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Enable with:
sudo systemctl enable modbus_gui.service
sudo systemctl start modbus_gui.service