From d6a5497020e8036b3a6fff95f11eb20b78a1a597 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:09:14 -0500 Subject: [PATCH 1/9] add some files --- hardware-testing/Makefile | 4 + .../modules/flex_stacker_evt_qc/__init__.py | 1 + .../modules/flex_stacker_evt_qc/__main__.py | 76 ++++++++++++++ .../modules/flex_stacker_evt_qc/config.py | 45 +++++++++ .../modules/flex_stacker_evt_qc/driver.py | 84 ++++++++++++++++ .../flex_stacker_evt_qc/test_connectivity.py | 98 +++++++++++++++++++ 6 files changed, 308 insertions(+) create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__init__.py create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py diff --git a/hardware-testing/Makefile b/hardware-testing/Makefile index 87edd408aa7..45b50b5a579 100755 --- a/hardware-testing/Makefile +++ b/hardware-testing/Makefile @@ -166,6 +166,10 @@ test-liquid-sense: .PHONY: test-integration test-integration: test-production-qc test-examples test-scripts test-gravimetric +.PHONY: test-stacker +test-stacker: + $(python) -m hardware_testing.modules.flex_stacker_evt_qc --simulate + .PHONY: lint lint: $(python) -m mypy hardware_testing tests diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__init__.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__init__.py new file mode 100644 index 00000000000..b79a4e5b836 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__init__.py @@ -0,0 +1 @@ +"""FLEX Stacker QC scripts for EVT.""" diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py new file mode 100644 index 00000000000..9eeb69a4c19 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py @@ -0,0 +1,76 @@ +"""FLEX Stacker EVT QC.""" +from os import environ + +# NOTE: this is required to get WIFI test to work +if "OT_SYSTEM_VERSION" not in environ: + environ["OT_SYSTEM_VERSION"] = "0.0.0" + +import argparse +import asyncio +from pathlib import Path +from typing import Tuple + +from hardware_testing.data import ui +from hardware_testing.opentrons_api import helpers_ot3 +from hardware_testing.data.csv_report import CSVReport + +from .config import TestSection, TestConfig, build_report, TESTS +from .driver import FlexStacker + + +def build_stacker_report(is_simulating: bool) -> Tuple[CSVReport, FlexStacker]: + """Report setup for FLEX Stacker qc script.""" + + test_name = Path(__file__).parent.name.replace("_", "-") + ui.print_title(test_name.upper()) + + stacker = FlexStacker.build_simulator() if is_simulating else FlexStacker.build() + + report = build_report(test_name) + report.set_operator( + "simulating" if is_simulating else input("enter OPERATOR name: ") + ) + info = stacker.get_device_info() + if not is_simulating: + barcode = input("SCAN device barcode: ").strip() + else: + barcode = "STACKER-SIMULATOR-SN" + report.set_tag(info.sn) + report.set_device_id(info.sn, barcode) + return report, stacker + + +async def _main(cfg: TestConfig) -> None: + # BUILD REPORT + report, stacker = build_stacker_report(cfg.simulate) + + # RUN TESTS + for section, test_run in cfg.tests.items(): + ui.print_title(section.value) + test_run(stacker, report, section.value) + + # SAVE REPORT + ui.print_title("DONE") + report.save_to_disk() + report.print_results() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--simulate", action="store_true") + # add each test-section as a skippable argument (eg: --skip-connectivity) + for s in TestSection: + parser.add_argument(f"--skip-{s.value.lower()}", action="store_true") + parser.add_argument(f"--only-{s.value.lower()}", action="store_true") + args = parser.parse_args() + _t_sections = {s: f for s, f in TESTS if getattr(args, f"only_{s.value.lower()}")} + if _t_sections: + assert ( + len(list(_t_sections.keys())) < 2 + ), 'use "--only" for just one test, not multiple tests' + else: + _t_sections = { + s: f for s, f in TESTS if not getattr(args, f"skip_{s.value.lower()}") + } + _config = TestConfig(simulate=args.simulate, tests=_t_sections) + asyncio.run(_main(_config)) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py new file mode 100644 index 00000000000..e8bc37da959 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py @@ -0,0 +1,45 @@ +"""Config.""" +from dataclasses import dataclass +import enum +from typing import Dict, Callable + +from hardware_testing.data.csv_report import CSVReport, CSVSection + +from . import ( + test_connectivity, +) + + +class TestSection(enum.Enum): + """Test Section.""" + + CONNECTIVITY = "CONNECTIVITY" + + +@dataclass +class TestConfig: + """Test Config.""" + + simulate: bool + tests: Dict[TestSection, Callable] + + +TESTS = [ + ( + TestSection.CONNECTIVITY, + test_connectivity.run, + ), +] + + +def build_report(test_name: str) -> CSVReport: + """Build report.""" + return CSVReport( + test_name=test_name, + sections=[ + CSVSection( + title=TestSection.CONNECTIVITY.value, + lines=test_connectivity.build_csv_lines(), + ) + ], + ) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py new file mode 100644 index 00000000000..a694dd6780e --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -0,0 +1,84 @@ +from dataclasses import dataclass +import serial +from serial.tools.list_ports import comports +import re +from enum import Enum + +STACKER_VID = 0x483 +STACKER_PID = 0xEF24 +STACKER_FREQ = 115200 + + +class HardwareRevision(Enum): + """Hardware Revision.""" + + NFF = "nff" + EVT = "a1" + + +@dataclass +class StackerInfo: + """Stacker Info.""" + + fw: str + hw: HardwareRevision + sn: str + + +class FlexStacker: + """FLEX Stacker Driver.""" + + @classmethod + def build(cls, port: str = "") -> "FlexStacker": + if not port: + for i in comports(): + if i.vid == STACKER_VID and i.pid == STACKER_PID: + port = i.device + break + assert port, "could not find connected FLEX Stacker" + return cls(port) + + @classmethod + def build_simulator(cls, port: str = "") -> "FlexStacker": + return cls(port, simulating=True) + + def __init__(self, port: str, simulating: bool = False) -> None: + self._serial = serial.Serial(port, baudrate=STACKER_FREQ) + self._simulating = simulating + + def _send_and_recv(self, msg: str, guard_ret: str = "") -> str: + """Internal utility to send a command and receive the response""" + self._serial.write(msg.encode()) + ret = self._serial.readline() + if guard_ret: + if not ret.startswith(guard_ret.encode()): + raise RuntimeError(f"Incorrect Response: {ret}") + if ret.startswith("ERR".encode()): + raise RuntimeError(ret) + return ret.decode() + + def get_device_info(self) -> StackerInfo: + """Get Device Info.""" + if self._simulating: + return StackerInfo( + "STACKER-FW", HardwareRevision.EVT, "STACKER-SIMULATOR-SN" + ) + + _DEV_INFO_RE = re.compile( + "^M115 FW:(?P.+) HW:Opentrons-flex-stacker-(?P.+) SerialNo:(?P.+) OK\n" + ) + res = self._send_and_recv("M115\n", "M115 FW:") + m = _DEV_INFO_RE.match(res) + if not m: + raise RuntimeError(f"Incorrect Response: {res}") + return StackerInfo( + m.group("fw"), HardwareRevision(m.group("hw")), m.group("sn") + ) + + def set_serial_number(self, sn: str) -> None: + if self._simulating: + return + self._send_and_recv(f"M996 {sn}\n", "M996 OK") + + def __del__(self) -> None: + self._serial.close() diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py new file mode 100644 index 00000000000..72655c72831 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py @@ -0,0 +1,98 @@ +# Validate USB communication works +# EX: Just send and receive a simple status GCODE, perhaps M119 for limit switch status. +# Validate EEPROM can be read and written +# EX: Write random data to EEPROM, read data back out and check validity +# We can flash the serial number as the EEPROM check or do the serial number just after the FW has been flashed +# Validate MCU LED works +# EX: This could just be validating it is flashing with the “heartbeat” +"""Test Connectivity.""" +import asyncio +from typing import List, Union + +from hardware_testing.data import ui +from hardware_testing.data.csv_report import ( + CSVReport, + CSVLine, + CSVLineRepeating, + CSVResult, +) + +from .driver import FlexStacker, HardwareRevision + +import logging + +LOG = logging.getLogger + +LOG = logging.getLogger(__name__) + +loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict] +for logger in loggers: + logger.setLevel(logging.CRITICAL) + +LOG.setLevel(logging.CRITICAL) + + +def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: + """Build CSV Lines.""" + return [ + CSVLine("usb-get-device-info", [str, str, str, CSVResult]), + CSVLine("eeprom-set-serial-number", [str, str, CSVResult]), + CSVLine("led-blinking", [bool, CSVResult]), + ] + + +def test_gcode(driver: FlexStacker, report: CSVReport): + """Send and receive response for GCODE M115.""" + success = True + info = driver.get_device_info() + print("Hardware Revision: ", info.hw, "\n") + if info is None or info.hw != HardwareRevision.EVT: + print("Hardware Revision must be EVT") + success = False + report( + "CONNECTIVITY", + "usb-get-device-info", + [info.fw, info.hw, info.sn, CSVResult.from_bool(success)], + ) + + +def test_eeprom(driver: FlexStacker, report: CSVReport): + """Set serial number and make sure device info is updated accordingly.""" + success = True + if not driver._simulating: + serial = input("enter Serial Number: ") + else: + serial = "STACKER-SIMULATOR-SN" + driver.set_serial_number(serial) + info = driver.get_device_info() + if info.sn != serial: + print("Serial number is not set properly") + success = False + report( + "CONNECTIVITY", + "eeprom-set-serial-number", + [serial, info.sn, CSVResult.from_bool(success)], + ) + + +def test_leds(driver: FlexStacker, report: CSVReport): + """Prompt tester to verify the status led is blinking.""" + if not driver._simulating: + is_blinking = ui.get_user_answer("Is the status LED blinking?") + else: + is_blinking = True + report( + "CONNECTIVITY", "led-blinking", [is_blinking, CSVResult.from_bool(is_blinking)] + ) + + +def run(driver: FlexStacker, report: CSVReport, section: str): + """Run.""" + ui.print_header("USB Communication") + test_gcode(driver, report) + + ui.print_header("EEPROM Communication") + test_eeprom(driver, report) + + ui.print_header("LED Blinking") + test_leds(driver, report) From 2b58d3e94d00a9a8a579a6a4145b946c89a5f852 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:58:59 -0500 Subject: [PATCH 2/9] formatting --- .../modules/flex_stacker_evt_qc/__main__.py | 2 -- .../modules/flex_stacker_evt_qc/driver.py | 12 ++++++-- .../flex_stacker_evt_qc/test_connectivity.py | 28 +++---------------- 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py index 9eeb69a4c19..2c4890023d4 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/__main__.py @@ -11,7 +11,6 @@ from typing import Tuple from hardware_testing.data import ui -from hardware_testing.opentrons_api import helpers_ot3 from hardware_testing.data.csv_report import CSVReport from .config import TestSection, TestConfig, build_report, TESTS @@ -20,7 +19,6 @@ def build_stacker_report(is_simulating: bool) -> Tuple[CSVReport, FlexStacker]: """Report setup for FLEX Stacker qc script.""" - test_name = Path(__file__).parent.name.replace("_", "-") ui.print_title(test_name.upper()) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py index a694dd6780e..d1a859a4093 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -1,6 +1,7 @@ +"""FLEX Stacker Driver.""" from dataclasses import dataclass -import serial -from serial.tools.list_ports import comports +import serial # type: ignore[import] +from serial.tools.list_ports import comports # type: ignore[import] import re from enum import Enum @@ -30,6 +31,7 @@ class FlexStacker: @classmethod def build(cls, port: str = "") -> "FlexStacker": + """Build FLEX Stacker driver.""" if not port: for i in comports(): if i.vid == STACKER_VID and i.pid == STACKER_PID: @@ -40,14 +42,16 @@ def build(cls, port: str = "") -> "FlexStacker": @classmethod def build_simulator(cls, port: str = "") -> "FlexStacker": + """Build FLEX Stacker simulator.""" return cls(port, simulating=True) def __init__(self, port: str, simulating: bool = False) -> None: + """Constructor.""" self._serial = serial.Serial(port, baudrate=STACKER_FREQ) self._simulating = simulating def _send_and_recv(self, msg: str, guard_ret: str = "") -> str: - """Internal utility to send a command and receive the response""" + """Internal utility to send a command and receive the response.""" self._serial.write(msg.encode()) ret = self._serial.readline() if guard_ret: @@ -76,9 +80,11 @@ def get_device_info(self) -> StackerInfo: ) def set_serial_number(self, sn: str) -> None: + """Set Serial Number.""" if self._simulating: return self._send_and_recv(f"M996 {sn}\n", "M996 OK") def __del__(self) -> None: + """Close serial port.""" self._serial.close() diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py index 72655c72831..86a0bda991d 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_connectivity.py @@ -1,12 +1,4 @@ -# Validate USB communication works -# EX: Just send and receive a simple status GCODE, perhaps M119 for limit switch status. -# Validate EEPROM can be read and written -# EX: Write random data to EEPROM, read data back out and check validity -# We can flash the serial number as the EEPROM check or do the serial number just after the FW has been flashed -# Validate MCU LED works -# EX: This could just be validating it is flashing with the “heartbeat” """Test Connectivity.""" -import asyncio from typing import List, Union from hardware_testing.data import ui @@ -19,18 +11,6 @@ from .driver import FlexStacker, HardwareRevision -import logging - -LOG = logging.getLogger - -LOG = logging.getLogger(__name__) - -loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict] -for logger in loggers: - logger.setLevel(logging.CRITICAL) - -LOG.setLevel(logging.CRITICAL) - def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: """Build CSV Lines.""" @@ -41,7 +21,7 @@ def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: ] -def test_gcode(driver: FlexStacker, report: CSVReport): +def test_gcode(driver: FlexStacker, report: CSVReport) -> None: """Send and receive response for GCODE M115.""" success = True info = driver.get_device_info() @@ -56,7 +36,7 @@ def test_gcode(driver: FlexStacker, report: CSVReport): ) -def test_eeprom(driver: FlexStacker, report: CSVReport): +def test_eeprom(driver: FlexStacker, report: CSVReport) -> None: """Set serial number and make sure device info is updated accordingly.""" success = True if not driver._simulating: @@ -75,7 +55,7 @@ def test_eeprom(driver: FlexStacker, report: CSVReport): ) -def test_leds(driver: FlexStacker, report: CSVReport): +def test_leds(driver: FlexStacker, report: CSVReport) -> None: """Prompt tester to verify the status led is blinking.""" if not driver._simulating: is_blinking = ui.get_user_answer("Is the status LED blinking?") @@ -86,7 +66,7 @@ def test_leds(driver: FlexStacker, report: CSVReport): ) -def run(driver: FlexStacker, report: CSVReport, section: str): +def run(driver: FlexStacker, report: CSVReport, section: str) -> None: """Run.""" ui.print_header("USB Communication") test_gcode(driver, report) From 6c9ddaf663072ab841b93ffe1d351365a47f4a4a Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:27:16 -0500 Subject: [PATCH 3/9] fix simulator returns --- .../hardware_testing/modules/flex_stacker_evt_qc/driver.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py index d1a859a4093..04d833fa8a5 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -47,11 +47,13 @@ def build_simulator(cls, port: str = "") -> "FlexStacker": def __init__(self, port: str, simulating: bool = False) -> None: """Constructor.""" - self._serial = serial.Serial(port, baudrate=STACKER_FREQ) self._simulating = simulating + if not self._simulating: + self._serial = serial.Serial(port, baudrate=STACKER_FREQ) def _send_and_recv(self, msg: str, guard_ret: str = "") -> str: """Internal utility to send a command and receive the response.""" + assert self._simulating self._serial.write(msg.encode()) ret = self._serial.readline() if guard_ret: @@ -87,4 +89,5 @@ def set_serial_number(self, sn: str) -> None: def __del__(self) -> None: """Close serial port.""" - self._serial.close() + if not self._simulating: + self._serial.close() From a5ff2de3fadd4723f7b28824092b25956006dfd1 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:19:44 -0500 Subject: [PATCH 4/9] add z test --- .../modules/flex_stacker_evt_qc/config.py | 12 ++- .../modules/flex_stacker_evt_qc/driver.py | 67 +++++++++++++ .../flex_stacker_evt_qc/test_z_axis.py | 96 +++++++++++++++++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py index e8bc37da959..b890fba62f7 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py @@ -7,6 +7,7 @@ from . import ( test_connectivity, + test_z_axis, ) @@ -14,6 +15,7 @@ class TestSection(enum.Enum): """Test Section.""" CONNECTIVITY = "CONNECTIVITY" + Z_AXIS = "Z_AXIS" @dataclass @@ -29,6 +31,10 @@ class TestConfig: TestSection.CONNECTIVITY, test_connectivity.run, ), + ( + TestSection.Z_AXIS, + test_z_axis.run, + ), ] @@ -40,6 +46,10 @@ def build_report(test_name: str) -> CSVReport: CSVSection( title=TestSection.CONNECTIVITY.value, lines=test_connectivity.build_csv_lines(), - ) + ), + CSVSection( + title=TestSection.Z_AXIS.value, + lines=test_z_axis.build_csv_lines(), + ), ], ) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py index 04d833fa8a5..bb0a14ff473 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -26,6 +26,41 @@ class StackerInfo: sn: str +class StackerAxis(Enum): + """Stacker Axis.""" + + X = "X" + Z = "Z" + L = "L" + + +class Direction(Enum): + """Direction.""" + + RETRACT = 0 + EXTENT = 1 + + def opposite(self) -> "Direction": + """Get opposite direction.""" + return Direction.EXTENT if self == Direction.RETRACT else Direction.RETRACT + + +@dataclass +class MoveParams: + """Move Parameters.""" + + max_speed: float | None = None + acceleration: float | None = None + max_speed_discont: float | None = None + + def __str__(self) -> str: + """Convert to string.""" + v = "V:" + str(self.max_speed) if self.max_speed else "" + a = "A:" + str(self.acceleration) if self.acceleration else "" + d = "D:" + str(self.max_speed_discont) if self.max_speed_discont else "" + return f"{v} {a} {d}".strip() + + class FlexStacker: """FLEX Stacker Driver.""" @@ -87,6 +122,38 @@ def set_serial_number(self, sn: str) -> None: return self._send_and_recv(f"M996 {sn}\n", "M996 OK") + def get_limit_switch(self, axis: StackerAxis, direction: Direction) -> bool: + """Get limit switch status. + + :return: True if limit switch is triggered, False otherwise + """ + if self._simulating: + return True + + _LS_RE = re.compile(rf"^M119 .*{axis.name}{direction.name[0]}:(\d) .*\n") + res = self._send_and_recv("M119\n", "M119 XE:") + match = _LS_RE.match(res) + assert match, f"Incorrect Response for limit switch: {res}" + return bool(int(match.group(1))) + + def move_in_mm( + self, axis: StackerAxis, distance: float, params: MoveParams | None = None + ) -> None: + """Move axis.""" + if self._simulating: + return + self._send_and_recv(f"G0 {axis.name}{distance} {params or ''}\n", "G0 OK") + + def move_to_limit_switch( + self, axis: StackerAxis, direction: Direction, params: MoveParams | None = None + ) -> None: + """Move until limit switch is triggered.""" + if self._simulating: + return + self._send_and_recv( + f"G5 {axis.name}{direction.value} {params or ''}\n", "G0 OK" + ) + def __del__(self) -> None: """Close serial port.""" if not self._simulating: diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py new file mode 100644 index 00000000000..65d185df748 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py @@ -0,0 +1,96 @@ +"""Test Z Axis.""" +from typing import List, Tuple, Union +from hardware_testing.data import ui +from hardware_testing.data.csv_report import ( + CSVReport, + CSVLine, + CSVLineRepeating, + CSVResult, +) + +from .driver import FlexStacker, StackerAxis, Direction, MoveParams + + +class LimitSwitchError(Exception): + """Limit Switch Error.""" + + pass + + +def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: + """Build CSV Lines.""" + return [ + CSVLine("initial-limit-switches", [bool, bool, CSVResult]), + CSVLine("positive-switch-triggered-at-default", [bool]), + CSVLine("positive-switch-untriggered", [CSVResult]), + CSVLine("trigger-positive-switch", [CSVResult]), + CSVLine("negative-switch-triggered-at-default", [bool]), + CSVLine("negative-switch-untriggered", [CSVResult]), + CSVLine("trigger-negative-switch", [CSVResult]), + ] + + +def get_limit_switches(driver: FlexStacker) -> Tuple[bool, bool]: + """Get limit switches.""" + z_extent = driver.get_limit_switch(StackerAxis.Z, Direction.EXTENT) + z_retract = driver.get_limit_switch(StackerAxis.Z, Direction.RETRACT) + print("(Switch triggered) Positive: ", z_extent, "; Negative: ", z_retract) + return z_extent, z_retract + + +def test_limit_switch( + driver: FlexStacker, direction: Direction, report: CSVReport, section: str, tag: str +) -> None: + """Sequence to test the limit switch for one direction.""" + triggered = get_limit_switches(driver)[direction.value] + + if triggered: + print( + "Limit switch already triggered, moving in opposite direction to untrigger..." + ) + report(section, f"{tag}-switch-triggered-at-default", [True]) + driver.move_in_mm( + StackerAxis.Z, 10 * (-1 if direction == Direction.EXTENT else 1) + ) + + triggered = get_limit_switches(driver)[direction.value] + if triggered: + print("!!! Limit switch still triggered !!!") + report(section, f"{tag}-switch-untriggered", [CSVResult.FAIL]) + return + + report(section, f"{tag}-switch-untriggered", [CSVResult.PASS]) + + print("Move to limit switch at speed: 50 mm/s") + driver.move_to_limit_switch(StackerAxis.Z, direction, MoveParams(max_speed=50)) + triggered = driver.get_limit_switch(StackerAxis.Z, direction) + print(f"Limit switch triggered: {triggered}") + + report(section, f"trigger-{tag}-switch", [CSVResult.from_bool(triggered)]) + + +def report_limit_switches( + driver: FlexStacker, report: CSVReport, section: str, tag: str +) -> bool: + """Report limit switch states.""" + lw_plus, lw_minus = get_limit_switches(driver) + if lw_plus and lw_minus: + print("!!! Limit switches cannot be both triggered !!!") + success = False + else: + success = True + + report(section, tag, [lw_plus, lw_minus, CSVResult.from_bool(success)]) + return success + + +def run(driver: FlexStacker, report: CSVReport, section: str) -> None: + """Run.""" + ui.print_header("Initial Limit Switch States") + report_limit_switches(driver, report, section, "initial-limit-switches") + + ui.print_header("Test Z+ Limit Switch") + test_limit_switch(driver, Direction.EXTENT, report, section, "positive") + + ui.print_header("Test Z- Limit Switch") + test_limit_switch(driver, Direction.RETRACT, report, section, "negative") From 42460a73f27f04b553da6c6ab80af1d69aba4083 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:27:23 -0500 Subject: [PATCH 5/9] PLAT-593 add Latch test --- .../modules/flex_stacker_evt_qc/config.py | 10 +++ .../flex_stacker_evt_qc/test_l_axis.py | 70 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_l_axis.py diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py index b890fba62f7..b28eb0eee07 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py @@ -8,6 +8,7 @@ from . import ( test_connectivity, test_z_axis, + test_l_axis, ) @@ -16,6 +17,7 @@ class TestSection(enum.Enum): CONNECTIVITY = "CONNECTIVITY" Z_AXIS = "Z_AXIS" + L_AXIS = "L_AXIS" @dataclass @@ -35,6 +37,10 @@ class TestConfig: TestSection.Z_AXIS, test_z_axis.run, ), + ( + TestSection.L_AXIS, + test_l_axis.run, + ), ] @@ -51,5 +57,9 @@ def build_report(test_name: str) -> CSVReport: title=TestSection.Z_AXIS.value, lines=test_z_axis.build_csv_lines(), ), + CSVSection( + title=TestSection.L_AXIS.value, + lines=test_l_axis.build_csv_lines(), + ), ], ) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_l_axis.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_l_axis.py new file mode 100644 index 00000000000..d892bdc1fd7 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_l_axis.py @@ -0,0 +1,70 @@ +"""Test L Axis.""" +from typing import List, Union +from hardware_testing.data import ui +from hardware_testing.data.csv_report import ( + CSVReport, + CSVLine, + CSVLineRepeating, + CSVResult, +) + +from .driver import FlexStacker, StackerAxis, Direction + + +class LimitSwitchError(Exception): + """Limit Switch Error.""" + + pass + + +def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: + """Build CSV Lines.""" + return [ + CSVLine("trigger-latch-switch", [CSVResult]), + CSVLine("release/open-latch", [CSVResult]), + CSVLine("hold/close-latch", [CSVResult]), + ] + + +def get_latch_held_switch(driver: FlexStacker) -> bool: + """Get limit switch.""" + held_switch = driver.get_limit_switch(StackerAxis.L, Direction.RETRACT) + print("(Held Switch triggered) : ", held_switch) + return held_switch + + +def close_latch(driver: FlexStacker) -> None: + """Close latch.""" + driver.move_to_limit_switch(StackerAxis.L, Direction.EXTENT) + + +def open_latch(driver: FlexStacker) -> None: + """Open latch.""" + driver.move_in_mm(StackerAxis.L, -22) + + +def run(driver: FlexStacker, report: CSVReport, section: str) -> None: + """Run.""" + if not get_latch_held_switch(driver): + print("Switch is not triggered, try to trigger it by closing latch...") + close_latch(driver) + if not get_latch_held_switch(driver): + print("!!! Held switch is still not triggered !!!") + report(section, "trigger-latch-switch", [CSVResult.FAIL]) + return + + report(section, "trigger-latch-switch", [CSVResult.PASS]) + + ui.print_header("Latch Release/Open") + open_latch(driver) + success = not get_latch_held_switch(driver) + report(section, "release/open-latch", [CSVResult.from_bool(success)]) + + ui.print_header("Latch Hold/Close") + if not success: + print("Latch must be open to close it") + report(section, "hold/close-latch", [CSVResult.FAIL]) + else: + close_latch(driver) + success = get_latch_held_switch(driver) + report(section, "hold/close-latch", [CSVResult.from_bool(success)]) From abddf68e6da9cdf6856048e4b362759e0208f227 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:55:04 -0500 Subject: [PATCH 6/9] add test utils --- .../modules/flex_stacker_evt_qc/driver.py | 42 +++++++++- .../flex_stacker_evt_qc/test_z_axis.py | 83 ++----------------- .../modules/flex_stacker_evt_qc/utils.py | 36 ++++++++ 3 files changed, 83 insertions(+), 78 deletions(-) create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py index bb0a14ff473..4b9b8f90ca2 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -33,6 +33,10 @@ class StackerAxis(Enum): Z = "Z" L = "L" + def __str__(self) -> str: + """Name.""" + return self.name + class Direction(Enum): """Direction.""" @@ -40,9 +44,17 @@ class Direction(Enum): RETRACT = 0 EXTENT = 1 + def __str__(self) -> str: + """Convert to tag for clear logging.""" + return "negative" if self == Direction.RETRACT else "positive" + def opposite(self) -> "Direction": """Get opposite direction.""" return Direction.EXTENT if self == Direction.RETRACT else Direction.RETRACT + + def distance(self, distance: float) -> float: + """Get signed distance, where retract direction is negative.""" + return distance * -1 if self == Direction.RETRACT else distance @dataclass @@ -130,12 +142,40 @@ def get_limit_switch(self, axis: StackerAxis, direction: Direction) -> bool: if self._simulating: return True - _LS_RE = re.compile(rf"^M119 .*{axis.name}{direction.name[0]}:(\d) .*\n") + _LS_RE = re.compile(rf"^M119 .*{axis.name}{direction.name[0]}:(\d) .* OK\n") res = self._send_and_recv("M119\n", "M119 XE:") match = _LS_RE.match(res) assert match, f"Incorrect Response for limit switch: {res}" return bool(int(match.group(1))) + def get_platform_sensor(self, direction: Direction) -> bool: + """Get platform sensor status. + + :return: True if platform is present, False otherwise + """ + if self._simulating: + return True + + _LS_RE = re.compile(rf"^M121 .*{direction.name[0]}:(\d) .* OK\n") + res = self._send_and_recv("M121\n", "M119 E:") + match = _LS_RE.match(res) + assert match, f"Incorrect Response for platform sensor: {res}" + return bool(int(match.group(1))) + + def get_hopper_door_closed(self) -> bool: + """Get whether or not door is closed. + + :return: True if door is closed, False otherwise + """ + if self._simulating: + return True + + _LS_RE = re.compile(r"^M122 (\d) OK\n") + res = self._send_and_recv("M122\n", "M122 ") + match = _LS_RE.match(res) + assert match, f"Incorrect Response for hopper door switch: {res}" + return bool(int(match.group(1))) + def move_in_mm( self, axis: StackerAxis, distance: float, params: MoveParams | None = None ) -> None: diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py index 65d185df748..fc34175ec54 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py @@ -8,89 +8,18 @@ CSVResult, ) -from .driver import FlexStacker, StackerAxis, Direction, MoveParams - - -class LimitSwitchError(Exception): - """Limit Switch Error.""" - - pass - +from .utils import test_limit_switches_per_direction +from .driver import FlexStacker, StackerAxis, Direction def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: """Build CSV Lines.""" return [ - CSVLine("initial-limit-switches", [bool, bool, CSVResult]), - CSVLine("positive-switch-triggered-at-default", [bool]), - CSVLine("positive-switch-untriggered", [CSVResult]), - CSVLine("trigger-positive-switch", [CSVResult]), - CSVLine("negative-switch-triggered-at-default", [bool]), - CSVLine("negative-switch-untriggered", [CSVResult]), - CSVLine("trigger-negative-switch", [CSVResult]), + CSVLine("limit-switch-trigger-positive-untrigger-negative", [bool, bool, CSVResult]), + CSVLine("limit-switch-trigger-negative-untrigger-positive", [bool, bool, CSVResult]), ] - -def get_limit_switches(driver: FlexStacker) -> Tuple[bool, bool]: - """Get limit switches.""" - z_extent = driver.get_limit_switch(StackerAxis.Z, Direction.EXTENT) - z_retract = driver.get_limit_switch(StackerAxis.Z, Direction.RETRACT) - print("(Switch triggered) Positive: ", z_extent, "; Negative: ", z_retract) - return z_extent, z_retract - - -def test_limit_switch( - driver: FlexStacker, direction: Direction, report: CSVReport, section: str, tag: str -) -> None: - """Sequence to test the limit switch for one direction.""" - triggered = get_limit_switches(driver)[direction.value] - - if triggered: - print( - "Limit switch already triggered, moving in opposite direction to untrigger..." - ) - report(section, f"{tag}-switch-triggered-at-default", [True]) - driver.move_in_mm( - StackerAxis.Z, 10 * (-1 if direction == Direction.EXTENT else 1) - ) - - triggered = get_limit_switches(driver)[direction.value] - if triggered: - print("!!! Limit switch still triggered !!!") - report(section, f"{tag}-switch-untriggered", [CSVResult.FAIL]) - return - - report(section, f"{tag}-switch-untriggered", [CSVResult.PASS]) - - print("Move to limit switch at speed: 50 mm/s") - driver.move_to_limit_switch(StackerAxis.Z, direction, MoveParams(max_speed=50)) - triggered = driver.get_limit_switch(StackerAxis.Z, direction) - print(f"Limit switch triggered: {triggered}") - - report(section, f"trigger-{tag}-switch", [CSVResult.from_bool(triggered)]) - - -def report_limit_switches( - driver: FlexStacker, report: CSVReport, section: str, tag: str -) -> bool: - """Report limit switch states.""" - lw_plus, lw_minus = get_limit_switches(driver) - if lw_plus and lw_minus: - print("!!! Limit switches cannot be both triggered !!!") - success = False - else: - success = True - - report(section, tag, [lw_plus, lw_minus, CSVResult.from_bool(success)]) - return success - - def run(driver: FlexStacker, report: CSVReport, section: str) -> None: """Run.""" - ui.print_header("Initial Limit Switch States") - report_limit_switches(driver, report, section, "initial-limit-switches") - - ui.print_header("Test Z+ Limit Switch") - test_limit_switch(driver, Direction.EXTENT, report, section, "positive") + test_limit_switches_per_direction(driver, StackerAxis.Z, Direction.EXTENT, report, section) - ui.print_header("Test Z- Limit Switch") - test_limit_switch(driver, Direction.RETRACT, report, section, "negative") + test_limit_switches_per_direction(driver, StackerAxis.Z, Direction.RETRACT, report, section) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py new file mode 100644 index 00000000000..aa71f7c9788 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py @@ -0,0 +1,36 @@ +from hardware_testing.data import ui +from hardware_testing.data.csv_report import ( + CSVReport, + CSVResult, +) + +from .driver import FlexStacker, StackerAxis, Direction, MoveParams + + +def test_limit_switches_per_direction( + driver: FlexStacker, + axis: StackerAxis, + direction: Direction, + report: CSVReport, + section: str, + speed: float = 50.0, +) -> None: + """Sequence to test the limit switch for one direction.""" + ui.print_header(f"{axis} Limit Switch - {direction} direction") + # first make sure switch is not already triggered by moving in the opposite direction + if driver.get_limit_switch(axis, direction): + print(f"{direction} switch already triggered, moving away...\n") + SAFE_DISTANCE = 10 # mm + driver.move_in_mm(axis, direction.opposite().distance(SAFE_DISTANCE)) + + # move until the limit switch is reached + print(f"moving towards {direction} limit switch...\n") + driver.move_to_limit_switch(axis, direction, MoveParams(max_speed=speed)) + result = driver.get_limit_switch(axis, direction) + opposite_result = not driver.get_limit_switch(axis, direction.opposite()) + print(f"{direction} switch triggered: {result}") + print(f"{direction.opposite()} switch untriggered: {opposite_result}") + report(section, + f"limit-switch-trigger-{direction}-untrigger-{direction.opposite()}", + [result, opposite_result, CSVResult.from_bool(result and opposite_result)] + ) \ No newline at end of file From 9e427dabd6ff575d26952578e48b51f9ac5828de Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:15:24 -0500 Subject: [PATCH 7/9] format axes tests --- .../modules/flex_stacker_evt_qc/config.py | 10 +++ .../modules/flex_stacker_evt_qc/driver.py | 4 +- .../flex_stacker_evt_qc/test_x_axis.py | 81 +++++++++++++++++++ .../flex_stacker_evt_qc/test_z_axis.py | 21 +++-- .../modules/flex_stacker_evt_qc/utils.py | 12 +-- 5 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_x_axis.py diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py index b28eb0eee07..a8fc32ca142 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/config.py @@ -8,6 +8,7 @@ from . import ( test_connectivity, test_z_axis, + test_x_axis, test_l_axis, ) @@ -18,6 +19,7 @@ class TestSection(enum.Enum): CONNECTIVITY = "CONNECTIVITY" Z_AXIS = "Z_AXIS" L_AXIS = "L_AXIS" + X_AXIS = "X_AXIS" @dataclass @@ -41,6 +43,10 @@ class TestConfig: TestSection.L_AXIS, test_l_axis.run, ), + ( + TestSection.X_AXIS, + test_x_axis.run, + ), ] @@ -61,5 +67,9 @@ def build_report(test_name: str) -> CSVReport: title=TestSection.L_AXIS.value, lines=test_l_axis.build_csv_lines(), ), + CSVSection( + title=TestSection.X_AXIS.value, + lines=test_x_axis.build_csv_lines(), + ), ], ) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py index 4b9b8f90ca2..3005405e61b 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/driver.py @@ -51,7 +51,7 @@ def __str__(self) -> str: def opposite(self) -> "Direction": """Get opposite direction.""" return Direction.EXTENT if self == Direction.RETRACT else Direction.RETRACT - + def distance(self, distance: float) -> float: """Get signed distance, where retract direction is negative.""" return distance * -1 if self == Direction.RETRACT else distance @@ -161,7 +161,7 @@ def get_platform_sensor(self, direction: Direction) -> bool: match = _LS_RE.match(res) assert match, f"Incorrect Response for platform sensor: {res}" return bool(int(match.group(1))) - + def get_hopper_door_closed(self) -> bool: """Get whether or not door is closed. diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_x_axis.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_x_axis.py new file mode 100644 index 00000000000..802c12bcae5 --- /dev/null +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_x_axis.py @@ -0,0 +1,81 @@ +"""Test X Axis.""" +from typing import List, Union +from hardware_testing.data import ui +from hardware_testing.data.csv_report import ( + CSVReport, + CSVLine, + CSVLineRepeating, + CSVResult, +) + +from .utils import test_limit_switches_per_direction +from .driver import FlexStacker, StackerAxis, Direction + + +def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: + """Build CSV Lines.""" + return [ + CSVLine( + "limit-switch-trigger-positive-untrigger-negative", [bool, bool, CSVResult] + ), + CSVLine( + "limit-switch-trigger-negative-untrigger-positive", [bool, bool, CSVResult] + ), + CSVLine( + "platform-sensor-trigger-positive-untrigger-negative", + [bool, bool, CSVResult], + ), + CSVLine( + "platform-sensor-trigger-negative-untrigger-positive", + [bool, bool, CSVResult], + ), + ] + + +def test_platform_sensors_for_direction( + driver: FlexStacker, direction: Direction, report: CSVReport, section: str +) -> None: + """Test platform sensors for a given direction.""" + ui.print_header(f"Platform Sensor - {direction} direction") + sensor_result = driver.get_platform_sensor(direction) + opposite_result = not driver.get_platform_sensor(direction.opposite()) + print(f"{direction} sensor triggered: {sensor_result}") + print(f"{direction.opposite()} sensor untriggered: {opposite_result}") + report( + section, + f"platform-sensor-trigger-{direction}-untrigger-{direction.opposite()}", + [ + sensor_result, + opposite_result, + CSVResult.from_bool(sensor_result and opposite_result), + ], + ) + + +def platform_is_removed(driver: FlexStacker) -> bool: + """Check if the platform is removed from the carrier.""" + plus_side = driver.get_platform_sensor(Direction.EXTENT) + minus_side = driver.get_platform_sensor(Direction.RETRACT) + return not plus_side and not minus_side + + +def run(driver: FlexStacker, report: CSVReport, section: str) -> None: + """Run.""" + if not driver._simulating and not platform_is_removed(driver): + print("FAILURE - Cannot start tests with platform on the carrier") + return + + test_limit_switches_per_direction( + driver, StackerAxis.X, Direction.EXTENT, report, section + ) + + if not driver._simulating: + ui.get_user_ready("Place the platform on the X carrier") + + test_platform_sensors_for_direction(driver, Direction.EXTENT, report, section) + + test_limit_switches_per_direction( + driver, StackerAxis.X, Direction.RETRACT, report, section + ) + + test_platform_sensors_for_direction(driver, Direction.RETRACT, report, section) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py index fc34175ec54..58fc733e0dc 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/test_z_axis.py @@ -1,6 +1,5 @@ """Test Z Axis.""" -from typing import List, Tuple, Union -from hardware_testing.data import ui +from typing import List, Union from hardware_testing.data.csv_report import ( CSVReport, CSVLine, @@ -11,15 +10,25 @@ from .utils import test_limit_switches_per_direction from .driver import FlexStacker, StackerAxis, Direction + def build_csv_lines() -> List[Union[CSVLine, CSVLineRepeating]]: """Build CSV Lines.""" return [ - CSVLine("limit-switch-trigger-positive-untrigger-negative", [bool, bool, CSVResult]), - CSVLine("limit-switch-trigger-negative-untrigger-positive", [bool, bool, CSVResult]), + CSVLine( + "limit-switch-trigger-positive-untrigger-negative", [bool, bool, CSVResult] + ), + CSVLine( + "limit-switch-trigger-negative-untrigger-positive", [bool, bool, CSVResult] + ), ] + def run(driver: FlexStacker, report: CSVReport, section: str) -> None: """Run.""" - test_limit_switches_per_direction(driver, StackerAxis.Z, Direction.EXTENT, report, section) + test_limit_switches_per_direction( + driver, StackerAxis.Z, Direction.EXTENT, report, section + ) - test_limit_switches_per_direction(driver, StackerAxis.Z, Direction.RETRACT, report, section) + test_limit_switches_per_direction( + driver, StackerAxis.Z, Direction.RETRACT, report, section + ) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py index aa71f7c9788..20c17783ee8 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py @@ -1,3 +1,4 @@ +"""Utility functions for the Flex Stacker EVT QC module.""" from hardware_testing.data import ui from hardware_testing.data.csv_report import ( CSVReport, @@ -20,7 +21,7 @@ def test_limit_switches_per_direction( # first make sure switch is not already triggered by moving in the opposite direction if driver.get_limit_switch(axis, direction): print(f"{direction} switch already triggered, moving away...\n") - SAFE_DISTANCE = 10 # mm + SAFE_DISTANCE = 10 # mm driver.move_in_mm(axis, direction.opposite().distance(SAFE_DISTANCE)) # move until the limit switch is reached @@ -30,7 +31,8 @@ def test_limit_switches_per_direction( opposite_result = not driver.get_limit_switch(axis, direction.opposite()) print(f"{direction} switch triggered: {result}") print(f"{direction.opposite()} switch untriggered: {opposite_result}") - report(section, - f"limit-switch-trigger-{direction}-untrigger-{direction.opposite()}", - [result, opposite_result, CSVResult.from_bool(result and opposite_result)] - ) \ No newline at end of file + report( + section, + f"limit-switch-trigger-{direction}-untrigger-{direction.opposite()}", + [result, opposite_result, CSVResult.from_bool(result and opposite_result)], + ) From 626a471f53e77925ad5de7ed5275a91724a1cc70 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:16:14 -0500 Subject: [PATCH 8/9] EXEC-985 EXEC-986 EXEC-987 From 91c8db85839bc14e1b7a23cf402da356d7cc5855 Mon Sep 17 00:00:00 2001 From: ahiuchingau <20424172+ahiuchingau@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:37:38 -0500 Subject: [PATCH 9/9] naming --- .../hardware_testing/modules/flex_stacker_evt_qc/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py index 20c17783ee8..2aca90c8886 100644 --- a/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py +++ b/hardware-testing/hardware_testing/modules/flex_stacker_evt_qc/utils.py @@ -21,8 +21,8 @@ def test_limit_switches_per_direction( # first make sure switch is not already triggered by moving in the opposite direction if driver.get_limit_switch(axis, direction): print(f"{direction} switch already triggered, moving away...\n") - SAFE_DISTANCE = 10 # mm - driver.move_in_mm(axis, direction.opposite().distance(SAFE_DISTANCE)) + SAFE_DISTANCE_MM = 10 + driver.move_in_mm(axis, direction.opposite().distance(SAFE_DISTANCE_MM)) # move until the limit switch is reached print(f"moving towards {direction} limit switch...\n")