"""ANC350v3Lib is a Python wrapper for the C++ library of the Attocube ANC350 driver (version 3)
It depends on anc350v3.dll (and libusb0.dll) which are provided by Attocube on the installation
disc. You can find the dll files for 32-bit and 64-bit in folder ANC350_Library.
Please the dlls into the working directory or specify the path when instantiating the ANC350v3Lib.
Author:
Lukas Lankes, Forschungszentrum Jülich GmbH / ZEA-2, l.lankes@fz-juelich.de
"""
import ctypes
import ctypes.util
from ctypes import c_int8, c_int32, c_uint32, c_double, c_void_p, byref
from ctypes import create_string_buffer as c_string
import locale
from typing import Any, Optional, Tuple, Union
import sys
from .interface import ANC350LibError, ANC350LibDeviceType, ANC350LibExternalTriggerMode, \
ANC350LibTriggerPolarity, ANC350LibActuatorType
__all__ = ["ANC350v3Lib", "ANC350v3LibError", "ANC350LibError", "ANC350LibDeviceType",
"ANC350LibExternalTriggerMode", "ANC350LibTriggerPolarity", "ANC350LibActuatorType"]
[docs]
class ANC350v3LibError(ANC350LibError):
"""Exception class for errors occurring in ``ANC350v3Lib`` and ``ANC350v4Lib``
Attributes:
message: Error message
code: Error code from dll (or None)
"""
[docs]
def __init__(self, message: Optional[str] = None, code: Optional[int] = None):
"""Create instance of ``ANC350v3LibError``
Args:
message: Error message
code: Error code from dll
"""
super().__init__(message, code)
@classmethod
def _get_message_for_code(cls, code: int) -> Optional[str]:
"""Override this function to convert return codes into error messages
Args:
code: Occurred error code
Returns:
Corresponding error message for code
"""
messages = {
-1: "Unspecified error",
0: "Success",
1: "Communication timeout",
2: "Not connected",
3: "Driver error",
7: "Device locked",
8: "Unknown error",
9: "Invalid device number",
10: "Invalid axis number",
11: "Parameter out of range",
12: "Function not available",
13: "Can't open or parse file"
}
return messages[code] if code in messages else None
[docs]
class ANC350v3Lib:
"""A wrapper class for version 3 of the ANC350 driver anc350v3.dll
This class adapts all functions of anc350v3.dll and forwards its calls to the dll.
"""
DEFAULT_PATH_TO_DLL = r"anc350v3.dll"
[docs]
def __init__(self, path_to_dll: Optional[str] = None):
"""Creates an instance of the anc350v3.dll-wrapper
Args:
path_to_dll: Path to anc350v3.dll or None, if it's stored in the working directory
"""
if not path_to_dll:
path_to_dll = self.DEFAULT_PATH_TO_DLL
try:
if sys.platform != 'win32':
self._dll: Any = None
self._encoding: Any = None
raise OSError("\"anc350v3.dll\" is only compatible with Microsoft Windows")
self._path_to_dll = ctypes.util.find_library(path_to_dll or self.DEFAULT_PATH_TO_DLL)
if self._path_to_dll is None:
raise FileNotFoundError("Could not find " + path_to_dll)
self._dll = ctypes.windll.LoadLibrary(self._path_to_dll)
# String encoding
self._encoding = locale.getpreferredencoding(False)
except Exception as exc:
raise ANC350v3LibError("Error loading " + path_to_dll) from exc
[docs]
def discover(self, search_usb: bool = True, search_tcp: bool = True) -> int:
"""Discover Devices
The function searches for connected ANC350RES devices on USB and LAN and initializes
internal data structures per device. Devices that arwe in use by another application or PC
are not found. The function must be called before connecting to a device and must not be
called as long as any devices are connected.
The number of devices found is returned. In subsequent functions, devices are identified by
a sequence number that must be less than the number returned.
Args:
search_usb: True (default) to search for USB devices; False otherwise
search_tcp: True (default) to search for TCP/IP devices; False otherwise
Returns:
Number of devices found
Raises:
ANC350LibError is raised, if the function call fails
"""
interfaces = (0x1 if search_usb else 0x0) | (0x2 if search_tcp else 0x0)
c_interfaces = c_int32(interfaces)
c_dev_count = c_uint32()
try:
return_code = self._dll.ANC_discover(c_interfaces, byref(c_dev_count))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_discover") from exc
ANC350v3LibError.check_error(return_code, "ANC_discover")
return c_dev_count.value
[docs]
def get_device_info(self, dev_no: int = 0) -> Tuple[ANC350LibDeviceType, int, str, str, bool]:
"""Device Information
Returns available information about a device. The function can not be called before
``discover`` but the devices don't have to be connected with ``connect``. All Pointers to
output parameters may be zero to ignore the respective value.
Args:
dev_no: Sequence number of the device. Must be smaller than the return value from the
last ``ANC_discover`` call (default: 0).
Returns:
A tuple containing the device's information:
0. dev_type: Type of the ANC350 device
1. id: Programmed hardware ID of the device
2. serial: The device's serial number
3. address: The device's interface address if applicable. Returns the IP address in
dotted-decimal notation or the string "USB", respectively
4. connected: True, if the device is already connected
Raises:
ANC350LibError is raised, if the function call fails
"""
c_dev_no = c_uint32(dev_no)
c_dev_type = c_int32()
c_id = c_int8()
c_serial = c_string(16)
c_address = c_string(16)
c_connected = c_int32()
try:
return_code = self._dll.ANC_getDeviceInfo(c_dev_no, byref(c_dev_type), byref(c_id),
byref(c_serial), byref(c_address),
byref(c_connected))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getDeviceInfo") from exc
ANC350v3LibError.check_error(return_code, "ANC_getDeviceInfo")
return ANC350LibDeviceType(c_dev_type.value), c_id.value,\
c_serial.value.decode(self._encoding), c_address.value.decode(self._encoding),\
bool(c_connected.value)
[docs]
def connect(self, dev_no: int = 0) -> c_void_p:
"""Connect Device
Initializes and connects the selected device.
This has to be done before any access to control variables or measured data.
Args:
dev_no: Sequence number of the device. Must be smaller than the return value from the
last ``discover`` call (default: 0).
Returns:
device: Handle to the opened device; or None on error
Raises:
ANC350LibError is raised, if the function call fails
"""
c_dev_no = c_uint32(dev_no)
c_dev_handle = c_void_p()
try:
return_code = self._dll.ANC_connect(c_dev_no, byref(c_dev_handle))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_connect") from exc
ANC350v3LibError.check_error(return_code, "ANC_connect")
if not c_dev_handle:
raise ANC350v3LibError("Received invalid handle from ANC_connect")
return c_dev_handle
[docs]
def disconnect(self, dev_handle: c_void_p) -> None:
"""Disconnect Device
Closes the connection to the device. The device handle becomes invalid.
Args:
dev_handle: Handle of the device to close
Raises:
ANC350LibError is raised, if the function call fails
"""
try:
return_code = self._dll.ANC_disconnect(dev_handle)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_disconnect") from exc
ANC350v3LibError.check_error(return_code, "ANC_disconnect")
[docs]
def get_device_config(self, dev_handle: c_void_p) -> Tuple[bool, bool, bool, bool]:
"""Read Device Configuration
Reads static device configuration data
Args:
dev_handle: Handle of the device to access
Returns:
A tuple containing which features of the device are enabled:
0. sync: Ethernet enabled (True) or disabled (False)
1. lockin: Low power loss measurement enabled (True) or disabled (False)
2. duty: Duty cycle enabled (True) or disabled (False)
3. app: Control by iOS app enabled (True) or disabled (False)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_features = c_uint32()
try:
return_code = self._dll.ANC_getDeviceConfig(dev_handle, byref(c_features))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getDeviceConfig") from exc
ANC350v3LibError.check_error(return_code, "ANC_getDeviceConfig")
features = c_features.value
feat_sync = bool(0x1 & features)
feat_lockin = bool(0x2 & features)
feat_duty = bool(0x4 & features)
feat_app = bool(0x8 & features)
return feat_sync, feat_lockin, feat_duty, feat_app
[docs]
def get_axis_status(self, dev_handle: c_void_p, axis_no: int) \
-> Tuple[bool, bool, bool, bool, bool, bool, bool]:
"""Read Axis Status
Reads status information about an axis of the device.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
A tuple containing the axis status:
0. connected: True, if the axis is connected to a sensor.
1. enabled: True, if the axis voltage output is enabled.
2. moving: True, if the axis is moving.
3. target: True, if the target is reached in automatic positioning.
4. eot_fwd: True, if end of travel detected in forward direction.
5. eot_bwd: True, if end of travel detected in backward direction.
6. error: True, if the axis' sensor is in error state.
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_connected = c_int32()
c_enabled = c_int32()
c_moving = c_int32()
c_target = c_int32()
c_eot_fwd = c_int32()
c_eot_bwd = c_int32()
c_error = c_int32()
try:
return_code = self._dll.ANC_getAxisStatus(dev_handle, c_axis_no,
byref(c_connected), byref(c_enabled),
byref(c_moving), byref(c_target),
byref(c_eot_fwd), byref(c_eot_bwd),
byref(c_error))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getAxisStatus") from exc
ANC350v3LibError.check_error(return_code, "ANC_getAxisStatus")
return bool(c_connected.value), bool(c_enabled.value), bool(c_moving.value), \
bool(c_target.value), bool(c_eot_fwd.value), bool(c_eot_bwd.value), \
bool(c_error.value)
[docs]
def set_axis_output(self, dev_handle: c_void_p, axis_no: int, enable: bool,
auto_disable: bool) -> None:
"""Enable Axis Output
Enables or disables the voltage output of an axis.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
enable: True, to enable the voltage output. False, to disable it.
auto_disable: True, if the voltage output is to be deactivated automatically when end of
travel is detected.
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_enable = c_int32(int(enable))
c_auto_disable = c_int32(int(auto_disable))
try:
return_code = self._dll.ANC_setAxisOutput(dev_handle, c_axis_no, c_enable,
c_auto_disable)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setAxisOutput") from exc
ANC350v3LibError.check_error(return_code, "ANC_setAxisOutput")
[docs]
def set_amplitude(self, dev_handle: c_void_p, axis_no: int, amplitude: float) -> None:
"""Set Amplitude
Sets the amplitude parameter for an axis
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
amplitude: Amplitude in Volts [V] (internal resolution is 1mV)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_amplitude = c_double(amplitude)
try:
return_code = self._dll.ANC_setAmplitude(dev_handle, c_axis_no, c_amplitude)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setAmplitude") from exc
ANC350v3LibError.check_error(return_code, "ANC_setAmplitude")
[docs]
def set_frequency(self, dev_handle: c_void_p, axis_no: int, frequency: float) -> None:
"""Set Frequency
Sets the frequency parameter for an axis
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
frequency: Frequency in Hertz [Hz], internal resolution is 1 Hz (although DLL accepts
double-values)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_frequency = c_double(frequency)
try:
return_code = self._dll.ANC_setFrequency(dev_handle, c_axis_no, c_frequency)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setFrequency") from exc
ANC350v3LibError.check_error(return_code, "ANC_setFrequency")
[docs]
def set_dc_voltage(self, dev_handle: c_void_p, axis_no: int, voltage: float) -> None:
"""Set DC Output Voltage
Sets the DC level on the voltage output when no sawtooth based motion and no feedback loop
is active.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
voltage: DC output voltage in Volts [V], internal resolution is 1 mV
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_voltage = c_double(voltage)
try:
return_code = self._dll.ANC_setDcVoltage(dev_handle, c_axis_no, c_voltage)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setDcVoltage") from exc
ANC350v3LibError.check_error(return_code, "ANC_setDcVoltage")
[docs]
def get_amplitude(self, dev_handle: c_void_p, axis_no: int) -> float:
"""Read Back Amplitude
Reads back the amplitude parameter of an axis.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Amplitude in Volts [V]
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_amplitude = c_double()
try:
return_code = self._dll.ANC_getAmplitude(dev_handle, c_axis_no, byref(c_amplitude))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getAmplitude") from exc
ANC350v3LibError.check_error(return_code, "ANC_getAmplitude")
return c_amplitude.value
[docs]
def get_frequency(self, dev_handle: c_void_p, axis_no: int) -> float:
"""Read back Frequency
Reads back the frequency parameter of an axis.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Frequency in Hertz [Hz]
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_frequency = c_double()
try:
return_code = self._dll.ANC_getFrequency(dev_handle, c_axis_no, byref(c_frequency))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getFrequency") from exc
ANC350v3LibError.check_error(return_code, "ANC_getFrequency")
return c_frequency.value
[docs]
def start_single_step(self, dev_handle: c_void_p, axis_no: int, backward: bool) -> None:
"""Single Step
Triggers a single step in desired direction.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
backward: Step direction forward (False) or backward (True)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_backward = c_int32(int(backward))
try:
return_code = self._dll.ANC_startSingleStep(dev_handle, c_axis_no, c_backward)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_startSingleStep") from exc
ANC350v3LibError.check_error(return_code, "ANC_startSingleStep")
[docs]
def start_continuous_move(self, dev_handle: c_void_p, axis_no: int, start: bool,
backward: bool) -> None:
"""Continuous Motion
Starts or stops continous motion in forward or backward direction.
Other kinds of motion are stopped.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
start: Starts (True) or stops (False) the motion
backward: Step direction forward (False) or backward (True)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_start = c_int32(int(start))
c_backward = c_int32(int(backward))
try:
return_code = self._dll.ANC_startContinousMove(dev_handle, c_axis_no, c_start,
c_backward)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_startContinousMove") from exc
ANC350v3LibError.check_error(return_code, "ANC_startContinousMove")
[docs]
def start_auto_move(self, dev_handle: c_void_p, axis_no: int, enable: bool,
relative: bool) -> None:
"""Set Automatic Motion
Switches automatic moving (i.e. following the target position) on or off
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
enable: Enables (True) or disables (False) automatic motion
relative: If the target position is to be interpreted absolute (False) or relative to
the current position (True)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_enable = c_int32(int(enable))
c_relative = c_int32(int(relative))
try:
return_code = self._dll.ANC_startAutoMove(dev_handle, c_axis_no, c_enable,
c_relative)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_startAutoMove") from exc
ANC350v3LibError.check_error(return_code, "ANC_startAutoMove")
[docs]
def set_target_position(self, dev_handle: c_void_p, axis_no: int, target: float) -> None:
"""Set Target Position
Sets the target position for automatic motion, see ``start_auto_move``.
For linear type actuators the position unit is m, for goniometers and rotators it is degree.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
target: Target position in meters [m] or degrees [°]. Internal resolution is 1 nm or
1 µ°.
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_target = c_double(target)
try:
return_code = self._dll.ANC_setTargetPosition(dev_handle, c_axis_no, c_target)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setTargetPosition") from exc
ANC350v3LibError.check_error(return_code, "ANC_setTargetPosition")
[docs]
def set_target_range(self, dev_handle: c_void_p, axis_no: int, target_range: float) -> None:
"""Set Target Range
Defines the range around the target position where the target is considered to be reached.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
target_range: Target range in meters [m] or degrees [°]. Internal resolution is 1 nm or
1 µ°.
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_target_range = c_double(target_range)
try:
return_code = self._dll.ANC_setTargetRange(dev_handle, c_axis_no, c_target_range)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_setTargetRange") from exc
ANC350v3LibError.check_error(return_code, "ANC_setTargetRange")
[docs]
def get_position(self, dev_handle: c_void_p, axis_no: int) -> float:
"""Read Current Position
Retrieves the current actuator position.
For linear type actuators the position unit is m; for goniometers and rotators it is degree.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Current position in meters [m] or degrees [°]
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_position = c_double()
try:
return_code = self._dll.ANC_getPosition(dev_handle, c_axis_no, byref(c_position))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getPosition") from exc
ANC350v3LibError.check_error(return_code, "ANC_getPosition")
return c_position.value
[docs]
def get_firmware_version(self, dev_handle: c_void_p) -> int:
"""Firmware version
Retrieves the version of currently loaded firmware.
Args:
dev_handle: Handle of the device to access
Returns:
Version number
Raises:
ANC350LibError is raised, if the function call fails
"""
c_version = c_int32()
try:
return_code = self._dll.ANC_getFirmwareVersion(dev_handle, byref(c_version))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getFirmwareVersion") from exc
ANC350v3LibError.check_error(return_code, "ANC_getFirmwareVersion")
return c_version.value
[docs]
def select_actuator(self, dev_handle: c_void_p, axis_no: int, actuator: int) -> None:
"""Select Actuator
Selects the actuator to be used for the axis from actuator presets.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
actuator: Actuator selection (0..255)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_actuator = c_uint32(actuator)
try:
return_code = self._dll.ANC_selectActuator(dev_handle, c_axis_no, c_actuator)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_selectActuator") from exc
ANC350v3LibError.check_error(return_code, "ANC_selectActuator")
[docs]
def get_actuator_name(self, dev_handle: c_void_p, axis_no: int) -> str:
"""Get Actuator Name
Get the name of the currently selected actuator
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Name of the actuator
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_name = c_string(20)
try:
return_code = self._dll.ANC_getActuatorName(dev_handle, c_axis_no, byref(c_name))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getActuatorName") from exc
ANC350v3LibError.check_error(return_code, "ANC_getActuatorName")
return c_name.value.decode(self._encoding)
[docs]
def get_actuator_type(self, dev_handle: c_void_p, axis_no: int) -> ANC350LibActuatorType:
"""Get Actuator Type
Get the type of the currently selected actuator
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Type of the actuator
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_type = c_int32()
try:
return_code = self._dll.ANC_getActuatorType(dev_handle, c_axis_no, byref(c_type))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getActuatorType") from exc
ANC350v3LibError.check_error(return_code, "ANC_getActuatorType")
return ANC350LibActuatorType(c_type.value)
[docs]
def measure_capacitance(self, dev_handle: c_void_p, axis_no: int) -> float:
"""Measure Motor Capacitance
Performs a measurement of the capacitance of the piezo motor and returns the result. If no
motor is connected, the result will be 0.
The function doesn't return before the measurement is complete; this will take a few seconds
of time.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Capacitance in Farad [F]
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_cap = c_double()
try:
return_code = self._dll.ANC_measureCapacitance(dev_handle, c_axis_no, byref(c_cap))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_measureCapacitance") from exc
ANC350v3LibError.check_error(return_code, "ANC_measureCapacitance")
return c_cap.value
[docs]
def save_params(self, dev_handle: c_void_p) -> None:
"""Save Parameters
Saves parameters to persistent flash memory in the device. They will be present as defaults
after the next power-on.
The following parameters are affected:
* amplitude (see ``set_amplitude``)
* frequency (see ``set_frequency``)
* target range (see ``set_target_range``)
* target ground (see ``set_target_ground``)
* actuator selection (see ``select_actuator``)
* trigger and quadrature settings
Args:
dev_handle: Handle of the device to access
Raises:
ANC350LibError is raised, if the function call fails
"""
try:
return_code = self._dll.ANC_saveParams(dev_handle)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_saveParams") from exc
ANC350v3LibError.check_error(return_code, "ANC_saveParams")
[docs]
def reset_position(self, dev_handle: c_void_p, axis_no: int) -> None:
"""Reset Position
Sets the current (relative) position of an axis to Zero.
Only applicable for NUM and FPS devices.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
try:
return_code = self._dll.ANC_resetPosition(dev_handle, c_axis_no)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_resetPosition") from exc
ANC350v3LibError.check_error(return_code, "ANC_resetPosition")
[docs]
def move_reference(self, dev_handle: c_void_p, axis_no: int) -> None:
"""Reset Reference
Starts an approach to the reference position. A running motion command is aborted; automatic
moving (see ``start_auto_move``) is switched on. Requires a valid reference position.
Only applicable for NUM devices.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
try:
return_code = self._dll.ANC_moveReference(dev_handle, c_axis_no)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_moveReference") from exc
ANC350v3LibError.check_error(return_code, "ANC_moveReference")
[docs]
def get_ref_position(self, dev_handle: c_void_p, axis_no: int) -> Tuple[float, bool]:
"""Read Reference Position
Retrieves the current reference position.
For linear type actuators the position unit is meter [m]; for goniometers and rotators it is
degree [°].
Only applicable for NUM devices.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
Returns:
Tuple containing the reference position:
0. position: Current reference position in meters [m] or degrees [°].
1. valid: True, if the reference position is valid.
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_position = c_double()
c_valid = c_int32()
try:
return_code = self._dll.ANC_getRefPosition(dev_handle, c_axis_no,
byref(c_position), byref(c_valid))
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_getRefPosition") from exc
ANC350v3LibError.check_error(return_code, "ANC_getRefPosition")
# TODO: Could we only return position if valid is True and return None, if valid is False?
# Then, one return value would be enough
return c_position.value, bool(c_valid.value)
[docs]
def enable_sensor(self, dev_handle: c_void_p, enable: bool) -> None:
"""Switch Sensor Power
Switches the sensor power for all axes on or off.
Only applicable for NUM devices.
Args:
dev_handle: Handle of the device to access
enable: Enable (True) or disable (False) the sensor
Raises:
ANC350LibError is raised, if the function call fails
"""
c_enable = c_int32(int(enable))
try:
return_code = self._dll.ANC_enableSensor(dev_handle, c_enable)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_enableSensor") from exc
ANC350v3LibError.check_error(return_code, "ANC_enableSensor")
[docs]
def enable_ref_auto_update(self, dev_handle: c_void_p, axis_no: int, enable: bool) -> None:
"""Enable Reference Auto Update
Enables or disables the reference auto update for an axis. When enabled, every time the
reference marking is hit, the reference position will be updated. When disabled, the
reference marking will be considered only the first time, later hits will be ignored.
Only applicable for NUM devices.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
enable: Enable (True) or disable (False) the feature
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_enable = c_int32(int(enable))
try:
return_code = self._dll.ANC_enableRefAutoUpdate(dev_handle, c_axis_no, c_enable)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_enableRefAutoUpdate") from exc
ANC350v3LibError.check_error(return_code, "ANC_enableRefAutoUpdate")
[docs]
def enable_ref_auto_reset(self, dev_handle: c_void_p, axis_no: int, enable: bool) -> None:
"""Enable Position Auto Reset
Enables or disables the position auto reset for an axis. When enabled, every time the
reference marking is hit, the position will be set to zero. When disabled, the reference
marking will be ignored.
Only applicable for NUM devices.
Args:
dev_handle: Handle of the device to access
axis_no: Axis number (0..2)
enable: Enable (True) or disable (False) the feature
Raises:
ANC350LibError is raised, if the function call fails
"""
c_axis_no = c_uint32(axis_no)
c_enable = c_int32(int(enable))
try:
return_code = self._dll.ANC_enableRefAutoReset(dev_handle, c_axis_no, c_enable)
except Exception as exc:
raise ANC350v3LibError("Unexpected error in ANC_enableRefAutoReset") from exc
ANC350v3LibError.check_error(return_code, "ANC_enableRefAutoReset")
# TODO: Function is part of DLL, but not documented
# def enable_trace(self, dev_handle: c_void_p, ...):
# try:
# return_code = self._dll.ANC_enableTrace(dev_handle, ...)
# except Exception as exc:
# raise ANC350LibError("Unexpected error in ANC_enableTrace") from exc
# ANC350LibError.check_error(return_code, "ANC_enableTrace")