From 48476567fdffc69ec51b1800fee31a25d6cadff0 Mon Sep 17 00:00:00 2001 From: adele080402 Date: Fri, 6 Dec 2024 17:11:07 +0100 Subject: [PATCH 01/14] rr --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index a02b6ca..8b17a33 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,8 @@ pymodaq_plugins_smaract (Smaract) ################################# + + .. image:: https://img.shields.io/pypi/v/pymodaq_plugins_smaract.svg :target: https://pypi.org/project/pymodaq_plugins_smaract/ :alt: Latest Version From 76ac6153bef6def96be4d67da499b67a4363fa4f Mon Sep 17 00:00:00 2001 From: adele080402 Date: Wed, 11 Dec 2024 18:07:18 +0100 Subject: [PATCH 02/14] =?UTF-8?q?cr=C3=A9ation=20du=20wrapper=20pour=20le?= =?UTF-8?q?=20SCU=20et=20ajout=20des=20fonctions=20de=20base?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hardware/smaract/bindings.py | 1644 +++++++++++++++++ .../hardware/smaract/smaract_SCU_wrapper.py | 285 +++ 2 files changed, 1929 insertions(+) create mode 100644 src/pymodaq_plugins_smaract/hardware/smaract/bindings.py create mode 100644 src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/bindings.py b/src/pymodaq_plugins_smaract/hardware/smaract/bindings.py new file mode 100644 index 0000000..ef8836a --- /dev/null +++ b/src/pymodaq_plugins_smaract/hardware/smaract/bindings.py @@ -0,0 +1,1644 @@ +####################################################################### +# Copyright (c) 2023 SmarAct GmbH +# +# THIS SOFTWARE, DOCUMENTS, FILES AND INFORMATION ARE PROVIDED 'AS IS' +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PURPOSE, OR THE WARRANTY OF NON - INFRINGEMENT. +# THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THIS SOFTWARE +# REMAINS WITH YOU. +# IN NO EVENT SHALL THE SMARACT GMBH BE LIABLE FOR ANY DIRECT, +# INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER DAMAGES ARISING +# OUT OF THE USE OR INABILITY TO USE THIS SOFTWARE. +# +# Generated on 2023-12-22 08:28 +0100 +# + +""" +Python bindings for SCU3DControl +(C) SmarAct GmbH +Refer to the SmarAct EULA for licensing +SCU Python API +""" + +from cffi import FFI +import enum +import sys + +assert sys.version_info >= (3, 4), "Python v3.4 or higher is required" +apigen_version = (1, 8, 1) +api_version = (1, 5, 16) + + +def __initBindings(libName): + global ffi, lib + ffi = FFI() + ffi.cdef(""" +typedef unsigned int SA_PACKET_TYPE; +typedef unsigned int SA_INDEX; +struct SA_packet{ SA_PACKET_TYPE packetType; SA_INDEX channelIndex; unsigned int data1; int data2; int data3;}; +typedef struct SA_packet SA_PACKET; +typedef unsigned int SA_STATUS; +SA_STATUS SA_GetDLLVersion(unsigned int *version); +SA_STATUS SA_GetAvailableDevices(unsigned int *idList, unsigned int *idListSize); +SA_STATUS SA_AddDeviceToInitDevicesList(unsigned int deviceId); +SA_STATUS SA_ClearInitDevicesList(); +SA_STATUS SA_InitDevices(unsigned int configuration); +SA_STATUS SA_ReleaseDevices(); +SA_STATUS SA_GetNumberOfDevices(unsigned int *number); +SA_STATUS SA_GetDeviceID(SA_INDEX deviceIndex, unsigned int *deviceId); +SA_STATUS SA_GetDeviceFirmwareVersion(SA_INDEX deviceIndex, unsigned int *version); +SA_STATUS SA_SetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); +SA_STATUS SA_GetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *frequency); +SA_STATUS SA_SetZero_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetSensorPresent_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *present); +SA_STATUS SA_SetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); +SA_STATUS SA_GetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *type); +SA_STATUS SA_SetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); +SA_STATUS SA_GetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *alignment, unsigned int *forwardAmplitude, unsigned int *backwardAmplitude); +SA_STATUS SA_SetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); +SA_STATUS SA_GetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *direction); +SA_STATUS SA_SetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); +SA_STATUS SA_GetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *scale, unsigned int *inverted); +SA_STATUS SA_SetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); +SA_STATUS SA_GetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int *value); +SA_STATUS SA_SetSystemProperty_S(SA_INDEX deviceIndex, int key, int value); +SA_STATUS SA_GetSystemProperty_S(SA_INDEX deviceIndex, int key, int *value); +SA_STATUS SA_MoveStep_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); +SA_STATUS SA_SetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); +SA_STATUS SA_MovePositionAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); +SA_STATUS SA_MovePositionRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); +SA_STATUS SA_MoveAngleAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); +SA_STATUS SA_MoveAngleRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); +SA_STATUS SA_CalibrateSensor_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_MoveToReference_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_MoveToEndStop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_Stop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetStatus_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *status); +SA_STATUS SA_GetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *amplitude); +SA_STATUS SA_GetPosition_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *position); +SA_STATUS SA_GetAngle_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *angle, int *revolution); +SA_STATUS SA_GetPhysicalPositionKnown_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *known); +SA_STATUS SA_SetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); +SA_STATUS SA_GetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetZero_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetSensorPresent_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); +SA_STATUS SA_GetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); +SA_STATUS SA_GetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); +SA_STATUS SA_GetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); +SA_STATUS SA_GetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetReportOnComplete_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int report); +SA_STATUS SA_SetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); +SA_STATUS SA_GetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key); +SA_STATUS SA_SetSystemProperty_A(SA_INDEX deviceIndex, int key, int value); +SA_STATUS SA_GetSystemProperty_A(SA_INDEX deviceIndex, int key); +SA_STATUS SA_MoveStep_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); +SA_STATUS SA_SetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); +SA_STATUS SA_MovePositionAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); +SA_STATUS SA_MovePositionRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); +SA_STATUS SA_MoveAngleAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); +SA_STATUS SA_MoveAngleRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); +SA_STATUS SA_CalibrateSensor_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_MoveToReference_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_MoveToEndStop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_Stop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetStatus_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetPosition_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetAngle_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetPhysicalPositionKnown_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetReceiveNotification_A(SA_INDEX deviceIndex, void *event); +SA_STATUS SA_ReceiveNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_ReceiveNextPacketIfChannel_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_LookAtNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_DiscardPacket_A(SA_INDEX deviceIndex); +""") + lib = ffi.dlopen(libName) + + +class Error(Exception): + def __init__(self, func, code, arguments): + self.func = func + self.code = code + self.arguments = arguments + + def __str__(self): + return "{} returned {} with arguments {}".format(self.func, self.code, self.arguments) + + +class packet: + """ + Members: + - packetType + - channelIndex + - data1 + - data2 + - data3 + + """ + __slots__ = ['packetType', 'channelIndex', 'data1', 'data2', 'data3', 'cHandle'] + + def __init__(self, packetType, channelIndex, data1, data2, data3, cHandle=None): + if packetType is not None: + self.packetType = packetType + if channelIndex is not None: + self.channelIndex = channelIndex + if data1 is not None: + self.data1 = data1 + if data2 is not None: + self.data2 = data2 + if data3 is not None: + self.data3 = data3 + self.cHandle = cHandle + + def __getattr__(self, attr): + if self.cHandle is not None: + value = getattr(self.cHandle, attr) + retValue = value + setattr(self, attr, retValue) + return retValue + else: + raise AttributeError(f"packet has no attribute: {attr}") + + def asFFI(self): + return ffi.new(_ffiApiGenCachedTypes[0], + {'packetType': self.packetType, 'channelIndex': self.channelIndex, 'data1': self.data1, + 'data2': self.data2, 'data3': self.data3}) + + +def GetDLLVersion(): + """ + Returns the version code of the library + + Return value(s): + - version: Library Version + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetDLLVersion(local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetDLLVersion", local_1, {}) + return local_0[0] + + +def GetAvailableDevices(idListSize=256): + """ + Returns a list of available device IDs + + Parameters: + - idListSize = 256: Length of the buffer to allocate + + Return value(s): + - idList: Buffer for device IDs + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[2], idListSize) + local_1 = ffi.new(_ffiApiGenCachedTypes[1], idListSize) + local_2 = lib.SA_GetAvailableDevices(local_0, local_1) + if local_2 != ErrorCode.OK.value: + raise Error("GetAvailableDevices", local_2, {}) + return ffi.unpack(local_0, local_1[0]) + + +def AddDeviceToInitDevicesList(deviceId): + """ + Used to acquire one or more specific devices + + Parameters: + - deviceId: ID that is to be acquired + """ + local_0 = lib.SA_AddDeviceToInitDevicesList(deviceId) + if local_0 != ErrorCode.OK.value: + raise Error("AddDeviceToInitDevicesList", local_0, {"deviceId": deviceId}) + + +def ClearInitDevicesList(): + """ + Clears the device initialization list + """ + local_0 = lib.SA_ClearInitDevicesList() + if local_0 != ErrorCode.OK.value: + raise Error("ClearInitDevicesList", local_0, {}) + + +def InitDevices(configuration): + """ + Global initialization function to acquire all devices available in the + DevicesList + + Parameters: + - configuration: Selection between synchronous and asynchronous + communication mode + """ + local_0 = lib.SA_InitDevices(configuration) + if local_0 != ErrorCode.OK.value: + raise Error("InitDevices", local_0, {"configuration": configuration}) + + +def ReleaseDevices(): + """ + Release all previously acquired devices (should be called before the + application closes) + """ + local_0 = lib.SA_ReleaseDevices() + if local_0 != ErrorCode.OK.value: + raise Error("ReleaseDevices", local_0, {}) + + +def GetNumberOfDevices(): + """ + Returns number of devices that that have been acquired by + SA_InitDevices + + Return value(s): + - number: Buffer for number of acquired devices + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetNumberOfDevices(local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetNumberOfDevices", local_1, {}) + return local_0[0] + + +def GetDeviceID(deviceIndex): + """ + Returns the ID of an acquired device + + Parameters: + - deviceIndex: Selects the device (zero-based) + + Return value(s): + - deviceId: Buffer for the corresponding device ID + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetDeviceID(deviceIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetDeviceID", local_1, {"deviceIndex": deviceIndex}) + return local_0[0] + + +def GetDeviceFirmwareVersion(deviceIndex): + """ + Returns the firmware version of a device + + Parameters: + - deviceIndex: Selects the device (zero-based) + + Return value(s): + - version: Buffer for the device's firmware version + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetDeviceFirmwareVersion(deviceIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetDeviceFirmwareVersion", local_1, {"deviceIndex": deviceIndex}) + return local_0[0] + + +def SetClosedLoopMaxFrequency_S(deviceIndex, channelIndex, frequency): + """ + Defines the maximum frequency used for closed-loop movements + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - frequency: Maximum driving frequency in Hz + """ + local_0 = lib.SA_SetClosedLoopMaxFrequency_S(deviceIndex, channelIndex, frequency) + if local_0 != ErrorCode.OK.value: + raise Error("SetClosedLoopMaxFrequency_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "frequency": frequency}) + + +def GetClosedLoopMaxFrequency_S(deviceIndex, channelIndex): + """ + Returns the currently configured maximum frequency used for closed-loop + movements + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - frequency: Buffer for the maximum driving frequency in Hz + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetClosedLoopMaxFrequency_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetClosedLoopMaxFrequency_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def SetZero_S(deviceIndex, channelIndex): + """ + Defines the current position as the zero position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_SetZero_S(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("SetZero_S", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetSensorPresent_S(deviceIndex, channelIndex): + """ + Returns whether a positioner is equipped with a sensor or not + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - present: Buffer for the information whether a sensor is available + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetSensorPresent_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetSensorPresent_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def SetSensorType_S(deviceIndex, channelIndex, type): + """ + Configures the type of positioner connected to a channel + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - type: Type of the positioner + """ + local_0 = lib.SA_SetSensorType_S(deviceIndex, channelIndex, type) + if local_0 != ErrorCode.OK.value: + raise Error("SetSensorType_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "type": type}) + + +def GetSensorType_S(deviceIndex, channelIndex): + """ + Returns the type of positioner for the given channel + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - type: Buffer for the currently configured positioner type + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetSensorType_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetSensorType_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def SetPositionerAlignment_S(deviceIndex, channelIndex, alignment, forwardAmplitude=0, backwardAmplitude=0): + """ + Sets advanced properties for vertically aligned positioners that carry + high loads + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - alignment: Specifies the alignment (horizontal or vertical) + - forwardAmplitude = 0: Step amplitude used for forward movements in + vertical mode + - backwardAmplitude = 0: Step amplitude used for backward movements in + vertical mode + """ + local_0 = lib.SA_SetPositionerAlignment_S(deviceIndex, channelIndex, alignment, forwardAmplitude, backwardAmplitude) + if local_0 != ErrorCode.OK.value: + raise Error("SetPositionerAlignment_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "alignment": alignment, + "forwardAmplitude": forwardAmplitude, "backwardAmplitude": backwardAmplitude}) + + +def GetPositionerAlignment_S(deviceIndex, channelIndex, alignment): + """ + Returns current alignment settings + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - alignment + + Return value(s): + - forwardAmplitude: Buffer for the currently configured step amplitude + used for forward movements in vertical mode + - backwardAmplitude: Buffer for the currently configured step + amplitude used for backward movements in vertical mode + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = ffi.new(_ffiApiGenCachedTypes[1]) + local_2 = lib.SA_GetPositionerAlignment_S(deviceIndex, channelIndex, alignment, local_0, local_1) + if local_2 != ErrorCode.OK.value: + raise Error("GetPositionerAlignment_S", local_2, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "alignment": alignment}) + return local_0[0], local_1[0] + + +def SetSafeDirection_S(deviceIndex, channelIndex, direction): + """ + Configures the safe direction + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - direction: Specifies the safe direction + """ + local_0 = lib.SA_SetSafeDirection_S(deviceIndex, channelIndex, direction) + if local_0 != ErrorCode.OK.value: + raise Error("SetSafeDirection_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "direction": direction}) + + +def GetSafeDirection_S(deviceIndex, channelIndex, direction): + """ + Returns the current safe direction + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - direction + """ + local_0 = lib.SA_GetSafeDirection_S(deviceIndex, channelIndex, direction) + if local_0 != ErrorCode.OK.value: + raise Error("GetSafeDirection_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "direction": direction}) + + +def SetScale_S(deviceIndex, channelIndex, scale, inverted): + """ + Configures the logical scale + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - scale: Scale shift relative to the positioner's physical scale + - inverted: Scale inversion + """ + local_0 = lib.SA_SetScale_S(deviceIndex, channelIndex, scale, inverted) + if local_0 != ErrorCode.OK.value: + raise Error("SetScale_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "scale": scale, "inverted": inverted}) + + +def GetScale_S(deviceIndex, channelIndex): + """ + Returns the logical scale configuration + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - scale: Buffer for the currently configured scale offset + - inverted: Buffer for the currently configured scale inversion + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = ffi.new(_ffiApiGenCachedTypes[1]) + local_2 = lib.SA_GetScale_S(deviceIndex, channelIndex, local_0, local_1) + if local_2 != ErrorCode.OK.value: + raise Error("GetScale_S", local_2, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0], local_1[0] + + +def SetChannelProperty_S(deviceIndex, channelIndex, key, value): + """ + Sets a channel specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - key: Target property + - value: Desired value + """ + local_0 = lib.SA_SetChannelProperty_S(deviceIndex, channelIndex, key, value) + if local_0 != ErrorCode.OK.value: + raise Error("SetChannelProperty_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "key": key, "value": value}) + + +def GetChannelProperty_S(deviceIndex, channelIndex, key): + """ + Returns a channel specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - key: Target property + + Return value(s): + - value: Buffer for the property value@ + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = lib.SA_GetChannelProperty_S(deviceIndex, channelIndex, key, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetChannelProperty_S", local_1, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "key": key}) + return local_0[0] + + +def SetSystemProperty_S(deviceIndex, key, value): + """ + Sets a system specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - key: Target property + - value: Desired value + """ + local_0 = lib.SA_SetSystemProperty_S(deviceIndex, key, value) + if local_0 != ErrorCode.OK.value: + raise Error("SetSystemProperty_S", local_0, {"deviceIndex": deviceIndex, "key": key, "value": value}) + + +def GetSystemProperty_S(deviceIndex, key): + """ + Returns a system specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - key: Target property + + Return value(s): + - value: Buffer for the property value + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = lib.SA_GetSystemProperty_S(deviceIndex, key, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetSystemProperty_S", local_1, {"deviceIndex": deviceIndex, "key": key}) + return local_0[0] + + +def MoveStep_S(deviceIndex, channelIndex, steps, amplitude, frequency): + """ + Performs a burst of steps with the given parameters + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude in 1/10th Volts that the steps are performed + with + - frequency: Frequency in Hz that the steps are performed with + """ + local_0 = lib.SA_MoveStep_S(deviceIndex, channelIndex, steps, amplitude, frequency) + if local_0 != ErrorCode.OK.value: + raise Error("MoveStep_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "steps": steps, "amplitude": amplitude, + "frequency": frequency}) + + +def SetAmplitude_S(deviceIndex, channelIndex, amplitude): + """ + Presets the target channel's amplitude + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - amplitude: Amplitude in 1/10th Volts that should be preset + """ + local_0 = lib.SA_SetAmplitude_S(deviceIndex, channelIndex, amplitude) + if local_0 != ErrorCode.OK.value: + raise Error("SetAmplitude_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "amplitude": amplitude}) + + +def MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime): + """ + Instructs a positioner to move to a specific position using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - position: Absolute position to move to in 1/10th micro meters + - holdTime: Time (in milliseconds) the position is actively held after + reaching the target + """ + local_0 = lib.SA_MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MovePositionAbsolute_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "position": position, + "holdTime": holdTime}) + + +def MovePositionRelative_S(deviceIndex, channelIndex, diff, holdTime): + """ + Instructs a positioner to move to a position relative to its current + position using closed-loop control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - diff: Relative position difference to move in 1/10th micro meters + - holdTime: Time (in milliseconds) the position is actively held after + reaching the target + """ + local_0 = lib.SA_MovePositionRelative_S(deviceIndex, channelIndex, diff, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MovePositionRelative_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "diff": diff, "holdTime": holdTime}) + + +def MoveAngleAbsolute_S(deviceIndex, channelIndex, angle, revolution, holdTime): + """ + Instructs a positioner to move to a specific angle using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angle: Absolute angle to move to in 1/10th milli degrees + - revolution: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + local_0 = lib.SA_MoveAngleAbsolute_S(deviceIndex, channelIndex, angle, revolution, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MoveAngleAbsolute_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "angle": angle, "revolution": revolution, + "holdTime": holdTime}) + + +def MoveAngleRelative_S(deviceIndex, channelIndex, angleDiff, revolutionDiff, holdTime): + """ + Instructs a positioner to move to an angle relative to its current + angle using closed-loop control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angleDiff: Relative angle difference to move in 1/10th milli degrees + + - revolutionDiff: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + local_0 = lib.SA_MoveAngleRelative_S(deviceIndex, channelIndex, angleDiff, revolutionDiff, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MoveAngleRelative_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "angleDiff": angleDiff, + "revolutionDiff": revolutionDiff, "holdTime": holdTime}) + + +def CalibrateSensor_S(deviceIndex, channelIndex): + """ + Starts the calibration procedure + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_CalibrateSensor_S(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("CalibrateSensor_S", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + local_0 = lib.SA_MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero) + if local_0 != ErrorCode.OK.value: + raise Error("MoveToReference_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "holdTime": holdTime, + "autoZero": autoZero}) + + +def MoveToEndStop_S(deviceIndex, channelIndex, direction, holdTime, autoZero): + """ + Moves the positioner to a mechanical end stop + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - direction: Specifies the movement direction + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the end stop + - autoZero: Selects whether the current positions is set to zero upon + reaching the end stop + """ + local_0 = lib.SA_MoveToEndStop_S(deviceIndex, channelIndex, direction, holdTime, autoZero) + if local_0 != ErrorCode.OK.value: + raise Error("MoveToEndStop_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "direction": direction, + "holdTime": holdTime, "autoZero": autoZero}) + + +def Stop_S(deviceIndex, channelIndex): + """ + Stops any ongoing movement of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_Stop_S(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("Stop_S", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetStatus_S(deviceIndex, channelIndex): + """ + Returns the current movement status of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - status: Buffer for the current status + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetStatus_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetStatus_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def GetAmplitude_S(deviceIndex, channelIndex): + """ + Returns the currently configured step amplitude + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - amplitude: Buffer for the current amplitude + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetAmplitude_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetAmplitude_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def GetPosition_S(deviceIndex, channelIndex): + """ + Returns the current position of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - position: Buffer for the current position given in 1/10th micro + meters + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = lib.SA_GetPosition_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetPosition_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def GetAngle_S(deviceIndex, channelIndex): + """ + Returns the current angle of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - angle: Buffer for the current angle given in 1/10th milli degrees + - revolution: Reserved for future use + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = ffi.new(_ffiApiGenCachedTypes[3]) + local_2 = lib.SA_GetAngle_S(deviceIndex, channelIndex, local_0, local_1) + if local_2 != ErrorCode.OK.value: + raise Error("GetAngle_S", local_2, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0], local_1[0] + + +def GetPhysicalPositionKnown_S(deviceIndex, channelIndex): + """ + Returns whether the positioner "knows" its physical position (has been + referenced) + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - known: Buffer for the physical position known state + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetPhysicalPositionKnown_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetPhysicalPositionKnown_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + + +def SetClosedLoopMaxFrequency_A(deviceIndex, channelIndex, frequency): + """ + Defines the maximum frequency used for closed-loop movements + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - frequency: Maximum driving frequency in Hz + """ + local_0 = lib.SA_SetClosedLoopMaxFrequency_A(deviceIndex, channelIndex, frequency) + if local_0 != ErrorCode.OK.value: + raise Error("SetClosedLoopMaxFrequency_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "frequency": frequency}) + + +def GetClosedLoopMaxFrequency_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the currently configured + maximum frequency used for closed-loop movements + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetClosedLoopMaxFrequency_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetClosedLoopMaxFrequency_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetZero_A(deviceIndex, channelIndex): + """ + Defines the current position as the zero position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_SetZero_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("SetZero_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetSensorPresent_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns whether a positioner is + equipped with a sensor or not + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetSensorPresent_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetSensorPresent_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetSensorType_A(deviceIndex, channelIndex, type): + """ + Configures the type of positioner connected to a channel + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - type: Type of the positioner + """ + local_0 = lib.SA_SetSensorType_A(deviceIndex, channelIndex, type) + if local_0 != ErrorCode.OK.value: + raise Error("SetSensorType_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "type": type}) + + +def GetSensorType_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current type of + positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetSensorType_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetSensorType_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetPositionerAlignment_A(deviceIndex, channelIndex, alignment, forwardAmplitude=0, backwardAmplitude=0): + """ + Sets advanced properties for vertically aligned positioners that carry + high loads + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - alignment: Specifies the alignment (horizontal or vertical) + - forwardAmplitude = 0: Step amplitude used for forward movements in + vertical mode + - backwardAmplitude = 0: Step amplitude used for backward movements in + vertical mode + """ + local_0 = lib.SA_SetPositionerAlignment_A(deviceIndex, channelIndex, alignment, forwardAmplitude, backwardAmplitude) + if local_0 != ErrorCode.OK.value: + raise Error("SetPositionerAlignment_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "alignment": alignment, + "forwardAmplitude": forwardAmplitude, "backwardAmplitude": backwardAmplitude}) + + +def GetPositionerAlignment_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current alignment + settings + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetPositionerAlignment_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetPositionerAlignment_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetSafeDirection_A(deviceIndex, channelIndex, direction): + """ + Configures the safe direction + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - direction: Specifies the safe direction + """ + local_0 = lib.SA_SetSafeDirection_A(deviceIndex, channelIndex, direction) + if local_0 != ErrorCode.OK.value: + raise Error("SetSafeDirection_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "direction": direction}) + + +def GetSafeDirection_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current safe direction + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetSafeDirection_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetSafeDirection_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetScale_A(deviceIndex, channelIndex, scale, inverted): + """ + Configures the logical scale + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - scale: Scale shift relative to the positioner's physical scale + - inverted: Scale inversion + """ + local_0 = lib.SA_SetScale_A(deviceIndex, channelIndex, scale, inverted) + if local_0 != ErrorCode.OK.value: + raise Error("SetScale_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "scale": scale, "inverted": inverted}) + + +def GetScale_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current logical scale + configuration + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetScale_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetScale_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetReportOnComplete_A(deviceIndex, channelIndex, report): + """ + Defines whether or not to report completion of the last movement + command + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - report: Enables/Disables Report On Complete + """ + local_0 = lib.SA_SetReportOnComplete_A(deviceIndex, channelIndex, report) + if local_0 != ErrorCode.OK.value: + raise Error("SetReportOnComplete_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "report": report}) + + +def SetChannelProperty_A(deviceIndex, channelIndex, key, value): + """ + Sets a channel specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - key: Target property + - value: Desired value + """ + local_0 = lib.SA_SetChannelProperty_A(deviceIndex, channelIndex, key, value) + if local_0 != ErrorCode.OK.value: + raise Error("SetChannelProperty_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "key": key, "value": value}) + + +def GetChannelProperty_A(deviceIndex, channelIndex, key): + """ + Sends a query to the channel that returns the selected property + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - key: Target property + """ + local_0 = lib.SA_GetChannelProperty_A(deviceIndex, channelIndex, key) + if local_0 != ErrorCode.OK.value: + raise Error("GetChannelProperty_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "key": key}) + + +def SetSystemProperty_A(deviceIndex, key, value): + """ + Sets a system specific property depending on the given key + + Parameters: + - deviceIndex: Selects the device (zero-based) + - key: Target property + - value: Desired value + """ + local_0 = lib.SA_SetSystemProperty_A(deviceIndex, key, value) + if local_0 != ErrorCode.OK.value: + raise Error("SetSystemProperty_A", local_0, {"deviceIndex": deviceIndex, "key": key, "value": value}) + + +def GetSystemProperty_A(deviceIndex, key): + """ + Sends a query to the device that returns the selected property + + Parameters: + - deviceIndex: Selects the device (zero-based) + - key: Target property + """ + local_0 = lib.SA_GetSystemProperty_A(deviceIndex, key) + if local_0 != ErrorCode.OK.value: + raise Error("GetSystemProperty_A", local_0, {"deviceIndex": deviceIndex, "key": key}) + + +def MoveStep_A(deviceIndex, channelIndex, steps, amplitude, frequency): + """ + Performs a burst of steps with the given parameters + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude that the steps are performed with + - frequency: Frequency in Hz that the steps are performed with + """ + local_0 = lib.SA_MoveStep_A(deviceIndex, channelIndex, steps, amplitude, frequency) + if local_0 != ErrorCode.OK.value: + raise Error("MoveStep_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "steps": steps, "amplitude": amplitude, + "frequency": frequency}) + + +def SetAmplitude_A(deviceIndex, channelIndex, amplitude): + """ + Presets the target channel's amplitude + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - amplitude: Amplitude in 1/10th Volts that should be preset + """ + local_0 = lib.SA_SetAmplitude_A(deviceIndex, channelIndex, amplitude) + if local_0 != ErrorCode.OK.value: + raise Error("SetAmplitude_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "amplitude": amplitude}) + + +def MovePositionAbsolute_A(deviceIndex, channelIndex, position, holdTime): + """ + Instructs a positioner to move to a specific position using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - position: Absolute position to move to in 1/10th micro meters + - holdTime: Time (in milliseconds) the position is actively held after + reaching the target + """ + local_0 = lib.SA_MovePositionAbsolute_A(deviceIndex, channelIndex, position, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MovePositionAbsolute_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "position": position, + "holdTime": holdTime}) + + +def MovePositionRelative_A(deviceIndex, channelIndex, diff, holdTime): + """ + Instructs a positioner to move to a position relative to its current + position using closed-loop control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - diff: Relative position difference to move in 1/10th micro meters + - holdTime: Time (in milliseconds) the position is actively held after + reaching the target + """ + local_0 = lib.SA_MovePositionRelative_A(deviceIndex, channelIndex, diff, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MovePositionRelative_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "diff": diff, "holdTime": holdTime}) + + +def MoveAngleAbsolute_A(deviceIndex, channelIndex, angle, revolution, holdTime): + """ + Instructs a positioner to move to a specific angle using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angle: Absolute angle to move to in 1/10th milli degrees + - revolution: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + local_0 = lib.SA_MoveAngleAbsolute_A(deviceIndex, channelIndex, angle, revolution, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MoveAngleAbsolute_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "angle": angle, "revolution": revolution, + "holdTime": holdTime}) + + +def MoveAngleRelative_A(deviceIndex, channelIndex, angleDiff, revolutionDiff, holdTime): + """ + Instructs a positioner to move to an angle relative to its current + angle using closed-loop control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angleDiff: Relative angle difference to move in 1/10th milli degrees + + - revolutionDiff: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + local_0 = lib.SA_MoveAngleRelative_A(deviceIndex, channelIndex, angleDiff, revolutionDiff, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MoveAngleRelative_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "angleDiff": angleDiff, + "revolutionDiff": revolutionDiff, "holdTime": holdTime}) + + +def CalibrateSensor_A(deviceIndex, channelIndex): + """ + Starts the calibration procedure + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_CalibrateSensor_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("CalibrateSensor_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def MoveToReference_A(deviceIndex, channelIndex, holdTime, autoZero): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + local_0 = lib.SA_MoveToReference_A(deviceIndex, channelIndex, holdTime, autoZero) + if local_0 != ErrorCode.OK.value: + raise Error("MoveToReference_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "holdTime": holdTime, + "autoZero": autoZero}) + + +def MoveToEndStop_A(deviceIndex, channelIndex, direction, holdTime, autoZero): + """ + Moves the positioner to a mechanical end stop + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - direction: Specifies the movement direction + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the end stop + - autoZero: Selects whether the current positions is set to zero upon + reaching the end stop + """ + local_0 = lib.SA_MoveToEndStop_A(deviceIndex, channelIndex, direction, holdTime, autoZero) + if local_0 != ErrorCode.OK.value: + raise Error("MoveToEndStop_A", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "direction": direction, + "holdTime": holdTime, "autoZero": autoZero}) + + +def Stop_A(deviceIndex, channelIndex): + """ + Stops any ongoing movement of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_Stop_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("Stop_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetStatus_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current movement status + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetStatus_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetStatus_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetAmplitude_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current step amplitude + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetAmplitude_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetAmplitude_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetPosition_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetPosition_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetPosition_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetAngle_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns the current angle + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetAngle_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetAngle_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def GetPhysicalPositionKnown_A(deviceIndex, channelIndex): + """ + Sends a query to the channel that returns whether the positioner + "knows" its physical position (has been referenced) + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_GetPhysicalPositionKnown_A(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("GetPhysicalPositionKnown_A", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + +def SetReceiveNotification_A(deviceIndex, event): + """ + Specifies an event used to inform the application when a data packet + has been received + + Parameters: + - deviceIndex: Selects the device (zero-based) + - event + """ + local_0 = lib.SA_SetReceiveNotification_A(deviceIndex, event) + if local_0 != ErrorCode.OK.value: + raise Error("SetReceiveNotification_A", local_0, {"deviceIndex": deviceIndex, "event": event}) + + +def ReceiveNextPacket_A(deviceIndex, timeout): + """ + Receives a data packet from the device + + Parameters: + - deviceIndex: Selects the device (zero-based) + - timeout: Specifies how long (in milliseconds) to wait for incoming + data + + Return value(s): + - packet: Buffer for the received data packet + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[4]) + local_1 = lib.SA_ReceiveNextPacket_A(deviceIndex, timeout, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("ReceiveNextPacket_A", local_1, {"deviceIndex": deviceIndex, "timeout": timeout}) + return packet(None, None, None, None, None, local_0) + + +def ReceiveNextPacketIfChannel_A(deviceIndex, channelIndex, timeout): + """ + Receives a data packet for the given channel + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - timeout: Specifies how long (in milliseconds) to wait for incoming + data + + Return value(s): + - packet: Buffer for the received data packet + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[4]) + local_1 = lib.SA_ReceiveNextPacketIfChannel_A(deviceIndex, channelIndex, timeout, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("ReceiveNextPacketIfChannel_A", local_1, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "timeout": timeout}) + return packet(None, None, None, None, None, local_0) + + +def LookAtNextPacket_A(deviceIndex, timeout): + """ + Receives a data packet from the device without actually consuming it + + Parameters: + - deviceIndex: Selects the device (zero-based) + - timeout: Specifies how long (in milliseconds) to wait for incoming + data + + Return value(s): + - packet: Buffer for the received data packet + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[4]) + local_1 = lib.SA_LookAtNextPacket_A(deviceIndex, timeout, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("LookAtNextPacket_A", local_1, {"deviceIndex": deviceIndex, "timeout": timeout}) + return packet(None, None, None, None, None, local_0) + + +def DiscardPacket_A(deviceIndex): + """ + Discards a received data packet + + Parameters: + - deviceIndex: Selects the device (zero-based) + """ + local_0 = lib.SA_DiscardPacket_A(deviceIndex) + if local_0 != ErrorCode.OK.value: + raise Error("DiscardPacket_A", local_0, {"deviceIndex": deviceIndex}) + + +class ApiVersion(enum.IntEnum): + MAJOR = 0x01 + MINOR = 0x05 + UPDATE = 0x10 + + +class Global(enum.IntEnum): + FALSE = 0x0 + TRUE = 0x1 + SYNCHRONOUS_COMMUNICATION = 0x0 + ASYNCHRONOUS_COMMUNICATION = 0x1 + HARDWARE_RESET = 0x2 + NO_REPORT_ON_COMPLETE = 0x0 + REPORT_ON_COMPLETE = 0x1 + BACKWARD_DIRECTION = 0x0 + FORWARD_DIRECTION = 0x1 + NO_AUTO_ZERO = 0x0 + AUTO_ZERO = 0x1 + NO_SENSOR_PRESENT = 0x0 + SENSOR_PRESENT = 0x1 + PHYSICAL_POSITION_UNKNOWN = 0x0 + PHYSICAL_POSITION_KNOWN = 0x1 + + +FALSE = Global.FALSE +TRUE = Global.TRUE +SYNCHRONOUS_COMMUNICATION = Global.SYNCHRONOUS_COMMUNICATION +ASYNCHRONOUS_COMMUNICATION = Global.ASYNCHRONOUS_COMMUNICATION +HARDWARE_RESET = Global.HARDWARE_RESET +NO_REPORT_ON_COMPLETE = Global.NO_REPORT_ON_COMPLETE +REPORT_ON_COMPLETE = Global.REPORT_ON_COMPLETE +BACKWARD_DIRECTION = Global.BACKWARD_DIRECTION +FORWARD_DIRECTION = Global.FORWARD_DIRECTION +NO_AUTO_ZERO = Global.NO_AUTO_ZERO +AUTO_ZERO = Global.AUTO_ZERO +NO_SENSOR_PRESENT = Global.NO_SENSOR_PRESENT +SENSOR_PRESENT = Global.SENSOR_PRESENT +PHYSICAL_POSITION_UNKNOWN = Global.PHYSICAL_POSITION_UNKNOWN +PHYSICAL_POSITION_KNOWN = Global.PHYSICAL_POSITION_KNOWN + + +class ErrorCode(enum.IntEnum): + OK = 0x00 + INITIALIZATION_ERROR = 0x01 + NOT_INITIALIZED_ERROR = 0x02 + NO_DEVICES_FOUND_ERROR = 0x03 + TOO_MANY_DEVICES_ERROR = 0x04 + INVALID_DEVICE_INDEX_ERROR = 0x05 + INVALID_CHANNEL_INDEX_ERROR = 0x06 + TRANSMIT_ERROR = 0x07 + WRITE_ERROR = 0x08 + INVALID_PARAMETER_ERROR = 0x09 + READ_ERROR = 0x0a + INTERNAL_ERROR = 0x0c + WRONG_MODE_ERROR = 0x0d + PROTOCOL_ERROR = 0x0e + TIMEOUT_ERROR = 0x0f + NOTIFICATION_ALREADY_SET_ERROR = 0x10 + ID_LIST_TOO_SMALL_ERROR = 0x11 + DEVICE_ALREADY_ADDED_ERROR = 0x12 + DEVICE_NOT_FOUND_ERROR = 0x13 + INVALID_COMMAND_ERROR = 0x80 + COMMAND_NOT_SUPPORTED_ERROR = 0x81 + NO_SENSOR_PRESENT_ERROR = 0x82 + WRONG_SENSOR_TYPE_ERROR = 0x83 + END_STOP_REACHED_ERROR = 0x84 + COMMAND_OVERRIDDEN_ERROR = 0x85 + HV_RANGE_ERROR = 0x86 + TEMP_OVERHEAT_ERROR = 0x87 + CALIBRATION_FAILED_ERROR = 0x88 + REFERENCING_FAILED_ERROR = 0x89 + NOT_PROCESSABLE_ERROR = 0x8a + OTHER_ERROR = 0xff + + +class PacketType(enum.IntEnum): + NO_PACKET = 0x00 + ERROR_PACKET = 0x01 + POSITION_PACKET = 0x02 + ANGLE_PACKET = 0x03 + COMPLETED_PACKET = 0x04 + STATUS_PACKET = 0x05 + CLOSED_LOOP_FREQUENCY_PACKET = 0x06 + SENSOR_TYPE_PACKET = 0x07 + SENSOR_PRESENT_PACKET = 0x08 + AMPLITUDE_PACKET = 0x09 + POSITIONER_ALIGNMENT_PACKET = 0x0a + SAFE_DIRECTION_PACKET = 0x0b + SCALE_PACKET = 0x0c + PHYSICAL_POSITION_KNOWN_PACKET = 0x0d + CHANNEL_PROPERTY_PACKET = 0x0e + SYSTEM_PROPERTY_PACKET = 0x0f + INVALID_PACKET = 0xff + + +class StatusCode(enum.IntEnum): + STOPPED = 0x0 + SETTING_AMPLITUDE = 0x1 + MOVING = 0x2 + TARGETING = 0x3 + HOLDING = 0x4 + CALIBRATING = 0x5 + MOVING_TO_REFERENCE = 0x6 + + +class SensorType(enum.IntEnum): + M_SENSOR_TYPE = 0x01 + GA_SENSOR_TYPE = 0x02 + GB_SENSOR_TYPE = 0x03 + GC_SENSOR_TYPE = 0x04 + GD_SENSOR_TYPE = 0x05 + GE_SENSOR_TYPE = 0x06 + RA_SENSOR_TYPE = 0x07 + GF_SENSOR_TYPE = 0x08 + RB_SENSOR_TYPE = 0x09 + SR36M_SENSOR_TYPE = 0x0a + SR36ME_SENSOR_TYPE = 0x0b + SR50M_SENSOR_TYPE = 0x0c + SR50ME_SENSOR_TYPE = 0x0d + MM50_SENSOR_TYPE = 0x0e + G935M_SENSOR_TYPE = 0x0f + MD_SENSOR_TYPE = 0x10 + TT254_SENSOR_TYPE = 0x11 + LC_SENSOR_TYPE = 0x12 + LR_SENSOR_TYPE = 0x13 + LCD_SENSOR_TYPE = 0x14 + L_SENSOR_TYPE = 0x15 + LD_SENSOR_TYPE = 0x16 + LE_SENSOR_TYPE = 0x17 + LED_SENSOR_TYPE = 0x18 + SL_S1I1E1_POSITIONER_TYPE = 0x19 + SL_D1I1E1_POSITIONER_TYPE = 0x1a + SL_S1I2E2_POSITIONER_TYPE = 0x1b + SL_D1I2E2_POSITIONER_TYPE = 0x1c + ST_S1I1E2_POSITIONER_TYPE = 0x1d + ST_S1I2E2_POSITIONER_TYPE = 0x25 + SG_D1L1S_POSITIONER_TYPE = 0x1e + SG_D1L1E_POSITIONER_TYPE = 0x1f + SG_D1L2S_POSITIONER_TYPE = 0x20 + SG_D1L2E_POSITIONER_TYPE = 0x21 + SG_D1M1E_POSITIONER_TYPE = 0x22 + SG_D1M2E_POSITIONER_TYPE = 0x23 + SI_S1L1S_POSITIONER_TYPE = 0x24 + SR_T5L3S_POSITIONER_TYPE = 0x26 + SI_S1L4E_POSITIONER_TYPE = 0x27 + SI_S1L1E_POSITIONER_TYPE = 0x28 + SI_S1L3E_POSITIONER_TYPE = 0x29 + NO_SENSOR_TYPE = 0x00 + L180_SENSOR_TYPE = 0x01 + G180R435_SENSOR_TYPE = 0x02 + G180R560_SENSOR_TYPE = 0x03 + G50R85_SENSOR_TYPE = 0x04 + + +class Alignment(enum.IntEnum): + HORIZONTAL = 0x0 + VERTICAL = 0x1 + + +class MovementType(enum.IntEnum): + LINEAR = 0x0 + ROTARY = 0x1 + GONIOMETER = 0x2 + + +class SystemProperty(enum.IntEnum): + INTERNAL_TEMPERATURE = 0x1 + INTERNAL_VOLTAGE = 0x2 + HARDWARE_VERSION_CODE = 0x3 + + +class ChannelProperty(enum.IntEnum): + TARGET_REACHED_THRESHOLD = 0x03 + KP = 0x05 + KPD = 0x06 + DEFAULT_MAX_CLOSED_LOOP_FREQUENCY = 0x0f + ADVANCED_STEPPING_MODE_ENABLED = 0x15 + MOVEMENT_TYPE = 0x19 + + +import platform + +__initBindings("SCU3DControl.dll" if platform.system() == "Windows" else ("lib" + "SCU3DControl".lower() + ".so")) + + +def __initFfiApiGenCachedTypes(): + global _ffiApiGenCachedTypes + _ffiApiGenCachedTypes = [ + ffi.typeof("struct SA_packet *"), + ffi.typeof("unsigned int *"), + ffi.typeof("unsigned int []"), + ffi.typeof("int *"), + ffi.typeof("SA_PACKET *")] + + +__initFfiApiGenCachedTypes() +__all__ = ["api_version", "apigen_version", "Error", "packet", "GetDLLVersion", "GetAvailableDevices", + "AddDeviceToInitDevicesList", "ClearInitDevicesList", "InitDevices", "ReleaseDevices", "GetNumberOfDevices", + "GetDeviceID", "GetDeviceFirmwareVersion", "SetClosedLoopMaxFrequency_S", "GetClosedLoopMaxFrequency_S", + "SetZero_S", "GetSensorPresent_S", "SetSensorType_S", "GetSensorType_S", "SetPositionerAlignment_S", + "GetPositionerAlignment_S", "SetSafeDirection_S", "GetSafeDirection_S", "SetScale_S", "GetScale_S", + "SetChannelProperty_S", "GetChannelProperty_S", "SetSystemProperty_S", "GetSystemProperty_S", "MoveStep_S", + "SetAmplitude_S", "MovePositionAbsolute_S", "MovePositionRelative_S", "MoveAngleAbsolute_S", + "MoveAngleRelative_S", "CalibrateSensor_S", "MoveToReference_S", "MoveToEndStop_S", "Stop_S", "GetStatus_S", + "GetAmplitude_S", "GetPosition_S", "GetAngle_S", "GetPhysicalPositionKnown_S", "SetClosedLoopMaxFrequency_A", + "GetClosedLoopMaxFrequency_A", "SetZero_A", "GetSensorPresent_A", "SetSensorType_A", "GetSensorType_A", + "SetPositionerAlignment_A", "GetPositionerAlignment_A", "SetSafeDirection_A", "GetSafeDirection_A", + "SetScale_A", "GetScale_A", "SetReportOnComplete_A", "SetChannelProperty_A", "GetChannelProperty_A", + "SetSystemProperty_A", "GetSystemProperty_A", "MoveStep_A", "SetAmplitude_A", "MovePositionAbsolute_A", + "MovePositionRelative_A", "MoveAngleAbsolute_A", "MoveAngleRelative_A", "CalibrateSensor_A", + "MoveToReference_A", "MoveToEndStop_A", "Stop_A", "GetStatus_A", "GetAmplitude_A", "GetPosition_A", + "GetAngle_A", "GetPhysicalPositionKnown_A", "SetReceiveNotification_A", "ReceiveNextPacket_A", + "ReceiveNextPacketIfChannel_A", "LookAtNextPacket_A", "DiscardPacket_A", "ApiVersion", "FALSE", "TRUE", + "SYNCHRONOUS_COMMUNICATION", "ASYNCHRONOUS_COMMUNICATION", "HARDWARE_RESET", "NO_REPORT_ON_COMPLETE", + "REPORT_ON_COMPLETE", "BACKWARD_DIRECTION", "FORWARD_DIRECTION", "NO_AUTO_ZERO", "AUTO_ZERO", + "NO_SENSOR_PRESENT", "SENSOR_PRESENT", "PHYSICAL_POSITION_UNKNOWN", "PHYSICAL_POSITION_KNOWN", "ErrorCode", + "PacketType", "StatusCode", "SensorType", "Alignment", "MovementType", "SystemProperty", "ChannelProperty"] diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py new file mode 100644 index 0000000..322e5a8 --- /dev/null +++ b/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py @@ -0,0 +1,285 @@ +from cffi import FFI + +import enum +import sys +assert sys.version_info >= (3, 4), "Python v3.4 or higher is required" +apigen_version = (1, 8, 1) +api_version = (1, 5, 16) +def __initBindings(libName): + global ffi, lib + ffi = FFI() + ffi.cdef(""" +typedef unsigned int SA_PACKET_TYPE; +typedef unsigned int SA_INDEX; +struct SA_packet{ SA_PACKET_TYPE packetType; SA_INDEX channelIndex; unsigned int data1; int data2; int data3;}; +typedef struct SA_packet SA_PACKET; +typedef unsigned int SA_STATUS; +SA_STATUS SA_GetDLLVersion(unsigned int *version); +SA_STATUS SA_GetAvailableDevices(unsigned int *idList, unsigned int *idListSize); +SA_STATUS SA_AddDeviceToInitDevicesList(unsigned int deviceId); +SA_STATUS SA_ClearInitDevicesList(); +SA_STATUS SA_InitDevices(unsigned int configuration); +SA_STATUS SA_ReleaseDevices(); +SA_STATUS SA_GetNumberOfDevices(unsigned int *number); +SA_STATUS SA_GetDeviceID(SA_INDEX deviceIndex, unsigned int *deviceId); +SA_STATUS SA_GetDeviceFirmwareVersion(SA_INDEX deviceIndex, unsigned int *version); +SA_STATUS SA_SetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); +SA_STATUS SA_GetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *frequency); +SA_STATUS SA_SetZero_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetSensorPresent_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *present); +SA_STATUS SA_SetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); +SA_STATUS SA_GetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *type); +SA_STATUS SA_SetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); +SA_STATUS SA_GetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *alignment, unsigned int *forwardAmplitude, unsigned int *backwardAmplitude); +SA_STATUS SA_SetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); +SA_STATUS SA_GetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *direction); +SA_STATUS SA_SetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); +SA_STATUS SA_GetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *scale, unsigned int *inverted); +SA_STATUS SA_SetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); +SA_STATUS SA_GetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int *value); +SA_STATUS SA_SetSystemProperty_S(SA_INDEX deviceIndex, int key, int value); +SA_STATUS SA_GetSystemProperty_S(SA_INDEX deviceIndex, int key, int *value); +SA_STATUS SA_MoveStep_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); +SA_STATUS SA_SetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); +SA_STATUS SA_MovePositionAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); +SA_STATUS SA_MovePositionRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); +SA_STATUS SA_MoveAngleAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); +SA_STATUS SA_MoveAngleRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); +SA_STATUS SA_CalibrateSensor_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_MoveToReference_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_MoveToEndStop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_Stop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetStatus_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *status); +SA_STATUS SA_GetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *amplitude); +SA_STATUS SA_GetPosition_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *position); +SA_STATUS SA_GetAngle_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *angle, int *revolution); +SA_STATUS SA_GetPhysicalPositionKnown_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *known); +SA_STATUS SA_SetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); +SA_STATUS SA_GetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetZero_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetSensorPresent_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); +SA_STATUS SA_GetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); +SA_STATUS SA_GetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); +SA_STATUS SA_GetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); +SA_STATUS SA_GetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetReportOnComplete_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int report); +SA_STATUS SA_SetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); +SA_STATUS SA_GetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key); +SA_STATUS SA_SetSystemProperty_A(SA_INDEX deviceIndex, int key, int value); +SA_STATUS SA_GetSystemProperty_A(SA_INDEX deviceIndex, int key); +SA_STATUS SA_MoveStep_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); +SA_STATUS SA_SetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); +SA_STATUS SA_MovePositionAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); +SA_STATUS SA_MovePositionRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); +SA_STATUS SA_MoveAngleAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); +SA_STATUS SA_MoveAngleRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); +SA_STATUS SA_CalibrateSensor_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_MoveToReference_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_MoveToEndStop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); +SA_STATUS SA_Stop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetStatus_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetPosition_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetAngle_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_GetPhysicalPositionKnown_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); +SA_STATUS SA_SetReceiveNotification_A(SA_INDEX deviceIndex, void *event); +SA_STATUS SA_ReceiveNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_ReceiveNextPacketIfChannel_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_LookAtNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); +SA_STATUS SA_DiscardPacket_A(SA_INDEX deviceIndex); +""") + lib = ffi.dlopen(libName) + +def __initFfiApiGenCachedTypes(): + global _ffiApiGenCachedTypes + _ffiApiGenCachedTypes = [ + ffi.typeof("struct SA_packet *"), + ffi.typeof("unsigned int *"), + ffi.typeof("unsigned int []"), + ffi.typeof("int *"), + ffi.typeof("SA_PACKET *")] + + +class Error(Exception): + def __init__(self, func, code, arguments): + self.func = func + self.code = code + self.arguments = arguments + def __str__(self): + return "{} returned {} with arguments {}".format(self.func, self.code, self.arguments) + + +class packet: + """ + Members: + - packetType + - channelIndex + - data1 + - data2 + - data3 + + """ + __slots__ = ['packetType', 'channelIndex', 'data1', 'data2', 'data3', 'cHandle'] + + def __init__(self, packetType, channelIndex, data1, data2, data3, cHandle=None): + if packetType is not None: + self.packetType = packetType + if channelIndex is not None: + self.channelIndex = channelIndex + if data1 is not None: + self.data1 = data1 + if data2 is not None: + self.data2 = data2 + if data3 is not None: + self.data3 = data3 + self.cHandle = cHandle + + def __getattr__(self, attr): + if self.cHandle is not None: + value = getattr(self.cHandle, attr) + retValue = value + setattr(self, attr, retValue) + return retValue + else: + raise AttributeError(f"packet has no attribute: {attr}") + + def asFFI(self): + return ffi.new(_ffiApiGenCachedTypes[0], + {'packetType': self.packetType, 'channelIndex': self.channelIndex, 'data1': self.data1, + 'data2': self.data2, 'data3': self.data3}) + +class SmarActSCUWrapper: + + def GetDLLVersion(): + """ + Returns the version code of the library + + Return value(s): + - version: Library Version + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[1]) + local_1 = lib.SA_GetDLLVersion(local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetDLLVersion", local_1, {}) + return local_0[0] + + def GetAvailableDevices(idListSize=256): + """ + Returns a list of available device IDs + + Parameters: + - idListSize = 256: Length of the buffer to allocate + + Return value(s): + - idList: Buffer for device IDs + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[2], idListSize) + local_1 = ffi.new(_ffiApiGenCachedTypes[1], idListSize) + local_2 = lib.SA_GetAvailableDevices(local_0, local_1) + if local_2 != ErrorCode.OK.value: + raise Error("GetAvailableDevices", local_2, {}) + return ffi.unpack(local_0, local_1[0]) + + def AddDeviceToInitDevicesList(deviceId): + """ + Used to acquire one or more specific devices + + Parameters: + - deviceId: ID that is to be acquired + """ + local_0 = lib.SA_AddDeviceToInitDevicesList(deviceId) + if local_0 != ErrorCode.OK.value: + raise Error("AddDeviceToInitDevicesList", local_0, {"deviceId": deviceId}) + + def ClearInitDevicesList(): + """ + Clears the device initialization list + """ + local_0 = lib.SA_ClearInitDevicesList() + if local_0 != ErrorCode.OK.value: + raise Error("ClearInitDevicesList", local_0, {}) + + def InitDevices(configuration): + """ + Global initialization function to acquire all devices available in the + DevicesList + + Parameters: + - configuration: Selection between synchronous and asynchronous + communication mode + """ + local_0 = lib.SA_InitDevices(configuration) + if local_0 != ErrorCode.OK.value: + raise Error("InitDevices", local_0, {"configuration": configuration}) + + def MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + local_0 = lib.SA_MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero) + if local_0 != ErrorCode.OK.value: + raise Error("MoveToReference_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "holdTime": holdTime, + "autoZero": autoZero}) + + def SetZero_S(deviceIndex, channelIndex): + """ + Defines the current position as the zero position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + """ + local_0 = lib.SA_SetZero_S(deviceIndex, channelIndex) + if local_0 != ErrorCode.OK.value: + raise Error("SetZero_S", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + + def MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime): + """ + Instructs a positioner to move to a specific position using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - position: Absolute position to move to in 1/10th micro meters + - holdTime: Time (in milliseconds) the position is actively held after + reaching the target + """ + local_0 = lib.SA_MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime) + if local_0 != ErrorCode.OK.value: + raise Error("MovePositionAbsolute_S", local_0, + {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "position": position, + "holdTime": holdTime}) + + def GetPosition_S(deviceIndex, channelIndex): + """ + Returns the current position of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - position: Buffer for the current position given in 1/10th micro + meters + """ + local_0 = ffi.new(_ffiApiGenCachedTypes[3]) + local_1 = lib.SA_GetPosition_S(deviceIndex, channelIndex, local_0) + if local_1 != ErrorCode.OK.value: + raise Error("GetPosition_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) + return local_0[0] + From db4f866a33a958a20f95819a889ee620c161fe30 Mon Sep 17 00:00:00 2001 From: adele080402 Date: Fri, 28 Mar 2025 16:37:00 +0100 Subject: [PATCH 03/14] Update of the SCUWrapper code, and beginning of pymodaq_plugin's code --- .../daq_move_SmarActSCUINSA.py | 137 +++++++ .../hardware/smaract/scu/__init__.py | 0 .../hardware/smaract/{ => scu}/bindings.py | 0 .../hardware/smaract/scu/scu_wrapper.py | 334 ++++++++++++++++++ .../hardware/smaract/smaract_SCU_wrapper.py | 1 - 5 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py create mode 100644 src/pymodaq_plugins_smaract/hardware/smaract/scu/__init__.py rename src/pymodaq_plugins_smaract/hardware/smaract/{ => scu}/bindings.py (100%) create mode 100644 src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py new file mode 100644 index 0000000..fe0cad0 --- /dev/null +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -0,0 +1,137 @@ +"""At the first run, if the program complains about a _build_scu programm not being present, just run the +_build_smaract.py, that will look at the C header file to produce connexion between the dll and the python files""" + + +from typing import Union, List, Dict + +from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun +from pymodaq.utils.daq_utils import ThreadCommand +from easydict import EasyDict as edict + +from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import SCUWrapper, SCULinear, SCURotation + +psets = get_devices(module='motion._smaract') +psets_str = [f"Dev. Id{pset['id']} channel {pset['index']}" for pset in psets] + + +class DAQ_Move_SmarActSCU(DAQ_Move_base): + """ + + """ + _controller_units = "" + _epsilon = 0.002 + # find controller locators + + is_multiaxes = False + stage_names = [] + + params = [ + {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, + {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 15000, 'limits':SCUWrapper.frequency_limits}, + {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100, 'limits':SCUWrapper.amplitude_limits}, + {'title': 'Max Frequency (Hz)', 'name': 'maxfreq', 'type': 'int', 'value': 18500}, + ] + comon_parameters_fun(is_multiaxes, epsilon=_epsilon) + ########################################################## + + def ini_attributes(self): + self.controller: Union[SCUWrapper, SCULinear] = None + self.settings.child("epsilon").setValue(0.002) + + def commit_settings(self, param): + if param.name() == 'amplitude': + self.controller.amplitude = self.controller.amp() + elif param.name() == 'frequency': + self.controller.frequency = param.value() + + elif param.name() == 'maxfreq': + self.controller.max_frequency = param.value() + self.settings.child('maxfreq').setValue(self.controller.max_frequency) + + def ini_stage(self, controller=None): + """Initialize the controller and stages (axes) with given parameters. + + """ + index = self.settings.child('device').opts['limits'].index(self.settings['device']) + if self.is_master: + self.controller = ... + else: + self.controller = controller + + self.settings.child('units').setValue(self.controller.units) + self.settings.child('amplitude').setOpts(limits=list(self.controller.amplitude_limits)) + self.settings.child('frequency').setOpts(limits=list(self.controller.frequency_limits)) + self.settings.child('amplitude').setValue(self.controller.amplitude) + self.settings.child('frequency').setValue(self.controller.frequency) + if not isinstance(self.controller, SCUWrapper): + self.settings.child('maxfreq').setValue(self.controller.max_frequency) + + info = '' + initialized = True + + return info, initialized + + def close(self): + """Close the communication with the SmarAct controller. + """ + self.controller.close() + self.controller = None + + def get_actuator_value(self): + """Get the current position from the hardware with scaling conversion. + + Returns + ------- + float: The position obtained after scaling conversion. + """ + position = self.controller.get_position() + # convert position if scaling options have been used, mandatory here + position = self.get_position_with_scaling(position) + #position = self.target_position + self.current_position = position + return position + + def move_abs(self, position): + """Move to an absolute position + + Parameters + ---------- + position: float + """ + # limit position if bounds options has been selected and if position is + # out of them + position = self.check_bound(position) + self.target_position = position + # convert the user set position to the controller position if scaling + # has been activated by user + position = self.set_position_with_scaling(position) + + self.controller.move_abs(self, position) + + def move_rel(self, position): + """Move to a relative position + + Parameters + ---------- + position: float + """ + 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) + + self.controller.move_rel(self, position) + + def move_home(self): + """Move to home and reset position to zero. + """ + self.controller.move_home() + self.get_actuator_value() + + def stop_motion(self): + """ + """ + self.controller.stop() + self.move_done() + + +if __name__ == "__main__": + main(__file__, init=False) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/__init__.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/bindings.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/bindings.py similarity index 100% rename from src/pymodaq_plugins_smaract/hardware/smaract/bindings.py rename to src/pymodaq_plugins_smaract/hardware/smaract/scu/bindings.py diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py new file mode 100644 index 0000000..fa3f6b5 --- /dev/null +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -0,0 +1,334 @@ +import time +from typing import Optional, List + +from pathlib import Path +import os + + + +from pymodaq_plugins_smaract.hardware.smaract.scu import bindings + + +def get_devices(): + """ + Get devices ids and informations about them + + Returns + ------- + list(int) + list(SCUWrapper or SCULinear or SCURotation) + """ + ids = bindings.GetAvailableDevices() + ##ids = [ids] + bindings.InitDevices(configuration=bindings.SYNCHRONOUS_COMMUNICATION) + ptype = [] + + for ind in enumerate(ids): + rotation = False + ind_channel = 0 + sensor = False + + while True: + try: + bindings.GetStatus_S(ids, ind_channel) + except bindings.Error as e: + # will fire an error if the ind_channel is invalid + break + try: + sensor = bool(bindings.GetSensorPresent_S(ind, ind_channel)) + except bindings.Error as e: + sensor = False + if sensor: + try: + bindings.GetAngle_S(ind,ind_channel) + rotation = True + except bindings.Error: + rotation = False + ind_channel += 1 + + for ind_channel in range(ind_channel): + ptype.append(SCUWrapper if not sensor else SCURotation if rotation else SCULinear) + + bindings.ReleaseDevices() + + return ids, ptype + + + +class SCUWrapper: + + dev_type = 'stepper' + units = 'steps' + + amplitude_limits = (150, 1001) + frequency_limits = (1, 18501) + steps_limits = (-30000, 30001) + angle_limits = (-3599999, 3599999) + + + def __init__(self): + + self.device_index: Optional[int] = None + self.channel_index = 0 + self.hold_time = 10 + self._amplitude = 400 #between 150 and 1000 + self._frequency = 15000 #between 1 and 18500 + self._steps = 20000 #between -30000 and 30000 + + + + @property + def amplitude (self): + """ + The amplitude should be defined in Volts, between 15V and 100V + """ + return self._amplitude + + @amplitude.setter + def amplitude(self, number : int): + if isinstance(number, int) and 100 > number > 15 : + self._amplitude = number * 10 + bindings.SetAmplitude_S(self.device_index, self.channel_index, self._amplitude) + + + @property + def frequency(self): + """ + The frequency should be defined in Hertz, between 1Hz and 18500Hz + """ + return self._frequency + + @frequency.setter + def frequency(self, number: int): + if isinstance(number, int) and 18500 > number > 1: + self._frequency = number + + @property + def steps(self): + """ + The steps should be between -30000 and 30000 + """ + return self._steps + + @steps.setter + def steps(self, number: int): + if isinstance(number, int) and 30000 > number > -30000: + self._steps = number + else: + self._steps=0 + + + def init_device (self, configuration=bindings.SYNCHRONOUS_COMMUNICATION) : + bindings.InitDevices(configuration) + + + def open(self, device_index: int, configuration=bindings.SYNCHRONOUS_COMMUNICATION) -> bool: + config = configuration.value + self.device_index = device_index + try: + error = bindings.InitDevices(config) + return True + except bindings.Error as e: + print(str(e)) + return False + + def close(self): + bindings.ReleaseDevices() + + def get_position(self) -> float: + """ + Returns the current position of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - position: Buffer for the current position given in 1/10th micro + meters + """ + + position = bindings.GetPosition_S(self.device_index, self.channel_index) + + return float(position / 10) + + def get_angle(self) -> float: + """ + Returns the current angle of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - angle: Buffer for the current angle given in 1/10th milli degrees + - revolution: Reserved for future use + """ + angle = bindings.GetAngle_S(self.device_index, self.channel_index) + return float(angle / 10) + + + def move_home(self): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) + + + + def amp(self): + """ + Presets the target channel's amplitude + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - amplitude: Amplitude in 1/10th Volts that should be preset + """ + amplitude = self._amplitude + bindings.SetAmplitude_S(self.device_index, self.channel_index, amplitude) + + + def steps_move(self): + """ + Performs a burst of steps with the given parameters + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude in 1/10th Volts that the steps are performed + with + - frequency: Frequency in Hz that the steps are performed with + """ + amplitude = int(self.amplitude) + bindings.MoveStep_S(self.device_index, self.channel_index, self._steps, amplitude, self._frequency) + + + def stop(self): + """Stop any ongoing movement of the positionner. This command also + stops the hold position feature of closed-loop commands. + + Parameters + ---------- + self.channel_index: unsigned int + """ + + bindings.Stop_S(self.device_index, self.channel_index) + +class SCULinear(SCUWrapper): + + units ="µm" + + + def move_rel(self, relative_move_value): + """Execute a relative move in microns. + If a mechanical end stop is detected while the command is in + execution, the movement will be aborted (without notice). + + Parameters + ---------- + self.channel_index: unsigned int + relative_move_value: signed int. Relative distance in picometer. + """ + + diff = 10 + bindings.MovePositionRelative_S(self.device_index, self.channel_index,diff, self.hold_time) + + + def move_abs(self, absolute_move_micron): + """Go to an absolute position in microns. + If a mechanical end stop is detected while the command is in + execution, the movement will be aborted (without notice). + + Parameters + ---------- + self.channel_index: unsigned int + absolute_move_micron: float + Absolute position in microns + """ + position = int(absolute_move_micron * 10) + bindings.MovePositionAbsolute_S(self.device_index, self.channel_index, position, self.hold_time) + +class SCURotation(SCUWrapper): + + units = "milli deg" + + def move_abs_rot(self,absolute_move_degrees): + """ + Instructs a positioner to move to a specific angle using closed-loop + control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angle: Absolute angle to move to in 1/10th milli degrees + - revolution: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + angle = int(absolute_move_degrees * 10) + revolution = 0 + bindings.MoveAngleAbsolute_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) + + def move_rel_rot(self, rel_move_degrees): + """ + Instructs a positioner to move to an angle relative to its current + angle using closed-loop control + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - angleDiff: Relative angle difference to move in 1/10th milli degrees + + - revolutionDiff: Reserved for future use + - holdTime: Time (in milliseconds) the angle is actively held after + reaching the target + """ + angle = int(rel_move_degrees * 10) + revolution=0 + bindings.MoveAngleRelative_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) + + + + + +if __name__ == '__main__': + + + ids = get_devices() + + wrapper = SCULinear() + + connect_to = 722998302 + device_index = ids.index(connect_to) + + wrapper.open(device_index) + try: + #channel = wrapper.get_number_of_channels() + + wrapper.move_home() + + time.sleep(2) + + #wrapper.absolute_move(1500) + + print(wrapper.get_position()) + + + except Exception as e: + print(e) + finally: + wrapper.close() + + + diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py index 322e5a8..754a8c5 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py @@ -282,4 +282,3 @@ def GetPosition_S(deviceIndex, channelIndex): if local_1 != ErrorCode.OK.value: raise Error("GetPosition_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) return local_0[0] - From ff8e6b931ae4ccc3a2a5bcf82dc3658363b306ae Mon Sep 17 00:00:00 2001 From: adele080402 Date: Sun, 30 Mar 2025 12:31:21 +0200 Subject: [PATCH 04/14] =?UTF-8?q?misa=20=C3=A0=20jour=20du=20code=20et=20c?= =?UTF-8?q?orrection=20d'erreurs=20sur=20le=20wrapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hardware/smaract/scu/scu_wrapper.py | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index fa3f6b5..b591e4e 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -18,8 +18,9 @@ def get_devices(): list(int) list(SCUWrapper or SCULinear or SCURotation) """ + ids = bindings.GetAvailableDevices() - ##ids = [ids] + #ids = [ids] bindings.InitDevices(configuration=bindings.SYNCHRONOUS_COMMUNICATION) ptype = [] @@ -30,24 +31,25 @@ def get_devices(): while True: try: - bindings.GetStatus_S(ids, ind_channel) + bindings.GetStatus_S(ids[ind[0]], ind_channel) except bindings.Error as e: # will fire an error if the ind_channel is invalid break try: - sensor = bool(bindings.GetSensorPresent_S(ind, ind_channel)) + sensor = bool(bindings.GetSensorPresent_S(ids[ind[0]], ind_channel)) except bindings.Error as e: sensor = False if sensor: try: - bindings.GetAngle_S(ind,ind_channel) + bindings.GetAngle_S(ids[ind[0]],ind_channel) rotation = True except bindings.Error: rotation = False - ind_channel += 1 + #ind_channel += 1 for ind_channel in range(ind_channel): - ptype.append(SCUWrapper if not sensor else SCURotation if rotation else SCULinear) + ptype.append(SCUWrapper if sensor else SCURotation if rotation else SCULinear) + ind_channel += 1 bindings.ReleaseDevices() @@ -309,18 +311,18 @@ def move_rel_rot(self, rel_move_degrees): wrapper = SCULinear() - connect_to = 722998302 - device_index = ids.index(connect_to) + + device_index = ids.index(ids[0]) wrapper.open(device_index) try: #channel = wrapper.get_number_of_channels() - wrapper.move_home() + #wrapper.move_home() - time.sleep(2) + #time.sleep(2) - #wrapper.absolute_move(1500) + wrapper.move_abs(0) print(wrapper.get_position()) From 4a318f7fb0ff3d478954278fe7a66d4e40eb7e7a Mon Sep 17 00:00:00 2001 From: adele080402 Date: Mon, 31 Mar 2025 19:29:54 +0200 Subject: [PATCH 05/14] =?UTF-8?q?Mise=20=C3=A0=20jour=20finale=20du=20wrap?= =?UTF-8?q?per?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daq_move_SmarActSCUINSA.py | 13 +- .../hardware/smaract/scu/scu_wrapper.py | 196 +++++++++++------- 2 files changed, 130 insertions(+), 79 deletions(-) diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index fe0cad0..7cc35e1 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -8,10 +8,11 @@ from pymodaq.utils.daq_utils import ThreadCommand from easydict import EasyDict as edict -from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import SCUWrapper, SCULinear, SCURotation +from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, + SCULinear, SCURotation) -psets = get_devices(module='motion._smaract') -psets_str = [f"Dev. Id{pset['id']} channel {pset['index']}" for pset in psets] +psets: list[SCUType] = get_devices() +psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel}" for pset in psets] class DAQ_Move_SmarActSCU(DAQ_Move_base): @@ -19,7 +20,7 @@ class DAQ_Move_SmarActSCU(DAQ_Move_base): """ _controller_units = "" - _epsilon = 0.002 + _epsilon = 2 # find controller locators is_multiaxes = False @@ -34,7 +35,7 @@ class DAQ_Move_SmarActSCU(DAQ_Move_base): ########################################################## def ini_attributes(self): - self.controller: Union[SCUWrapper, SCULinear] = None + self.controller: Union[SCUWrapper, SCULinear, SCURotation] = None self.settings.child("epsilon").setValue(0.002) def commit_settings(self, param): @@ -53,7 +54,7 @@ def ini_stage(self, controller=None): """ index = self.settings.child('device').opts['limits'].index(self.settings['device']) if self.is_master: - self.controller = ... + self.controller = psets[index].scu_type() else: self.controller = controller diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index b591e4e..abf417e 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -1,6 +1,6 @@ import time from typing import Optional, List - +from dataclasses import dataclass from pathlib import Path import os @@ -8,10 +8,19 @@ from pymodaq_plugins_smaract.hardware.smaract.scu import bindings +class SCUType: + def __init__(self, id: int, scu_type, channel: int): + self.device_id = id + self.scu_type = scu_type + self.channel = channel + + def __repr__(self): + return f'SN: {self.device_id}, type:{self.scu_type}, channel: {self.channel}' + def get_devices(): """ - Get devices ids and informations about them + Get devices ids and information about them Returns ------- @@ -23,37 +32,37 @@ def get_devices(): #ids = [ids] bindings.InitDevices(configuration=bindings.SYNCHRONOUS_COMMUNICATION) ptype = [] + n_channel = 1 # SCU devices have only one channel - for ind in enumerate(ids): + for ind_device, dev_sn in enumerate(ids): rotation = False - ind_channel = 0 - sensor = False + for ind_channel in range(n_channel): + sensor = False - while True: try: - bindings.GetStatus_S(ids[ind[0]], ind_channel) + bindings.GetStatus_S(ind_device, ind_channel) except bindings.Error as e: # will fire an error if the ind_channel is invalid break try: - sensor = bool(bindings.GetSensorPresent_S(ids[ind[0]], ind_channel)) + sensor = bool(bindings.GetSensorPresent_S(ind_device, ind_channel)) except bindings.Error as e: sensor = False if sensor: try: - bindings.GetAngle_S(ids[ind[0]],ind_channel) + bindings.GetAngle_S(ind_device,ind_channel) rotation = True except bindings.Error: rotation = False - #ind_channel += 1 + #ind_channel += 1 - for ind_channel in range(ind_channel): - ptype.append(SCUWrapper if sensor else SCURotation if rotation else SCULinear) - ind_channel += 1 + ptype.append(SCUType(dev_sn, + SCUWrapper if not sensor else SCURotation if rotation else SCULinear, + ind_channel)) bindings.ReleaseDevices() - return ids, ptype + return ptype @@ -75,7 +84,7 @@ def __init__(self): self.hold_time = 10 self._amplitude = 400 #between 150 and 1000 self._frequency = 15000 #between 1 and 18500 - self._steps = 20000 #between -30000 and 30000 + self._steps = 0 #between -30000 and 30000 @@ -116,8 +125,6 @@ def steps(self): def steps(self, number: int): if isinstance(number, int) and 30000 > number > -30000: self._steps = number - else: - self._steps=0 def init_device (self, configuration=bindings.SYNCHRONOUS_COMMUNICATION) : @@ -137,38 +144,6 @@ def open(self, device_index: int, configuration=bindings.SYNCHRONOUS_COMMUNICATI def close(self): bindings.ReleaseDevices() - def get_position(self) -> float: - """ - Returns the current position of a positioner - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - Return value(s): - - position: Buffer for the current position given in 1/10th micro - meters - """ - - position = bindings.GetPosition_S(self.device_index, self.channel_index) - - return float(position / 10) - - def get_angle(self) -> float: - """ - Returns the current angle of a positioner - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - Return value(s): - - angle: Buffer for the current angle given in 1/10th milli degrees - - revolution: Reserved for future use - """ - angle = bindings.GetAngle_S(self.device_index, self.channel_index) - return float(angle / 10) - def move_home(self): """ @@ -183,8 +158,7 @@ def move_home(self): - autoZero: Selects whether the current position is set to zero upon reaching the reference position """ - bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) - + print("not implemented") def amp(self): @@ -200,7 +174,7 @@ def amp(self): bindings.SetAmplitude_S(self.device_index, self.channel_index, amplitude) - def steps_move(self): + def steps_move(self, n_steps : int): """ Performs a burst of steps with the given parameters @@ -212,8 +186,23 @@ def steps_move(self): with - frequency: Frequency in Hz that the steps are performed with """ - amplitude = int(self.amplitude) - bindings.MoveStep_S(self.device_index, self.channel_index, self._steps, amplitude, self._frequency) + self.steps += n_steps + bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude, self.frequency) + + + def get_position(self) -> float: + """ + Returns the current position of a positioner + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - position: Buffer for the current position given in steps + meters + """ + return self._steps def stop(self): @@ -231,6 +220,20 @@ class SCULinear(SCUWrapper): units ="µm" + def move_abs(self, absolute_move_micron): + """Go to an absolute position in microns. + If a mechanical end stop is detected while the command is in + execution, the movement will be aborted (without notice). + + Parameters + ---------- + self.channel_index: unsigned int + absolute_move_micron: float + Absolute position in microns + """ + position = int(absolute_move_micron * 10) + bindings.MovePositionAbsolute_S(self.device_index, self.channel_index, position, self.hold_time) + def move_rel(self, relative_move_value): """Execute a relative move in microns. @@ -240,32 +243,49 @@ def move_rel(self, relative_move_value): Parameters ---------- self.channel_index: unsigned int - relative_move_value: signed int. Relative distance in picometer. + relative_move_value: signed int. Relative distance in 1/10th micrometers """ diff = 10 bindings.MovePositionRelative_S(self.device_index, self.channel_index,diff, self.hold_time) - def move_abs(self, absolute_move_micron): - """Go to an absolute position in microns. - If a mechanical end stop is detected while the command is in - execution, the movement will be aborted (without notice). + def get_position(self) -> float: + """ + Returns the current position of a positioner - Parameters - ---------- - self.channel_index: unsigned int - absolute_move_micron: float - Absolute position in microns + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + + Return value(s): + - position: Buffer for the current position given in 1/10th micrometers """ - position = int(absolute_move_micron * 10) - bindings.MovePositionAbsolute_S(self.device_index, self.channel_index, position, self.hold_time) + position = bindings.GetPosition_S(self.device_index, self.channel_index) + + return float(position / 10) + + def move_home(self): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) -class SCURotation(SCUWrapper): - units = "milli deg" +class SCURotation(SCULinear): - def move_abs_rot(self,absolute_move_degrees): + units = "millidegree" + + def move_abs(self,absolute_move_degrees): """ Instructs a positioner to move to a specific angle using closed-loop control @@ -282,7 +302,7 @@ def move_abs_rot(self,absolute_move_degrees): revolution = 0 bindings.MoveAngleAbsolute_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) - def move_rel_rot(self, rel_move_degrees): + def move_rel(self, rel_move_degrees): """ Instructs a positioner to move to an angle relative to its current angle using closed-loop control @@ -300,8 +320,35 @@ def move_rel_rot(self, rel_move_degrees): revolution=0 bindings.MoveAngleRelative_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) + def get_position(self) -> float: + """ + Returns the current angle of a positioner + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + Return value(s): + - angle: Buffer for the current angle given in 1/10th milli degrees + - revolution: Reserved for future use + """ + angle = bindings.GetAngle_S(self.device_index, self.channel_index) + return float(angle / 10) + + def move_home(self): + """ + Starts the referencing procedure and moves the positioner to a known + physical position + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - holdTime: Time (in milliseconds) the position/angle is actively held + after reaching the target + - autoZero: Selects whether the current position is set to zero upon + reaching the reference position + """ + bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) if __name__ == '__main__': @@ -318,12 +365,15 @@ def move_rel_rot(self, rel_move_degrees): try: #channel = wrapper.get_number_of_channels() - #wrapper.move_home() + wrapper.move_home() + + time.sleep(2) - #time.sleep(2) + #wrapper.move_abs(0) - wrapper.move_abs(0) + #print(wrapper.get_position()) + #wrapper.steps_move(15000) print(wrapper.get_position()) From c90331ae06fa2ea68ac595d96fe599522fdc64b1 Mon Sep 17 00:00:00 2001 From: adele080402 Date: Thu, 3 Apr 2025 16:10:30 +0200 Subject: [PATCH 06/14] Modification --- .../daq_move_SmarActSCUINSA.py | 236 +++++++++++------- 1 file changed, 146 insertions(+), 90 deletions(-) diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index 7cc35e1..bac8efa 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -1,138 +1,194 @@ -"""At the first run, if the program complains about a _build_scu programm not being present, just run the -_build_smaract.py, that will look at the C header file to produce connexion between the dll and the python files""" - - from typing import Union, List, Dict +from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun, + main, DataActuatorType, DataActuator) -from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun -from pymodaq.utils.daq_utils import ThreadCommand -from easydict import EasyDict as edict +from pymodaq_utils.utils import ThreadCommand # object used to send info back to the main thread +from pymodaq_gui.parameter import Parameter from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, SCULinear, SCURotation) -psets: list[SCUType] = get_devices() -psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel}" for pset in psets] +class SCUWrapper: -class DAQ_Move_SmarActSCU(DAQ_Move_base): - """ + pass - """ - _controller_units = "" - _epsilon = 2 - # find controller locators +class DAQ_Move_SmarActSCUINSA(DAQ_Move_base): + """ Instrument plugin class for an actuator. + + This object inherits all functionalities to communicate with PyMoDAQ’s DAQ_Move module through inheritance via + DAQ_Move_base. It makes a bridge between the DAQ_Move module and the Python wrapper of a particular instrument. + TODO Complete the docstring of your plugin with: + * The set of controllers and actuators that should be compatible with this instrument plugin. + * With which instrument and controller it has been tested. + * The version of PyMoDAQ during the test. + * The version of the operating system. + * Installation instructions: what manufacturer’s drivers should be installed to make it run? + + Attributes: + ----------- + controller: object + The particular object that allow the communication with the hardware, in general a python wrapper around the + hardware library. + + # TODO add your particular attributes here if any + + """ is_multiaxes = False - stage_names = [] + _axis_names: Union[List[str], Dict[str, int]] = ['Axis1', 'Axis2'] # TODO for your plugin: complete the list + _controller_units: Union[str, List[str]] = ['µm','millidegree'] + _epsilon: float = 2 + data_actuator_type = DataActuatorType.DataActuator # wether you use the new data style for actuator otherwise set this + # as DataActuatorType.float (or entirely remove the line) params = [ - {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, - {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 15000, 'limits':SCUWrapper.frequency_limits}, - {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100, 'limits':SCUWrapper.amplitude_limits}, + {'title': 'Device', 'name': 'device', 'type': 'list', 'limits': psets_str}, + {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 15000}, + {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100}, {'title': 'Max Frequency (Hz)', 'name': 'maxfreq', 'type': 'int', 'value': 18500}, - ] + comon_parameters_fun(is_multiaxes, epsilon=_epsilon) + ] + comon_parameters_fun(is_multiaxes, epsilon=_epsilon) + ########################################################## def ini_attributes(self): - self.controller: Union[SCUWrapper, SCULinear, SCURotation] = None - self.settings.child("epsilon").setValue(0.002) + # TODO declare the type of the wrapper (and assign it to self.controller) you're going to use for easy + # autocompletion + self.controller: Union[SCUWrapper, SCULinear = None - def commit_settings(self, param): - if param.name() == 'amplitude': - self.controller.amplitude = self.controller.amp() - elif param.name() == 'frequency': - self.controller.frequency = param.value() + # TODO declare here attributes you want/need to init with a default value + pass - elif param.name() == 'maxfreq': - self.controller.max_frequency = param.value() - self.settings.child('maxfreq').setValue(self.controller.max_frequency) - - def ini_stage(self, controller=None): - """Initialize the controller and stages (axes) with given parameters. + def get_actuator_value(self): + """Get the current value from the hardware with scaling conversion. + Returns + ------- + float: The position obtained after scaling conversion. """ - index = self.settings.child('device').opts['limits'].index(self.settings['device']) - if self.is_master: - self.controller = psets[index].scu_type() - else: - self.controller = controller - - self.settings.child('units').setValue(self.controller.units) - self.settings.child('amplitude').setOpts(limits=list(self.controller.amplitude_limits)) - self.settings.child('frequency').setOpts(limits=list(self.controller.frequency_limits)) - self.settings.child('amplitude').setValue(self.controller.amplitude) - self.settings.child('frequency').setValue(self.controller.frequency) - if not isinstance(self.controller, SCUWrapper): - self.settings.child('maxfreq').setValue(self.controller.max_frequency) + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + pos = DataActuator( + data=self.controller.your_method_to_get_the_actuator_value()) # when writing your own plugin replace this line + pos = self.get_position_with_scaling(pos) + return pos + + def user_condition_to_reach_target(self) -> bool: + """ Implement a condition for exiting the polling mechanism and specifying that the + target value has been reached + + Returns + ------- + bool: if True, PyMoDAQ considers the target value has been reached + """ + # TODO either delete this method if the usual polling is fine with you, but if need you can + # add here some other condition to be fullfilled either a completely new one or + # using or/and operations between the epsilon_bool and some other custom booleans + # for a usage example see DAQ_Move_brushlessMotor from the Thorlabs plugin + return True - info = '' - initialized = True + def close(self): + """Terminate the communication protocol""" + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + # self.controller.your_method_to_terminate_the_communication() # when writing your own plugin replace this line - return info, initialized + def commit_settings(self, param: Parameter): + """Apply the consequences of a change of value in the detector settings - def close(self): - """Close the communication with the SmarAct controller. + Parameters + ---------- + param: Parameter + A given parameter (within detector_settings) whose value has been changed by the user """ - self.controller.close() - self.controller = None + ## TODO for your custom plugin + if param.name() == 'axis': + self.axis_unit = self.controller.your_method_to_get_correct_axis_unit() + # do this only if you can and if the units are not known beforehand, for instance + # if the motors connected to the controller are of different type (mm, µm, nm, , etc...) + # see BrushlessDCMotor from the thorlabs plugin for an exemple + + elif param.name() == "a_parameter_you've_added_in_self.params": + self.controller.your_method_to_apply_this_param_change() + else: + pass - def get_actuator_value(self): - """Get the current position from the hardware with scaling conversion. + def ini_stage(self, controller=None): + """Actuator communication initialization + + Parameters + ---------- + controller: (object) + custom object of a PyMoDAQ plugin (Slave case). None if only one actuator by controller (Master case) Returns ------- - float: The position obtained after scaling conversion. + info: str + initialized: bool + False if initialization failed otherwise True """ - position = self.controller.get_position() - # convert position if scaling options have been used, mandatory here - position = self.get_position_with_scaling(position) - #position = self.target_position - self.current_position = position - return position + raise NotImplemented # TODO when writing your own plugin remove this line and modify the ones below + self.ini_stage_init(slave_controller=controller) # will be useful when controller is slave + + if self.is_master: # is needed when controller is master + self.controller = PythonWrapperOfYourInstrument(arg1, arg2, ...) # arguments for instantiation!) + # todo: enter here whatever is needed for your controller initialization and eventual + # opening of the communication channel + + info = "Whatever info you want to log" + initialized = self.controller.a_method_or_atttribute_to_check_if_init() # todo + return info, initialized - def move_abs(self, position): - """Move to an absolute position + def move_abs(self, value: DataActuator): + """ Move the actuator to the absolute target defined by value Parameters ---------- - position: float + value: (float) value of the absolute target positioning """ - # limit position if bounds options has been selected and if position is - # out of them - position = self.check_bound(position) - self.target_position = position - # convert the user set position to the controller position if scaling - # has been activated by user - position = self.set_position_with_scaling(position) - self.controller.move_abs(self, position) + value = self.check_bound(value) # if user checked bounds, the defined bounds are applied here + self.target_value = value + value = self.set_position_with_scaling(value) # apply scaling if the user specified one + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + self.controller.your_method_to_set_an_absolute_value( + value.value()) # when writing your own plugin replace this line + self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) - def move_rel(self, position): - """Move to a relative position + def move_rel(self, value: DataActuator): + """ Move the actuator to the relative target actuator value defined by value Parameters ---------- - position: float + value: (float) value of the relative target positioning """ - 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) + value = self.check_bound(self.current_position + value) - self.current_position + self.target_value = value + self.current_position + value = self.set_position_relative_with_scaling(value) - self.controller.move_rel(self, position) + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + self.controller.your_method_to_set_a_relative_value( + value.value()) # when writing your own plugin replace this line + self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) def move_home(self): - """Move to home and reset position to zero. - """ - self.controller.move_home() - self.get_actuator_value() + """Call the reference method of the controller""" + + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + self.controller.your_method_to_get_to_a_known_reference() # when writing your own plugin replace this line + self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) def stop_motion(self): - """ - """ - self.controller.stop() - self.move_done() + """Stop the actuator and emits move_done signal""" + + ## TODO for your custom plugin + raise NotImplemented # when writing your own plugin remove this line + self.controller.your_method_to_stop_positioning() # when writing your own plugin replace this line + self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) -if __name__ == "__main__": - main(__file__, init=False) +if __name__ == '__main__': + main(__file__) From f6f682ecc3e826c1bcbda324ccdae1387cb97b8a Mon Sep 17 00:00:00 2001 From: adele080402 Date: Thu, 3 Apr 2025 16:16:19 +0200 Subject: [PATCH 07/14] scu --- .../hardware/smaract/scu/scu_wrapper.py | 50 +++++-------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index abf417e..96f6dc0 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -71,10 +71,10 @@ class SCUWrapper: dev_type = 'stepper' units = 'steps' - amplitude_limits = (150, 1001) - frequency_limits = (1, 18501) - steps_limits = (-30000, 30001) - angle_limits = (-3599999, 3599999) + #amplitude_limits = (150, 1001) + #frequency_limits = (1, 18501) + #steps_limits = (-30000, 30001) + #angle_limits = (-3599999, 3599999) def __init__(self): @@ -161,19 +161,6 @@ def move_home(self): print("not implemented") - def amp(self): - """ - Presets the target channel's amplitude - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - amplitude: Amplitude in 1/10th Volts that should be preset - """ - amplitude = self._amplitude - bindings.SetAmplitude_S(self.device_index, self.channel_index, amplitude) - - def steps_move(self, n_steps : int): """ Performs a burst of steps with the given parameters @@ -216,6 +203,8 @@ def stop(self): bindings.Stop_S(self.device_index, self.channel_index) + + class SCULinear(SCUWrapper): units ="µm" @@ -246,8 +235,8 @@ def move_rel(self, relative_move_value): relative_move_value: signed int. Relative distance in 1/10th micrometers """ - diff = 10 - bindings.MovePositionRelative_S(self.device_index, self.channel_index,diff, self.hold_time) + diff = int(relative_move_value*10) + bindings.MovePositionRelative_S(self.device_index, self.channel_index, diff, self.hold_time) def get_position(self) -> float: @@ -283,7 +272,7 @@ def move_home(self): class SCURotation(SCULinear): - units = "millidegree" + units = "degree" def move_abs(self,absolute_move_degrees): """ @@ -298,7 +287,7 @@ def move_abs(self,absolute_move_degrees): - holdTime: Time (in milliseconds) the angle is actively held after reaching the target """ - angle = int(absolute_move_degrees * 10) + angle = int(absolute_move_degrees * 10000) revolution = 0 bindings.MoveAngleAbsolute_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) @@ -316,7 +305,7 @@ def move_rel(self, rel_move_degrees): - holdTime: Time (in milliseconds) the angle is actively held after reaching the target """ - angle = int(rel_move_degrees * 10) + angle = int(rel_move_degrees * 10000) revolution=0 bindings.MoveAngleRelative_S(self.device_index, self.channel_index, angle, revolution, self.hold_time) @@ -333,22 +322,7 @@ def get_position(self) -> float: - revolution: Reserved for future use """ angle = bindings.GetAngle_S(self.device_index, self.channel_index) - return float(angle / 10) - - def move_home(self): - """ - Starts the referencing procedure and moves the positioner to a known - physical position - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - holdTime: Time (in milliseconds) the position/angle is actively held - after reaching the target - - autoZero: Selects whether the current position is set to zero upon - reaching the reference position - """ - bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) + return float(angle / 10000) if __name__ == '__main__': From 5446ac59bdcfeed4eedc619fb9168e3a84597fb2 Mon Sep 17 00:00:00 2001 From: adele080402 Date: Mon, 7 Apr 2025 11:26:07 +0200 Subject: [PATCH 08/14] =?UTF-8?q?derni=C3=A8re=20mise=20=C3=A0=20jour=20de?= =?UTF-8?q?s=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daq_move_SmarActSCUINSA.py | 230 +++++++----------- .../hardware/smaract/scu/scu_wrapper.py | 36 ++- 2 files changed, 109 insertions(+), 157 deletions(-) diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index bac8efa..2603605 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -1,194 +1,130 @@ +"""At the first run, if the program complains about a _build_scu programm not being present, just run the +_build_smaract.py, that will look at the C header file to produce connexion between the dll and the python files""" + + from typing import Union, List, Dict -from pymodaq.control_modules.move_utility_classes import (DAQ_Move_base, comon_parameters_fun, - main, DataActuatorType, DataActuator) -from pymodaq_utils.utils import ThreadCommand # object used to send info back to the main thread -from pymodaq_gui.parameter import Parameter +from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun +from pymodaq.utils.daq_utils import ThreadCommand +from easydict import EasyDict as edict from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, SCULinear, SCURotation) +psets: list[SCUType] = get_devices() +psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel}" for pset in psets] -class SCUWrapper: - - pass class DAQ_Move_SmarActSCUINSA(DAQ_Move_base): - """ Instrument plugin class for an actuator. - - This object inherits all functionalities to communicate with PyMoDAQ’s DAQ_Move module through inheritance via - DAQ_Move_base. It makes a bridge between the DAQ_Move module and the Python wrapper of a particular instrument. - - TODO Complete the docstring of your plugin with: - * The set of controllers and actuators that should be compatible with this instrument plugin. - * With which instrument and controller it has been tested. - * The version of PyMoDAQ during the test. - * The version of the operating system. - * Installation instructions: what manufacturer’s drivers should be installed to make it run? - - Attributes: - ----------- - controller: object - The particular object that allow the communication with the hardware, in general a python wrapper around the - hardware library. - - # TODO add your particular attributes here if any + """ """ - is_multiaxes = False - _axis_names: Union[List[str], Dict[str, int]] = ['Axis1', 'Axis2'] # TODO for your plugin: complete the list - _controller_units: Union[str, List[str]] = ['µm','millidegree'] - _epsilon: float = 2 - data_actuator_type = DataActuatorType.DataActuator # wether you use the new data style for actuator otherwise set this - # as DataActuatorType.float (or entirely remove the line) + _controller_units = "" + _epsilon = 2 + # find controller locators - params = [ - {'title': 'Device', 'name': 'device', 'type': 'list', 'limits': psets_str}, - {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 15000}, - {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100}, - {'title': 'Max Frequency (Hz)', 'name': 'maxfreq', 'type': 'int', 'value': 18500}, - ] + comon_parameters_fun(is_multiaxes, epsilon=_epsilon) + is_multiaxes = True + _axis_names = ['1'] + params = [ + {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, + {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 1000, 'limits': SCUWrapper.frequency_limits}, + {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100, 'limits':SCUWrapper.amplitude_limits}, + ] + comon_parameters_fun(is_multiaxes=is_multiaxes, axis_names=_axis_names, epsilon=_epsilon) ########################################################## def ini_attributes(self): - # TODO declare the type of the wrapper (and assign it to self.controller) you're going to use for easy - # autocompletion - self.controller: Union[SCUWrapper, SCULinear = None + self.controller: Union[SCUWrapper, SCULinear, SCURotation] = None + self.settings.child("epsilon").setValue(2) - # TODO declare here attributes you want/need to init with a default value - pass + def commit_settings(self, param): + if param.name() == 'amplitude': + self.controller.amplitude = param.value() + elif param.name() == 'frequency': + self.controller.frequency = param.value() - def get_actuator_value(self): - """Get the current value from the hardware with scaling conversion. + def ini_stage(self, controller=None): + """Initialize the controller and stages (axes) with given parameters. - Returns - ------- - float: The position obtained after scaling conversion. """ - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - pos = DataActuator( - data=self.controller.your_method_to_get_the_actuator_value()) # when writing your own plugin replace this line - pos = self.get_position_with_scaling(pos) - return pos - - def user_condition_to_reach_target(self) -> bool: - """ Implement a condition for exiting the polling mechanism and specifying that the - target value has been reached - - Returns - ------- - bool: if True, PyMoDAQ considers the target value has been reached - """ - # TODO either delete this method if the usual polling is fine with you, but if need you can - # add here some other condition to be fullfilled either a completely new one or - # using or/and operations between the epsilon_bool and some other custom booleans - # for a usage example see DAQ_Move_brushlessMotor from the Thorlabs plugin - return True + index = self.settings.child('device').opts['limits'].index(self.settings['device']) + if self.is_master: + self.controller = psets[index].scu_type() + self.controller.open(index) + self.controller.amplitude = self.settings['amplitude'] + self.controller.frequency = self.settings['frequency'] - def close(self): - """Terminate the communication protocol""" - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - # self.controller.your_method_to_terminate_the_communication() # when writing your own plugin replace this line + else: + self.controller = controller - def commit_settings(self, param: Parameter): - """Apply the consequences of a change of value in the detector settings + self.axis_unit = self.controller.units - Parameters - ---------- - param: Parameter - A given parameter (within detector_settings) whose value has been changed by the user - """ - ## TODO for your custom plugin - if param.name() == 'axis': - self.axis_unit = self.controller.your_method_to_get_correct_axis_unit() - # do this only if you can and if the units are not known beforehand, for instance - # if the motors connected to the controller are of different type (mm, µm, nm, , etc...) - # see BrushlessDCMotor from the thorlabs plugin for an exemple - - elif param.name() == "a_parameter_you've_added_in_self.params": - self.controller.your_method_to_apply_this_param_change() - else: - pass + info = '' + initialized = True - def ini_stage(self, controller=None): - """Actuator communication initialization + return info, initialized - Parameters - ---------- - controller: (object) - custom object of a PyMoDAQ plugin (Slave case). None if only one actuator by controller (Master case) + def close(self): + """Close the communication with the SmarAct controller. + """ + self.controller.close() + + def get_actuator_value(self): + """Get the current position from the hardware with scaling conversion. Returns ------- - info: str - initialized: bool - False if initialization failed otherwise True + float: The position obtained after scaling conversion. """ - raise NotImplemented # TODO when writing your own plugin remove this line and modify the ones below - self.ini_stage_init(slave_controller=controller) # will be useful when controller is slave - - if self.is_master: # is needed when controller is master - self.controller = PythonWrapperOfYourInstrument(arg1, arg2, ...) # arguments for instantiation!) - # todo: enter here whatever is needed for your controller initialization and eventual - # opening of the communication channel - - info = "Whatever info you want to log" - initialized = self.controller.a_method_or_atttribute_to_check_if_init() # todo - return info, initialized + position = self.controller.get_position() + # convert position if scaling options have been used, mandatory here + position = self.get_position_with_scaling(position) + #position = self.target_position + self.current_position = position + return position - def move_abs(self, value: DataActuator): - """ Move the actuator to the absolute target defined by value + def move_abs(self, position): + """Move to an absolute position Parameters ---------- - value: (float) value of the absolute target positioning + position: float """ + # limit position if bounds options has been selected and if position is + # out of them + position = self.check_bound(position) + self.target_position = position + # convert the user set position to the controller position if scaling + # has been activated by user + position = self.set_position_with_scaling(position) - value = self.check_bound(value) # if user checked bounds, the defined bounds are applied here - self.target_value = value - value = self.set_position_with_scaling(value) # apply scaling if the user specified one - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - self.controller.your_method_to_set_an_absolute_value( - value.value()) # when writing your own plugin replace this line - self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) + self.controller.move_abs(position) - def move_rel(self, value: DataActuator): - """ Move the actuator to the relative target actuator value defined by value + def move_rel(self, position): + """Move to a relative position Parameters ---------- - value: (float) value of the relative target positioning + position: float """ - value = self.check_bound(self.current_position + value) - self.current_position - self.target_value = value + self.current_position - value = self.set_position_relative_with_scaling(value) + 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) - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - self.controller.your_method_to_set_a_relative_value( - value.value()) # when writing your own plugin replace this line - self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) + self.controller.move_rel(position) def move_home(self): - """Call the reference method of the controller""" - - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - self.controller.your_method_to_get_to_a_known_reference() # when writing your own plugin replace this line - self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) + """Move to home and reset position to zero. + """ + self.controller.move_home() + self.get_actuator_value() def stop_motion(self): - """Stop the actuator and emits move_done signal""" - - ## TODO for your custom plugin - raise NotImplemented # when writing your own plugin remove this line - self.controller.your_method_to_stop_positioning() # when writing your own plugin replace this line - self.emit_status(ThreadCommand('Update_Status', ['Some info you want to log'])) + """ + """ + self.controller.stop() + self.move_done() -if __name__ == '__main__': - main(__file__) +if __name__ == "__main__": + main(__file__, init=False) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index 96f6dc0..cfa0a0e 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -69,12 +69,12 @@ def get_devices(): class SCUWrapper: dev_type = 'stepper' - units = 'steps' + units = '' - #amplitude_limits = (150, 1001) - #frequency_limits = (1, 18501) - #steps_limits = (-30000, 30001) - #angle_limits = (-3599999, 3599999) + amplitude_limits = (15, 100) + frequency_limits = (1, 18500) + steps_limits = (-30000, 30000) + angle_limits = (-3599999, 3599999) def __init__(self): @@ -82,7 +82,7 @@ def __init__(self): self.device_index: Optional[int] = None self.channel_index = 0 self.hold_time = 10 - self._amplitude = 400 #between 150 and 1000 + self._amplitude = 40 #between 150 and 1000 self._frequency = 15000 #between 1 and 18500 self._steps = 0 #between -30000 and 30000 @@ -98,8 +98,8 @@ def amplitude (self): @amplitude.setter def amplitude(self, number : int): if isinstance(number, int) and 100 > number > 15 : - self._amplitude = number * 10 - bindings.SetAmplitude_S(self.device_index, self.channel_index, self._amplitude) + self._amplitude = number + bindings.SetAmplitude_S(self.device_index, self.channel_index, self._amplitude*10) @property @@ -161,7 +161,7 @@ def move_home(self): print("not implemented") - def steps_move(self, n_steps : int): + def move_rel(self, n_steps : int): """ Performs a burst of steps with the given parameters @@ -174,7 +174,23 @@ def steps_move(self, n_steps : int): - frequency: Frequency in Hz that the steps are performed with """ self.steps += n_steps - bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude, self.frequency) + bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude*10, self.frequency) + + def move_abs(self, n_steps): + """ + Performs a burst of steps with the given parameters + + Parameters: + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude in 1/10th Volts that the steps are performed + with + - frequency: Frequency in Hz that the steps are performed with + """ + + self.steps = self.steps - n_steps + bindings.MoveStep_S(self.device_index, self.channel_index, int(self.steps), self.amplitude*10, self.frequency) def get_position(self) -> float: From 8759c32771ab8bbd76e82f2139da2c089d6a34c4 Mon Sep 17 00:00:00 2001 From: adele080402 Date: Tue, 6 May 2025 11:53:45 +0200 Subject: [PATCH 09/14] =?UTF-8?q?derni=C3=A8re=20mise=20=C3=A0=20jour=20de?= =?UTF-8?q?s=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daq_move_SmarActSCUINSA.py | 24 ++-- .../hardware/smaract/scu/scu_wrapper.py | 104 +++++++++++------- 2 files changed, 77 insertions(+), 51 deletions(-) diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index 2603605..5491b4d 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -65,12 +65,14 @@ def ini_stage(self, controller=None): return info, initialized def close(self): - """Close the communication with the SmarAct controller. + """ + Close the communication with the SmarAct controller. """ self.controller.close() def get_actuator_value(self): - """Get the current position from the hardware with scaling conversion. + """ + Get the current position from the hardware with scaling conversion. Returns ------- @@ -84,11 +86,12 @@ def get_actuator_value(self): return position def move_abs(self, position): - """Move to an absolute position + """ + Move to an absolute position - Parameters + Parameters: ---------- - position: float + - position: float """ # limit position if bounds options has been selected and if position is # out of them @@ -101,11 +104,12 @@ def move_abs(self, position): self.controller.move_abs(position) def move_rel(self, position): - """Move to a relative position + """ + Move to a relative position - Parameters + Parameters: ---------- - position: float + - position: float """ position = (self.check_bound(self.current_position + position) - self.current_position) self.target_position = position + self.current_position @@ -114,13 +118,15 @@ def move_rel(self, position): self.controller.move_rel(position) def move_home(self): - """Move to home and reset position to zero. + """ + Move to home and reset position to zero. """ self.controller.move_home() self.get_actuator_value() def stop_motion(self): """ + Stop any ongoing movement of the positionner. """ self.controller.stop() self.move_done() diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index cfa0a0e..93563e0 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -32,7 +32,7 @@ def get_devices(): #ids = [ids] bindings.InitDevices(configuration=bindings.SYNCHRONOUS_COMMUNICATION) ptype = [] - n_channel = 1 # SCU devices have only one channel + n_channel = 1 # SCU devices only have one channel for ind_device, dev_sn in enumerate(ids): rotation = False @@ -54,7 +54,6 @@ def get_devices(): rotation = True except bindings.Error: rotation = False - #ind_channel += 1 ptype.append(SCUType(dev_sn, SCUWrapper if not sensor else SCURotation if rotation else SCULinear, @@ -82,8 +81,8 @@ def __init__(self): self.device_index: Optional[int] = None self.channel_index = 0 self.hold_time = 10 - self._amplitude = 40 #between 150 and 1000 - self._frequency = 15000 #between 1 and 18500 + self._amplitude = 1000 #between 150 and 1000 + self._frequency = 440 #between 1 and 18500 self._steps = 0 #between -30000 and 30000 @@ -151,43 +150,48 @@ def move_home(self): physical position Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) - holdTime: Time (in milliseconds) the position/angle is actively held - after reaching the target + after reaching the target - autoZero: Selects whether the current position is set to zero upon - reaching the reference position + reaching the reference position """ print("not implemented") def move_rel(self, n_steps : int): """ - Performs a burst of steps with the given parameters - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - steps: Number and direction of steps to perform - - amplitude: Amplitude in 1/10th Volts that the steps are performed - with - - frequency: Frequency in Hz that the steps are performed with + Performs a burst of steps with the given parameters + + Parameters: + ---------- + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude in Volts that the steps are performed with + Note: The library expects the value in 1/10th Volts, + so the value will be converted accordingly + - frequency: Frequency in Hz that the steps are performed with """ self.steps += n_steps bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude*10, self.frequency) def move_abs(self, n_steps): """ - Performs a burst of steps with the given parameters + Performs a burst of steps with the given parameters - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - steps: Number and direction of steps to perform - - amplitude: Amplitude in 1/10th Volts that the steps are performed - with - - frequency: Frequency in Hz that the steps are performed with - """ + Parameters: + ---------- + - deviceIndex: Selects the device (zero-based) + - channelIndex: Selects the channel (zero-based) + - steps: Number and direction of steps to perform + - amplitude: Amplitude in Volts that the steps are performed with + Note: The library expects the value in 1/10th Volts, + so the value will be converted accordingly + - frequency: Frequency in Hz that the steps are performed with + """ self.steps = self.steps - n_steps bindings.MoveStep_S(self.device_index, self.channel_index, int(self.steps), self.amplitude*10, self.frequency) @@ -198,6 +202,7 @@ def get_position(self) -> float: Returns the current position of a positioner Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) @@ -209,12 +214,12 @@ def get_position(self) -> float: def stop(self): - """Stop any ongoing movement of the positionner. This command also + """Stop any ongoing movement of the positioner. This command also stops the hold position feature of closed-loop commands. - Parameters - ---------- - self.channel_index: unsigned int + Parameters: + ---------- + - self.channel_index: unsigned int """ bindings.Stop_S(self.device_index, self.channel_index) @@ -230,11 +235,13 @@ def move_abs(self, absolute_move_micron): If a mechanical end stop is detected while the command is in execution, the movement will be aborted (without notice). - Parameters - ---------- - self.channel_index: unsigned int - absolute_move_micron: float + Parameters + ---------- + - self.channel_index: unsigned int + - absolute_move_micron: float Absolute position in microns + Note: The library uses the value in 1/10th micrometers, + so the value will be converted accordingly """ position = int(absolute_move_micron * 10) bindings.MovePositionAbsolute_S(self.device_index, self.channel_index, position, self.hold_time) @@ -245,10 +252,12 @@ def move_rel(self, relative_move_value): If a mechanical end stop is detected while the command is in execution, the movement will be aborted (without notice). - Parameters - ---------- - self.channel_index: unsigned int - relative_move_value: signed int. Relative distance in 1/10th micrometers + Parameters + ---------- + - self.channel_index: unsigned int + - relative_move_value: signed int. Relative distance in micrometers + Note: The library expects the value in 1/10th micrometers, + so the value will be converted accordingly """ diff = int(relative_move_value*10) @@ -264,7 +273,9 @@ def get_position(self) -> float: - channelIndex: Selects the channel (zero-based) Return value(s): - - position: Buffer for the current position given in 1/10th micrometers + - position: Buffer for the current position given in micrometers + Note: The library uses the value in 1/10th micrometers, + so the value will be converted accordingly """ position = bindings.GetPosition_S(self.device_index, self.channel_index) @@ -276,6 +287,7 @@ def move_home(self): physical position Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) - holdTime: Time (in milliseconds) the position/angle is actively held @@ -296,9 +308,12 @@ def move_abs(self,absolute_move_degrees): control Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) - - angle: Absolute angle to move to in 1/10th milli degrees + - angle: Absolute angle to move to in degrees + Note: The library expects the value in 1/10th milli degrees, + so the value will be converted accordingly - revolution: Reserved for future use - holdTime: Time (in milliseconds) the angle is actively held after reaching the target @@ -313,10 +328,12 @@ def move_rel(self, rel_move_degrees): angle using closed-loop control Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) - - angleDiff: Relative angle difference to move in 1/10th milli degrees - + - angleDiff: Relative angle difference to move in degrees + Note: The library expects the value in 1/10th milli degrees, + so the value will be converted accordingly - revolutionDiff: Reserved for future use - holdTime: Time (in milliseconds) the angle is actively held after reaching the target @@ -330,11 +347,14 @@ def get_position(self) -> float: Returns the current angle of a positioner Parameters: + ---------- - deviceIndex: Selects the device (zero-based) - channelIndex: Selects the channel (zero-based) Return value(s): - - angle: Buffer for the current angle given in 1/10th milli degrees + - angle: Buffer for the current angle given in degrees + Note: The library uses the value in 1/10th milli degrees, + so the value will be converted accordingly - revolution: Reserved for future use """ angle = bindings.GetAngle_S(self.device_index, self.channel_index) @@ -359,7 +379,7 @@ def get_position(self) -> float: time.sleep(2) - #wrapper.move_abs(0) + bindings.MoveStep_S(0,0, 10000, 440, 18000) #print(wrapper.get_position()) From dbdd3c3d77df2626462bae0a1e2af401905ec77b Mon Sep 17 00:00:00 2001 From: adele080402 Date: Wed, 7 May 2025 13:47:24 +0200 Subject: [PATCH 10/14] =?UTF-8?q?derni=C3=A8re=20mise=20=C3=A0=20jour=20de?= =?UTF-8?q?s=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hardware/smaract/scu/scu_wrapper.py | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index 93563e0..2b0e700 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -361,36 +361,4 @@ def get_position(self) -> float: return float(angle / 10000) -if __name__ == '__main__': - - - ids = get_devices() - - wrapper = SCULinear() - - - device_index = ids.index(ids[0]) - - wrapper.open(device_index) - try: - #channel = wrapper.get_number_of_channels() - - wrapper.move_home() - - time.sleep(2) - - bindings.MoveStep_S(0,0, 10000, 440, 18000) - - #print(wrapper.get_position()) - - #wrapper.steps_move(15000) - print(wrapper.get_position()) - - - except Exception as e: - print(e) - finally: - wrapper.close() - - From 3bcacef4a951c353a570d2446478d7f5d0e38ccf Mon Sep 17 00:00:00 2001 From: adele080402 Date: Fri, 16 May 2025 10:18:28 +0200 Subject: [PATCH 11/14] Final modifications of the Wrapper and DaqMove files --- .../daq_move_SmarActSCUINSA.py | 3 - .../hardware/smaract/scu/scu_wrapper.py | 2 +- .../hardware/smaract/smaract_SCU_wrapper.py | 284 ------------------ 3 files changed, 1 insertion(+), 288 deletions(-) delete mode 100644 src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index 5491b4d..506ec55 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -1,6 +1,3 @@ -"""At the first run, if the program complains about a _build_scu programm not being present, just run the -_build_smaract.py, that will look at the C header file to produce connexion between the dll and the python files""" - from typing import Union, List, Dict diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index 2b0e700..d58f7e8 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -298,7 +298,7 @@ def move_home(self): bindings.MoveToReference_S(self.device_index, self.channel_index, self.hold_time, autoZero=bindings.AUTO_ZERO) -class SCURotation(SCULinear): +class SCURotation(SCUWrapper): units = "degree" diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py deleted file mode 100644 index 754a8c5..0000000 --- a/src/pymodaq_plugins_smaract/hardware/smaract/smaract_SCU_wrapper.py +++ /dev/null @@ -1,284 +0,0 @@ -from cffi import FFI - -import enum -import sys -assert sys.version_info >= (3, 4), "Python v3.4 or higher is required" -apigen_version = (1, 8, 1) -api_version = (1, 5, 16) -def __initBindings(libName): - global ffi, lib - ffi = FFI() - ffi.cdef(""" -typedef unsigned int SA_PACKET_TYPE; -typedef unsigned int SA_INDEX; -struct SA_packet{ SA_PACKET_TYPE packetType; SA_INDEX channelIndex; unsigned int data1; int data2; int data3;}; -typedef struct SA_packet SA_PACKET; -typedef unsigned int SA_STATUS; -SA_STATUS SA_GetDLLVersion(unsigned int *version); -SA_STATUS SA_GetAvailableDevices(unsigned int *idList, unsigned int *idListSize); -SA_STATUS SA_AddDeviceToInitDevicesList(unsigned int deviceId); -SA_STATUS SA_ClearInitDevicesList(); -SA_STATUS SA_InitDevices(unsigned int configuration); -SA_STATUS SA_ReleaseDevices(); -SA_STATUS SA_GetNumberOfDevices(unsigned int *number); -SA_STATUS SA_GetDeviceID(SA_INDEX deviceIndex, unsigned int *deviceId); -SA_STATUS SA_GetDeviceFirmwareVersion(SA_INDEX deviceIndex, unsigned int *version); -SA_STATUS SA_SetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); -SA_STATUS SA_GetClosedLoopMaxFrequency_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *frequency); -SA_STATUS SA_SetZero_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetSensorPresent_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *present); -SA_STATUS SA_SetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); -SA_STATUS SA_GetSensorType_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *type); -SA_STATUS SA_SetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); -SA_STATUS SA_GetPositionerAlignment_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *alignment, unsigned int *forwardAmplitude, unsigned int *backwardAmplitude); -SA_STATUS SA_SetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); -SA_STATUS SA_GetSafeDirection_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *direction); -SA_STATUS SA_SetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); -SA_STATUS SA_GetScale_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *scale, unsigned int *inverted); -SA_STATUS SA_SetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); -SA_STATUS SA_GetChannelProperty_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int *value); -SA_STATUS SA_SetSystemProperty_S(SA_INDEX deviceIndex, int key, int value); -SA_STATUS SA_GetSystemProperty_S(SA_INDEX deviceIndex, int key, int *value); -SA_STATUS SA_MoveStep_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); -SA_STATUS SA_SetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); -SA_STATUS SA_MovePositionAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); -SA_STATUS SA_MovePositionRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); -SA_STATUS SA_MoveAngleAbsolute_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); -SA_STATUS SA_MoveAngleRelative_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); -SA_STATUS SA_CalibrateSensor_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_MoveToReference_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); -SA_STATUS SA_MoveToEndStop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); -SA_STATUS SA_Stop_S(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetStatus_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *status); -SA_STATUS SA_GetAmplitude_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *amplitude); -SA_STATUS SA_GetPosition_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *position); -SA_STATUS SA_GetAngle_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, int *angle, int *revolution); -SA_STATUS SA_GetPhysicalPositionKnown_S(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int *known); -SA_STATUS SA_SetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int frequency); -SA_STATUS SA_GetClosedLoopMaxFrequency_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetZero_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetSensorPresent_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int type); -SA_STATUS SA_GetSensorType_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int alignment, unsigned int forwardAmplitude, unsigned int backwardAmplitude); -SA_STATUS SA_GetPositionerAlignment_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction); -SA_STATUS SA_GetSafeDirection_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int scale, unsigned int inverted); -SA_STATUS SA_GetScale_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetReportOnComplete_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int report); -SA_STATUS SA_SetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key, int value); -SA_STATUS SA_GetChannelProperty_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int key); -SA_STATUS SA_SetSystemProperty_A(SA_INDEX deviceIndex, int key, int value); -SA_STATUS SA_GetSystemProperty_A(SA_INDEX deviceIndex, int key); -SA_STATUS SA_MoveStep_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int steps, unsigned int amplitude, unsigned int frequency); -SA_STATUS SA_SetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int amplitude); -SA_STATUS SA_MovePositionAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int position, unsigned int holdTime); -SA_STATUS SA_MovePositionRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int diff, unsigned int holdTime); -SA_STATUS SA_MoveAngleAbsolute_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angle, int revolution, unsigned int holdTime); -SA_STATUS SA_MoveAngleRelative_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, int angleDiff, int revolutionDiff, unsigned int holdTime); -SA_STATUS SA_CalibrateSensor_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_MoveToReference_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int holdTime, unsigned int autoZero); -SA_STATUS SA_MoveToEndStop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int direction, unsigned int holdTime, unsigned int autoZero); -SA_STATUS SA_Stop_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetStatus_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetAmplitude_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetPosition_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetAngle_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_GetPhysicalPositionKnown_A(SA_INDEX deviceIndex, SA_INDEX channelIndex); -SA_STATUS SA_SetReceiveNotification_A(SA_INDEX deviceIndex, void *event); -SA_STATUS SA_ReceiveNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); -SA_STATUS SA_ReceiveNextPacketIfChannel_A(SA_INDEX deviceIndex, SA_INDEX channelIndex, unsigned int timeout, SA_PACKET *packet); -SA_STATUS SA_LookAtNextPacket_A(SA_INDEX deviceIndex, unsigned int timeout, SA_PACKET *packet); -SA_STATUS SA_DiscardPacket_A(SA_INDEX deviceIndex); -""") - lib = ffi.dlopen(libName) - -def __initFfiApiGenCachedTypes(): - global _ffiApiGenCachedTypes - _ffiApiGenCachedTypes = [ - ffi.typeof("struct SA_packet *"), - ffi.typeof("unsigned int *"), - ffi.typeof("unsigned int []"), - ffi.typeof("int *"), - ffi.typeof("SA_PACKET *")] - - -class Error(Exception): - def __init__(self, func, code, arguments): - self.func = func - self.code = code - self.arguments = arguments - def __str__(self): - return "{} returned {} with arguments {}".format(self.func, self.code, self.arguments) - - -class packet: - """ - Members: - - packetType - - channelIndex - - data1 - - data2 - - data3 - - """ - __slots__ = ['packetType', 'channelIndex', 'data1', 'data2', 'data3', 'cHandle'] - - def __init__(self, packetType, channelIndex, data1, data2, data3, cHandle=None): - if packetType is not None: - self.packetType = packetType - if channelIndex is not None: - self.channelIndex = channelIndex - if data1 is not None: - self.data1 = data1 - if data2 is not None: - self.data2 = data2 - if data3 is not None: - self.data3 = data3 - self.cHandle = cHandle - - def __getattr__(self, attr): - if self.cHandle is not None: - value = getattr(self.cHandle, attr) - retValue = value - setattr(self, attr, retValue) - return retValue - else: - raise AttributeError(f"packet has no attribute: {attr}") - - def asFFI(self): - return ffi.new(_ffiApiGenCachedTypes[0], - {'packetType': self.packetType, 'channelIndex': self.channelIndex, 'data1': self.data1, - 'data2': self.data2, 'data3': self.data3}) - -class SmarActSCUWrapper: - - def GetDLLVersion(): - """ - Returns the version code of the library - - Return value(s): - - version: Library Version - """ - local_0 = ffi.new(_ffiApiGenCachedTypes[1]) - local_1 = lib.SA_GetDLLVersion(local_0) - if local_1 != ErrorCode.OK.value: - raise Error("GetDLLVersion", local_1, {}) - return local_0[0] - - def GetAvailableDevices(idListSize=256): - """ - Returns a list of available device IDs - - Parameters: - - idListSize = 256: Length of the buffer to allocate - - Return value(s): - - idList: Buffer for device IDs - """ - local_0 = ffi.new(_ffiApiGenCachedTypes[2], idListSize) - local_1 = ffi.new(_ffiApiGenCachedTypes[1], idListSize) - local_2 = lib.SA_GetAvailableDevices(local_0, local_1) - if local_2 != ErrorCode.OK.value: - raise Error("GetAvailableDevices", local_2, {}) - return ffi.unpack(local_0, local_1[0]) - - def AddDeviceToInitDevicesList(deviceId): - """ - Used to acquire one or more specific devices - - Parameters: - - deviceId: ID that is to be acquired - """ - local_0 = lib.SA_AddDeviceToInitDevicesList(deviceId) - if local_0 != ErrorCode.OK.value: - raise Error("AddDeviceToInitDevicesList", local_0, {"deviceId": deviceId}) - - def ClearInitDevicesList(): - """ - Clears the device initialization list - """ - local_0 = lib.SA_ClearInitDevicesList() - if local_0 != ErrorCode.OK.value: - raise Error("ClearInitDevicesList", local_0, {}) - - def InitDevices(configuration): - """ - Global initialization function to acquire all devices available in the - DevicesList - - Parameters: - - configuration: Selection between synchronous and asynchronous - communication mode - """ - local_0 = lib.SA_InitDevices(configuration) - if local_0 != ErrorCode.OK.value: - raise Error("InitDevices", local_0, {"configuration": configuration}) - - def MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero): - """ - Starts the referencing procedure and moves the positioner to a known - physical position - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - holdTime: Time (in milliseconds) the position/angle is actively held - after reaching the target - - autoZero: Selects whether the current position is set to zero upon - reaching the reference position - """ - local_0 = lib.SA_MoveToReference_S(deviceIndex, channelIndex, holdTime, autoZero) - if local_0 != ErrorCode.OK.value: - raise Error("MoveToReference_S", local_0, - {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "holdTime": holdTime, - "autoZero": autoZero}) - - def SetZero_S(deviceIndex, channelIndex): - """ - Defines the current position as the zero position - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - """ - local_0 = lib.SA_SetZero_S(deviceIndex, channelIndex) - if local_0 != ErrorCode.OK.value: - raise Error("SetZero_S", local_0, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) - - def MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime): - """ - Instructs a positioner to move to a specific position using closed-loop - control - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - position: Absolute position to move to in 1/10th micro meters - - holdTime: Time (in milliseconds) the position is actively held after - reaching the target - """ - local_0 = lib.SA_MovePositionAbsolute_S(deviceIndex, channelIndex, position, holdTime) - if local_0 != ErrorCode.OK.value: - raise Error("MovePositionAbsolute_S", local_0, - {"deviceIndex": deviceIndex, "channelIndex": channelIndex, "position": position, - "holdTime": holdTime}) - - def GetPosition_S(deviceIndex, channelIndex): - """ - Returns the current position of a positioner - - Parameters: - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - Return value(s): - - position: Buffer for the current position given in 1/10th micro - meters - """ - local_0 = ffi.new(_ffiApiGenCachedTypes[3]) - local_1 = lib.SA_GetPosition_S(deviceIndex, channelIndex, local_0) - if local_1 != ErrorCode.OK.value: - raise Error("GetPosition_S", local_1, {"deviceIndex": deviceIndex, "channelIndex": channelIndex}) - return local_0[0] From 469e24f4b4e9b624acf03e2d1139890f686f6105 Mon Sep 17 00:00:00 2001 From: Malik Irain Date: Wed, 23 Jul 2025 11:49:22 +0200 Subject: [PATCH 12/14] fixed SCUWrapper for simple steppers --- .../hardware/smaract/scu/scu_wrapper.py | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index d58f7e8..422bd3f 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -54,10 +54,9 @@ def get_devices(): rotation = True except bindings.Error: rotation = False - - ptype.append(SCUType(dev_sn, - SCUWrapper if not sensor else SCURotation if rotation else SCULinear, - ind_channel)) + ptype.append(SCUType(dev_sn, + SCUWrapper if not sensor else SCURotation if rotation else SCULinear, + ind_channel)) bindings.ReleaseDevices() @@ -80,8 +79,8 @@ def __init__(self): self.device_index: Optional[int] = None self.channel_index = 0 - self.hold_time = 10 - self._amplitude = 1000 #between 150 and 1000 + self.hold_time = 0 + self._amplitude = 100 #between 15 and 100 self._frequency = 440 #between 1 and 18500 self._steps = 0 #between -30000 and 30000 @@ -96,7 +95,7 @@ def amplitude (self): @amplitude.setter def amplitude(self, number : int): - if isinstance(number, int) and 100 > number > 15 : + if isinstance(number, int) and SCUWrapper.amplitude_limits[0] < number < SCUWrapper.amplitude_limits[1]: self._amplitude = number bindings.SetAmplitude_S(self.device_index, self.channel_index, self._amplitude*10) @@ -110,7 +109,7 @@ def frequency(self): @frequency.setter def frequency(self, number: int): - if isinstance(number, int) and 18500 > number > 1: + if isinstance(number, int) and SCUWrapper.frequency_limits[0] < number < SCUWrapper.frequency_limits[1]: self._frequency = number @property @@ -122,7 +121,7 @@ def steps(self): @steps.setter def steps(self, number: int): - if isinstance(number, int) and 30000 > number > -30000: + if isinstance(number, int) and SCUWrapper.steps_limits[0] < number < SCUWrapper.steps_limits[1]: self._steps = number @@ -149,18 +148,11 @@ def move_home(self): Starts the referencing procedure and moves the positioner to a known physical position - Parameters: - ---------- - - deviceIndex: Selects the device (zero-based) - - channelIndex: Selects the channel (zero-based) - - holdTime: Time (in milliseconds) the position/angle is actively held - after reaching the target - - autoZero: Selects whether the current position is set to zero upon - reaching the reference position """ print("not implemented") + def move_rel(self, n_steps : int): """ Performs a burst of steps with the given parameters @@ -178,7 +170,7 @@ def move_rel(self, n_steps : int): self.steps += n_steps bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude*10, self.frequency) - def move_abs(self, n_steps): + def move_abs(self, steps): """ Performs a burst of steps with the given parameters @@ -193,7 +185,7 @@ def move_abs(self, n_steps): - frequency: Frequency in Hz that the steps are performed with """ - self.steps = self.steps - n_steps + self.steps = steps - self.steps bindings.MoveStep_S(self.device_index, self.channel_index, int(self.steps), self.amplitude*10, self.frequency) From 3cc0552eb8daef4c98c974f4fb1628c268f6a850 Mon Sep 17 00:00:00 2001 From: Malik Irain Date: Mon, 28 Jul 2025 13:59:39 +0200 Subject: [PATCH 13/14] Use DataActuator objects and better stepper position/step control --- .../daq_move_plugins/daq_move_SmarActSCUINSA.py | 14 +++++++++----- .../hardware/smaract/scu/scu_wrapper.py | 14 +++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py index 506ec55..8720531 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py @@ -1,15 +1,17 @@ from typing import Union, List, Dict -from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun +from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun, DataActuatorType from pymodaq.utils.daq_utils import ThreadCommand from easydict import EasyDict as edict from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, SCULinear, SCURotation) +from pymodaq.utils.data import DataActuator + psets: list[SCUType] = get_devices() -psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel}" for pset in psets] +psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel} ({pset.scu_type.__name__})" for pset in psets] class DAQ_Move_SmarActSCUINSA(DAQ_Move_base): @@ -23,6 +25,8 @@ class DAQ_Move_SmarActSCUINSA(DAQ_Move_base): is_multiaxes = True _axis_names = ['1'] + data_actuator_type = DataActuatorType.DataActuator + params = [ {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 1000, 'limits': SCUWrapper.frequency_limits}, @@ -75,7 +79,7 @@ def get_actuator_value(self): ------- float: The position obtained after scaling conversion. """ - position = self.controller.get_position() + position = DataActuator(data=self.controller.get_position(), units=self.axis_unit) # convert position if scaling options have been used, mandatory here position = self.get_position_with_scaling(position) #position = self.target_position @@ -98,7 +102,7 @@ def move_abs(self, position): # has been activated by user position = self.set_position_with_scaling(position) - self.controller.move_abs(position) + self.controller.move_abs(position.value()) def move_rel(self, position): """ @@ -112,7 +116,7 @@ def move_rel(self, position): self.target_position = position + self.current_position position = self.set_position_relative_with_scaling(position) - self.controller.move_rel(position) + self.controller.move_rel(position.value()) def move_home(self): """ diff --git a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py index 422bd3f..8f2c65a 100644 --- a/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py +++ b/src/pymodaq_plugins_smaract/hardware/smaract/scu/scu_wrapper.py @@ -15,7 +15,7 @@ def __init__(self, id: int, scu_type, channel: int): self.channel = channel def __repr__(self): - return f'SN: {self.device_id}, type:{self.scu_type}, channel: {self.channel}' + return f'SN: {self.device_id}, type:{self.scu_type.__name__}, channel: {self.channel}' def get_devices(): @@ -82,8 +82,7 @@ def __init__(self): self.hold_time = 0 self._amplitude = 100 #between 15 and 100 self._frequency = 440 #between 1 and 18500 - self._steps = 0 #between -30000 and 30000 - + self._position = 0 #between -30000 and 30000 @property @@ -167,8 +166,8 @@ def move_rel(self, n_steps : int): so the value will be converted accordingly - frequency: Frequency in Hz that the steps are performed with """ - self.steps += n_steps bindings.MoveStep_S(self.device_index, self.channel_index, int(n_steps), self.amplitude*10, self.frequency) + self._position += int(n_steps) def move_abs(self, steps): """ @@ -185,8 +184,9 @@ def move_abs(self, steps): - frequency: Frequency in Hz that the steps are performed with """ - self.steps = steps - self.steps - bindings.MoveStep_S(self.device_index, self.channel_index, int(self.steps), self.amplitude*10, self.frequency) + n_steps = int(steps - self._position) + bindings.MoveStep_S(self.device_index, self.channel_index, n_steps, self.amplitude*10, self.frequency) + self._position = steps def get_position(self) -> float: @@ -202,7 +202,7 @@ def get_position(self) -> float: - position: Buffer for the current position given in steps meters """ - return self._steps + return self._position def stop(self): From acd034352cbb16898b42aed2e8021b5c4fb4fb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Weber?= Date: Tue, 4 Nov 2025 19:22:02 +0100 Subject: [PATCH 14/14] replaced the legacy SCu plugin with a new one --- pyproject.toml | 2 - .../daq_move_plugins/daq_move_SmarActSCU.py | 100 +++++++------ .../daq_move_SmarActSCUINSA.py | 137 ------------------ 3 files changed, 49 insertions(+), 190 deletions(-) delete mode 100644 src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py diff --git a/pyproject.toml b/pyproject.toml index 16f7fc8..7841af5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,8 +14,6 @@ description = 'Set of PyMoDAQ plugins for linear actuators from Smaract (SLC pos dependencies = [ "pymodaq>5.0.0", - 'instrumental-lib', - 'nicelib', ] authors = [ diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCU.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCU.py index 0277c87..4c952ae 100644 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCU.py +++ b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCU.py @@ -1,22 +1,17 @@ -"""At the first run, if the program complains about a _build_scu programm not being present, just run the -_build_smaract.py, that will look at the C header file to produce connexion between the dll and the python files""" +from typing import Union, List, Dict -from typing import Union +from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun, DataActuatorType +from pymodaq.utils.daq_utils import ThreadCommand +from easydict import EasyDict as edict -from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun -from pymodaq_utils.logger import set_logger, get_module_name -logger = set_logger(get_module_name(__file__)) +from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, + SCULinear, SCURotation) -from instrumental import instrument, list_instruments -try: - from instrumental.drivers.motion._smaract.scu import SCU, SCULinear, SCURotation, Q_ -except Exception as e: - logger.exception(f'Could not load the SmarAct instrumental drivers: {str(e)}') +from pymodaq.utils.data import DataActuator - -psets = list_instruments(module='motion._smaract') -psets_str = [f"Dev. Id{pset['id']} channel {pset['index']}" for pset in psets] +psets: list[SCUType] = get_devices() +psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel} ({pset.scu_type.__name__})" for pset in psets] class DAQ_Move_SmarActSCU(DAQ_Move_base): @@ -24,48 +19,46 @@ class DAQ_Move_SmarActSCU(DAQ_Move_base): """ _controller_units = "" - _epsilon = 0.002 + _epsilon = 2 # find controller locators - is_multiaxes = False - stage_names = [] + is_multiaxes = True + _axis_names = ['1'] + + data_actuator_type = DataActuatorType.DataActuator params = [ - {'title': 'Device', 'name': 'device', 'type': 'list', 'limits': psets_str}, - {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 450}, - {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100}, - {'title': 'Max Frequency (Hz)', 'name': 'maxfreq', 'type': 'int', 'value': 18500}, - ] + comon_parameters_fun(is_multiaxes, epsilon=_epsilon) + {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, + {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 1000, 'limits': SCUWrapper.frequency_limits}, + {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100, 'limits':SCUWrapper.amplitude_limits}, + ] + comon_parameters_fun(is_multiaxes=is_multiaxes, axis_names=_axis_names, epsilon=_epsilon) ########################################################## def ini_attributes(self): - self.controller: Union[SCU, SCULinear, SCURotation] = None - self.settings.child("epsilon").setValue(0.002) + self.controller: Union[SCUWrapper, SCULinear, SCURotation] = None + self.settings.child("epsilon").setValue(2) def commit_settings(self, param): if param.name() == 'amplitude': - self.controller.amplitude = Q_(param.value(), units='V') + self.controller.amplitude = param.value() elif param.name() == 'frequency': - self.controller.frequency = Q_(param.value(), 'Hz') - - elif param.name() == 'maxfreq': - self.controller.max_frequency = Q_(param.value(), 'Hz') - self.settings.child('maxfreq').setValue(self.controller.max_frequency.m_as('Hz')) + self.controller.frequency = param.value() def ini_stage(self, controller=None): """Initialize the controller and stages (axes) with given parameters. """ index = self.settings.child('device').opts['limits'].index(self.settings['device']) - self.ini_stage_init(controller, instrument(psets[index])) + if self.is_master: + self.controller = psets[index].scu_type() + self.controller.open(index) + self.controller.amplitude = self.settings['amplitude'] + self.controller.frequency = self.settings['frequency'] - self.settings.child('units').setValue(self.controller.units) - self.settings.child('amplitude').setOpts(limits=list(self.controller.amplitude_limits.m_as('V'))) - self.settings.child('frequency').setOpts(limits=list(self.controller.frequency_limits.m_as('Hz'))) - self.settings.child('amplitude').setValue(self.controller.amplitude.m_as('V')) - self.settings.child('frequency').setValue(self.controller.frequency.m_as('Hz')) - if not isinstance(self.controller, SCU): - self.settings.child('maxfreq').setValue(self.controller.max_frequency.m_as('Hz')) + else: + self.controller = controller + + self.axis_unit = self.controller.units info = '' initialized = True @@ -73,19 +66,20 @@ def ini_stage(self, controller=None): return info, initialized def close(self): - """Close the communication with the SmarAct controller. + """ + Close the communication with the SmarAct controller. """ self.controller.close() - self.controller = None def get_actuator_value(self): - """Get the current position from the hardware with scaling conversion. + """ + Get the current position from the hardware with scaling conversion. Returns ------- float: The position obtained after scaling conversion. """ - position = self.controller.check_position().magnitude + position = DataActuator(data=self.controller.get_position(), units=self.axis_unit) # convert position if scaling options have been used, mandatory here position = self.get_position_with_scaling(position) #position = self.target_position @@ -93,11 +87,12 @@ def get_actuator_value(self): return position def move_abs(self, position): - """Move to an absolute position + """ + Move to an absolute position - Parameters + Parameters: ---------- - position: float + - position: float """ # limit position if bounds options has been selected and if position is # out of them @@ -107,29 +102,32 @@ def move_abs(self, position): # has been activated by user position = self.set_position_with_scaling(position) - self.controller.move_to(Q_(position, self.settings['units']), 'abs') + self.controller.move_abs(position.value()) def move_rel(self, position): - """Move to a relative position + """ + Move to a relative position - Parameters + Parameters: ---------- - position: float + - position: float """ 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) - self.controller.move_to(Q_(position, self.settings['units']), 'rel') + self.controller.move_rel(position.value()) def move_home(self): - """Move to home and reset position to zero. + """ + Move to home and reset position to zero. """ self.controller.move_home() self.get_actuator_value() def stop_motion(self): """ + Stop any ongoing movement of the positionner. """ self.controller.stop() self.move_done() diff --git a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py b/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py deleted file mode 100644 index 8720531..0000000 --- a/src/pymodaq_plugins_smaract/daq_move_plugins/daq_move_SmarActSCUINSA.py +++ /dev/null @@ -1,137 +0,0 @@ - -from typing import Union, List, Dict - -from pymodaq.control_modules.move_utility_classes import DAQ_Move_base, main, comon_parameters_fun, DataActuatorType -from pymodaq.utils.daq_utils import ThreadCommand -from easydict import EasyDict as edict - -from pymodaq_plugins_smaract.hardware.smaract.scu.scu_wrapper import (get_devices, SCUType, SCUWrapper, - SCULinear, SCURotation) - -from pymodaq.utils.data import DataActuator - -psets: list[SCUType] = get_devices() -psets_str = [f"Dev. Id{pset.device_id} channel {pset.channel} ({pset.scu_type.__name__})" for pset in psets] - - -class DAQ_Move_SmarActSCUINSA(DAQ_Move_base): - """ - - """ - _controller_units = "" - _epsilon = 2 - # find controller locators - - is_multiaxes = True - _axis_names = ['1'] - - data_actuator_type = DataActuatorType.DataActuator - - params = [ - {'title': 'Device', 'name': 'device', 'type': 'list','limits': psets_str}, - {'title': 'Frequency (Hz)', 'name': 'frequency', 'type': 'int', 'value': 1000, 'limits': SCUWrapper.frequency_limits}, - {'title': 'Amplitude (V)', 'name': 'amplitude', 'type': 'int', 'value': 100, 'limits':SCUWrapper.amplitude_limits}, - ] + comon_parameters_fun(is_multiaxes=is_multiaxes, axis_names=_axis_names, epsilon=_epsilon) - ########################################################## - - def ini_attributes(self): - self.controller: Union[SCUWrapper, SCULinear, SCURotation] = None - self.settings.child("epsilon").setValue(2) - - def commit_settings(self, param): - if param.name() == 'amplitude': - self.controller.amplitude = param.value() - elif param.name() == 'frequency': - self.controller.frequency = param.value() - - def ini_stage(self, controller=None): - """Initialize the controller and stages (axes) with given parameters. - - """ - index = self.settings.child('device').opts['limits'].index(self.settings['device']) - if self.is_master: - self.controller = psets[index].scu_type() - self.controller.open(index) - self.controller.amplitude = self.settings['amplitude'] - self.controller.frequency = self.settings['frequency'] - - else: - self.controller = controller - - self.axis_unit = self.controller.units - - info = '' - initialized = True - - return info, initialized - - def close(self): - """ - Close the communication with the SmarAct controller. - """ - self.controller.close() - - def get_actuator_value(self): - """ - Get the current position from the hardware with scaling conversion. - - Returns - ------- - float: The position obtained after scaling conversion. - """ - position = DataActuator(data=self.controller.get_position(), units=self.axis_unit) - # convert position if scaling options have been used, mandatory here - position = self.get_position_with_scaling(position) - #position = self.target_position - self.current_position = position - return position - - def move_abs(self, position): - """ - Move to an absolute position - - Parameters: - ---------- - - position: float - """ - # limit position if bounds options has been selected and if position is - # out of them - position = self.check_bound(position) - self.target_position = position - # convert the user set position to the controller position if scaling - # has been activated by user - position = self.set_position_with_scaling(position) - - self.controller.move_abs(position.value()) - - def move_rel(self, position): - """ - Move to a relative position - - Parameters: - ---------- - - position: float - """ - 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) - - self.controller.move_rel(position.value()) - - def move_home(self): - """ - Move to home and reset position to zero. - """ - self.controller.move_home() - self.get_actuator_value() - - def stop_motion(self): - """ - Stop any ongoing movement of the positionner. - """ - self.controller.stop() - self.move_done() - - -if __name__ == "__main__": - main(__file__, init=False)