mmcb-rs232-avt 1.0.20__py3-none-any.whl → 1.1.37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mmcb_rs232_avt-1.1.37.dist-info/METADATA +210 -0
- mmcb_rs232_avt-1.1.37.dist-info/RECORD +26 -0
- {mmcb_rs232_avt-1.0.20.dist-info → mmcb_rs232_avt-1.1.37.dist-info}/WHEEL +1 -1
- mmcb_rs232_avt-1.1.37.dist-info/entry_points.txt +12 -0
- mmcb_rs232_avt-1.1.37.dist-info/top_level.txt +1 -0
- mmcbrs232/MDP.py +35 -0
- mmcbrs232/broker_and_workers.py +582 -0
- {mmcb_rs232 → mmcbrs232}/common.py +57 -35
- {mmcb_rs232 → mmcbrs232}/detect.py +459 -137
- mmcbrs232/dmm.py +220 -0
- {mmcb_rs232 → mmcbrs232}/dmm_interface.py +25 -4
- {mmcb_rs232 → mmcbrs232}/iv.py +36 -10
- {mmcb_rs232 → mmcbrs232}/lexicon.py +12 -0
- mmcbrs232/liveplot.py +335 -0
- mmcbrs232/mdbroker.py +311 -0
- mmcbrs232/mdcliapi.py +110 -0
- mmcbrs232/mdclientlib.py +266 -0
- mmcbrs232/mdwrkapi.py +183 -0
- {mmcb_rs232 → mmcbrs232}/psuset.py +96 -64
- {mmcb_rs232 → mmcbrs232}/psustat.py +197 -16
- {mmcb_rs232 → mmcbrs232}/psuwatch.py +13 -8
- {mmcb_rs232 → mmcbrs232}/sequence.py +2 -3
- {mmcb_rs232 → mmcbrs232}/ult80.py +123 -79
- mmcbrs232/zhelpers.py +58 -0
- mmcbrs232/zpsustat.py +72 -0
- mmcb_rs232/dmm.py +0 -126
- mmcb_rs232_avt-1.0.20.dist-info/METADATA +0 -62
- mmcb_rs232_avt-1.0.20.dist-info/RECORD +0 -17
- mmcb_rs232_avt-1.0.20.dist-info/entry_points.txt +0 -10
- mmcb_rs232_avt-1.0.20.dist-info/top_level.txt +0 -1
- {mmcb_rs232 → mmcbrs232}/__init__.py +0 -0
|
@@ -10,8 +10,11 @@ If this turns out not to be the case, we can read the list of available FTDI
|
|
|
10
10
|
serial port devices, then exclude any serial ports found in cache.json, then
|
|
11
11
|
leave the user to choose which of the remaining serial ports to use.
|
|
12
12
|
|
|
13
|
-
Refer to the following for RS232 command sequences:
|
|
14
|
-
https://www.atecorp.com/
|
|
13
|
+
Refer to the following for RS232 command sequences (pp.25-28):
|
|
14
|
+
https://www.atecorp.com/getmedia/038930d4-42ed-4f12-bfda-a37e08d48bac/
|
|
15
|
+
neslab-ult-80-95_manual_1.pdf
|
|
16
|
+
https://gitlab.ph.liv.ac.uk/avt/atlas-itk-pmmcb/-/blob/main/reference/
|
|
17
|
+
thermoneslab/neslab-ult-80-95_manual.pdf
|
|
15
18
|
|
|
16
19
|
Also see 'setup loop' starting on page 10 to enable RS232.
|
|
17
20
|
|
|
@@ -62,24 +65,27 @@ Stor (store changes)
|
|
|
62
65
|
"""
|
|
63
66
|
|
|
64
67
|
import argparse
|
|
65
|
-
import
|
|
68
|
+
import fcntl
|
|
69
|
+
import threading
|
|
70
|
+
import weakref
|
|
66
71
|
|
|
67
72
|
import serial
|
|
68
|
-
import serial.tools.list_ports as stlp
|
|
69
73
|
|
|
70
|
-
from
|
|
74
|
+
from mmcbrs232 import common
|
|
71
75
|
|
|
72
76
|
|
|
73
77
|
##############################################################################
|
|
74
78
|
# command line option handler
|
|
75
79
|
##############################################################################
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
|
|
82
|
+
def check_arguments(command=None):
|
|
78
83
|
"""
|
|
79
84
|
Handle command line options.
|
|
80
85
|
|
|
81
86
|
--------------------------------------------------------------------------
|
|
82
|
-
args
|
|
87
|
+
args
|
|
88
|
+
command : str
|
|
83
89
|
--------------------------------------------------------------------------
|
|
84
90
|
returns : class argparse.ArgumentParser
|
|
85
91
|
--------------------------------------------------------------------------
|
|
@@ -102,50 +108,47 @@ def check_arguments():
|
|
|
102
108
|
help='Set Setpoint (control point).',
|
|
103
109
|
default=None)
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
parser.add_argument(
|
|
112
|
+
'-q', '--quiet',
|
|
113
|
+
action='store_true',
|
|
114
|
+
help='Only output the requested raw value, and no other text.')
|
|
115
|
+
|
|
116
|
+
if command is None:
|
|
117
|
+
args = parser.parse_args()
|
|
118
|
+
else:
|
|
119
|
+
args = parser.parse_args(
|
|
120
|
+
command.strip().partition(' ')[-1].split(' ')
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
return args
|
|
106
125
|
|
|
107
126
|
|
|
108
127
|
##############################################################################
|
|
109
|
-
#
|
|
128
|
+
# data structures
|
|
110
129
|
##############################################################################
|
|
111
130
|
|
|
112
|
-
def find_ult80(port, config):
|
|
113
|
-
"""
|
|
114
|
-
Return serial port configuration if the serial port was successfully
|
|
115
|
-
opened.
|
|
116
131
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
config : dict
|
|
122
|
-
serial port configuration
|
|
123
|
-
--------------------------------------------------------------------------
|
|
124
|
-
returns
|
|
125
|
-
retval :
|
|
126
|
-
settings : dict (if port could be opened) or None otherwise
|
|
127
|
-
Note that the dictionary does not contain the serial port
|
|
128
|
-
identifier.
|
|
129
|
-
--------------------------------------------------------------------------
|
|
132
|
+
class Production:
|
|
133
|
+
"""
|
|
134
|
+
Locks to support threaded operation in the underlying library code (1 lock
|
|
135
|
+
per serial port).
|
|
130
136
|
"""
|
|
131
|
-
ser = serial.Serial()
|
|
132
|
-
ser.apply_settings(config)
|
|
133
|
-
ser.port = port
|
|
134
|
-
|
|
135
|
-
try:
|
|
136
|
-
ser.open()
|
|
137
|
-
except (OSError, serial.SerialException):
|
|
138
|
-
sys.exit(f'could not open port {port}, exiting.')
|
|
139
|
-
else:
|
|
140
|
-
settings = ser.get_settings()
|
|
141
|
-
ser.close()
|
|
142
|
-
|
|
143
|
-
return settings
|
|
144
137
|
|
|
138
|
+
def __init__(self, instrument_channels):
|
|
139
|
+
"""
|
|
140
|
+
-----------------------------------------------------------------------
|
|
141
|
+
args
|
|
142
|
+
instrument_channels : list of <class 'mmcbrs232.common.Channel'>
|
|
143
|
+
-----------------------------------------------------------------------
|
|
144
|
+
returns : none
|
|
145
|
+
-----------------------------------------------------------------------
|
|
146
|
+
"""
|
|
147
|
+
self.portaccess = {
|
|
148
|
+
port: threading.Lock()
|
|
149
|
+
for port in {channel.port for channel in instrument_channels}
|
|
150
|
+
}
|
|
145
151
|
|
|
146
|
-
##############################################################################
|
|
147
|
-
# data structures
|
|
148
|
-
##############################################################################
|
|
149
152
|
|
|
150
153
|
class Ult80:
|
|
151
154
|
"""
|
|
@@ -155,8 +158,62 @@ class Ult80:
|
|
|
155
158
|
_address = 0x0001
|
|
156
159
|
_nbits = 16
|
|
157
160
|
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
_cached_chillers = common.cache_read({'chiller'})
|
|
162
|
+
|
|
163
|
+
_channels = []
|
|
164
|
+
for port, details in _cached_chillers.items():
|
|
165
|
+
(
|
|
166
|
+
_config,
|
|
167
|
+
_device_type,
|
|
168
|
+
_serial_number,
|
|
169
|
+
_model,
|
|
170
|
+
_manufacturer,
|
|
171
|
+
_device_channels,
|
|
172
|
+
_release_delay,
|
|
173
|
+
) = details
|
|
174
|
+
|
|
175
|
+
for device_channel in _device_channels:
|
|
176
|
+
_channels.append(
|
|
177
|
+
common.Channel(
|
|
178
|
+
port,
|
|
179
|
+
_config,
|
|
180
|
+
_serial_number,
|
|
181
|
+
_model,
|
|
182
|
+
_manufacturer,
|
|
183
|
+
device_channel,
|
|
184
|
+
_device_type,
|
|
185
|
+
_release_delay,
|
|
186
|
+
None,
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
_pipeline = Production(_channels)
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
_channel = _channels[0]
|
|
194
|
+
except IndexError:
|
|
195
|
+
pass
|
|
196
|
+
|
|
197
|
+
def __init__(self):
|
|
198
|
+
try:
|
|
199
|
+
self.ser = serial.Serial(port=self._channel.port)
|
|
200
|
+
except OSError:
|
|
201
|
+
self.init_failed = True
|
|
202
|
+
else:
|
|
203
|
+
self.init_failed = False
|
|
204
|
+
self._finalizer = weakref.finalize(self, self.ser.close)
|
|
205
|
+
self.ser.apply_settings(self._channel.config)
|
|
206
|
+
self.ser.reset_input_buffer()
|
|
207
|
+
self.ser.reset_output_buffer()
|
|
208
|
+
|
|
209
|
+
def remove(self):
|
|
210
|
+
"""manual garbage collection: close serial port"""
|
|
211
|
+
self._finalizer()
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def removed(self):
|
|
215
|
+
"""check (indirectly) if the serial port has been closed"""
|
|
216
|
+
return not self._finalizer.alive
|
|
160
217
|
|
|
161
218
|
##########################################################################
|
|
162
219
|
# public functions
|
|
@@ -437,62 +494,49 @@ def main():
|
|
|
437
494
|
"""
|
|
438
495
|
args = check_arguments()
|
|
439
496
|
|
|
440
|
-
|
|
441
|
-
all_ports = {com.device for com in stlp.comports() if common.rs232_port_is_valid(com)}
|
|
442
|
-
if not all_ports:
|
|
443
|
-
sys.exit('No usable serial ports found')
|
|
444
|
-
|
|
445
|
-
# find ports already allocated to other devices
|
|
446
|
-
cache = common.cache_read()
|
|
447
|
-
|
|
448
|
-
# If a port has None in its settings field, then it was not identified by
|
|
449
|
-
# detect.py, and can therefore still be considered for use by this
|
|
450
|
-
# script.
|
|
451
|
-
identified_ports_in_cache = {k for k, v in cache.items() if v[0] is not None}
|
|
452
|
-
|
|
453
|
-
# usable ports for this script
|
|
454
|
-
available_ports = all_ports - identified_ports_in_cache
|
|
497
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
455
498
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
elif not available_ports:
|
|
459
|
-
sys.exit('No usable serial ports available')
|
|
499
|
+
# acquire the RS232 global lock
|
|
500
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
460
501
|
|
|
461
|
-
|
|
462
|
-
print(f'using port {port}')
|
|
463
|
-
config = {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1,
|
|
464
|
-
'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1,
|
|
465
|
-
'write_timeout': 1, 'inter_byte_timeout': None}
|
|
502
|
+
# --------------------------------------------------------------------
|
|
466
503
|
|
|
467
|
-
|
|
468
|
-
if settings is None:
|
|
469
|
-
sys.exit('Serial port could not be opened')
|
|
470
|
-
|
|
471
|
-
with serial.Serial(port=port) as ser:
|
|
472
|
-
ser.apply_settings(settings)
|
|
473
|
-
|
|
474
|
-
ult80 = Ult80(ser)
|
|
504
|
+
ult80 = Ult80()
|
|
475
505
|
|
|
476
506
|
if args.read_internal_temperature:
|
|
477
507
|
rval = ult80.read_internal_temperature()
|
|
478
508
|
if rval is None:
|
|
479
509
|
print('no response from device')
|
|
480
510
|
else:
|
|
481
|
-
|
|
511
|
+
if args.quiet:
|
|
512
|
+
print(rval)
|
|
513
|
+
else:
|
|
514
|
+
print(f'read_internal_temperature, returned value {rval}°C')
|
|
482
515
|
|
|
483
516
|
if args.read_setpoint:
|
|
484
517
|
rval = ult80.read_setpoint_control_point()
|
|
485
518
|
if rval is None:
|
|
486
519
|
print('no response from device')
|
|
487
520
|
else:
|
|
488
|
-
|
|
521
|
+
if args.quiet:
|
|
522
|
+
print(rval)
|
|
523
|
+
else:
|
|
524
|
+
print(f'read_setpoint_control_point, returned value {rval}°C')
|
|
489
525
|
|
|
490
526
|
if args.set_setpoint:
|
|
491
527
|
rval = ult80.set_setpoint_control_point(float(args.set_setpoint[0]))
|
|
492
528
|
if rval is None:
|
|
493
529
|
print('no response from device')
|
|
494
530
|
else:
|
|
495
|
-
|
|
531
|
+
if args.quiet:
|
|
532
|
+
print(rval)
|
|
533
|
+
else:
|
|
534
|
+
print(f'set_setpoint_control_point, returned value {rval}°C')
|
|
535
|
+
|
|
536
|
+
# --------------------------------------------------------------------
|
|
537
|
+
|
|
538
|
+
# release the RS232 global lock
|
|
539
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
496
540
|
|
|
497
541
|
|
|
498
542
|
##############################################################################
|
mmcbrs232/zhelpers.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
"""
|
|
3
|
+
Helper module for example applications. Mimics ZeroMQ Guide's zhelpers.h.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import print_function
|
|
6
|
+
|
|
7
|
+
import binascii
|
|
8
|
+
import os
|
|
9
|
+
from random import randint
|
|
10
|
+
|
|
11
|
+
import zmq
|
|
12
|
+
|
|
13
|
+
def socket_set_hwm(socket, hwm=-1):
|
|
14
|
+
"""libzmq 2/3/4 compatible sethwm"""
|
|
15
|
+
try:
|
|
16
|
+
socket.sndhwm = socket.rcvhwm = hwm
|
|
17
|
+
except AttributeError:
|
|
18
|
+
socket.hwm = hwm
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def dump(msg_or_socket):
|
|
22
|
+
"""Receives all message parts from socket, printing each frame neatly"""
|
|
23
|
+
if isinstance(msg_or_socket, zmq.Socket):
|
|
24
|
+
# it's a socket, call on current message
|
|
25
|
+
msg = msg_or_socket.recv_multipart()
|
|
26
|
+
else:
|
|
27
|
+
msg = msg_or_socket
|
|
28
|
+
print("----------------------------------------")
|
|
29
|
+
for part in msg:
|
|
30
|
+
print("[%03d]" % len(part), end=' ')
|
|
31
|
+
is_text = True
|
|
32
|
+
try:
|
|
33
|
+
print(part.decode('ascii'))
|
|
34
|
+
except UnicodeDecodeError:
|
|
35
|
+
print(r"0x%s" % (binascii.hexlify(part).decode('ascii')))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def set_id(zsocket):
|
|
39
|
+
"""Set simple random printable identity on socket"""
|
|
40
|
+
identity = u"%04x-%04x" % (randint(0, 0x10000), randint(0, 0x10000))
|
|
41
|
+
zsocket.setsockopt_string(zmq.IDENTITY, identity)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def zpipe(ctx):
|
|
45
|
+
"""build inproc pipe for talking to threads
|
|
46
|
+
|
|
47
|
+
mimic pipe used in czmq zthread_fork.
|
|
48
|
+
|
|
49
|
+
Returns a pair of PAIRs connected via inproc
|
|
50
|
+
"""
|
|
51
|
+
a = ctx.socket(zmq.PAIR)
|
|
52
|
+
b = ctx.socket(zmq.PAIR)
|
|
53
|
+
a.linger = b.linger = 0
|
|
54
|
+
a.hwm = b.hwm = 1
|
|
55
|
+
iface = "inproc://%s" % binascii.hexlify(os.urandom(8))
|
|
56
|
+
a.bind(iface)
|
|
57
|
+
b.connect(iface)
|
|
58
|
+
return a,b
|
mmcbrs232/zpsustat.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Instantaneous snapshot of a single power supply channel from a device
|
|
4
|
+
connected by a FTDI USB to RS232 adaptors. The value is obtained from the
|
|
5
|
+
ZeroMQ serial port server running on atldaq1.
|
|
6
|
+
|
|
7
|
+
E.g.
|
|
8
|
+
|
|
9
|
+
zpsustat --serial 103877 --channel 3 --sv
|
|
10
|
+
|
|
11
|
+
Use "zpsustat -h" for help
|
|
12
|
+
|
|
13
|
+
All power supplies supported by detect.py are usable by this script.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import itertools
|
|
17
|
+
import sys
|
|
18
|
+
import types
|
|
19
|
+
|
|
20
|
+
from mmcbrs232 import mdclientlib
|
|
21
|
+
from mmcbrs232.psustat import check_arguments
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
##############################################################################
|
|
25
|
+
# main
|
|
26
|
+
##############################################################################
|
|
27
|
+
|
|
28
|
+
def main():
|
|
29
|
+
"""
|
|
30
|
+
Instantaneous snapshot of a single power supply channel from a device
|
|
31
|
+
connected by a FTDI USB to RS232 adaptors. The value is obtained from the
|
|
32
|
+
ZeroMQ serial port server running on atldaq1.
|
|
33
|
+
"""
|
|
34
|
+
status = types.SimpleNamespace(success=0, unreserved_error_code=3)
|
|
35
|
+
|
|
36
|
+
settings = {
|
|
37
|
+
'alias': None,
|
|
38
|
+
'channel': None,
|
|
39
|
+
'manufacturer': None,
|
|
40
|
+
'model': None,
|
|
41
|
+
'port': None,
|
|
42
|
+
'serial': None,
|
|
43
|
+
'time': None,
|
|
44
|
+
}
|
|
45
|
+
check_arguments(settings)
|
|
46
|
+
|
|
47
|
+
# handle ./ prefix, though this should not be present when this script is packaged
|
|
48
|
+
options = sys.argv[1:]
|
|
49
|
+
if not options:
|
|
50
|
+
print('please specify options sufficient to identify a single channel')
|
|
51
|
+
return status.unreserved_error_code
|
|
52
|
+
|
|
53
|
+
command = ' '.join(itertools.chain(['psustat'], options))
|
|
54
|
+
|
|
55
|
+
mdc = mdclientlib.Rs232()
|
|
56
|
+
try:
|
|
57
|
+
response = mdc._reply_value(mdc._issue_serial_command(command))
|
|
58
|
+
except TypeError:
|
|
59
|
+
print('No response')
|
|
60
|
+
return status.unreserved_error_code
|
|
61
|
+
|
|
62
|
+
if response is None:
|
|
63
|
+
print('No response')
|
|
64
|
+
return status.unreserved_error_code
|
|
65
|
+
|
|
66
|
+
print(response)
|
|
67
|
+
return status.success
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
##############################################################################
|
|
71
|
+
if __name__ == '__main__':
|
|
72
|
+
sys.exit(main())
|
mmcb_rs232/dmm.py
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Read values from the Keithley DMM6500.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import argparse
|
|
7
|
-
import itertools
|
|
8
|
-
import sys
|
|
9
|
-
import time
|
|
10
|
-
|
|
11
|
-
from mmcb_rs232 import common
|
|
12
|
-
from mmcb_rs232 import dmm_interface
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
##############################################################################
|
|
16
|
-
# command line option handler
|
|
17
|
-
##############################################################################
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def check_arguments():
|
|
21
|
-
"""
|
|
22
|
-
handle command line options
|
|
23
|
-
|
|
24
|
-
--------------------------------------------------------------------------
|
|
25
|
-
args : none
|
|
26
|
-
--------------------------------------------------------------------------
|
|
27
|
-
returns
|
|
28
|
-
args : <class 'argparse.Namespace'>
|
|
29
|
-
--------------------------------------------------------------------------
|
|
30
|
-
"""
|
|
31
|
-
parser = argparse.ArgumentParser(
|
|
32
|
-
description='Reads voltage or current from the Keithley DMM6500.'
|
|
33
|
-
)
|
|
34
|
-
parser.add_argument(
|
|
35
|
-
'-p', '--plain',
|
|
36
|
-
action='store_true',
|
|
37
|
-
help='print the requested figure only')
|
|
38
|
-
parser.add_argument(
|
|
39
|
-
'-c', '--capacitance',
|
|
40
|
-
action='store_true',
|
|
41
|
-
help='Read capacitance (F)')
|
|
42
|
-
parser.add_argument(
|
|
43
|
-
'--currentac',
|
|
44
|
-
action='store_true',
|
|
45
|
-
help='Read AC current (A)')
|
|
46
|
-
parser.add_argument(
|
|
47
|
-
'-i', '--currentdc',
|
|
48
|
-
action='store_true',
|
|
49
|
-
help='Read DC current (A)')
|
|
50
|
-
parser.add_argument(
|
|
51
|
-
'-r', '--resistance',
|
|
52
|
-
action='store_true',
|
|
53
|
-
help='Read two-wire resistance (\u03a9)')
|
|
54
|
-
parser.add_argument(
|
|
55
|
-
'-t', '--temperature',
|
|
56
|
-
action='store_true',
|
|
57
|
-
help='Read temperature (\u00b0C)')
|
|
58
|
-
parser.add_argument(
|
|
59
|
-
'--voltageac',
|
|
60
|
-
action='store_true',
|
|
61
|
-
help='Read AC voltage (V)')
|
|
62
|
-
parser.add_argument(
|
|
63
|
-
'-v', '--voltagedc',
|
|
64
|
-
action='store_true',
|
|
65
|
-
help='Read DC voltage (V)')
|
|
66
|
-
|
|
67
|
-
args = parser.parse_args()
|
|
68
|
-
|
|
69
|
-
return args
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
##############################################################################
|
|
73
|
-
# main
|
|
74
|
-
##############################################################################
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def main():
|
|
78
|
-
""" Read values from the Keithley DMM6500 """
|
|
79
|
-
|
|
80
|
-
args = check_arguments()
|
|
81
|
-
|
|
82
|
-
dmm = dmm_interface.Dmm6500()
|
|
83
|
-
if dmm.init_failed:
|
|
84
|
-
print('could not initialise serial port')
|
|
85
|
-
return 3
|
|
86
|
-
|
|
87
|
-
configure = {
|
|
88
|
-
'capacitance': dmm.configure_read_capacitance,
|
|
89
|
-
'currentac': dmm.configure_read_ac_current,
|
|
90
|
-
'currentdc': dmm.configure_read_dc_current,
|
|
91
|
-
'resistance': dmm.configure_read_resistance,
|
|
92
|
-
'temperature': dmm.configure_read_temperature,
|
|
93
|
-
'voltagedc': dmm.configure_read_dc_voltage,
|
|
94
|
-
'voltageac': dmm.configure_read_ac_voltage,
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
# AC quantities sometimes return None on the first attempt
|
|
98
|
-
retries = 3
|
|
99
|
-
|
|
100
|
-
success = []
|
|
101
|
-
params = []
|
|
102
|
-
for function, required in vars(args).items():
|
|
103
|
-
if not required or function=='plain':
|
|
104
|
-
continue
|
|
105
|
-
|
|
106
|
-
configure[function]()
|
|
107
|
-
|
|
108
|
-
value = None
|
|
109
|
-
for _ in itertools.repeat(None, retries):
|
|
110
|
-
value = dmm.read_value()
|
|
111
|
-
if value is not None:
|
|
112
|
-
success.append(True)
|
|
113
|
-
break
|
|
114
|
-
time.sleep(0.1)
|
|
115
|
-
|
|
116
|
-
if args.plain:
|
|
117
|
-
print(value)
|
|
118
|
-
else:
|
|
119
|
-
print(f'{function}, {common.si_prefix(value)}, {value}')
|
|
120
|
-
|
|
121
|
-
return 0 if any(success) else 3
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
##############################################################################
|
|
125
|
-
if __name__ == '__main__':
|
|
126
|
-
sys.exit(main())
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: mmcb_rs232-avt
|
|
3
|
-
Version: 1.0.20
|
|
4
|
-
Summary: ATLAS ITK Pixels Multi-Module Cycling Box environmental monitoring/control (RS232)
|
|
5
|
-
Home-page: https://gitlab.ph.liv.ac.uk/avt/atlas-itk-pmmcb-rs232
|
|
6
|
-
Author: Alan Taylor
|
|
7
|
-
Author-email: avt@hep.ph.liv.ac.uk
|
|
8
|
-
Maintainer: Alan Taylor
|
|
9
|
-
Maintainer-email: avt@hep.ph.liv.ac.uk
|
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
|
11
|
-
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: Intended Audience :: Science/Research
|
|
13
|
-
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
|
-
Classifier: Environment :: Console
|
|
15
|
-
Classifier: Environment :: X11 Applications
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
27
|
-
Classifier: Natural Language :: English
|
|
28
|
-
Classifier: License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)
|
|
29
|
-
Requires-Python: >=3.6
|
|
30
|
-
Description-Content-Type: text/markdown
|
|
31
|
-
Requires-Dist: numpy
|
|
32
|
-
Requires-Dist: pandas
|
|
33
|
-
Requires-Dist: matplotlib
|
|
34
|
-
Requires-Dist: zmq
|
|
35
|
-
Requires-Dist: pyserial==3.4.*
|
|
36
|
-
Requires-Dist: tables
|
|
37
|
-
Requires-Dist: yoctopuce
|
|
38
|
-
Dynamic: author
|
|
39
|
-
Dynamic: author-email
|
|
40
|
-
Dynamic: classifier
|
|
41
|
-
Dynamic: description
|
|
42
|
-
Dynamic: description-content-type
|
|
43
|
-
Dynamic: home-page
|
|
44
|
-
Dynamic: maintainer
|
|
45
|
-
Dynamic: maintainer-email
|
|
46
|
-
Dynamic: requires-dist
|
|
47
|
-
Dynamic: requires-python
|
|
48
|
-
Dynamic: summary
|
|
49
|
-
|
|
50
|
-
# Software support for the ATLAS ITK pixels multi-module cycling box (RS232 only)
|
|
51
|
-
|
|
52
|
-
[](https://badge.fury.io/py/mmcb-rs232-avt)
|
|
53
|
-
|
|
54
|
-

|
|
55
|
-
|
|
56
|
-
*Particle Physics, University of Liverpool, UK*
|
|
57
|
-
|
|
58
|
-
----
|
|
59
|
-
|
|
60
|
-
This repository provides command line tools to monitor and control equipment in the *ATLAS ITK pixels multi-module cycling box* test setup. It is used in the test setups for a number of other projects.
|
|
61
|
-
|
|
62
|
-
This repository mirrors a subset of files contained in the original [atlas-mmcb-avt](https://gitlab.ph.liv.ac.uk/avt/atlas-itk-pmmcb/) repository, the later remains the reference. This package contains only the RS232 laboratory control command line scripts, and excludes the Raspberry Pi specific I2C environmenal monitoring parts.
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
mmcb_rs232/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
mmcb_rs232/common.py,sha256=xI3Iqh_Y0iEvLLc-9bSQSHuTKBhSrY4AAMyV-X_dfvQ,99594
|
|
3
|
-
mmcb_rs232/detect.py,sha256=NnJHsfcPl6Lk3dw1xKp3bVgIV5ug4atx-or95rKncLg,34888
|
|
4
|
-
mmcb_rs232/dmm.py,sha256=6SUkm3Nf_oGC0LgtiSE8czFGwDw1Bjg6f2O95Ed7GGM,3511
|
|
5
|
-
mmcb_rs232/dmm_interface.py,sha256=XrNVEsq6H9SXBx1RhQ_pVcR1m2CItco7vZDAe_P8Bm0,4700
|
|
6
|
-
mmcb_rs232/iv.py,sha256=Mb6nXEyczX20PMLjG1ej9OpHXa1FEmVqwP4r2V4ICgk,115342
|
|
7
|
-
mmcb_rs232/lexicon.py,sha256=x30iZ6pMZjdpdmwmZfhhX5MfMCZu4GH6gaPJyXIG_y0,24903
|
|
8
|
-
mmcb_rs232/psuset.py,sha256=7kMg7q8DWaeESEMCHbq7WEFfbTh-FMUvKdP9pBBKLLQ,37513
|
|
9
|
-
mmcb_rs232/psustat.py,sha256=5qK_51jnmT_DKeLZlerUULIUy2AJJKIkb4BlFCD7BLM,26668
|
|
10
|
-
mmcb_rs232/psuwatch.py,sha256=tI_CK6XuxFA_aoAeeDA_b9pM9Ra30B2dh5-fCK8YlAM,21662
|
|
11
|
-
mmcb_rs232/sequence.py,sha256=mZhVwqkzWVwIz7BKH3a7dUgYeUcJdzQKXIvxucsKCtk,17711
|
|
12
|
-
mmcb_rs232/ult80.py,sha256=VYVKjGSJLKgSr4F4QABGyWnpZUmTvFmybohyP5Kq9BU,17665
|
|
13
|
-
mmcb_rs232_avt-1.0.20.dist-info/METADATA,sha256=B-wM8R9dRDsKNUKY1TbfjYCU5WOSt8g_zpVMIO4HgLU,2590
|
|
14
|
-
mmcb_rs232_avt-1.0.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
15
|
-
mmcb_rs232_avt-1.0.20.dist-info/entry_points.txt,sha256=QkJcHeTjO0v5yfgbY814Lm2NedyZ81A55nYqtDz1l8s,302
|
|
16
|
-
mmcb_rs232_avt-1.0.20.dist-info/top_level.txt,sha256=R7MQdVXJyyGxoZ1lBG0-7RGElplTd0tsPKJzVjMqYVc,11
|
|
17
|
-
mmcb_rs232_avt-1.0.20.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
[console_scripts]
|
|
2
|
-
detect = mmcb_rs232.detect:main
|
|
3
|
-
dmm = mmcb_rs232.dmm:main
|
|
4
|
-
iv = mmcb_rs232.iv:main
|
|
5
|
-
liveplot = mmcb_rs232.liveplot:main
|
|
6
|
-
log2dat = mmcb_rs232.log2dat:main
|
|
7
|
-
psuset = mmcb_rs232.psuset:main
|
|
8
|
-
psustat = mmcb_rs232.psustat:main
|
|
9
|
-
psuwatch = mmcb_rs232.psuwatch:main
|
|
10
|
-
ult80 = mmcb_rs232.ult80:main
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
mmcb_rs232
|
|
File without changes
|