如何读取光伏逆变器USB串口数据,实现数据自动导出?
解决光伏逆变器串口数据读取问题的建议
核心问题定位
你的代码当前最大的问题是发送的指令格式错误:你把带空格的十六进制字符串直接encode()发送,这会将字符串中的每个字符(包括空格)转换成ASCII字节,而非逆变器需要的十六进制原始字节。比如字符串'01'会被转换成0x30 0x31,而不是逆变器期望的0x01,这直接导致设备无法识别指令,自然没有响应。
具体解决步骤
1. 修正指令发送方式
将十六进制指令字符串去掉空格后,用bytes.fromhex()转换成原始字节发送:
import serial import time # 初始化串口,调整超时为2秒(给设备足够响应时间) serialPort = serial.Serial( port="COM3", baudrate=115200, bytesize=serial.EIGHTBITS, timeout=2, # 替换原0值,避免非阻塞空读 stopbits=serial.STOPBITS_ONE, parity=serial.PARITY_NONE # 可根据实际情况调整为PARITY_EVEN/PARITY_ODD ) # 原始指令去掉空格,转成十六进制字节 command = bytes.fromhex('0103002D002D15DE') while True: serialPort.write(command) # 尝试读取固定长度响应(Modbus RTU响应长度可计算:1+1+2+45*2+2=95字节) response = serialPort.read(95) if response: # 先打印十六进制格式的响应,避免解码错误 print("响应十六进制:", response.hex(' ')) # 若确认响应是ASCII编码再尝试解码 # print("响应文本:", response.decode('ascii')) time.sleep(1) # 添加延迟,避免频繁发送指令导致设备不响应
2. 确认所有串口参数完全匹配
除了波特率、数据位、停止位,务必检查以下参数:
- 奇偶校验(parity):工业设备常用
PARITY_EVEN(偶校验)或PARITY_ODD(奇校验),可逐个尝试 - 流控制:部分设备需要开启硬件流控制(
rtscts=True)或软件流控制(xonxoff=True),可根据串口监视器的配置调整
3. 避免使用readline()读取非文本格式数据
逆变器的串口数据通常是二进制/十六进制的工业协议数据(比如Modbus RTU),并非带换行符的文本,readline()会因为找不到换行符而超时返回空。建议:
- 先通过
read(n)读取固定长度的响应(长度可根据协议计算,比如Modbus RTU响应长度=地址+功能码+字节数+数据+CRC) - 或者用
serialPort.read_all()读取当前缓冲区所有数据
4. 验证协议与CRC校验
你发送的指令是标准Modbus RTU格式(地址01,功能码03,读取寄存器),最后两位是CRC16校验码。如果手动输入的校验码有误,设备也会拒绝响应:
- 可以用在线CRC计算器验证
01 03 00 2D 00 2D的CRC16是否为15 DE - 更可靠的方式是使用Modbus库生成指令,比如
pymodbus:
from pymodbus.client import ModbusSerialClient client = ModbusSerialClient( port="COM3", baudrate=115200, parity='N', stopbits=1, bytesize=8, timeout=2 ) client.connect() # 读取从地址0x2D开始的45个寄存器 response = client.read_holding_registers(address=0x2D, count=45, unit=0x01) if not response.isError(): print("寄存器数据:", response.registers) client.close()
5. 排查硬件连接与权限
- 确认USB转串口线的驱动正常,设备管理器中COM端口无黄色感叹号
- Windows下确保串口未被其他程序占用(比如官方应用、串口监视器)
- Linux/macOS下需要给当前用户串口访问权限(比如加入
dialout组)
内容的提问来源于stack exchange,提问作者Cassidy
相关产品推荐
相关产品推荐

