From 3bd7f3420c741d91ed248f2a9c265583dc593cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 12 May 2025 13:58:29 +0200 Subject: [PATCH 1/3] master stuff --- pyproject.toml | 3 ++- .../daq_move_plugins/daq_move_PiezoConcept.py | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5629ffc..949e1b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,8 @@ classifiers = [ [build-system] requires = [ "hatchling>=1.9.0", - "hatch-vcs", "toml", + "hatch-vcs", + "toml", "pymodaq_utils>=0.0.6", ] build-backend = "hatchling.build" diff --git a/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py b/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py index a4e426a..6e5e9d5 100644 --- a/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py +++ b/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py @@ -7,6 +7,7 @@ config = Config() + class DAQ_Move_PiezoConcept(DAQ_Move_base): """ Plugin to drive piezoconcpet XY (Z) stages. There is a string nonlinear offset between the set position and the read @@ -43,9 +44,10 @@ def ini_stage(self, controller=None): """ """ - - self.ini_stage_init(old_controller=controller, - new_controller=PiezoConcept()) + if self.is_master: + self.controller = PiezoConcept() + else: + self.controller = controller controller_id = self.do_init() @@ -54,7 +56,7 @@ def ini_stage(self, controller=None): return info, initialized def do_init(self) -> str: - if self.settings['multiaxes', 'multi_status'] == "Master": + if self.is_master: self.controller.init_communication(self.settings['com_port']) controller_id = self.controller.get_controller_infos() From f00b201823d75e1be04e4a6fed48fecb0dbd05a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 12 May 2025 14:09:18 +0200 Subject: [PATCH 2/3] use pymodaq version with check bounds patch --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 949e1b8..cce0391 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ name = "pymodaq_plugins_piezoconcept" description = 'Set of PyMoDAQ plugins for Actuators from Piezoconcept (Tested on the Bio200 XY stage. Include a version of the controller firmware emulating functions from PhysikInstrumente)' dependencies = [ - "pymodaq>=5.0.0", + "pymodaq>=5.0.8", 'pyserial', 'pyvisa', ] From 0ef91e2409771e82f06628a6eab513d431a97623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Mon, 12 May 2025 14:46:29 +0200 Subject: [PATCH 3/3] units handling: check bounds, scaling --- pyproject.toml | 2 +- .../daq_move_plugins/daq_move_PiezoConcept.py | 70 ++++++++----------- .../resources/config_template.toml | 2 +- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cce0391..477cd34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ name = "pymodaq_plugins_piezoconcept" description = 'Set of PyMoDAQ plugins for Actuators from Piezoconcept (Tested on the Bio200 XY stage. Include a version of the controller firmware emulating functions from PhysikInstrumente)' dependencies = [ - "pymodaq>=5.0.8", + "pymodaq>=5.0.9", 'pyserial', 'pyvisa', ] diff --git a/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py b/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py index 6e5e9d5..5ff8447 100644 --- a/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py +++ b/src/pymodaq_plugins_piezoconcept/daq_move_plugins/daq_move_PiezoConcept.py @@ -1,41 +1,41 @@ from qtpy.QtCore import QThread -from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, comon_parameters_fun, main +from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun, main, + DataActuatorType, DataActuator) from pymodaq_plugins_piezoconcept.hardware.piezoconcept.piezoconcept import PiezoConcept, Position, Time from pymodaq_plugins_piezoconcept.utils import Config config = Config() +# find available COM ports +import serial.tools.list_ports + +ports = [str(port)[0:4] for port in list(serial.tools.list_ports.comports())] +port = config('com_port') if config('com_port') in ports else ports[0] if len(ports) > 0 else '' class DAQ_Move_PiezoConcept(DAQ_Move_base): """ - Plugin to drive piezoconcpet XY (Z) stages. There is a string nonlinear offset between the set position and the read + Plugin to drive piezoconcpet XY (Z) stages. There is a nonlinear offset between the set position and the read position. It seems to bnot be problem in the sens where a given displacement is maintained. But because the read position is not "accurate", I've decided to ignore it and just trust the set position. So the return will be always strictly equal to the set position. However, if there is more that 10% difference raise a warning """ + axis_names = ['X', 'Y', 'Z'] _controller_units = 'µm' + _epsilons = [1, 1, 1] - #find available COM ports - import serial.tools.list_ports - ports = [str(port)[0:4] for port in list(serial.tools.list_ports.comports())] - port = config('com_port') if config('com_port') in ports else ports[0] if len(ports) > 0 else '' - #if ports==[]: - # ports.append('') - _epsilon = 1 - - is_multiaxes = True - stage_names = ['X', 'Y', 'Z'] min_bound = -95 #*µm max_bound = 95 #µm offset = 100 #µm + data_actuator_type = DataActuatorType.DataActuator + params= [{'title': 'Time interval (ms):', 'name': 'time_interval', 'type': 'int', 'value': 200}, {'title': 'Controller Info:', 'name': 'controller_id', 'type': 'text', 'value': '', 'readonly': True}, {'title': 'COM Port:', 'name': 'com_port', 'type': 'list', 'limits': ports, 'value': port}, - ] + comon_parameters_fun(is_multiaxes, stage_names, epsilon=_epsilon) + ] + comon_parameters_fun(axis_names=axis_names) def ini_attributes(self): self.controller: PiezoConcept = None @@ -67,7 +67,7 @@ def do_init(self) -> str: self.settings.child('bounds', 'max_bound').setValue(self.max_bound) self.settings.child('scaling', 'use_scaling').setValue(True) self.settings.child('scaling', 'offset').setValue(self.offset) - self.move_abs(0) + self.move_abs(DataActuator(data=0, units=self.axis_unit)) return controller_id def close(self): @@ -75,21 +75,22 @@ def close(self): close the current instance of Piezo instrument. """ if self.controller is not None: - self.move_abs(0) + self.move_abs(DataActuator(0, units='um')) QThread.msleep(1000) self.controller.close_communication() self.controller = None - def get_actuator_value(self): + def get_actuator_value(self) -> DataActuator: """ """ - position = self.controller.get_position(self.settings.child('multiaxes', 'axis').value()) #in mm - pos = position.pos/1000 # in um - pos = self.get_position_with_scaling(pos) + pos: Position = self.controller.get_position(self.axis_name) + position = DataActuator(data=pos.pos, + units='nm' if pos.unit == 'n' else 'um') + position = self.get_position_with_scaling(position) self.current_position = self.target_position #should be pos but not precise enough conpared to set position return self.target_position - def move_abs(self, position): + def move_abs(self, position: DataActuator): """ Parameters @@ -102,39 +103,25 @@ def move_abs(self, position): """ position = self.check_bound(position) #limits the position within the specified bounds (-100,100) self.target_position = position + position = self.set_position_with_scaling(position) #get positions in controller units - position = self.set_position_with_scaling(position) - pos = Position(self.settings.child('multiaxes', 'axis').value(), int(position*1000), unit='n') + pos = Position(self.axis_name, position.value('nm'), unit='n') out = self.controller.move_axis('ABS', pos) - #self.move_is_done = True - QThread.msleep(50) #to make sure the closed loop converged - - def move_rel(self,position): - """ - Make the hardware relative move of the Piezo instrument from the given position after thread command signal was received in DAQ_Move_main. - - =============== ========= ======================= - **Parameters** **Type** **Description** - - *position* float The absolute position - =============== ========= ======================= - - See Also - -------- - DAQ_Move_base.set_position_with_scaling, DAQ_Move_base.poll_moving + QThread.msleep(50) # to make sure the closed loop converged + def move_rel(self, position: DataActuator): + """ Make the hardware relative move of the Piezo instrument from the given position """ position = self.check_bound(self.current_position+position)-self.current_position self.target_position = position+self.current_position position = self.set_position_relative_with_scaling(position) - pos = Position(self.settings.child('multiaxes', 'axis').value(), position*1000, unit='n') # always use microns for simplicity + pos = Position(self.axis_name, position.value('nm'), unit='n') out = self.controller.move_axis('REL', pos) QThread.msleep(50) # to make sure the closed loop converged - def move_home(self): """ Move to the absolute vlue 100 corresponding the default point of the Piezo instrument. @@ -143,7 +130,8 @@ def move_home(self): -------- DAQ_Move_base.move_abs """ - self.move_abs(100) #put the axis on the middle position so 100µm + self.move_abs(DataActuator(data=100, units='um')) + # put the axis on the middle position so 100µm def stop_motion(self): """ diff --git a/src/pymodaq_plugins_piezoconcept/resources/config_template.toml b/src/pymodaq_plugins_piezoconcept/resources/config_template.toml index 64912c7..910df92 100644 --- a/src/pymodaq_plugins_piezoconcept/resources/config_template.toml +++ b/src/pymodaq_plugins_piezoconcept/resources/config_template.toml @@ -1,3 +1,3 @@ title = 'this is the configuration file of the Piezoconcept plugin' -com_port = 'COM6' \ No newline at end of file +com_port = 'COM5' \ No newline at end of file