2025-09-09 17:32:28 +08:00

87 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
The app will try to start charging
and show the charger voltage, battery voltage and charging current
stop charging in 30 seconds
'''
from minimalmodbus import Instrument, MODE_RTU
import sys
import time
VERSION = '0.3.0'
UNIT = 16
MODBUS_FC_READ_SINGLE_COIL = int("0x01", 16)
MODBUS_FC_READ_SINGLE_DISCRETE = int("0x02", 16)
MODBUS_FC_READ_HOLDING_REGISTERS = int("0x03", 16)
MODBUS_FC_READ_INPUT_REGISTERS = int("0x04", 16)
MODBUS_FC_WRITE_SINGLE_REGISTER = int("0x06", 16)
enable_charger_address = 0
charger_voltage_adddress = 30
batery_voltage_address = 32
current_address = 31
def monitor_charger(instrument, interval=1, duration=30):
"""
Monitor the charger voltage, battery voltage and current for a given duration.
"""
t = 0
while t < duration:
try:
charger_voltage = instrument.read_registers(registeraddress=charger_voltage_adddress, number_of_registers=1, functioncode=MODBUS_FC_READ_INPUT_REGISTERS)
battery_voltage = instrument.read_registers(registeraddress=batery_voltage_address, number_of_registers=1, functioncode=MODBUS_FC_READ_INPUT_REGISTERS)
current = instrument.read_registers(registeraddress=current_address, number_of_registers=1, functioncode=MODBUS_FC_READ_INPUT_REGISTERS)
print(f'Time: {t}s - Charger Voltage: {charger_voltage[0]}({charger_voltage[0] / 128:.2f} V ) '
f'Battery Voltage: {battery_voltage[0]}({battery_voltage[0] / 128:.2f} V ) '
f'Current: {current[0]}({current[0] / 128:.2f} A )')
sys.stdout.flush()
except Exception as e:
print(f'Error reading registers: {e}')
pass
time.sleep(interval)
t += interval
print()
def run():
import argparse
parser = argparse.ArgumentParser(description='xnergy charger control demo')
parser.add_argument('port', type=str, help='The serial port(RS485) that connect to xnergy RCU')
parser.add_argument('--duration-on', type=int, default=100, help='The duration time in seconds to keep the charger on, default is 100 seconds')
parser.add_argument('--duration-off', type=int, default=10, help='The duration time in seconds to keep the charger off, default is 10 seconds')
parser.add_argument('-r', '--repeat', type=int, default=1, help='The number of times to repeat the charging cycle, default is 1')
parser.add_argument('-q', '--quiet', action='store_true', help='quiet mode, suppress all output')
parser.add_argument('-v', '--version', action='version', version=f'%(prog)s {VERSION}')
args = parser.parse_args()
instrument = Instrument(port=args.port, mode=MODE_RTU, slaveaddress=UNIT, debug=not args.quiet)
instrument.serial.baudrate = 9600
print(f'Start Charging, will start/stop charging {args.repeat} times with on duration {args.duration_on}s and off duration {args.duration_off}s')
counter = 0
while counter <= args.repeat:
# start charging
instrument.write_bit(registeraddress=enable_charger_address, value=1)
monitor_charger(instrument, duration=args.duration_on)
print()
# stop charging
instrument.write_bit(registeraddress=enable_charger_address, value=0)
monitor_charger(instrument, duration=args.duration_off)
print()
counter += 1
print(f'Charging cycle {counter} completed.')
if __name__ == "__main__":
run()