update server

This commit is contained in:
2026-07-30 11:12:31 +08:00
commit 4312cb878c
99 changed files with 24034 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
import numpy as np
import time
def measure_volume(conn_mgr,
q_in_slm=50.0, dt=0.1,
xa=1000, p_max=200.0,
fit_low=50.0, fit_high=150.0,
T_delta=30.0,
should_stop=None, log=print, on_sample=None):
"""充气升压测试,辨识系统等效体积 V(可直接被 GUI 导入调用)。
连接由调用方负责:传入已连接的 ConnectionManager。
本函数不创建客户端、不调用 exit()、不画图、不阻塞,只跑测试并返回结果。
参数:
conn_mgr : 已连接的 ConnectionManager(需有 read_pressure() / set_motor_position()
q_in_slm : 进气流量设定 (SLM)
dt : 控制/采样周期 (秒)
xa : 阀门全开对应的电机位置指令
p_max : 升压上限,超过即停止并关阀 (kPa)
fit_low/high : 用于线性拟合的压力区间 (kPa)
t_std : 流量计标况温度 (K)
t_tank : 充气时估计气体温度 (K)
should_stop : 可选回调,返回 True 时提前中止(供 GUI 停止按钮用)
log : 日志回调,默认 printGUI 可传入 self.log_message
on_sample : 可选回调 on_sample(t, pressure),每个采样点调用一次(供 GUI 刷新界面)
返回:
dict: {
'record_time': [...], 'p_actual': [...],
'slope': float | None, 'intercept': float | None,
'c1': float | None, 'volume_L': float | None,
'valid_points': int, 'payload_data': dict | None,
'success': bool
}
"""
p_actual = []
record_time = []
conn_mgr.set_motor_position(xa)
# time.sleep(5) # 等待压力稳定
begin_time = time.perf_counter()
current_pressure = conn_mgr.read_pressure()
while True:
if should_stop is not None and should_stop():
log("测试被手动中止")
conn_mgr.set_motor_position(0)
break
start_time = time.perf_counter()
if current_pressure is not None and current_pressure > p_max:
conn_mgr.set_motor_position(0)
break
current_pressure = conn_mgr.read_pressure()
t = time.perf_counter() - begin_time
if current_pressure is not None:
p_actual.append(current_pressure)
record_time.append(t)
print(f"time:{t:.2f}, current_pressure:{current_pressure}")
if on_sample is not None:
on_sample(t, current_pressure)
i += 1
cycle_time = time.perf_counter() - start_time
time.sleep(max(dt - cycle_time, 0.001))
# ==========================================
# 自动计算 升压速率(dP/dt) 与 c1、等效体积 V
# ==========================================
valid_times = []
valid_pressures = []
for tt, p in zip(record_time, p_actual):
if fit_low <= p <= fit_high:
valid_times.append(tt)
valid_pressures.append(p)
result = {
'record_time': record_time,
'p_actual': p_actual,
'slope': None,
'intercept': None,
'c1': None,
'volume_L': None,
'valid_points': len(valid_times),
'payload_data': None,
'success': False,
}
log("=" * 40)
log("物理参数辨识结果")
log("=" * 40)
t_std = 293.15
t_tank = t_std + T_delta
if len(valid_times) > 1:
slope, intercept = np.polyfit(valid_times, valid_pressures, 1)
c1 = slope / q_in_slm
P_atm = 101.325
volume_L = P_atm / (60 * c1) * (t_tank / t_std)
# 打包json上传到云端
payload_data = {
"slope": slope,
"intercept": intercept,
"c1": c1,
"volume_L": volume_L,
"valid_points": len(valid_times),
"q_in_slm": q_in_slm,
}
result.update({
'slope': float(slope),
'intercept': float(intercept),
'c1': float(c1),
'volume_L': float(volume_L),
'payload_data': payload_data,
'success': True,
})
print(f"有效数据点数量: {len(valid_times)}")
print(f"实测升压速率 (dP/dt) : {slope:.4f} kPa/s")
print(f"进气流量设定 (q_in) : {q_in_slm} SLM")
print(f"最终进气增益 (c1) : {c1:.4f}")
print(f"系统真实等效体积 (V) : {volume_L:.4f} L")
else:
log(f"警告:{fit_low:.0f}~{fit_high:.0f}kPa 区间内的数据点太少,无法计算斜率!")
log("=" * 40)
return result
def main():
"""独立运行入口:自建连接、跑测试、画图验证。"""
import matplotlib.pyplot as plt
from PcControl import Easy521ModbusClient, MotorModbusRTUClient
q_in_slm = 50.0
modbus_client = Easy521ModbusClient()
if modbus_client.connect():
print("成功连接到PLC")
modbus_client.start_control()
motor = MotorModbusRTUClient()
if not motor.connect():
print("电机连接失败,退出。")
return
time.sleep(1) # 增加短暂延时,等待驱动器接口就绪
if not motor.init():
print("电机初始化失败,退出。")
motor.disconnect()
return
result = measure_volume(modbus_client, motor, q_in_slm=q_in_slm)
modbus_client.stop_control()
motor.disconnect()
record_time = result['record_time']
p_actual = result['p_actual']
# ==========================================
# 画图验证
# ==========================================
plt.figure(figsize=(10, 6))
plt.plot(record_time, p_actual, 'b.-', label='Actual P (kPa)')
if result['success']:
slope = result['slope']
intercept = result['intercept']
valid_times = [t for t, p in zip(record_time, p_actual) if 50 <= p <= 150]
ideal_p = [slope * t + intercept for t in valid_times]
plt.plot(valid_times, ideal_p, 'r--', linewidth=2, label=f'Linear Fit (slope={slope:.1f})')
plt.title('Pressure Rise Test')
plt.xlabel('Time (s)')
plt.ylabel('Pressure (kPa)')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()