fco730 dev

This commit is contained in:
st-ten-9 2023-10-12 19:37:39 +02:00
parent 6a254e7922
commit dce65caa55
10 changed files with 113 additions and 202 deletions

View File

@ -50,15 +50,15 @@ description_field: descrizione
tecna_discharge_enable: yes tecna_discharge_enable: yes
dimensione_lotto_abilitata: x dimensione_lotto_abilitata: x
tempo_pre_riempimento: 0 tempo_pre_riempimento: 0
pressione_pre_riempimento: 1000 pressione_pre_riempimento: 0
tempo_riempimento: 15 tempo_riempimento: 5
tempo_assestamento: 15 tempo_assestamento: 10
tempo_di_test: 10 tempo_di_test: 10
percentuale_minima_pressione_assestamento: 5 percentuale_minima_pressione_assestamento: 5
percentuale_massima_pressione_assestamento: 5 percentuale_massima_pressione_assestamento: 5
pressione_di_test_delta_minimo: 30 pressione_di_test_delta_minimo: 20 # +mbar
pressione_di_test: 7000 pressione_di_test: 5000 # mbar
pressione_di_test_delta_massimo: 30 pressione_di_test_delta_massimo: 20 # -mbar
tempo_svuotamento: 1 tempo_svuotamento: 1
pressione_svuotamento: 100 pressione_svuotamento: 100
canale_di_prova: 1 canale_di_prova: 1

View File

@ -1,4 +1,4 @@
echo on echo on
SET mypath=%~dp0 SET mypath=%~dp0
cd %mypath% cd %mypath%
.\venv\Scripts\activate.bat && python -O "./src/main.py" --no-edgetpu --no-tflite/ .\venv\Scripts\activate.bat && python -O "./src/main.py"

View File

@ -1,4 +1,4 @@
echo on echo on
SET mypath=%~dp0 SET mypath=%~dp0
cd %mypath% cd %mypath%
.\venv\Scripts\activate.bat && python -O "./src/main.py" --no-edgetpu --no-tflite --no-autotest .\venv\Scripts\activate.bat && python -O "./src/main.py" --no-autotest

View File

@ -1,9 +1,10 @@
registers = { registers = {
"program_data":b'A000', "program_data":b'A000',
"product_data":b'B000', "product_data":b'B050',
"function_data":b'D000', "function_data":b'D000',
"counters":b'E000', "counters":b'E000',
"change_cur_prod":b'F000', "change_cur_prod":b'F000',
"change_cur_prod_50":b'F050',
"start_test": b'G000', "start_test": b'G000',
"reset_test": b'H000', "reset_test": b'H000',
"version_num_range": b'I000', "version_num_range": b'I000',
@ -16,20 +17,27 @@ registers = {
"printer_settings": b'S000', "printer_settings": b'S000',
"comm_settings": b'x000' "comm_settings": b'x000'
} }
tags = { product_tags = {
"product_id": b'a', "product_id": b'a',
"test_press": b'b', "test_pressure": b'b',
"tolerance": b'c', "tolerance": b'c',
"+fail": b'd', "+fail": b'd',
"-fail": b'e', "-fail": b'e',
"fill_time": b'f', "fill_time": b'f',
"stab_time": b'g', "stab_time": b'g',
"test_time": b'h', "test_time": b'h',
"prefill_time": b'i', "prefill_time": b'l',
"vent_time": b'm', "vent_time": b'm',
"test_type": b'n', "test_type": b'n',
"fail_high": b'o', "fail_high": b'o',
"fail_low": b'p', "fail_low": b'p',
"outputs_a_h": b'q', "outputs_a_h": b'q',
"prefill_pressure": b'r',
}
program_tags={
"leak_units":b'a',
"press_units": b'b',
"leak_at_eot":b'c',
"product":b'l',
} }

View File

@ -1,6 +1,10 @@
registers = { registers = {
} }
settings = { product_tags = {
}
program_tags = {
} }

View File

@ -3,8 +3,8 @@ import sys
from components.component import Component from components.component import Component
from components.furness_controls_fco730_registers import registers as fco730_registers from components.furness_controls_fco730_registers import registers as fco730_registers
from components.furness_controls_fco780_registers import registers as fco780_registers from components.furness_controls_fco780_registers import registers as fco780_registers
from components.furness_controls_fco730_registers import settings as fco730_settings from components.furness_controls_fco730_registers import product_tags as fco730_product_tags
from components.furness_controls_fco780_registers import settings as fco780_settings from components.furness_controls_fco780_registers import product_tags as fco780_product_tags
if "--sim-furness-controls" in sys.argv: if "--sim-furness-controls" in sys.argv:
from components.dummies.serial import serial from components.dummies.serial import serial
else: else:
@ -21,6 +21,7 @@ class FurnessControlsLeakTester(Component):
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True): def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True):
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded) super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.product_tags = None
self.bytesize = None self.bytesize = None
self.timeout = None self.timeout = None
self.parity = None self.parity = None
@ -39,10 +40,10 @@ class FurnessControlsLeakTester(Component):
self.model = self.config[self.name]["model"].lower() self.model = self.config[self.name]["model"].lower()
if self.model == "fco730": if self.model == "fco730":
self.registers = fco730_registers self.registers = fco730_registers
self.settings = fco730_settings self.product_tags = fco730_product_tags
elif self.model == "fco730": elif self.model == "fco780":
self.registers = fco780_registers self.registers = fco780_registers
self.settings = fco780_settings self.product_tags = fco780_product_tags
else: else:
raise NotImplementedError(f"Furness Controls model {self.model!r} not implemented.") raise NotImplementedError(f"Furness Controls model {self.model!r} not implemented.")
self.port = self.config[self.name]["port"] self.port = self.config[self.name]["port"]
@ -50,7 +51,7 @@ class FurnessControlsLeakTester(Component):
self.stopbits = 1 self.stopbits = 1
self.parity = serial.PARITY_NONE self.parity = serial.PARITY_NONE
self.bytesize = serial.EIGHTBITS self.bytesize = serial.EIGHTBITS
self.timeout = 0.5 self.timeout = 0.2
if self.conn is not None: if self.conn is not None:
self.conn.close() self.conn.close()
self.conn = serial.Serial( self.conn = serial.Serial(
@ -73,126 +74,13 @@ class FurnessControlsLeakTester(Component):
data = data * self.units[formatting][0] data = data * self.units[formatting][0]
return data return data
def _convert_to_format(self, data, formatting=None, encoding_map=None):
if formatting is not None:
data = int(data / self.units[formatting][0])
if encoding_map is not None and data in encoding_map:
data = encoding_map[data]
return data
@Component.reconfig_on_error
def read(self, register, *args, data_type=None, gain=None, offset=None, formatting=None, decoding_map=None, **kwargs):
if type(register) is str:
register, s = self.registers[register]
if data_type is None:
data_type = s.get("dt", None)
if gain is None:
gain = s.get("g", None)
if offset is None:
offset = s.get("o", None)
if formatting is None:
formatting = s.get("f", None)
if decoding_map is None:
decoding_map = s.get("decoding", None)
if not len(args):
args = s.get("a", [])
if not len(kwargs):
kwargs = s.get("k", {})
if data_type is None:
data_type = "16bit_uint"
if gain is None:
gain = 1
if offset is None:
offset = 0
return self._convert_from_format(
super().read(
register,
*args,
data_type=data_type,
gain=gain,
offset=offset,
**kwargs,
),
formatting=formatting,
decoding_map=decoding_map,
)
@Component.reconfig_on_error
def write(self, register, data, *args, data_type=None, gain=None, offset=None, formatting=None, encoding_map=None, **kwargs):
if type(register) is str:
register, s = self.registers[register]
if data_type is None:
data_type = s.get("dt", None)
if gain is None:
gain = s.get("g", None)
if offset is None:
offset = s.get("o", None)
if formatting is None:
formatting = s.get("f", None)
if encoding_map is None:
encoding_map = s.get("encoding", None)
if not len(args):
args = s.get("a", [])
if not len(kwargs):
kwargs = s.get("k", {})
if data_type is None:
data_type = "16bit_uint"
if gain is None:
gain = 1
if offset is None:
offset = 0
return super().write(
register,
self._convert_to_format(
data,
formatting=formatting,
encoding_map=encoding_map,
),
*args,
data_type=data_type,
gain=gain,
offset=offset,
**kwargs,
)
@Component.reconfig_on_error @Component.reconfig_on_error
def _get(self): def _get(self):
# READ INFO # READ INFO
info = {r: self.read(r) for r in [ current_status=self.send_enquiry("current_status")
"Real time test pressure output",
"Real time differential pressure output",
"Real time pressure line regulator",
"Active alarm flags",
"Active test program number",
"Running test: active phase",
"Running test: test type",
"Running test: sequence index",
"Digital inputs status (mask)",
# "Digital outputs status (mask)",
]}
if self.model == "t3p":
pass
elif self.model == "t3l":
info.update({r: self.read(r) for r in [
"Active not severe alarm flags",
]})
else:
raise NotImplementedError(f"Tecna t3 model {self.model!r} not implemented.")
if info["Running test: active phase"] == "FINE TEST": # "END TEST, WAITING THE START OF A NEW TEST":
info.update(self.get_test_results())
for round_me in ["measured leak"]:
if round_me in info.keys():
info.update({round_me:float(f"{info[round_me]:.2f}")})
self.log.debug(str(info))
super()._get([info])
@Component.reconfig_on_error self.log.info(str(current_status))
def _set(self, val=None): #super()._get([])
if val is not None: # handle request:
for register, value in val.items():
print(register, value)
self.write(register, value)
super()._set(val)
def start_test(self, table=None): def start_test(self, table=None):
if table is None: if table is None:
@ -204,65 +92,60 @@ class FurnessControlsLeakTester(Component):
def stop_test(self): def stop_test(self):
self.log.warning("stopping test") self.log.warning("stopping test")
pass self.current_status = self.send_enquiry("current_status")
status = self.get_status_param("state")
if status =='0':
self.log.info("ready to start")
else:
self.log.warning("error state, performing self check to reset")
self.send_command("self_check")
def get_status_param(self,param):
par_len = 1
if param=="state":
tag="f"
tag_idx=self.current_status.find(b'f')
data=self.current_status[tag_idx+1:tag_idx+1+par_len]
return str(data,encoding="ascii")
def get_test_results(self): def get_test_results(self):
self.log.info("getting test results") self.log.info("getting test results")
return {r: self.read(r) for r in [
#"Running test: phase backwards time",
"Running test: filling pressure",
"Running test: pressure at the end of settling",
#"Running test: burst pressure",
"Running test: measured leak",
#"Running test: calculated leak flow rate",
#"Running test: calculate RVP%",
"Running test: result",
]}
def write_recipe(self, recipe, step, table=None): def write_recipe(self, recipe, step, table=None):
if table is None: # PREPARE DATA
table = self.max_program_number product_id='"'+recipe.part_number[:16]+'"'
recipe_name = recipe.part_number[:16].encode("ascii") product_id=product_id.encode("ascii")
recipe_name += b"\x00" * (16 - len(recipe_name)) test_press_bar=step.spec["test_pressure"]/1000
recipe_barcode = f"j{recipe.part_number}"[:16].encode("ascii") prefill_press_bar=step.spec["pre_filling_pressure"]/1000
recipe_barcode += b"\x00" * (24 - len(recipe_barcode)) tolerance=int(step.spec["settling_pressure_min_percent"])
test_flags = 0b0110100001010100 if (step.spec.get("autotest", False) in ["ko_check"]) else 0b0110000001010100 fail_pos=test_press_bar+(int(step.spec["test_pressure_qpos"])/1000)
pid_mode = int(self.config["recipes_defaults"]["pid_mode"])<<4 fail_neg=test_press_bar+(int(step.spec["test_pressure_qneg"])/1000)
test_flags = test_flags | pid_mode fill_time=float(step.spec["filling_time"])
pid_ramps=0b0000000000000000 | int(self.config["recipes_defaults"]["pid_level"])<<8 | int(self.config["recipes_defaults"]["pid_speed"])<<12 stab_time=float(step.spec["settling_time"])
spec = { test_time=float(step.spec["test_time"])
"Flag: Instrument settings": 0b0000000000000000, prefill_time=float(step.spec["pre_filling_time"])
"Test program for read/write operation": table, vent_time=float(step.spec["flush_time"])
**{719 - 1 + i: (recipe_name[i * 2 + 1] << 8) + recipe_name[i * 2] for i in range(8)}, # program name # SEND RECIPE PARAMETERS
**{727 - 1 + i: (recipe_barcode[i * 2 + 1] << 8) + recipe_barcode[i * 2] for i in range(12)}, # program associated bar-code self.send_command("change_cur_prod_50")
**{761 - 1 + i: (recipe_name[i * 2 + 1] << 8) + recipe_name[i * 2] for i in range(8)}, # print field 1 self.send_product_tag("product_id", product_id)
# **{769 - 1 + i: (recipe_name[i * 2 + 1] << 8) + recipe_name[i * 2] for i in range(8)}, # print field 2 self.send_product_tag("prefill_pressure", f"{prefill_press_bar:2.3f}")
"Print options": 0b0000000000000000 | self.saver_label_count << 12 | self.saver_print_on_fail << 8 | self.saver_label_template, self.send_product_tag("test_pressure", f"{test_press_bar:2.3f}")
"Test type": "Leak Test", self.send_product_tag("tolerance", f"{tolerance:3.1f}")
"Test flags": test_flags, self.send_product_tag("+fail", f"{fail_pos:3.1f}")
"T0 - Pre-filling time": step.spec["pre_filling_time"], self.send_product_tag("-fail", f"{fail_neg:3.1f}")
"P0 - Pre-filling pressure": step.spec["pre_filling_pressure"], self.send_product_tag("fill_time", f"{fill_time:3.1f}")
"T1 - Filling time": step.spec["filling_time"], self.send_product_tag("stab_time", f"{stab_time:3.1f}")
"T2 - Settling time": step.spec["settling_time"], self.send_product_tag("test_time", f"{test_time:3.1f}")
"PR- - Min pressure tolerance %": step.spec["settling_pressure_min_percent"], self.send_product_tag("prefill_time", f"{prefill_time:3.1f}")
"PR+ - Max pressure tolerance % (P+)": step.spec["settling_pressure_max_percent"], self.send_product_tag("vent_time", f"{vent_time:3.1f}")
"T3 - Measure time": step.spec["test_time"], self.send_product_tag("fail_high", f"{fail_pos:3.1f}")
"Q- Lower test leak limit": step.spec["test_pressure_qneg"], self.send_product_tag("fail_low", f"{fail_neg:3.1f}")
"PREL - Nominal test pressure": step.spec["test_pressure"], self.send_product_tag("outputs_a_h", f"{int(0b01000000)}")
"Q+ Upper test leak limit": step.spec["test_pressure_qpos"],
"FST - Discharge time": step.spec["flush_time"],
"FSL - Discharge limit": step.spec["flush_pressure"],
"PSQ - Next sequence program PSOUT mode": 0,
"RAMPS: T1 configuration": pid_ramps,
"PID: pressure correction": 100,
"Various flags": 0b0000000000010000 if self.config["recipes_defaults"]["tecna_discharge_enable"]=="yes" else 0b0000000000000000
}
self.log.debug(str(spec))
for register, value in spec.items():
self.write(register, value)
def send_command(self,command): def send_command(self,command):
if type(command) is str:
command=self.registers[command]
out_bytes= bytearray() out_bytes= bytearray()
out_bytes.extend(EOT) out_bytes.extend(EOT)
out_bytes.extend(self.id1) out_bytes.extend(self.id1)
@ -277,10 +160,12 @@ class FurnessControlsLeakTester(Component):
if response == ACK: if response == ACK:
return True return True
else: else:
self.log.error(f"SEND COMMAND:{response}") self.log.error(f"SEND COMMAND({command}):{response}")
return None return None
def send_enquiry(self,enquiry): def send_enquiry(self,enquiry):
if type(enquiry) is str:
enquiry=self.registers[enquiry]
out_bytes=bytearray(EOT) out_bytes=bytearray(EOT)
out_bytes.extend(self.id1) out_bytes.extend(self.id1)
out_bytes.extend(self.id2) out_bytes.extend(self.id2)
@ -291,14 +176,26 @@ class FurnessControlsLeakTester(Component):
self.conn.write(out_bytes) self.conn.write(out_bytes)
response = self.conn.read(100) response = self.conn.read(100)
if len(response):
read_checksum = response[-1] read_checksum = response[-1]
else:
read_checksum = None
calculated_checksum = self.calc_checksum(response[0:-1],start_idx=0) calculated_checksum = self.calc_checksum(response[0:-1],start_idx=0)
if read_checksum != calculated_checksum: if read_checksum != calculated_checksum:
self.log.error(f"SEND COMMAND:{response}") self.log.error(f"SEND COMMAND:{response}")
else: else:
return response return response
def calc_checksum(self,data,start_idx=1): def send_product_tag(self,tag,tag_data):
self.log.info(f"Sending tag:{tag}={tag_data}")
command=bytearray(self.registers["product_data"])
if type(tag_data) is str:
tag_data=bytearray(tag_data,encoding="ascii")
command.extend(self.product_tags[tag])
command.extend(tag_data)
self.send_command(command)
@staticmethod
def calc_checksum(data, start_idx=1):
checksum = 0 checksum = 0
for i, data_byte in enumerate(data): for i, data_byte in enumerate(data):
if i < start_idx: if i < start_idx:

View File

@ -34,7 +34,7 @@ class Recipe_Selection(Widget):
self.defaults = self.config.get("recipes_defaults", noner) self.defaults = self.config.get("recipes_defaults", noner)
self.unsupported_steps = unsupported_steps self.unsupported_steps = unsupported_steps
if not self.second_leak_test_enabled: if not self.second_leak_test_enabled:
self.unsupported_steps.add("second_leak_test") self.unsupported_steps.add("leak_2")
session = Users.get_session() session = Users.get_session()
if session.is_admin: if session.is_admin:
readonly = False readonly = False
@ -129,7 +129,7 @@ class Recipe_Selection(Widget):
self.delete_all_b.setVisible(False) self.delete_all_b.setVisible(False)
# TESTING # TESTING
if "--auto-select" in sys.argv: if "--auto-select" in sys.argv:
recipe = "000952054" recipe = "R54967"
cn = self.crud.select_index["name"] cn = self.crud.select_index["name"]
self.crud.db_tw.clearSelection() self.crud.db_tw.clearSelection()
for rn in range(1, self.crud.db_tw.rowCount()): for rn in range(1, self.crud.db_tw.rowCount()):

View File

@ -12,6 +12,7 @@ from ui.screws_step_editor import Screws_Step_Editor
from ui.vision_step_editor import Vision_Step_Editor from ui.vision_step_editor import Vision_Step_Editor
from ui.instruction_step_editor import Instruction_Step_Editor from ui.instruction_step_editor import Instruction_Step_Editor
class Recipe_Spec_And_Step_Editor(Editor): class Recipe_Spec_And_Step_Editor(Editor):
def __init__(self, action=None, cell_widget=None, unsupported_steps=None): def __init__(self, action=None, cell_widget=None, unsupported_steps=None):
super().__init__(action=action, cell_widget=cell_widget) super().__init__(action=action, cell_widget=cell_widget)

View File

@ -55,6 +55,7 @@ class Test(Widget):
else: else:
self.recipe_selection_mode = "table" self.recipe_selection_mode = "table"
self.step = None self.step = None
self.tester_component = "tecna_t3" if "tecna_t3" in self.components.keys() else "furness_controls"
self.unsupported_steps = set() self.unsupported_steps = set()
self.steps_dependencies = { self.steps_dependencies = {
"count": set(), "count": set(),
@ -62,8 +63,8 @@ class Test(Widget):
"instruction":{"digital_io"}, "instruction":{"digital_io"},
"screws": {"screwdriver", "tecna_t3", }, "screws": {"screwdriver", "tecna_t3", },
"resistance": {"multicomp", }, "resistance": {"multicomp", },
"leak_1": {"tecna_t3", }, "leak_1": {self.tester_component, },
"leak_2": {"tecna_t3", }, "leak_2": {self.tester_component, },
"vision": {("uvc_camera", "galaxy_camera", ), "vision", "vision_saver", }, # "neo_pixels", }, "vision": {("uvc_camera", "galaxy_camera", ), "vision", "vision_saver", }, # "neo_pixels", },
"print": {"label_printer", }, "print": {"label_printer", },
} }

View File

@ -105,10 +105,10 @@ class Test_Leak(Test_Test):
self.meas_time_l.setText(f"{self.step.spec['test_time']}") self.meas_time_l.setText(f"{self.step.spec['test_time']}")
# SETUP TEST LOOP # SETUP TEST LOOP
if self.step.spec.get("autotest", False) != False: # IF AUTOTESTING UPLOAD RECIPE EVERY TIME if self.step.spec.get("autotest", False): # IF AUTOTESTING UPLOAD RECIPE EVERY TIME
self.recipe_written = False self.recipe_written = False
if self.parent.config["hardware_config"].get("second_leak_test", None) != False: # IF SECOND LEAK TEST ENABLED UPLOAD RECIPE EVERY TIME if self.parent.config["hardware_config"].get("second_leak_test", None): # IF SECOND LEAK TEST ENABLED UPLOAD RECIPE EVERY TIME
self.recipe_written = False self.recipe_written = False
if not self.recipe_written: if not self.recipe_written: