dev free_fall

This commit is contained in:
edo-neo 2025-10-15 13:08:01 +02:00
parent f0fb7a47d1
commit c1321ce0b4
8 changed files with 158 additions and 53 deletions

View File

@ -371,6 +371,18 @@ class TecnaMarpossProvasetT3(ModbusComponent):
test_flags = (test_flags & ~(7 << 4)) | (pid_mode_value << 4)
pid_ramps=0b0000000000000000 | int(self.config["recipes_defaults"]["pid_level"])<<8 | int(self.config["recipes_defaults"]["pid_speed"])<<12
# Build a robust map of parameters with safe defaults, so Free Fall (minimal spec) won't crash
_defs = self.config.get("recipes_defaults", {}) or {}
_s = step.spec or {}
def _gv(key, def_key=None, fallback_key=None):
if key in _s:
return _s.get(key)
if fallback_key and fallback_key in _s:
return _s.get(fallback_key)
if def_key is not None:
return int(_defs.get(def_key, 0)) if isinstance(_defs.get(def_key, 0), (int, float, str)) else 0
return 0
test_pressure_val = _gv("test_pressure", "pressione_di_test", fallback_key="filling_pressure")
spec = {
"Flag: Instrument settings": 0b0000000000000000,
"Test program for read/write operation": table,
@ -381,21 +393,21 @@ class TecnaMarpossProvasetT3(ModbusComponent):
"Print options": 0b0000000000000000 | self.saver_label_count << 12 | self.saver_print_on_fail << 8 | self.saver_label_template,
"Test type": "Leak Test",
"Test flags": test_flags,
"T0 - Pre-filling time": step.spec["pre_filling_time"],
"P0 - Pre-filling pressure": step.spec["pre_filling_pressure"],
"T1 - Filling time": step.spec["filling_time"],
"T2 - Settling time": step.spec["settling_time"],
"PR- - Min pressure tolerance %": step.spec["settling_pressure_min_percent"],
"PR+ - Max pressure tolerance % (P+)": step.spec["settling_pressure_max_percent"],
"T3 - Measure time": step.spec["test_time"],
"Q- Lower test leak limit": step.spec["test_pressure_qneg"],
"PREL - Nominal test pressure": step.spec["test_pressure"],
"Q+ Upper test leak limit": step.spec["test_pressure_qpos"],
"FST - Discharge time": step.spec["flush_time"],
"FSL - Discharge limit": step.spec["flush_pressure"],
"T0 - Pre-filling time": _gv("pre_filling_time", "tempo_pre_riempimento"),
"P0 - Pre-filling pressure": _gv("pre_filling_pressure", "pressione_pre_riempimento"),
"T1 - Filling time": _gv("filling_time", "tempo_riempimento"),
"T2 - Settling time": _gv("settling_time", "tempo_assestamento"),
"PR- - Min pressure tolerance %": _gv("settling_pressure_min_percent", "percentuale_minima_pressione_assestamento"),
"PR+ - Max pressure tolerance % (P+)": _gv("settling_pressure_max_percent", "percentuale_massima_pressione_assestamento"),
"T3 - Measure time": _gv("test_time", "tempo_di_test"),
"Q- Lower test leak limit": _gv("test_pressure_qneg", "pressione_di_test_delta_minimo"),
"PREL - Nominal test pressure": test_pressure_val,
"Q+ Upper test leak limit": _gv("test_pressure_qpos", "pressione_di_test_delta_massimo"),
"FST - Discharge time": _gv("flush_time", "tempo_svuotamento"),
"FSL - Discharge limit": _gv("flush_pressure", "pressione_svuotamento"),
"PSQ - Next sequence program PSOUT mode": 0,
"RAMPS: T1 configuration": pid_ramps,
"PID: pressure correction": step.spec.get("pid_pressure_correction",0),
"PID: pressure correction": _gv("pid_pressure_correction", "pid_pressure_correction"),
"Various flags": 0b0000000000010000 if self.config["recipes_defaults"]["tester_discharge_enable"] in ("yes", "x") else 0b0000000000000000
}
@ -404,8 +416,8 @@ class TecnaMarpossProvasetT3(ModbusComponent):
elif self.model == "t3l":
spec.update({
"Use programs or use products": 0,
"Nominal peak pressure": step.spec["test_pressure"],
"Pn - Nominal test pressure": step.spec["test_pressure"],
"Nominal peak pressure": test_pressure_val,
"Pn - Nominal test pressure": test_pressure_val,
})
else:
raise NotImplementedError(f"tecna t3 model {self.model!r} not implemented.")

View File

@ -107,42 +107,16 @@ def read_steps(row, config, defaults=None, unsupported_steps=None):
"pid_mod_config": safe_parse(row.get("pid_mod_config", defaults["pid_mod_config"])),
},
"test_freefall_leak": {
"pre_filling_time": safe_parse(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"])),
"pre_filling_pressure": safe_parse(
row.get("pressione_pre_riempimento", defaults["pressione_pre_riempimento"]))
,
"filling_time": safe_parse(row.get("tempo_riempimento", defaults["tempo_riempimento"])),
"settling_time": safe_parse(get_default_value(row, "tempo_assestamento")),
"settling_pressure_min_percent": safe_parse(
row.get("percentuale_minima_pressione_assestamento",
defaults["percentuale_minima_pressione_assestamento"]))
,
"settling_pressure_max_percent": safe_parse(
row.get("percentuale_massima_pressione_assestamento",
defaults["percentuale_massima_pressione_assestamento"]))
,
"test_time": safe_parse(row.get("tempo_di_test", defaults["tempo_di_test"])),
"test_pressure_qneg": safe_parse(
row.get("pressione_di_test_delta_minimo", defaults["pressione_di_test_delta_minimo"]))
,
"test_pressure": safe_parse(row.get("pressione_di_test", defaults["pressione_di_test"])),
"test_pressure_qpos": safe_parse(
row.get("pressione_di_test_delta_massimo", defaults["pressione_di_test_delta_massimo"]))
,
"flush_time": safe_parse(row.get("tempo_svuotamento", defaults["tempo_svuotamento"])),
"flush_pressure": safe_parse(row.get("pressione_svuotamento", defaults["pressione_svuotamento"]))
,
"chan_sel": safe_parse(row.get("canale_di_prova", defaults["canale_di_prova"]))
,
"ext_flush_time": safe_parse(row.get("tempo_svuotamento_esterno", defaults["tempo_svuotamento_esterno"]))
,
"ext_blow_time": safe_parse(row.get("tempo_soffiaggio_esterno", defaults["tempo_soffiaggio_esterno"]))
,
"pid_pressure_correction": safe_parse(
row.get("pid_pressure_correction", defaults["pid_pressure_correction"]))
,
"pid_mod_config": safe_parse(row.get("pid_mod_config", defaults["pid_mod_config"]))
,
# Dedicated Free Fall parameters
# Tempo riempimento (seconds)
"filling_time": safe_parse(row.get("tempo_riempimento_free_fall", row.get("tempo_riempimento", defaults.get("tempo_riempimento", 0)))),
# Pressione riempimento (mbar)
"filling_pressure": safe_parse(row.get("pressione_riempimento_free_fall", row.get("pressione_pre_riempimento", defaults.get("pressione_pre_riempimento", 0)))),
# Pressione minima/massima (mbar)
"pressure_min": safe_parse(row.get("pressione_min_free_fall", defaults.get("pressione_min_free_fall", 0))),
"pressure_max": safe_parse(row.get("pressione_max_free_fall", defaults.get("pressione_max_free_fall", 0))),
# Riempimento continuo (si/no)
"continuous_filling": str(row.get("riempimento_continuo_free_fall", "")).strip().lower() in {"si","s","x","yes","y","true","1"},
},
"leak_2": {
"pre_filling_time": safe_parse(row.get("tempo_pre_riempimento_2", defaults["tempo_pre_riempimento_2"])),

View File

@ -0,0 +1 @@
from .freefall_step_editor import FreeFall_Step_Editor

View File

@ -0,0 +1,14 @@
from ui.editor import Editor
class FreeFall_Step_Editor(Editor):
def __init__(self, action=None, cell_widget=None):
super().__init__(action=action, cell_widget=cell_widget)
# Map only the Free Fall specific parameters
self.spec.update({
"filling_time": self.filling_time_sb,
"filling_pressure": self.filling_pressure_sb,
"pressure_min": self.pressure_min_sb,
"pressure_max": self.pressure_max_sb,
"continuous_filling": self.continuous_filling_cb,
})

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FreeFall_Step_Editor</class>
<widget class="QWidget" name="FreeFall_Step_Editor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>160</height>
</rect>
</property>
<property name="windowTitle">
<string>Free Fall Step Editor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_fill_time">
<property name="text">
<string>T1: Tempo riempimento (s)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="filling_time_sb">
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_fill_pressure">
<property name="text">
<string>P1: Pressione riempimento (mbar)</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="filling_pressure_sb">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_pmin">
<property name="text">
<string>Pmin: Pressione minima (mbar)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="pressure_min_sb">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_pmax">
<property name="text">
<string>Pmax: Pressione massima (mbar)</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="pressure_max_sb">
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QCheckBox" name="continuous_filling_cb">
<property name="text">
<string>Riempimento continuo (sì/no)</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -5,6 +5,7 @@ from ui.count_step_editor import Count_Step_Editor
from ui.editor import Editor
from ui.helpers import replace_widget
from ui.leak_step_editor import Leak_Step_Editor
from ui.freefall_step_editor import FreeFall_Step_Editor
from ui.pipe_cutter_step_editor import Pipe_Cutter_Step_Editor
from ui.print_step_editor import Print_Step_Editor
from ui.resistance_step_editor import Resistance_Step_Editor
@ -85,7 +86,7 @@ class Recipe_Spec_And_Step_Editor(Editor):
"type": "test_freefall_leak",
"enable": self.free_fall_enabled_cb,
"widget": "free_fall_editor_w",
"editor": Leak_Step_Editor(),
"editor": FreeFall_Step_Editor(),
"tab": self.free_fall_t,
},
"leak_2": {

View File

@ -5,6 +5,7 @@ from PyQt5.QtWidgets import QPushButton
from ui.crud import Cell, Combo_Box_Cell_Widget, Crud
from ui.dialog import Dialog
from ui.leak_step_editor import Leak_Step_Editor
from ui.freefall_step_editor import FreeFall_Step_Editor
from ui.vision_step_editor import Vision_Step_Editor
from ui.widget import Widget
@ -14,7 +15,7 @@ class Step_Spec_JEDECW(QPushButton, Cell):
self.editors = {
"vision": Vision_Step_Editor(cell_widget=self),
"leak_1": Leak_Step_Editor(cell_widget=self),
"test_freefall_leak": Leak_Step_Editor(cell_widget=self),
"test_freefall_leak": FreeFall_Step_Editor(cell_widget=self),
"leak_2": Leak_Step_Editor(cell_widget=self),
}
self.editor = None

View File

@ -1,6 +1,7 @@
import sys
import time
import weakref
import os
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QMessageBox, QDialog, QApplication
@ -154,8 +155,25 @@ class Test_Leak(Test_Test):
else:
if step.step_type == "test_freefall_leak":
self.display_text(text="COLLAUDARE USANDO IL SISTEMA DI FLUSSAGGIO ALLA FINE DELLA PROVA POSIZIONRE IL PEZZO PER LA PROVATENUTA")
# Try to load custom Free Fall image from instruction images
try:
instr_folder = (self.config.get("machine", {}) or {}).get("instruction_folder", getattr(self.config, "machine_id", "")).strip() or getattr(self.config, "machine_id", "")
except Exception:
instr_folder = getattr(self.config, "machine_id", "")
img_path = None
for ext in ("png", "jpg", "jpeg"):
candidate = f"config/instruction_images/{instr_folder}/free_fall.{ext}"
if os.path.exists(candidate):
img_path = candidate
break
if img_path is not None:
super().visualize(None, img=QPixmap(img_path))
else:
# Fallback to default image
super().visualize(None, img=self.status_imgs_full[None])
else:
self.display_text(text="COLLEGARE GLI ATTACCHI PNEUMATICI E PREMERE START PER INIZIARE LA PROVA TENUTA")
super().visualize(None, img=self.status_imgs_full[None])
self.template_print_l.setVisible(True)
self.template_label.setVisible(True)
if self.simulate: