Skip to content

Commit

Permalink
Merge pull request #33 from lankes-fzj/driver/Standa_10MWA168
Browse files Browse the repository at this point in the history
Standa 10MWA168 driver
  • Loading branch information
astafan8 authored Jan 20, 2020
2 parents 7e91067 + 08178ac commit 959b1f3
Show file tree
Hide file tree
Showing 4 changed files with 336 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,6 @@
('py:class', 'SPI_rack'),
('py:class', 'unittest.case.TestCase'),
('py:class', 'builtins.AssertionError'),
('py:class', '_ctypes.Structure'),
('py:exc', 'visa.VisaIOError')
]
128 changes: 128 additions & 0 deletions docs/examples/Standa_10MWA168.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Qcodes example with Standa 10MWA168"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"ExecuteTime": {
"end_time": "2019-03-05T12:33:46.552440Z",
"start_time": "2019-03-05T12:33:46.522440Z"
}
},
"outputs": [],
"source": [
"from qcodes_contrib_drivers.drivers.Standa.Standa_10MWA168 import Standa_10MWA168"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initialize instrument"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"ExecuteTime": {
"end_time": "2019-03-05T12:34:08.039225Z",
"start_time": "2019-03-05T12:34:07.969226Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Connected to: None Standa_10MWA168 (serial:None, firmware:None) in 0.06s\n"
]
}
],
"source": [
"standa = Standa_10MWA168(\"Standa_10MWA168\", '37866131')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"hide_input": false,
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
},
"nbsphinx": {
"execute": "never"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
207 changes: 207 additions & 0 deletions qcodes_contrib_drivers/drivers/Standa/Standa_10MWA168.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
from qcodes import Instrument
import ctypes
import numpy as np
import os
import time


class DeviceInformation(ctypes.Structure):
_fields_ = [
("Manufacturer", ctypes.c_char * 5),
("ManufacturerId", ctypes.c_char * 3),
("ProductDescription", ctypes.c_char * 9),
("Major", ctypes.c_uint),
("Minor", ctypes.c_uint),
("Release", ctypes.c_uint),
]


class GetPosition(ctypes.Structure):
_fields_ = [
("Position", ctypes.c_int),
("uPosition", ctypes.c_int),
("EncPosition", ctypes.c_longlong),
]


class Status(ctypes.Structure):
_fields_ = [
("MoveSts", ctypes.c_uint),
("MvCmdSts", ctypes.c_uint),
("PWRSts", ctypes.c_uint),
("EncSts", ctypes.c_uint),
("WindSts", ctypes.c_uint),
("CurPosition", ctypes.c_int),
("uCurPosition", ctypes.c_int),
("EncPosition", ctypes.c_longlong),
("CurSpeed", ctypes.c_int),
("uCurSpeed", ctypes.c_int),
("Ipwr", ctypes.c_int),
("Upwr", ctypes.c_int),
("Iusb", ctypes.c_int),
("Uusb", ctypes.c_int),
("CurT", ctypes.c_int),
("Flags", ctypes.c_uint),
("GPIOFlags", ctypes.c_uint),
("CmdBufFreeSpace", ctypes.c_uint),
]


class libximc:
# TODO: use error check, implement wait for stop function from dll

# default dll path
_dll_path = 'C:\\Program Files\\XILab\\libximc.dll'

# success and error codes
_success_codes = {0: 'Ok'}
_error_codes = {-1: 'Error', -2: 'NotImplemented', -3: 'ValueError', -4: 'NoDevice'}

def __init__(self, dll_path=None, verbose=False):
# save attributes
self.verbose = verbose

# connect to the dll
current_path = os.getcwd()
try:
os.chdir(os.path.dirname(self._dll_path))
self.dll = ctypes.windll.LoadLibrary(dll_path or self._dll_path)
finally:
os.chdir(current_path)

# set resource type
self.dll.enumerate_devices.restype = ctypes.POINTER(DeviceInformation)

def error_check(self, code, function_name=''):
if code in self._success_codes.keys():
if self.verbose:
print("libximc: [%s]: %s" % (function_name, self._success_codes[code]))
elif code in self._error_codes.keys():
print("libximc: [%s]: %s" % (function_name, self._error_codes[code]))
raise Exception(self._error_codes[code])
else:
print("libximc: [%s]: Unknown code: %s" % (function_name, code))
raise Exception()

def command_move(self, device_id, position, u_position):
self.dll.command_move(device_id, position, u_position)

def enumerate_devices(self, probe_flags):
enumeration = self.dll.enumerate_devices(probe_flags, b"")
return enumeration

def get_device_name(self, device_enumeration, device_index):
device_name = self.dll.get_device_name(device_enumeration, device_index)
return device_name

def get_position(self, device_id, get_position):
self.dll.get_position(device_id, get_position)

def get_status(self, device_id, status):
self.dll.get_status(device_id, status)

def open_device(self, device_name):
device_id = self.dll.open_device(device_name)
return device_id


class Standa_10MWA168(Instrument):

def __init__(self, name, serial_number, dll_path=None, **kwargs):
super().__init__(name, **kwargs)

# link to dll
self.libximc = libximc(dll_path=dll_path)

# instrument constants
self.filter_wheel_1 = [-1, 0, 1, -1, 1, 2, -1, 1, 2, 3, 3, 3, 1, 2, 4, 4, 1, 2, 5, 5, 4, 1, 2, 6, 6, 6, 2, 5, 6, 6, 6]
self.filter_wheel_2 = [-1, 0, -1, 1, 1, 1, 2, 2, 2, -1, 1, 2, 3, 3, -1, 2, 4, 4, -1, 1, 3, 5, 5, -1, 1, 2, 6, 4, 4, 5, 6]
self.offset_wheel_1 = 0.
self.offset_wheel_2 = 62.
self.revolution = 200.
self.distance = self.revolution / 8.

# initialization
self.serial_number = serial_number
device_enumeration = self.libximc.enumerate_devices(0)
enumeration_name = self.libximc.get_device_name(device_enumeration, 0)
self.device_id = self.libximc.open_device(enumeration_name)

# Time to wait (in seconds) between setting up wheel 1 and 2
self.set_transmittance_sleep_time = 10.0

# add parameters
self.add_parameter('transmittance',
set_cmd=self._set_transmittance,
label='Transmittance',
val_mapping={
1: 0, 0: 1, 9.0e-1: 2, 8.0e-1: 3, 7.2e-1: 4, 4.0e-1: 5, 3.0e-1: 6, 2.7e-1: 7,
1.5e-1: 8, 1.0e-1: 9, 8.0e-2: 10, 3.0e-2: 11, 2.7e-2: 12, 1.5e-2: 13, 1.0e-2: 14,
3.0e-3: 15, 2.7e-3: 16, 1.5e-3: 17, 1.0e-3: 18, 8.0e-4: 19, 3.0e-4: 20, 2.7e-4: 21,
1.5e-4: 22, 1.0e-4: 23, 8.0e-5: 24, 3.0e-5: 25, 1.5e-5: 26, 3.0e-6: 27, 3.0e-7: 28,
3.0e-8: 29, 3.0e-9: 30})

self.add_parameter('position',
set_cmd=self._set_position,
get_cmd=self._get_position,
get_parser=float,
label='Position')

self.add_parameter('status',
get_cmd=self._get_status,
get_parser=int,
label='status')

self.connect_message()

# get methods
def _get_position(self):
position = GetPosition()
self.libximc.get_position(self.device_id, ctypes.byref(position))
return position.Position

def _get_status(self):
status = Status()
self.libximc.get_status(self.device_id, ctypes.byref(status))
return status.MoveSts

# set methods
def _set_position(self, position):
self.libximc.command_move(self.device_id, int(position), 0)

def _set_transmittance(self, transmittance_id):
# get filter to set
filter_wheel_1 = self.filter_wheel_1[transmittance_id]
filter_wheel_2 = self.filter_wheel_2[transmittance_id]

# get current position
current_position = self.position.get()

# determine new positions
position_wheel_2 = self.offset_wheel_2 + self.distance * filter_wheel_2 + \
np.ceil(current_position / self.revolution + 2) * self.revolution
position_wheel_1 = self.offset_wheel_1 + self.distance * filter_wheel_1 + \
np.ceil(current_position / self.revolution + 2) * self.revolution

if position_wheel_1 > position_wheel_2:
print('new', position_wheel_1, position_wheel_2)
position_wheel_1 -= self.revolution

# set position of the second wheel
self.position.set(np.floor(position_wheel_2))
time.sleep(self.sleep_time / 10.0) # default: 1 s
for i in range(100):
if self.status.get() == 0:
break

# wait another time
time.sleep(self.sleep_time) # default: 10 s

# set position of the first wheel
self.position.set(np.floor(position_wheel_1))
time.sleep(self.sleep_time / 10.0) # default: 1 s
for i in range(100):
if self.status.get() == 0:
break

time.sleep(self.sleep_time / 100.0) # default: 0.1 s
Empty file.

0 comments on commit 959b1f3

Please sign in to comment.