open_loop.py文件的记录数据部分再新加两列,一列是"P_abs_ratio",定义为阀后绝对压力比阀前绝对压力的,绝对压力为传感器读数加大气压值。另一列是"is_ratio_smaller_than_0.528",判断这个比值是否小于0.528(临界压力比),是的话就填Y,不是就填N.
然后再新画一个图,就是"P_abs_ratio"随时间变化的图,并且标出0.528代表的那条直线。这个图与已有的两幅图放在一个窗口中绘制。
This commit is contained in:
+59
-6
@@ -6,8 +6,8 @@
|
||||
2. 逐个开度:写入电机行程 → 以固定周期采集控流阀前后 4 个传感器
|
||||
(前压力、前流量、后压力、后流量)→ 等待“控流阀后流量”进入稳态后
|
||||
切换到下一个开度;
|
||||
3. 全程逐周期写 CSV,结束后在单个窗口内输出两张子图(前后压力、前后流量),
|
||||
保存到工程目录下的 open_loop_data/。
|
||||
3. 全程逐周期写 CSV,结束后在单个窗口内输出三张子图(前后压力、前后流量、
|
||||
绝对压力比),保存到工程目录下的 open_loop_data/。
|
||||
|
||||
示例:
|
||||
python open_loop.py
|
||||
@@ -71,6 +71,11 @@ PLOT_DPI = config.PLOT_DPI
|
||||
ANNOTATE_STEPS = True # 曲线上标注开度步
|
||||
|
||||
|
||||
# 绝对压力 = 表压读数 + 大气压;临界压力比用于判断是否出现壅塞(choked)流动。
|
||||
ATMOSPHERIC_PRESSURE_KPA = 101.325 # 标准大气压(kPa)
|
||||
CRITICAL_PRESSURE_RATIO = 0.528 # 临界压力比(阀后绝对压力 / 阀前绝对压力)
|
||||
|
||||
|
||||
CSV_FIELDS = (
|
||||
"time_s",
|
||||
"step_index",
|
||||
@@ -80,6 +85,8 @@ CSV_FIELDS = (
|
||||
"flow_after_slm",
|
||||
"pressure_before_kpa",
|
||||
"pressure_after_kpa",
|
||||
"P_abs_ratio",
|
||||
"is_ratio_smaller_than_0.528",
|
||||
)
|
||||
|
||||
|
||||
@@ -140,7 +147,7 @@ class SteadyStateDetector:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class OpenLoopRecorder:
|
||||
"""逐周期写 CSV,结束时输出两张子图(前后压力、前后流量)。"""
|
||||
"""逐周期写 CSV,结束时输出三张子图(前后压力、前后流量、绝对压力比)。"""
|
||||
|
||||
def __init__(self, output_directory, *, plot_dpi=160):
|
||||
output_dir = Path(output_directory)
|
||||
@@ -176,6 +183,18 @@ class OpenLoopRecorder:
|
||||
if self._closed:
|
||||
raise RuntimeError("记录器已关闭")
|
||||
|
||||
p_abs_ratio = self._absolute_pressure_ratio(
|
||||
pressure_before_kpa, pressure_after_kpa
|
||||
)
|
||||
if p_abs_ratio is None:
|
||||
p_abs_ratio_text = ""
|
||||
is_smaller_text = ""
|
||||
else:
|
||||
p_abs_ratio_text = f"{p_abs_ratio:.6f}"
|
||||
is_smaller_text = (
|
||||
"Y" if p_abs_ratio < CRITICAL_PRESSURE_RATIO else "N"
|
||||
)
|
||||
|
||||
self._writer.writerow(
|
||||
{
|
||||
"time_s": self._fmt(time_s),
|
||||
@@ -186,6 +205,8 @@ class OpenLoopRecorder:
|
||||
"flow_after_slm": self._fmt(flow_after_slm),
|
||||
"pressure_before_kpa": self._fmt(pressure_before_kpa),
|
||||
"pressure_after_kpa": self._fmt(pressure_after_kpa),
|
||||
"P_abs_ratio": p_abs_ratio_text,
|
||||
"is_ratio_smaller_than_0.528": is_smaller_text,
|
||||
}
|
||||
)
|
||||
self._file.flush()
|
||||
@@ -195,6 +216,21 @@ class OpenLoopRecorder:
|
||||
self.steps.append((float(time_s), float(opening_pct)))
|
||||
self._last_step_index = step_index
|
||||
|
||||
@staticmethod
|
||||
def _absolute_pressure_ratio(pressure_before_kpa, pressure_after_kpa):
|
||||
"""阀后绝对压力 / 阀前绝对压力;读数缺失或分母非法时返回 None。"""
|
||||
if pressure_before_kpa is None or pressure_after_kpa is None:
|
||||
return None
|
||||
try:
|
||||
before_abs = float(pressure_before_kpa) + ATMOSPHERIC_PRESSURE_KPA
|
||||
after_abs = float(pressure_after_kpa) + ATMOSPHERIC_PRESSURE_KPA
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
if before_abs <= 0:
|
||||
return None
|
||||
ratio = after_abs / before_abs
|
||||
return ratio if math.isfinite(ratio) else None
|
||||
|
||||
def finalize(self):
|
||||
"""关闭 CSV 并生成 PNG;无采样点时只保留 CSV。"""
|
||||
self.close()
|
||||
@@ -221,6 +257,7 @@ class OpenLoopRecorder:
|
||||
flow_after = []
|
||||
pressure_before = []
|
||||
pressure_after = []
|
||||
p_abs_ratio = []
|
||||
|
||||
with self.csv_path.open("r", newline="", encoding="utf-8-sig") as file:
|
||||
for row in csv.DictReader(file):
|
||||
@@ -233,11 +270,12 @@ class OpenLoopRecorder:
|
||||
pressure_after.append(
|
||||
self._float_or_nan(row["pressure_after_kpa"])
|
||||
)
|
||||
p_abs_ratio.append(self._float_or_nan(row["P_abs_ratio"]))
|
||||
|
||||
figure, axes = plt.subplots(
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
figsize=(12, 9),
|
||||
figsize=(12, 12),
|
||||
sharex=True,
|
||||
constrained_layout=True,
|
||||
)
|
||||
@@ -264,10 +302,25 @@ class OpenLoopRecorder:
|
||||
"Flow after valve", "#6A1B9A",
|
||||
)
|
||||
axes[1].set_ylabel("Flow (SLM)")
|
||||
axes[1].set_xlabel("Time (s)")
|
||||
axes[1].set_title("Flow across control valve")
|
||||
axes[1].legend(loc="best")
|
||||
|
||||
self._plot_series(
|
||||
axes[2], time_s, p_abs_ratio,
|
||||
"P_abs_ratio (after/before)", "#EF6C00",
|
||||
)
|
||||
axes[2].axhline(
|
||||
CRITICAL_PRESSURE_RATIO,
|
||||
color="#B71C1C",
|
||||
linestyle="--",
|
||||
linewidth=1.2,
|
||||
label=f"Critical ratio {CRITICAL_PRESSURE_RATIO:.3f}",
|
||||
)
|
||||
axes[2].set_ylabel("P_abs_ratio")
|
||||
axes[2].set_xlabel("Time (s)")
|
||||
axes[2].set_title("Absolute pressure ratio across control valve")
|
||||
axes[2].legend(loc="best")
|
||||
|
||||
if ANNOTATE_STEPS and self.steps:
|
||||
y_top = axes[1].get_ylim()[1]
|
||||
for step_time, opening in self.steps:
|
||||
|
||||
Reference in New Issue
Block a user