Skip to content

Commit

Permalink
Added KJL300 pressure gauge
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexShkarin committed Dec 22, 2021
1 parent 830d1df commit 4495e22
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 1 deletion.
24 changes: 24 additions & 0 deletions docs/.apidoc/pylablib.devices.KJL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pylablib.devices.KJL package
============================

Submodules
----------

pylablib.devices.KJL.base module
--------------------------------

.. automodule:: pylablib.devices.KJL.base
:members:
:inherited-members:
:undoc-members:
:show-inheritance:


Module contents
---------------

.. automodule:: pylablib.devices.KJL
:members:
:inherited-members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions docs/.apidoc/pylablib.devices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Subpackages
pylablib.devices.HighFinesse
pylablib.devices.IMAQ
pylablib.devices.IMAQdx
pylablib.devices.KJL
pylablib.devices.Lakeshore
pylablib.devices.LaserQuantum
pylablib.devices.Leybold
Expand Down
39 changes: 39 additions & 0 deletions docs/devices/KJL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.. _sensors_kjl:

.. note::
Basic sensors communication concepts are described on the corresponding :ref:`page <basic_sensors_basics>`

Kurt J. Lesker pressure gauges
==============================

KJL manufactures a range of pressure gauges and controllers with several different standards and communication protocols. The code has been tested with KJL300 pressure gauge using its built-in RS232 connection.

The main device classes are :class:`pylablib.devices.KJL.KJL300<.KJL.base.KJL300>`.


Software requirements
-----------------------

The devices provide a bare RS232 interface, so any appropriate USB-to-RS232 adapter should work.


Connection
-----------------------

Since the devices are identified as COM ports, they use the standard :ref:`connection method <devices_connection>`, and all you need to know is their COM-port address (e.g., ``COM5``)::

>> from pylablib.devices import KJL
>> gauge = KJL.KJL300("COM5")
>> gauge.close()


Operation
-----------------------

KJL300
~~~~~~~~~~~~~~~~~~~~~~~

The operation of this gauge is fairly straightforward, but there is a couple of points to keep in mind:

- Even standard RS232 operation requires specifying the device RS485 address. IT can be specified using ``addr`` parameter on creation. By default, the class assumes the factory default of 1, but if it is ever changed on the device, it needs to be specified correctly.
- By default, the pressure is always returned and set in Pa regardless of the display units.
1 change: 1 addition & 0 deletions docs/devices/basic_sensors_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
- :ref:`Lakeshore <sensors_lakeshore>`: temperature sensors. Tested with Lakeshore 218.
- :ref:`Pfeiffer <sensors_pfeiffer>`: pressure gauges. Tested with TPG261 and DPG202 controllers.
- :ref:`Leybold <sensors_leybold>`: pressure gauges. Tested with ITR90 gauge.
- :ref:`Kurt J. Lesker <sensors_kjl>`: pressure gauges. Tested with KJL300 gauge.
- :ref:`Thorlabs quadrature detector controller <stages_thorlabs_kinesis_quad>`. Tested with TPA101.
3 changes: 2 additions & 1 deletion docs/devices/basic_sensors_root.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ Currently supported sensors:
Ophir
Lakeshore
Pfeiffer
Leybold
Leybold
KJL
1 change: 1 addition & 0 deletions pylablib/devices/KJL/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .base import KJL300, KJLError
117 changes: 117 additions & 0 deletions pylablib/devices/KJL/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from ...core.devio import comm_backend

import collections
import re
import time



class KJLError(comm_backend.DeviceError):
"""Generic KJL device error"""
class KJLBackendError(KJLError,comm_backend.DeviceBackendError):
"""Generic KJL backend communication error"""



TKJL300DeviceInfo=collections.namedtuple("TKJL300DeviceInfo",["swver"])
class KJL300(comm_backend.ICommBackendWrapper):
"""
KJL300 series pressure gauge.
Args:
conn: serial connection parameters (usually port or a tuple containing port and baudrate)
addr: RS485 address (reqired both for RS-485 and for RS-232 communication; factory default is 1)
"""
Error=KJLError
def __init__(self, conn, addr=1):
instr=comm_backend.new_backend(conn,"serial",term_read="\r",term_write="\r",defaults={"serial":("COM1",19200)},datatype="str",reraise_error=KJLBackendError)
comm_backend.ICommBackendWrapper.__init__(self,instr)
self.addr=addr
self._add_info_variable("device_info",self.get_device_info)
self._add_status_variable("pressure",self.get_pressure,priority=5)
self._add_settings_variable("relay_setpoints",self.get_relay_setpoints,self.set_relay_setpoints,mux=((1,2),))
try:
self.query("VER")
except self.instr.Error:
self.close()
raise

def _make_msg(self, msg):
return "#{:02X}{}".format(self.addr,msg)
_reply_re=re.compile(r"^(\*|\?)(\d{2}) (.*)$")
def _parse_reply(self, msg):
m=self._reply_re.match(msg)
if m is None:
raise self.Error("can not parse the reply: {}".format(msg))
if int(m[2])!=self.addr:
raise self.Error("reply address {} does not agree with the set address {}".format(int(m[1]),self.addr))
if m[1]=="?":
raise self.Error("request raised an error: {}".format(m[3]))
return m[3]
def comm(self, msg):
"""Send a command to the device"""
fmsg=self._make_msg(msg)
freply=self.instr.ask(fmsg)
reply=self._parse_reply(freply)
if reply!="PROGM OK":
raise self.Error("unexpected command reply: '{}' (expect '{}')".format(reply,"PROGM OK"))
def query(self, msg):
fmsg=self._make_msg(msg)
freply=self.instr.ask(fmsg)
return self._parse_reply(freply)

def get_device_info(self):
"""Get device info (a tuple ``(swver)``)"""
return TKJL300DeviceInfo(self.query("VER"))

def reset(self, confirm_addr=False):
"""
Reset the controller.
If ``confirm_addr==True``, set current RS485 address again (required for resetting after some commands).
"""
if confirm_addr:
self.comm("SA{:02X}".format(self.addr))
fmsg=self._make_msg("RST")
self.instr.write(fmsg)
time.sleep(50E-3)

def _toPa(self, v):
return float(v)*133.322 # return and set values are always in Torr
def _fromPa(self, v):
return "{:0.2E}".format(v/133.322) # return and set values are always in Torr
def get_pressure(self):
"""Get current pressure in Pa"""
return self._toPa(self.query("RD"))

def get_relay_setpoints(self, relay=1):
"""
Get relay setpoints (in Pa).
`relay` is the relay index (either 1 or 2).
Return tuple ``(on, off)`` for on-below and off-above pressures (``on`` is always smaller than ``off``)
"""
q="RL" if relay==1 else "RH"
return self._toPa(self.query("{}+".format(q))),self._toPa(self.query("{}-".format(q)))
def set_relay_setpoints(self, relay=1, on=None, off=None, reset=True):
"""
Set relay setpoints (in Pa).
`relay` is the relay index (either 1 or 2). `on` and `off` are on-below and off-above pressures (``on`` is always smaller than ``off``).
If ``reset==True``, reset the device after changing the setpoints (required to take effect).
``None`` values are left unchanged.
"""
q="SL" if relay==1 else "SH"
if on is not None:
self.comm("{}+{}".format(q,self._fromPa(on)))
if off is not None:
self.comm("{}-{}".format(q,self._fromPa(off)))
if reset:
self.reset(confirm_addr=True)
return self.get_relay_setpoints()
def set_zero(self, pressure=0):
"""Set vacuum calibration point (in Pa)"""
self.comm("TZ{}".format(self._fromPa(pressure)))
def set_span(self, pressure=1E5):
"""Set atmosphere calibration point (in Pa)"""
self.comm("TS{}".format(self._fromPa(pressure)))
1 change: 1 addition & 0 deletions pylablib/thread/devices/KJL/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .base import KJL300Thread
31 changes: 31 additions & 0 deletions pylablib/thread/devices/KJL/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from ... import device_thread


class KJL300Thread(device_thread.DeviceThread):
"""
KJL300 pressure gauge device thread.
Device args:
- ``conn``: device connection (usually, COM-port address)
- ``addr``: RS485 address (reqired both for RS-485 and for RS-232 communication; factory default is 1)
Variables:
- ``pressure``: last measured pressure
"""
def connect_device(self):
with self.using_devclass("KJL.KJL300",host=self.remote) as cls:
self.device=cls(conn=self.conn,addr=self.addr)
def setup_task(self, conn, addr=1, remote=None):
self.device_reconnect_tries=5
self.conn=conn
self.addr=addr
self.remote=remote
self.add_job("update_measurements",self.update_measurements,.5)
self.add_job("update_parameters",self.update_parameters,5)
def update_measurements(self):
"""Update current measurements"""
if self.open():
self.v["pressure"]=self.device.get_pressure()
else:
self.v["pressure"]=0
self.sleep(1.)

0 comments on commit 4495e22

Please sign in to comment.