diff --git a/api/src/opentrons/config/types.py b/api/src/opentrons/config/types.py index 15a5cceddc8..22a8047484e 100644 --- a/api/src/opentrons/config/types.py +++ b/api/src/opentrons/config/types.py @@ -138,7 +138,11 @@ class LiquidProbeSettings: aspirate_while_sensing: bool auto_zero_sensor: bool num_baseline_reads: int +<<<<<<< HEAD data_files: Optional[Dict[InstrumentProbeType, str]] +======= + data_file: Optional[str] +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) @dataclass(frozen=True) diff --git a/api/src/opentrons/hardware_control/backends/flex_protocol.py b/api/src/opentrons/hardware_control/backends/flex_protocol.py index 7bd2969de6b..dd6bdaf63f8 100644 --- a/api/src/opentrons/hardware_control/backends/flex_protocol.py +++ b/api/src/opentrons/hardware_control/backends/flex_protocol.py @@ -147,7 +147,11 @@ async def liquid_probe( plunger_speed: float, threshold_pascals: float, output_format: OutputOptions = OutputOptions.can_bus_only, +<<<<<<< HEAD data_files: Optional[Dict[InstrumentProbeType, str]] = None, +======= + data_file: Optional[str] = None, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) auto_zero_sensor: bool = True, num_baseline_reads: int = 10, probe: InstrumentProbeType = InstrumentProbeType.PRIMARY, diff --git a/api/src/opentrons/hardware_control/backends/ot3controller.py b/api/src/opentrons/hardware_control/backends/ot3controller.py index 774dcd68881..80b8862f844 100644 --- a/api/src/opentrons/hardware_control/backends/ot3controller.py +++ b/api/src/opentrons/hardware_control/backends/ot3controller.py @@ -1357,7 +1357,11 @@ async def liquid_probe( plunger_speed: float, threshold_pascals: float, output_option: OutputOptions = OutputOptions.can_bus_only, +<<<<<<< HEAD data_files: Optional[Dict[InstrumentProbeType, str]] = None, +======= + data_file: Optional[str] = None, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) auto_zero_sensor: bool = True, num_baseline_reads: int = 10, probe: InstrumentProbeType = InstrumentProbeType.PRIMARY, @@ -1378,6 +1382,7 @@ async def liquid_probe( can_bus_only_output = bool( output_option.value & OutputOptions.can_bus_only.value ) +<<<<<<< HEAD data_files_transposed = ( None if data_files is None @@ -1386,6 +1391,8 @@ async def liquid_probe( for probe in data_files.keys() } ) +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) positions = await liquid_probe( messenger=self._messenger, tool=tool, @@ -1397,7 +1404,11 @@ async def liquid_probe( csv_output=csv_output, sync_buffer_output=sync_buffer_output, can_bus_only_output=can_bus_only_output, +<<<<<<< HEAD data_files=data_files_transposed, +======= + data_file=data_file, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) auto_zero_sensor=auto_zero_sensor, num_baseline_reads=num_baseline_reads, sensor_id=sensor_id_for_instrument(probe), diff --git a/api/src/opentrons/hardware_control/backends/ot3simulator.py b/api/src/opentrons/hardware_control/backends/ot3simulator.py index e0c8fe1bc89..510413d5362 100644 --- a/api/src/opentrons/hardware_control/backends/ot3simulator.py +++ b/api/src/opentrons/hardware_control/backends/ot3simulator.py @@ -346,7 +346,11 @@ async def liquid_probe( plunger_speed: float, threshold_pascals: float, output_format: OutputOptions = OutputOptions.can_bus_only, +<<<<<<< HEAD data_files: Optional[Dict[InstrumentProbeType, str]] = None, +======= + data_file: Optional[str] = None, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) auto_zero_sensor: bool = True, num_baseline_reads: int = 10, probe: InstrumentProbeType = InstrumentProbeType.PRIMARY, diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index a0e0c5735a2..6b86e5329f7 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -2623,7 +2623,11 @@ async def liquid_probe( (probe_settings.plunger_speed * plunger_direction), probe_settings.sensor_threshold_pascals, probe_settings.output_option, +<<<<<<< HEAD probe_settings.data_files, +======= + probe_settings.data_file, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) probe_settings.auto_zero_sensor, probe_settings.num_baseline_reads, probe=probe if probe else InstrumentProbeType.PRIMARY, diff --git a/api/tests/opentrons/hardware_control/test_ot3_api.py b/api/tests/opentrons/hardware_control/test_ot3_api.py index 7ab0a2f1c00..d45e9515c91 100644 --- a/api/tests/opentrons/hardware_control/test_ot3_api.py +++ b/api/tests/opentrons/hardware_control/test_ot3_api.py @@ -820,7 +820,11 @@ async def test_liquid_probe( (fake_settings_aspirate.plunger_speed * -1), fake_settings_aspirate.sensor_threshold_pascals, fake_settings_aspirate.output_option, +<<<<<<< HEAD fake_settings_aspirate.data_files, +======= + fake_settings_aspirate.data_file, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) fake_settings_aspirate.auto_zero_sensor, fake_settings_aspirate.num_baseline_reads, probe=InstrumentProbeType.PRIMARY, diff --git a/hardware-testing/hardware_testing/gravimetric/config.py b/hardware-testing/hardware_testing/gravimetric/config.py index f80d87d7124..6061d3144e5 100644 --- a/hardware-testing/hardware_testing/gravimetric/config.py +++ b/hardware-testing/hardware_testing/gravimetric/config.py @@ -194,7 +194,11 @@ def _get_liquid_probe_settings( plunger_speed=lqid_cfg["plunger_speed"], sensor_threshold_pascals=lqid_cfg["sensor_threshold_pascals"], expected_liquid_height=110, +<<<<<<< HEAD output_option=OutputOptions.sync_only, +======= + output_option=OutputOptions.stream_to_csv, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) aspirate_while_sensing=False, auto_zero_sensor=True, num_baseline_reads=10, diff --git a/hardware/opentrons_hardware/firmware_bindings/messages/messages.py b/hardware/opentrons_hardware/firmware_bindings/messages/messages.py index 9906aa8dc07..1a677dc46df 100644 --- a/hardware/opentrons_hardware/firmware_bindings/messages/messages.py +++ b/hardware/opentrons_hardware/firmware_bindings/messages/messages.py @@ -111,7 +111,10 @@ defs.GetHepaUVStateResponse, defs.SendAccumulatedPressureDataRequest, defs.AddSensorLinearMoveRequest, +<<<<<<< HEAD defs.SendAccumulatedPressureDataRequest, +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) ] diff --git a/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py b/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py index c351495ba5b..1d218254c8a 100644 --- a/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py +++ b/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py @@ -683,7 +683,10 @@ class GetHepaUVStatePayloadResponse(EmptyPayload): uv_duration_s: utils.UInt32Field uv_light_on: utils.UInt8Field remaining_time_s: utils.UInt32Field +<<<<<<< HEAD uv_current_ma: utils.UInt16Field +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) @dataclass(eq=False) diff --git a/hardware/opentrons_hardware/hardware_control/move_group_runner.py b/hardware/opentrons_hardware/hardware_control/move_group_runner.py index 4b7f409b38b..47b142a2728 100644 --- a/hardware/opentrons_hardware/hardware_control/move_group_runner.py +++ b/hardware/opentrons_hardware/hardware_control/move_group_runner.py @@ -23,7 +23,11 @@ ErrorSeverity, GearMotorId, MoveAckId, +<<<<<<< HEAD MotorDriverErrorCode, +======= + SensorId, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) ) from opentrons_hardware.drivers.can_bus.can_messenger import CanMessenger from opentrons_hardware.firmware_bindings.messages import MessageDefinition @@ -40,7 +44,10 @@ TipActionResponse, ErrorMessage, StopRequest, +<<<<<<< HEAD ReadMotorDriverErrorStatusResponse, +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) AddSensorLinearMoveRequest, ) from opentrons_hardware.firmware_bindings.messages.payloads import ( @@ -307,7 +314,10 @@ def _get_stepper_motor_message( return HomeRequest(payload=home_payload) elif step.move_type == MoveType.sensor: # stop_condition = step.stop_condition.value +<<<<<<< HEAD assert step.sensor_id is not None +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) stop_condition = MoveStopCondition.sync_line sensor_move_payload = AddSensorLinearMoveBasePayload( request_stop_condition=MoveStopConditionField(stop_condition), @@ -328,7 +338,11 @@ def _get_stepper_motor_message( velocity_mm=Int32Field( int((step.velocity_mm_sec / interrupts_per_sec) * (2**31)) ), +<<<<<<< HEAD sensor_id=SensorIdField(step.sensor_id), +======= + sensor_id=SensorIdField(SensorId.S0), +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) ) return AddSensorLinearMoveRequest(payload=sensor_move_payload) else: diff --git a/hardware/opentrons_hardware/hardware_control/tool_sensors.py b/hardware/opentrons_hardware/hardware_control/tool_sensors.py index c2dcac25502..d71f4ce84a6 100644 --- a/hardware/opentrons_hardware/hardware_control/tool_sensors.py +++ b/hardware/opentrons_hardware/hardware_control/tool_sensors.py @@ -106,7 +106,10 @@ def _build_pass_step( duration=float64(abs(distance[movers[0]] / speed[movers[0]])), present_nodes=pipette_nodes, stop_condition=MoveStopCondition.sensor_report, +<<<<<<< HEAD sensor_to_use=sensor_to_use, +======= +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) ) for node in pipette_nodes: move_group[node] = pipette_move[node] @@ -116,11 +119,16 @@ def _build_pass_step( async def run_sync_buffer_to_csv( messenger: CanMessenger, sensor_driver: SensorDriver, +<<<<<<< HEAD +======= + pressure_sensor: PressureSensor, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) mount_speed: float, plunger_speed: float, threshold_pascals: float, head_node: NodeId, move_group: MoveGroupRunner, +<<<<<<< HEAD log_files: Dict[SensorId, str], tool: PipetteProbeTarget, ) -> Dict[NodeId, MotorPositionStatus]: @@ -156,31 +164,82 @@ async def run_sync_buffer_to_csv( ) ), ) +======= + log_file: str, + tool: PipetteProbeTarget, + sensor_id: SensorId, +) -> Dict[NodeId, MotorPositionStatus]: + """Runs the sensor pass move group and creates a csv file with the results.""" + sensor_metadata = [0, 0, mount_speed, plunger_speed, threshold_pascals] + sensor_capturer = LogListener( + mount=head_node, + data_file=log_file, + file_heading=pressure_output_file_heading, + sensor_metadata=sensor_metadata, + ) + async with sensor_capturer: + print("starting move group runner") + positions = await move_group.run(can_messenger=messenger) + messenger.add_listener(sensor_capturer, None) + await messenger.send( + node_id=tool, + message=SendAccumulatedPressureDataRequest( + payload=SendAccumulatedPressureDataPayload( + sensor_id=SensorIdField(sensor_id) + ) + ), + ) + await asyncio.sleep(10) + messenger.remove_listener(sensor_capturer) + await messenger.send( + node_id=tool, + message=BindSensorOutputRequest( + payload=BindSensorOutputRequestPayload( + sensor=SensorTypeField(SensorType.pressure), + sensor_id=SensorIdField(sensor_id), + binding=SensorOutputBindingField(SensorOutputBinding.none), + ) + ), + ) +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) return positions async def run_stream_output_to_csv( messenger: CanMessenger, sensor_driver: SensorDriver, +<<<<<<< HEAD pressure_sensors: Dict[SensorId, PressureSensor], +======= + pressure_sensor: PressureSensor, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) mount_speed: float, plunger_speed: float, threshold_pascals: float, head_node: NodeId, move_group: MoveGroupRunner, +<<<<<<< HEAD log_files: Dict[SensorId, str], +======= + log_file: str, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) ) -> Dict[NodeId, MotorPositionStatus]: """Runs the sensor pass move group and creates a csv file with the results.""" sensor_metadata = [0, 0, mount_speed, plunger_speed, threshold_pascals] sensor_capturer = LogListener( mount=head_node, +<<<<<<< HEAD data_file=log_files[ next(iter(log_files)) ], # hardcode to the first file, need to think more on this +======= + data_file=log_file, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) file_heading=pressure_output_file_heading, sensor_metadata=sensor_metadata, ) binding = [SensorOutputBinding.sync, SensorOutputBinding.report] +<<<<<<< HEAD binding_field = SensorOutputBindingField.from_flags(binding) for sensor_id in pressure_sensors.keys(): sensor_info = pressure_sensors[sensor_id].sensor @@ -284,6 +343,17 @@ async def _run_with_binding( ), ) return result +======= + + async with sensor_driver.bind_output(messenger, pressure_sensor, binding): + messenger.add_listener(sensor_capturer, None) + + async with sensor_capturer: + positions = await move_group.run(can_messenger=messenger) + messenger.remove_listener(sensor_capturer) + + return positions +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) async def liquid_probe( @@ -297,7 +367,12 @@ async def liquid_probe( csv_output: bool = False, sync_buffer_output: bool = False, can_bus_only_output: bool = False, +<<<<<<< HEAD data_files: Optional[Dict[SensorId, str]] = None, +======= + # output_option: OutputOptions, + data_file: Optional[str] = None, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) auto_zero_sensor: bool = True, num_baseline_reads: int = 10, sensor_id: SensorId = SensorId.S0, @@ -316,6 +391,17 @@ async def liquid_probe( auto_zero_sensor, ) +<<<<<<< HEAD +======= + if auto_zero_sensor: + pressure_baseline = await sensor_driver.get_baseline( + messenger, pressure_sensor, num_baseline_reads + ) + LOG.debug(f"found baseline pressure: {pressure_baseline} pascals") + + await sensor_driver.send_stop_threshold(messenger, pressure_sensor) + +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) sensor_group = _build_pass_step( movers=[head_node, tool], distance={head_node: max_z_distance, tool: max_z_distance}, @@ -325,16 +411,25 @@ async def liquid_probe( ) sensor_runner = MoveGroupRunner(move_groups=[[sensor_group]]) +<<<<<<< HEAD +======= + log_file: str = "/var/pressure_sensor_data.csv" if not data_file else data_file +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) if csv_output: return await run_stream_output_to_csv( messenger, sensor_driver, +<<<<<<< HEAD pressure_sensors, +======= + pressure_sensor, +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) mount_speed, plunger_speed, threshold_pascals, head_node, sensor_runner, +<<<<<<< HEAD log_files, ) elif sync_buffer_output: @@ -359,6 +454,43 @@ async def liquid_probe( return await _run_with_binding( messenger, pressure_sensors, sensor_runner, binding ) +======= + log_file, + ) + elif sync_buffer_output: + return await run_sync_buffer_to_csv( + messenger, + sensor_driver, + pressure_sensor, + mount_speed, + plunger_speed, + threshold_pascals, + head_node, + sensor_runner, + log_file, + tool=tool, + sensor_id=sensor_id, + ) + elif can_bus_only_output: + async with sensor_driver.bind_output( + messenger, + pressure_sensor, + [ + SensorOutputBinding.sync, + SensorOutputBinding.report, + ], + ): + return await sensor_runner.run(can_messenger=messenger) + else: # none + async with sensor_driver.bind_output( + messenger, + pressure_sensor, + [ + SensorOutputBinding.sync, + ], + ): + return await sensor_runner.run(can_messenger=messenger) +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) async def check_overpressure( diff --git a/hardware/tests/opentrons_hardware/hardware_control/test_tool_sensors.py b/hardware/tests/opentrons_hardware/hardware_control/test_tool_sensors.py index ba391da2c14..44ace8ffe1d 100644 --- a/hardware/tests/opentrons_hardware/hardware_control/test_tool_sensors.py +++ b/hardware/tests/opentrons_hardware/hardware_control/test_tool_sensors.py @@ -193,6 +193,38 @@ def move_responder( data=SensorDataType.build(threshold_pascals * 65536, sensor_info.sensor_type), mode=SensorThresholdMode.absolute, ) +<<<<<<< HEAD +======= + mock_bind_output.assert_called_once() + assert mock_bind_output.call_args_list[0][0][3] == [SensorOutputBinding.sync] + + with patch( + "opentrons_hardware.hardware_control.tool_sensors", LogListener + ) as mock_log: + + mock_log.__aenter__ = AsyncMock(return_value=mock_log) # type: ignore + mock_log.__aexit__ = AsyncMock(return_value=None) # type: ignore + + await liquid_probe( + messenger=mock_messenger, + tool=target_node, + head_node=motor_node, + max_z_distance=40, + mount_speed=10, + plunger_speed=8, + threshold_pascals=threshold_pascals, + csv_output=False, + sync_buffer_output=False, + can_bus_only_output=False, + auto_zero_sensor=True, + num_baseline_reads=8, + sensor_id=SensorId.S0, + ) + mock_bind_output.assert_called() + assert mock_bind_output.call_args_list[1][0][3] == [ + SensorOutputBinding.sync, + ] +>>>>>>> 7995d78c39 (refactor(hardware): give options for sensor data output during probe (#14673)) @pytest.mark.parametrize(