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
mmcbrs232/dmm.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Read values from the Keithley DMM6500.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import fcntl
|
|
8
|
+
import itertools
|
|
9
|
+
import sys
|
|
10
|
+
import time
|
|
11
|
+
|
|
12
|
+
from mmcbrs232 import common
|
|
13
|
+
from mmcbrs232 import dmm_interface
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
##############################################################################
|
|
17
|
+
# command line option handler
|
|
18
|
+
##############################################################################
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def check_arguments():
|
|
22
|
+
"""
|
|
23
|
+
handle command line options
|
|
24
|
+
|
|
25
|
+
--------------------------------------------------------------------------
|
|
26
|
+
args : none
|
|
27
|
+
--------------------------------------------------------------------------
|
|
28
|
+
returns
|
|
29
|
+
args : int, <class 'argparse.Namespace'>
|
|
30
|
+
--------------------------------------------------------------------------
|
|
31
|
+
"""
|
|
32
|
+
parser = argparse.ArgumentParser(
|
|
33
|
+
description='Reads voltage or current from the Keithley DMM6500.'
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
'channel', nargs='?', metavar='channel',
|
|
38
|
+
help=(
|
|
39
|
+
'Select measurement channel. '
|
|
40
|
+
'For use with the 2001-SCAN card.'
|
|
41
|
+
),
|
|
42
|
+
choices=range(1, 11),
|
|
43
|
+
type=int, default=None)
|
|
44
|
+
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
'-p', '--plain',
|
|
47
|
+
action='store_true',
|
|
48
|
+
help='print the requested figure only (deprecated: use -q instead)')
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
'-q', '--quiet',
|
|
51
|
+
action='store_true',
|
|
52
|
+
help='print the requested figure only')
|
|
53
|
+
parser.add_argument(
|
|
54
|
+
'-c', '--capacitance',
|
|
55
|
+
action='store_true',
|
|
56
|
+
help='Read capacitance (F)')
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
'--currentac',
|
|
59
|
+
action='store_true',
|
|
60
|
+
help='Read AC current (A)')
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
'-i', '--currentdc',
|
|
63
|
+
action='store_true',
|
|
64
|
+
help='Read DC current (A)')
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
'-r', '--resistance',
|
|
67
|
+
action='store_true',
|
|
68
|
+
help='Read two-wire resistance (\u03a9)')
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
'-t', '--temperature',
|
|
71
|
+
action='store_true',
|
|
72
|
+
help='Read temperature (\u00b0C)')
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
'--voltageac',
|
|
75
|
+
action='store_true',
|
|
76
|
+
help='Read AC voltage (V)')
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
'-v', '--voltagedc',
|
|
79
|
+
action='store_true',
|
|
80
|
+
help='Read DC voltage (V)')
|
|
81
|
+
|
|
82
|
+
args = parser.parse_args()
|
|
83
|
+
|
|
84
|
+
channel = args.channel
|
|
85
|
+
del args.channel
|
|
86
|
+
|
|
87
|
+
return channel, args
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
##############################################################################
|
|
91
|
+
# serial port identification
|
|
92
|
+
##############################################################################
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def port_name():
|
|
96
|
+
"""
|
|
97
|
+
Get the port name from the cache ASSUMING that there's only one instrument
|
|
98
|
+
in the test environment.
|
|
99
|
+
|
|
100
|
+
--------------------------------------------------------------------------
|
|
101
|
+
args : none
|
|
102
|
+
--------------------------------------------------------------------------
|
|
103
|
+
returns : string or None
|
|
104
|
+
e.g. '/dev/ttyUSB0'
|
|
105
|
+
--------------------------------------------------------------------------
|
|
106
|
+
"""
|
|
107
|
+
_cached_instruments = common.cache_read({'instrument'})
|
|
108
|
+
|
|
109
|
+
_channels = []
|
|
110
|
+
for _port, _details in _cached_instruments.items():
|
|
111
|
+
(
|
|
112
|
+
_config,
|
|
113
|
+
_device_type,
|
|
114
|
+
_serial_number,
|
|
115
|
+
_model,
|
|
116
|
+
_manufacturer,
|
|
117
|
+
_device_channels,
|
|
118
|
+
_release_delay,
|
|
119
|
+
) = _details
|
|
120
|
+
|
|
121
|
+
for _device_channel in _device_channels:
|
|
122
|
+
_channels.append(
|
|
123
|
+
common.Channel(
|
|
124
|
+
_port,
|
|
125
|
+
_config,
|
|
126
|
+
_serial_number,
|
|
127
|
+
_model,
|
|
128
|
+
_manufacturer,
|
|
129
|
+
_device_channel,
|
|
130
|
+
_device_type,
|
|
131
|
+
_release_delay,
|
|
132
|
+
None,
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
_channel = _channels[0]
|
|
138
|
+
except IndexError:
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
return _channel.port
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
##############################################################################
|
|
145
|
+
# main
|
|
146
|
+
##############################################################################
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def main():
|
|
150
|
+
""" Read values from the Keithley DMM6500 """
|
|
151
|
+
|
|
152
|
+
channel, args = check_arguments()
|
|
153
|
+
|
|
154
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
155
|
+
|
|
156
|
+
# acquire the RS232 global lock
|
|
157
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
158
|
+
|
|
159
|
+
# --------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
dmm = dmm_interface.Dmm6500()
|
|
162
|
+
if dmm.init_failed:
|
|
163
|
+
print('could not initialise serial port')
|
|
164
|
+
return 3
|
|
165
|
+
|
|
166
|
+
if channel is not None:
|
|
167
|
+
# isolate all relays
|
|
168
|
+
dmm.mux_open_all_channels()
|
|
169
|
+
# enable relay for given channel
|
|
170
|
+
dmm.mux_close_channel(channel)
|
|
171
|
+
|
|
172
|
+
configure = {
|
|
173
|
+
'capacitance': dmm.configure_read_capacitance,
|
|
174
|
+
'currentac': dmm.configure_read_ac_current,
|
|
175
|
+
'currentdc': dmm.configure_read_dc_current,
|
|
176
|
+
'resistance': dmm.configure_read_resistance,
|
|
177
|
+
'temperature': dmm.configure_read_temperature,
|
|
178
|
+
'voltagedc': dmm.configure_read_dc_voltage,
|
|
179
|
+
'voltageac': dmm.configure_read_ac_voltage,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
# AC quantities sometimes return None on the first attempt
|
|
183
|
+
retries = 3
|
|
184
|
+
|
|
185
|
+
success = []
|
|
186
|
+
|
|
187
|
+
for function, required in vars(args).items():
|
|
188
|
+
if not required or function == 'plain' or function == 'quiet':
|
|
189
|
+
continue
|
|
190
|
+
|
|
191
|
+
configure[function]()
|
|
192
|
+
|
|
193
|
+
value = None
|
|
194
|
+
for _ in itertools.repeat(None, retries):
|
|
195
|
+
value = dmm.read_value()
|
|
196
|
+
if value is not None:
|
|
197
|
+
success.append(True)
|
|
198
|
+
break
|
|
199
|
+
time.sleep(0.1)
|
|
200
|
+
|
|
201
|
+
if args.plain or args.quiet:
|
|
202
|
+
print(value)
|
|
203
|
+
else:
|
|
204
|
+
print(f'{function}, {common.si_prefix(value)}, {value}')
|
|
205
|
+
|
|
206
|
+
if channel is not None:
|
|
207
|
+
# isolate relay
|
|
208
|
+
dmm.mux_open_channel(channel)
|
|
209
|
+
|
|
210
|
+
# --------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
# release the RS232 global lock
|
|
213
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
214
|
+
|
|
215
|
+
return 0 if any(success) else 3
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
##############################################################################
|
|
219
|
+
if __name__ == '__main__':
|
|
220
|
+
sys.exit(main())
|
|
@@ -9,8 +9,8 @@ import weakref
|
|
|
9
9
|
|
|
10
10
|
import serial
|
|
11
11
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
12
|
+
from mmcbrs232 import common
|
|
13
|
+
from mmcbrs232 import lexicon
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class Production:
|
|
@@ -96,7 +96,7 @@ class Dmm6500:
|
|
|
96
96
|
"""check (indirectly) if the serial port has been closed"""
|
|
97
97
|
return not self._finalizer.alive
|
|
98
98
|
|
|
99
|
-
def _send_command(self, command):
|
|
99
|
+
def _send_command(self, command, argument1=None):
|
|
100
100
|
"""
|
|
101
101
|
Issue command to instrument.
|
|
102
102
|
|
|
@@ -111,7 +111,7 @@ class Dmm6500:
|
|
|
111
111
|
self._pipeline,
|
|
112
112
|
self._ser,
|
|
113
113
|
self._channel,
|
|
114
|
-
lexicon.instrument(self._channel.model, command),
|
|
114
|
+
lexicon.instrument(self._channel.model, command, argument1),
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
def configure_read_capacitance(self):
|
|
@@ -160,3 +160,24 @@ class Dmm6500:
|
|
|
160
160
|
value = None
|
|
161
161
|
|
|
162
162
|
return value
|
|
163
|
+
|
|
164
|
+
def mux_close_channel(self, channel):
|
|
165
|
+
"""
|
|
166
|
+
Close channel (switch mux relay output to rear terminals; relay on).
|
|
167
|
+
For use with the 2001-SCAN card.
|
|
168
|
+
"""
|
|
169
|
+
self._send_command('mux_close_channel', channel)
|
|
170
|
+
|
|
171
|
+
def mux_open_channel(self, channel):
|
|
172
|
+
"""
|
|
173
|
+
Open channel (isolate relay from rear terminals).
|
|
174
|
+
For use with the 2001-SCAN card.
|
|
175
|
+
"""
|
|
176
|
+
self._send_command('mux_open_channel', channel)
|
|
177
|
+
|
|
178
|
+
def mux_open_all_channels(self):
|
|
179
|
+
"""
|
|
180
|
+
Open all channels (isolate all relays from rear terminals).
|
|
181
|
+
For use with the 2001-SCAN card.
|
|
182
|
+
"""
|
|
183
|
+
self._send_command('mux_open_all_channels')
|
{mmcb_rs232 → mmcbrs232}/iv.py
RENAMED
|
@@ -25,6 +25,7 @@ import contextlib
|
|
|
25
25
|
import csv
|
|
26
26
|
import ctypes
|
|
27
27
|
import datetime
|
|
28
|
+
import fcntl
|
|
28
29
|
import functools
|
|
29
30
|
import itertools
|
|
30
31
|
import logging
|
|
@@ -54,9 +55,9 @@ from yoctopuce import yocto_api as yapi
|
|
|
54
55
|
from yoctopuce import yocto_temperature as ytemp
|
|
55
56
|
from yoctopuce import yocto_humidity as yhumi
|
|
56
57
|
|
|
57
|
-
from
|
|
58
|
-
from
|
|
59
|
-
from
|
|
58
|
+
from mmcbrs232 import common
|
|
59
|
+
from mmcbrs232 import lexicon
|
|
60
|
+
from mmcbrs232 import sequence
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
##############################################################################
|
|
@@ -994,7 +995,7 @@ def sense(pipeline, zmq_skt, settings):
|
|
|
994
995
|
pi@raspberrypi:~/dev/1d-phantom/utilities $ sudo netstat -ltnp
|
|
995
996
|
Active Internet connections (only servers)
|
|
996
997
|
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
|
|
997
|
-
tcp 0 0 0.0.0.0:
|
|
998
|
+
tcp 0 0 0.0.0.0:5566 0.0.0.0:* LISTEN 32539/python3
|
|
998
999
|
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 776/sshd
|
|
999
1000
|
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 27597/cupsd
|
|
1000
1001
|
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 992/exim4
|
|
@@ -1030,7 +1031,7 @@ def sense(pipeline, zmq_skt, settings):
|
|
|
1030
1031
|
"""
|
|
1031
1032
|
# configure communication with sense.py
|
|
1032
1033
|
# Use REP/REQ (with handshaking) instead of PUB/SUB to avoid packet loss
|
|
1033
|
-
port =
|
|
1034
|
+
port = 5566
|
|
1034
1035
|
try:
|
|
1035
1036
|
zmq_skt.bind(f'tcp://*:{port}')
|
|
1036
1037
|
except zmq.error.ZMQError as zerr:
|
|
@@ -2775,7 +2776,19 @@ def main():
|
|
|
2775
2776
|
# Check status of outputs and interlock (inhibit) on all power supplies
|
|
2776
2777
|
##########################################################################
|
|
2777
2778
|
|
|
2778
|
-
common.
|
|
2779
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
2780
|
+
|
|
2781
|
+
# acquire the RS232 global lock
|
|
2782
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
2783
|
+
|
|
2784
|
+
# --------------------------------------------------------------------
|
|
2785
|
+
|
|
2786
|
+
common.initial_power_supply_check(settings, pipeline, psus, channels)
|
|
2787
|
+
|
|
2788
|
+
# --------------------------------------------------------------------
|
|
2789
|
+
|
|
2790
|
+
# release the RS232 global lock
|
|
2791
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
2779
2792
|
|
|
2780
2793
|
##########################################################################
|
|
2781
2794
|
# detect presence of temperature and humidity sensors
|
|
@@ -2820,10 +2833,23 @@ def main():
|
|
|
2820
2833
|
|
|
2821
2834
|
_gidfp_pf = functools.partial(get_iv_data_from_psu, settings=settings,
|
|
2822
2835
|
pipeline=pipeline, graceful_quit=graceful_quit)
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2836
|
+
|
|
2837
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
2838
|
+
|
|
2839
|
+
# acquire the RS232 global lock
|
|
2840
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
2841
|
+
|
|
2842
|
+
# --------------------------------------------------------------------
|
|
2843
|
+
|
|
2844
|
+
with cf.ThreadPoolExecutor() as executor:
|
|
2845
|
+
board_iv = (executor.submit(_gidfp_pf, channel) for channel in channels)
|
|
2846
|
+
for future in cf.as_completed(board_iv):
|
|
2847
|
+
consignment.packets.append(future.result())
|
|
2848
|
+
|
|
2849
|
+
# --------------------------------------------------------------------
|
|
2850
|
+
|
|
2851
|
+
# release the RS232 global lock
|
|
2852
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
2827
2853
|
|
|
2828
2854
|
##########################################################################
|
|
2829
2855
|
# release resources for YoctoPuce API and threads
|
|
@@ -563,6 +563,18 @@ def instrument(model, command, argument1=None, argument2=None):
|
|
|
563
563
|
'identify': '*IDN?',
|
|
564
564
|
'read value': 'print(dmm.measure.read())',
|
|
565
565
|
'reset': 'dmm.reset()',
|
|
566
|
+
|
|
567
|
+
# --------------------------------------------------------------------
|
|
568
|
+
# multiplexer 2001-SCAN expansion card
|
|
569
|
+
# --------------------------------------------------------------------
|
|
570
|
+
|
|
571
|
+
'mux_close_channel': f'channel.close("{argument1}")',
|
|
572
|
+
'mux_close_all_channels': 'channel.close("1,2,3,4,5,6,7,8,9,10")',
|
|
573
|
+
'mux_open_channel': f'channel.open("{argument1}")',
|
|
574
|
+
'mux_open_all_channels': 'channel.open("1,2,3,4,5,6,7,8,9,10")',
|
|
575
|
+
|
|
576
|
+
# this should return '[1]=0' (channel open) or '[1]=channel.IND_CLOSED'
|
|
577
|
+
'read channel getstate': f'print(channel.getstate("{argument1}"))',
|
|
566
578
|
}
|
|
567
579
|
|
|
568
580
|
instructions = {
|