变频器集成以及增加点动控制(0209)
This commit is contained in:
394
tests/485test.py
394
tests/485test.py
@ -1,339 +1,79 @@
|
||||
import serial
|
||||
import minimalmodbus
|
||||
import time
|
||||
import struct
|
||||
|
||||
from serial import SerialException
|
||||
|
||||
class InovanceMD520:
|
||||
def __init__(self, port='COM4', baudrate=9600, timeout=1):
|
||||
"""
|
||||
初始化汇川MD520变频器通信
|
||||
:param port: 串口名称,Windows为COMx,Linux为/dev/ttyUSBx
|
||||
:param baudrate: 波特率,默认9600
|
||||
:param timeout: 超时时间,秒
|
||||
"""
|
||||
self.port = port
|
||||
self.baudrate = baudrate
|
||||
self.timeout = timeout
|
||||
self.ser = None
|
||||
|
||||
def connect(self):
|
||||
"""连接串口"""
|
||||
try:
|
||||
self.ser = serial.Serial(
|
||||
port=self.port,
|
||||
baudrate=self.baudrate,
|
||||
bytesize=serial.EIGHTBITS,
|
||||
parity=serial.PARITY_NONE,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
timeout=self.timeout
|
||||
)
|
||||
print(f"成功连接到串口 {self.port}")
|
||||
return True
|
||||
except serial.SerialException as e:
|
||||
print(f"连接串口失败: {e}")
|
||||
return False
|
||||
|
||||
def disconnect(self):
|
||||
"""断开串口连接"""
|
||||
if self.ser and self.ser.is_open:
|
||||
self.ser.close()
|
||||
print("串口连接已关闭")
|
||||
|
||||
def calculate_crc(self, data):
|
||||
"""
|
||||
计算Modbus CRC16校验码
|
||||
:param data: 字节数据
|
||||
:return: CRC校验码(低位在前,高位在后)
|
||||
"""
|
||||
crc = 0xFFFF
|
||||
for byte in data:
|
||||
crc ^= byte
|
||||
for _ in range(8):
|
||||
if crc & 0x0001:
|
||||
crc = (crc >> 1) ^ 0xA001
|
||||
else:
|
||||
crc = crc >> 1
|
||||
return struct.pack('<H', crc) # 小端序,低位在前
|
||||
|
||||
def query_frequency(self, slave_addr=0x01):
|
||||
"""
|
||||
查询变频器运行频率
|
||||
:param slave_addr: 从站地址,默认1
|
||||
:return: 频率值(Hz),如查询失败返回None
|
||||
"""
|
||||
if not self.ser or not self.ser.is_open:
|
||||
print("串口未连接")
|
||||
return None
|
||||
|
||||
# 构建查询指令:读取运行频率(地址1001H)
|
||||
# 01 03 10 01 00 01
|
||||
cmd_data = bytes([
|
||||
slave_addr, # 从站地址
|
||||
0x03, # 功能码:读取保持寄存器
|
||||
0x10, 0x01, # 寄存器地址:1001H(运行频率)
|
||||
0x00, 0x01 # 读取1个寄存器
|
||||
])
|
||||
|
||||
# 计算CRC
|
||||
crc = self.calculate_crc(cmd_data)
|
||||
|
||||
# 完整指令
|
||||
full_cmd = cmd_data + crc
|
||||
|
||||
print(f"发送查询指令: {full_cmd.hex().upper()}")
|
||||
|
||||
try:
|
||||
# 清空输入缓冲区
|
||||
self.ser.reset_input_buffer()
|
||||
|
||||
# 发送指令
|
||||
self.ser.write(full_cmd)
|
||||
|
||||
# 等待响应(根据文档需要等待3.5个字节时间)
|
||||
time.sleep(0.01) # 约10ms延迟
|
||||
|
||||
# 读取响应
|
||||
# 正常响应格式:地址(1) + 功能码(1) + 字节数(1) + 数据(2) + CRC(2) = 7字节
|
||||
response = self.ser.read(7)
|
||||
|
||||
if len(response) < 7:
|
||||
print(f"响应数据长度不足: {len(response)} 字节")
|
||||
return None
|
||||
|
||||
print(f"收到响应: {response.hex().upper()}")
|
||||
|
||||
# 验证响应
|
||||
if response[0] != slave_addr:
|
||||
print(f"从站地址不匹配: 期望{slave_addr:02X}, 收到{response[0]:02X}")
|
||||
return None
|
||||
|
||||
if response[1] != 0x03:
|
||||
print(f"功能码错误: 期望03, 收到{response[1]:02X}")
|
||||
return None
|
||||
|
||||
if response[2] != 0x02:
|
||||
print(f"数据长度错误: 期望02, 收到{response[2]:02X}")
|
||||
return None
|
||||
|
||||
# 验证CRC
|
||||
received_crc = response[-2:]
|
||||
calculated_crc = self.calculate_crc(response[:-2])
|
||||
if received_crc != calculated_crc:
|
||||
print("CRC校验失败")
|
||||
return None
|
||||
|
||||
# 解析频率数据(高字节在前)
|
||||
frequency_raw = (response[3] << 8) | response[4]
|
||||
frequency_hz = frequency_raw / 100.0 # 转换为Hz(单位0.01Hz)
|
||||
|
||||
print(f"原始频率值: {frequency_raw} (0x{frequency_raw:04X})")
|
||||
print(f"实际频率: {frequency_hz:.2f} Hz")
|
||||
|
||||
return frequency_hz
|
||||
|
||||
except Exception as e:
|
||||
print(f"通信错误: {e}")
|
||||
return None
|
||||
|
||||
def set_frequency(self, slave_addr=0x01,frequency=210):
|
||||
"""
|
||||
变频器运行频率
|
||||
:param slave_addr: 从站地址,默认1
|
||||
:return: 频率值(Hz),如查询失败返回None
|
||||
"""
|
||||
if not self.ser or not self.ser.is_open:
|
||||
print("串口未连接")
|
||||
return None
|
||||
|
||||
# 构建查询指令:读取运行频率(地址1001H)
|
||||
# 01 03 10 01 00 01
|
||||
cmd_data = bytes([
|
||||
slave_addr, # 从站地址
|
||||
0x06, # 功能码:读取保持寄存器
|
||||
0x10, 0x00, # 寄存器地址:1001H(运行频率)
|
||||
0x1B, 0x58 # 读取1个寄存器
|
||||
])
|
||||
|
||||
# 计算CRC
|
||||
crc = self.calculate_crc(cmd_data)
|
||||
|
||||
# 完整指令
|
||||
full_cmd = cmd_data + crc
|
||||
|
||||
print(f"发送查询指令: {full_cmd.hex().upper()}")
|
||||
|
||||
try:
|
||||
# 清空输入缓冲区
|
||||
self.ser.reset_input_buffer()
|
||||
|
||||
# 发送指令
|
||||
self.ser.write(full_cmd)
|
||||
|
||||
# 等待响应(根据文档需要等待3.5个字节时间)
|
||||
time.sleep(0.01) # 约10ms延迟
|
||||
|
||||
# 读取响应
|
||||
# 正常响应格式:地址(1) + 功能码(1) + 字节数(1) + 数据(2) + CRC(2) = 7字节
|
||||
response = self.ser.read(7)
|
||||
|
||||
if len(response) < 7:
|
||||
print(f"响应数据长度不足: {len(response)} 字节")
|
||||
return None
|
||||
|
||||
print(f"收到响应: {response.hex().upper()}")
|
||||
|
||||
# 验证响应
|
||||
if response[0] != slave_addr:
|
||||
print(f"从站地址不匹配: 期望{slave_addr:02X}, 收到{response[0]:02X}")
|
||||
return None
|
||||
|
||||
if response[1] != 0x06:
|
||||
print(f"功能码错误: 期望03, 收到{response[1]:02X}")
|
||||
return None
|
||||
|
||||
# 验证CRC
|
||||
received_crc = response[-2:]
|
||||
calculated_crc = self.calculate_crc(response[:-2])
|
||||
if received_crc != calculated_crc:
|
||||
print("CRC校验失败")
|
||||
return None
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"通信错误: {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
def read_register(self, slave_addr, register_addr, register_count=1):
|
||||
"""
|
||||
通用读取寄存器方法
|
||||
:param slave_addr: 从站地址
|
||||
:param register_addr: 寄存器地址(16位)
|
||||
:param register_count: 读取的寄存器数量
|
||||
:return: 读取的数据列表
|
||||
"""
|
||||
if not self.ser or not self.ser.is_open:
|
||||
print("串口未连接")
|
||||
return None
|
||||
|
||||
# 构建读取指令
|
||||
cmd_data = bytes([
|
||||
slave_addr, # 从站地址
|
||||
0x03, # 功能码:读取保持寄存器
|
||||
(register_addr >> 8) & 0xFF, # 寄存器地址高字节
|
||||
register_addr & 0xFF, # 寄存器地址低字节
|
||||
(register_count >> 8) & 0xFF, # 寄存器数量高字节
|
||||
register_count & 0xFF # 寄存器数量低字节
|
||||
])
|
||||
|
||||
# 计算CRC
|
||||
crc = self.calculate_crc(cmd_data)
|
||||
full_cmd = cmd_data + crc
|
||||
|
||||
print(f"发送读取指令: {full_cmd.hex().upper()}")
|
||||
|
||||
try:
|
||||
self.ser.reset_input_buffer()
|
||||
self.ser.write(full_cmd)
|
||||
time.sleep(0.01)
|
||||
|
||||
# 计算预期响应长度
|
||||
expected_length = 5 + 2 * register_count # 地址1 + 功能码1 + 字节数1 + 数据2*N + CRC2
|
||||
response = self.ser.read(expected_length)
|
||||
|
||||
if len(response) < expected_length:
|
||||
print(f"响应数据长度不足: {len(response)} 字节,期望 {expected_length} 字节")
|
||||
return None
|
||||
|
||||
print(f"收到响应: {response.hex().upper()}")
|
||||
|
||||
# 验证CRC
|
||||
received_crc = response[-2:]
|
||||
calculated_crc = self.calculate_crc(response[:-2])
|
||||
if received_crc != calculated_crc:
|
||||
print("CRC校验失败")
|
||||
return None
|
||||
|
||||
# 解析数据
|
||||
data_length = response[2]
|
||||
data_bytes = response[3:3 + data_length]
|
||||
|
||||
results = []
|
||||
for i in range(0, len(data_bytes), 2):
|
||||
value = (data_bytes[i] << 8) | data_bytes[i + 1]
|
||||
results.append(value)
|
||||
|
||||
return results
|
||||
|
||||
except Exception as e:
|
||||
print(f"通信错误: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
# 创建变频器对象
|
||||
inverter = InovanceMD520(port='COM3', baudrate=9600)
|
||||
|
||||
# 连接串口
|
||||
if not inverter.connect():
|
||||
return
|
||||
|
||||
# 设置频率为55Hz并启动变频器
|
||||
def start_inverter_55hz():
|
||||
try:
|
||||
while True:
|
||||
print("\n" + "=" * 50)
|
||||
print("汇川MD520变频器频率查询")
|
||||
print("=" * 50)
|
||||
# 1. 连接到变频器
|
||||
# COM3: 串口地址
|
||||
# 1: 从站地址
|
||||
inverter = minimalmodbus.Instrument('COM3', 1)
|
||||
|
||||
# 2. 配置串口参数
|
||||
inverter.serial.baudrate = 9600 # 波特率
|
||||
inverter.serial.bytesize = 8 # 数据位
|
||||
inverter.serial.parity = 'N' # 无校验
|
||||
inverter.serial.stopbits = 1 # 停止位
|
||||
inverter.serial.timeout = 1.0 # 超时时间
|
||||
inverter.mode = minimalmodbus.MODE_RTU # RTU模式
|
||||
|
||||
print("✅ 已连接到变频器")
|
||||
|
||||
# 3. 设置频率为55Hz
|
||||
# 假设最大频率为50Hz,55Hz对应110% = 11000
|
||||
# # 如果您的最大频率不同,请调整下面的计算
|
||||
# frequency_value = int(70 * 100)
|
||||
# inverter.write_register(0x1000, frequency_value)
|
||||
# print(f"✅ 频率设置为200Hz")
|
||||
|
||||
# 设置允许频率
|
||||
frequency = inverter.set_frequency(slave_addr=0x01, frequency=210.0)
|
||||
if frequency is not None:
|
||||
print(f"✅ 设置成功")
|
||||
else:
|
||||
print("❌ 频率设置失败")
|
||||
frequency_value = int(210 * 100)
|
||||
inverter.write_register(0x7310, frequency_value)
|
||||
|
||||
# 查询运行频率
|
||||
frequency = inverter.query_frequency(slave_addr=0x01)
|
||||
# freq = inverter.read_register(0x7310)
|
||||
# print(f" 读取到的频率值: {freq}")
|
||||
|
||||
if frequency is not None:
|
||||
print(f"✅ 当前运行频率: {frequency:.2f} Hz")
|
||||
else:
|
||||
print("❌ 频率查询失败")
|
||||
# max_freq = 300
|
||||
# target_freq = 230
|
||||
# frequency_value = int(target_freq / max_freq * 100 * 100) # = 2333
|
||||
# inverter.write_register(0x1000, frequency_value)
|
||||
|
||||
# time.sleep(0.5) # 等待一下
|
||||
|
||||
# 4. 启动变频器(正转运行)
|
||||
inverter.write_register(0x2000, 1) # 1=正转运行
|
||||
print("✅ 变频器已启动(正转运行)")
|
||||
|
||||
# time.sleep()
|
||||
|
||||
|
||||
# 可选:读取其他监控参数
|
||||
print("\n--- 其他监控参数 ---")
|
||||
|
||||
# 读取母线电压 (地址1002H)
|
||||
voltage_data = inverter.read_register(0x01, 0x1002)
|
||||
if voltage_data:
|
||||
voltage = voltage_data[0] / 10.0 # 单位0.1V
|
||||
print(f"母线电压: {voltage:.1f} V")
|
||||
|
||||
# 读取输出电压 (地址1003H)
|
||||
output_voltage_data = inverter.read_register(0x01, 0x1003)
|
||||
if output_voltage_data:
|
||||
output_voltage = output_voltage_data[0] # 单位1V
|
||||
print(f"输出电压: {output_voltage} V")
|
||||
|
||||
# 读取输出电流 (地址1004H)
|
||||
current_data = inverter.read_register(0x01, 0x1004)
|
||||
if current_data:
|
||||
current = current_data[0] / 100.0 # 单位0.01A
|
||||
print(f"输出电流: {current:.2f} A")
|
||||
|
||||
# 等待5秒后再次查询
|
||||
print("\n等待5秒后继续查询...")
|
||||
time.sleep(5)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n用户中断查询")
|
||||
# inverter.write_register(0x2000, 6) # 1=正转运行
|
||||
# print("✅ 变频器已停止(正转运行)")
|
||||
|
||||
# 5. 检查状态
|
||||
time.sleep(1)
|
||||
#读取3000H可直接读取变频器的当前状态(0001:正转运行;0002:反转运行;0003:停机;0004:电机参数辨识;0005:故障)。
|
||||
status = inverter.read_register(0x3000)
|
||||
|
||||
if status == 1:
|
||||
print("✅ 变频器正在正转运行")
|
||||
elif status == 5:
|
||||
print("⚠️ 变频器故障")
|
||||
else:
|
||||
print(f"📊 变频器状态码: {status}")
|
||||
|
||||
except SerialException:
|
||||
print('无法连接或打开串口')
|
||||
except Exception as e:
|
||||
print(f"❌ 错误: {e}")
|
||||
print("请检查:")
|
||||
print("1. COM3端口是否正确?")
|
||||
print("2. 变频器电源和通信线是否连接正常?")
|
||||
print("3. 变频器地址和波特率设置是否正确?")
|
||||
|
||||
finally:
|
||||
# 断开连接
|
||||
inverter.disconnect()
|
||||
|
||||
print("脚本执行完成")
|
||||
|
||||
# 运行
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
start_inverter_55hz()
|
||||
93
tests/api_service_test.py
Normal file
93
tests/api_service_test.py
Normal file
@ -0,0 +1,93 @@
|
||||
"""
|
||||
API接口
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
import time
|
||||
from busisness.blls import ArtifactBll,PDRecordBll
|
||||
from busisness.models import ArtifactInfoModel,PDRecordModel
|
||||
from service.mould_service import app_web_service
|
||||
|
||||
|
||||
_model_task=None
|
||||
artifact_bll=ArtifactBll()
|
||||
pdrecord_bll=PDRecordBll()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# 初始化三个列表用于跟踪ArtifactActionID
|
||||
processed_artifact_actions = [] # 已处理的ArtifactActionID列表
|
||||
processed_pd_records = [] # 已插入PDRecord表的ArtifactActionID列表
|
||||
|
||||
# db = SQLiteHandler.get_instance("db/three.db", max_readers=50, busy_timeout=4000)
|
||||
while True:
|
||||
# 测试获取未浇筑管片信息
|
||||
try:
|
||||
not_poured = app_web_service.get_not_pour_artifacts()
|
||||
if not_poured:
|
||||
for item in reversed(not_poured):
|
||||
# 检查MouldCode是否已处理
|
||||
if item.MouldCode in processed_artifact_actions:
|
||||
print(f"待浇筑:MouldCode {item.MouldCode} 已处理,跳过")
|
||||
continue
|
||||
|
||||
_model_data = ArtifactInfoModel(**item.__dict__)
|
||||
artifact_bll.insert_artifact_task(_model_data)
|
||||
# 标记为已处理
|
||||
processed_artifact_actions.append(item.MouldCode)
|
||||
# 限制最多保存3条记录,删除最旧的
|
||||
if len(processed_artifact_actions) > 3:
|
||||
processed_artifact_actions.pop(0)
|
||||
print(f"待浇筑:已处理MouldCode {item.MouldCode}")
|
||||
|
||||
if item.MouldCode in processed_pd_records:
|
||||
print(f"派单:MouldCode {item.MouldCode} 已处理,跳过")
|
||||
continue
|
||||
|
||||
if item.BetonTaskID is not None and item.BetonTaskID != '':
|
||||
#获取taskid
|
||||
if _model_task is None or item.BetonTaskID != _model_task.TaskID:
|
||||
_model_task = app_web_service.get_task_info(item.BetonTaskID)
|
||||
if _model_task is None:
|
||||
print(f"异常:BetonTaskID {item.BetonTaskID} 不存在,跳过")
|
||||
continue
|
||||
|
||||
_pd_record_data = PDRecordModel(
|
||||
ArtifactID=item.ArtifactID,
|
||||
TaskID=_model_task.TaskID,
|
||||
ProjectName=_model_task.ProjectName,
|
||||
ProduceMixID=_model_task.ProduceMixID,
|
||||
BetonGrade=_model_task.BetonGrade,
|
||||
BetonVolume=item.BetonVolume,
|
||||
MouldCode=item.MouldCode,
|
||||
SkeletonID=item.SkeletonID,
|
||||
RingTypeCode=item.RingTypeCode,
|
||||
SizeSpecification=item.SizeSpecification,
|
||||
BuriedDepth=item.BuriedDepth,
|
||||
BlockNumber=item.BlockNumber
|
||||
)
|
||||
|
||||
pdrecord_bll.insert_PD_record(_pd_record_data)
|
||||
# 标记为已处理
|
||||
processed_pd_records.append(item.MouldCode)
|
||||
# 限制最多保存3条记录,删除最旧的
|
||||
if len(processed_pd_records) > 3:
|
||||
processed_pd_records.pop(0)
|
||||
print(f"派单:已处理MouldCode {item.MouldCode}")
|
||||
else:
|
||||
print(f"异常:MouldCode {item.MouldCode} 无BetonTaskID,跳过")
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理MouldCode {item.MouldCode} 时发生错误: {e}")
|
||||
|
||||
time.sleep(5)
|
||||
except KeyboardInterrupt:
|
||||
|
||||
print("\n测试被用户中断")
|
||||
except Exception as e:
|
||||
|
||||
print(f"测试过程中发生错误: {e}")
|
||||
@ -54,7 +54,7 @@ def test_rfid_functions():
|
||||
"""
|
||||
global rfid
|
||||
# 初始化RFID控制器
|
||||
rfid = rfid_service(host='192.168.250.67', port=6000)
|
||||
rfid = rfid_service(host='192.168.250.77', port=6000)
|
||||
|
||||
# print("=== RFID硬件测试开始 ===")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user