Commit 15cb32bea94 by Julien Salort

Enable powersupply TTI to use USB as well as GPIB. To do that, it was necessary…

Enable powersupply TTI to use USB as well as GPIB. To do that, it was necessary to get the Interface constructor to ignore keyword parameters, because we need to specify xonxoff in the device default parameter for it to work on Serial, but the other interfaces do not require this parameter.
parent 3798ac4b67a
......@@ -12,7 +12,7 @@ __all__ = ["TtiCpx400dp"]
from fluidlab.instruments.iec60488 import IEC60488
from fluidlab.instruments.features import FloatValue, BoolValue
from fluidlab.interfaces import PhysicalInterfaceType
class TtiCpx400dpUnitValue(FloatValue):
def _convert_from_str(self, value):
......@@ -27,15 +27,52 @@ class TtiCpx400dpUnitValue(FloatValue):
class TtiCpx400dp(IEC60488):
"""Driver for the power supply TTI CPX400DP
Dual 420 watt DC Power Supply
"""
===========================================
Dual 420 watt DC Power Supply.
Default interface is GPIB, but the device can work also
with LAN, RS-232 and USB connection.
USB connection is actually a USB-Serial converter.
e.g. on linux with USB connection:
.. code-block:: python
with TtiCpx400dp('/dev/ttyACM0') as tti:
tti.onoffall.set(True)
v = tti.vdc.get(channel=1)
print(v)
On Windows or Linux with GPIB connection:
.. code-block:: python
with TtiCpx400dp('/dev/ttyACM0') as tti:
tti.onoffall.set(True)
v = tti.vdc.get(channel=1)
print(v)
"""
# the default params below are for use with Serial connection (RS-232 or USB)
# they are ignored by the GPIBInterface, VISAInterface and SocketInterface
# classes.
default_inter_params = {
"baudrate": 9600,
"bytesize": 8,
"parity": "N",
"stopbits": 1,
"timeout": 1,
"xonxoff": True,
"rtscts": False,
"dsrdtr": False,
"eol": "\r\n",
"use_readlines": False,
}
features = [
TtiCpx400dpUnitValue(
"vdc",
doc="Get actual voltage/Set voltage setpoint on specified channel",
doc="Get actual voltage/Set voltage setpoint on specified channel. Channel is 1 or 2.",
command_set="V{channel:d} {value}",
command_get="V{channel:d}O?",
channel_argument=True,
......@@ -43,7 +80,7 @@ features = [
),
TtiCpx400dpUnitValue(
"idc",
doc="Get actual current/Set current setpoint on specified channel",
doc="Get actual current/Set current setpoint on specified channel. Channel is 1 or 2.",
command_set="I{channel:d} {value}",
command_get="I{channel:d}O?",
channel_argument=True,
......@@ -51,7 +88,7 @@ features = [
),
BoolValue(
"onoff",
doc="Toogle output ON/OFF for specified channel",
doc="Toogle output ON/OFF for specified channel. Channel is 1 or 2.",
command_set="OP{channel:d} {value}",
command_get="OP{channel:d}?",
channel_argument=True,
......@@ -61,7 +98,7 @@ features = [
),
BoolValue(
"onoffall",
doc="Toogle output ON/OFF for both channels simultaneously",
doc="Toogle output ON/OFF for both channels simultaneously.",
command_set="OPALL ",
channel_argument=False,
check_instrument_value=False,
......
......@@ -103,6 +103,9 @@ def interface_classname_from_string(
elif isinstance(name, (ipaddress.IPv4Address, ipaddress.IPv6Address)):
name = str(name)
physical_interface = PhysicalInterfaceType.Ethernet
elif name.startswith('/dev/tty'):
physical_interface = PhysicalInterfaceType.Serial
classname = "SerialInterface"
else:
try:
_ = ipaddress.ip_address(name)
......@@ -190,7 +193,7 @@ class Interface:
# do the actual close (without testing self.opened)
raise NotImplementedError
def __init__(self):
def __init__(self, **kwargs):
self.opened = False
def open(self):
......
......@@ -44,7 +44,7 @@ def closest_timeout(t):
class GPIBInterface(QueryInterface):
def __init__(self, board_adress, instrument_adress, timeout=1.0):
def __init__(self, board_adress, instrument_adress, timeout=1.0, **kwargs):
super().__init__()
self.board_adress = board_adress
self.instrument_adress = instrument_adress
......
......@@ -25,7 +25,7 @@ from fluidlab.interfaces import Interface
class ModbusInterface(Interface):
def __init__(self, port, method="rtu", slave_address=1, timeout=1):
def __init__(self, port, method="rtu", slave_address=1, timeout=1, **kwargs):
self.port = port
self.method = method
self.slave_address = slave_address
......
......@@ -32,6 +32,8 @@ class SerialInterface(QueryInterface):
eol=None,
multilines=False,
autoremove_eol=False,
use_readlines=True,
**kwargs,
):
"""
if eol is not None, the serial port is wrapped into TextIOWrapper to
......@@ -57,6 +59,7 @@ class SerialInterface(QueryInterface):
self.eol = eol
self.multilines = multilines
self.autoremove_eol = autoremove_eol
self.use_readlines = use_readlines
def __str__(self):
return f'SerialInterface("{self.port:}")'
......@@ -80,7 +83,7 @@ class SerialInterface(QueryInterface):
)
self._lowlevel = self.serial_port = sp
self._close = sp.close
if self.eol is not None:
if self.eol is not None and self.use_readlines:
self.ser_io = io.TextIOWrapper(
io.BufferedRWPair(sp, sp, 1),
newline=self.eol,
......@@ -92,11 +95,15 @@ class SerialInterface(QueryInterface):
args = [a.strip() + "\n" for a in args]
# print('->', repr(args[0]))
if self.eol is not None:
return self.ser_io.write(*args)
# ensure no unicode strings sent to serial_port.write
args = [a.encode("ascii") if isinstance(a, str) else a for a in args]
return self.serial_port.write(*args)
if self.use_readlines:
return self.ser_io.write(*args)
else:
for a in args:
self.serial_port.write(a.encode('ascii') + self.eol.encode('ascii'))
else:
# ensure no unicode strings sent to serial_port.write
args = [a.encode("ascii") if isinstance(a, str) else a for a in args]
return self.serial_port.write(*args)
def readline(self, *args):
if self.eol is not None:
......@@ -121,6 +128,11 @@ class SerialInterface(QueryInterface):
return self.serial_port.readlines(*args)
def _read(self):
if not self.use_readlines:
iw = self.serial_port.inWaiting()
data = self.serial_port.read(iw).decode('ascii')
return data
if self.multilines:
result = self.readlines()
return "\n".join(result)
......
......@@ -21,7 +21,7 @@ class SocketInterface(QueryInterface):
Concrete classes are UDPSocketInterface and TCPSocketInterface
"""
def __init__(self, ip_address, autoremove_eol):
def __init__(self, ip_address, autoremove_eol, **kwargs):
super().__init__()
self.ip_address = ip_address
self.autoremove_eol = autoremove_eol
......@@ -47,7 +47,7 @@ class SocketInterface(QueryInterface):
class UDPSocketInterface(SocketInterface):
def __init__(self, ip_address, in_port, out_port, autoremove_eol=True):
def __init__(self, ip_address, in_port, out_port, autoremove_eol=True, **kwargs):
super().__init__(ip_address, autoremove_eol)
if callable(in_port):
self.in_port = in_port(ip_address)
......@@ -91,7 +91,7 @@ class UDPSocketInterface(SocketInterface):
class TCPSocketInterface(SocketInterface):
def __init__(self, ip_address, port, autoremove_eol=True):
def __init__(self, ip_address, port, autoremove_eol=True, **kwargs):
super().__init__(ip_address, autoremove_eol)
self.port = port
......
......@@ -27,7 +27,7 @@ from fluidlab.interfaces import QueryInterface
class USBTMCInterface(QueryInterface):
def __init__(self, device=0):
def __init__(self, device=0, **kwargs):
"""
Create a new USBTMCInterface.
......
......@@ -25,7 +25,7 @@ def set_default_pyvisa_backend(backend):
class VISAInterface(QueryInterface):
def __init__(self, resource_name, backend=None):
def __init__(self, resource_name, backend=None, **kwargs):
super().__init__()
self.resource_name = resource_name
if backend is None:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment