60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Scan an RS485 bus for ZLAC8015D drivers and report which node IDs answer.
|
|
|
|
Requires: pip install pymodbus pyserial
|
|
|
|
Example:
|
|
python3 zltech_scan_ids.py --port /dev/tty.usbserial-XXXX
|
|
python3 zltech_scan_ids.py --port COM5 --baud 115200 --range 1 10
|
|
"""
|
|
import argparse
|
|
import sys
|
|
|
|
from zltech_modbus import REG_NODE_ID, make_client, read_register
|
|
|
|
|
|
def scan(port: str, baud: int, id_range, timeout: float):
|
|
found = []
|
|
client = make_client(port, baud, timeout)
|
|
if not client.connect():
|
|
print(f"ERROR: could not open serial port {port}")
|
|
sys.exit(1)
|
|
try:
|
|
for node_id in id_range:
|
|
values = read_register(client, node_id, REG_NODE_ID, 1)
|
|
if values is not None:
|
|
found.append((node_id, values[0]))
|
|
print(f" id {node_id:3d}: responded (node-id register reads {values[0]})")
|
|
finally:
|
|
client.close()
|
|
return found
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument("--port", required=True, help="Serial port, e.g. /dev/tty.usbserial-XXXX or COM5")
|
|
parser.add_argument("--baud", type=int, default=115200, help="Baud rate (default 115200, the driver default)")
|
|
parser.add_argument("--range", nargs=2, type=int, metavar=("START", "END"), default=[1, 16],
|
|
help="Inclusive node-ID range to scan (default 1 16)")
|
|
parser.add_argument("--timeout", type=float, default=0.15, help="Per-ID response timeout in seconds")
|
|
args = parser.parse_args()
|
|
|
|
start, end = args.range
|
|
id_range = range(start, end + 1)
|
|
|
|
print(f"Scanning {args.port} @ {args.baud}bps for node IDs {start}-{end} ...")
|
|
found = scan(args.port, args.baud, id_range, args.timeout)
|
|
|
|
print()
|
|
if found:
|
|
print(f"Found {len(found)} driver(s):")
|
|
for node_id, _ in found:
|
|
print(f" -> ID {node_id}")
|
|
else:
|
|
print("No drivers responded. Check wiring, baud rate, and that only powered drivers are on the bus.")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|