mmcb-rs232-avt 1.0.13__py3-none-any.whl → 1.0.18__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/__init__.py +0 -0
- mmcb_rs232/common.py +2605 -0
- mmcb_rs232/detect.py +1053 -0
- mmcb_rs232/dmm.py +126 -0
- mmcb_rs232/dmm_interface.py +162 -0
- mmcb_rs232/iv.py +2868 -0
- mmcb_rs232/lexicon.py +580 -0
- mmcb_rs232/psuset.py +938 -0
- mmcb_rs232/psustat.py +705 -0
- mmcb_rs232/psuwatch.py +540 -0
- mmcb_rs232/sequence.py +483 -0
- mmcb_rs232/ult80.py +500 -0
- {mmcb_rs232_avt-1.0.13.dist-info → mmcb_rs232_avt-1.0.18.dist-info}/METADATA +2 -2
- mmcb_rs232_avt-1.0.18.dist-info/RECORD +17 -0
- mmcb_rs232_avt-1.0.18.dist-info/top_level.txt +1 -0
- mmcb_rs232_avt-1.0.13.dist-info/RECORD +0 -5
- mmcb_rs232_avt-1.0.13.dist-info/top_level.txt +0 -1
- {mmcb_rs232_avt-1.0.13.dist-info → mmcb_rs232_avt-1.0.18.dist-info}/WHEEL +0 -0
- {mmcb_rs232_avt-1.0.13.dist-info → mmcb_rs232_avt-1.0.18.dist-info}/entry_points.txt +0 -0
mmcb_rs232/dmm.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
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 import common
|
|
12
|
+
from mmcb 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())
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Read values from the Keithley DMM6500.
|
|
3
|
+
|
|
4
|
+
https://docs.python.org/3.6/library/weakref.html#comparing-finalizers-with-del-methods
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import threading
|
|
8
|
+
import weakref
|
|
9
|
+
|
|
10
|
+
import serial
|
|
11
|
+
|
|
12
|
+
from mmcb import common
|
|
13
|
+
from mmcb import lexicon
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Production:
|
|
17
|
+
"""
|
|
18
|
+
Locks to support threaded operation in the underlying library code (1 lock
|
|
19
|
+
per serial port).
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, instrument_channels):
|
|
23
|
+
"""
|
|
24
|
+
-----------------------------------------------------------------------
|
|
25
|
+
args
|
|
26
|
+
instrument_channels : list of <class 'mmcb.common.Channel'>
|
|
27
|
+
-----------------------------------------------------------------------
|
|
28
|
+
returns : none
|
|
29
|
+
-----------------------------------------------------------------------
|
|
30
|
+
"""
|
|
31
|
+
self.portaccess = {
|
|
32
|
+
port: threading.Lock()
|
|
33
|
+
for port in {channel.port for channel in instrument_channels}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Dmm6500:
|
|
38
|
+
"""
|
|
39
|
+
Connection and reading from Keithley DMM 6500.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
_cached_instruments = common.cache_read({'instrument'})
|
|
43
|
+
|
|
44
|
+
_channels = []
|
|
45
|
+
for _port, _details in _cached_instruments.items():
|
|
46
|
+
(
|
|
47
|
+
_config,
|
|
48
|
+
_device_type,
|
|
49
|
+
_serial_number,
|
|
50
|
+
_model,
|
|
51
|
+
_manufacturer,
|
|
52
|
+
_device_channels,
|
|
53
|
+
_release_delay,
|
|
54
|
+
) = _details
|
|
55
|
+
|
|
56
|
+
for _device_channel in _device_channels:
|
|
57
|
+
_channels.append(
|
|
58
|
+
common.Channel(
|
|
59
|
+
_port,
|
|
60
|
+
_config,
|
|
61
|
+
_serial_number,
|
|
62
|
+
_model,
|
|
63
|
+
_manufacturer,
|
|
64
|
+
_device_channel,
|
|
65
|
+
_device_type,
|
|
66
|
+
_release_delay,
|
|
67
|
+
None,
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
_pipeline = Production(_channels)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
_channel = _channels[0]
|
|
75
|
+
except IndexError:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def __init__(self):
|
|
79
|
+
try:
|
|
80
|
+
self._ser = serial.Serial(port=self._channel.port)
|
|
81
|
+
except OSError:
|
|
82
|
+
self.init_failed = True
|
|
83
|
+
else:
|
|
84
|
+
self.init_failed = False
|
|
85
|
+
self._finalizer = weakref.finalize(self, self._ser.close)
|
|
86
|
+
self._ser.apply_settings(self._channel.config)
|
|
87
|
+
self._ser.reset_input_buffer()
|
|
88
|
+
self._ser.reset_output_buffer()
|
|
89
|
+
|
|
90
|
+
def remove(self):
|
|
91
|
+
"""manual garbage collection: close serial port"""
|
|
92
|
+
self._finalizer()
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def removed(self):
|
|
96
|
+
"""check (indirectly) if the serial port has been closed"""
|
|
97
|
+
return not self._finalizer.alive
|
|
98
|
+
|
|
99
|
+
def _send_command(self, command):
|
|
100
|
+
"""
|
|
101
|
+
Issue command to instrument.
|
|
102
|
+
|
|
103
|
+
-----------------------------------------------------------------------
|
|
104
|
+
args
|
|
105
|
+
command : string
|
|
106
|
+
-----------------------------------------------------------------------
|
|
107
|
+
returns : none
|
|
108
|
+
-----------------------------------------------------------------------
|
|
109
|
+
"""
|
|
110
|
+
common.send_command(
|
|
111
|
+
self._pipeline,
|
|
112
|
+
self._ser,
|
|
113
|
+
self._channel,
|
|
114
|
+
lexicon.instrument(self._channel.model, command),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def configure_read_capacitance(self):
|
|
118
|
+
self._send_command('configure to read capacitance')
|
|
119
|
+
|
|
120
|
+
def configure_read_ac_current(self):
|
|
121
|
+
self._send_command('configure to read ac current')
|
|
122
|
+
|
|
123
|
+
def configure_read_dc_current(self):
|
|
124
|
+
self._send_command('configure to read dc current')
|
|
125
|
+
|
|
126
|
+
def configure_read_resistance(self):
|
|
127
|
+
self._send_command('configure to read resistance')
|
|
128
|
+
|
|
129
|
+
def configure_read_temperature(self):
|
|
130
|
+
self._send_command('configure to read temperature')
|
|
131
|
+
|
|
132
|
+
def configure_read_dc_voltage(self):
|
|
133
|
+
self._send_command('configure to read dc voltage')
|
|
134
|
+
|
|
135
|
+
def configure_read_ac_voltage(self):
|
|
136
|
+
self._send_command('configure to read ac voltage')
|
|
137
|
+
|
|
138
|
+
def read_value(self):
|
|
139
|
+
"""
|
|
140
|
+
Read the value of the previously configured parameter from the
|
|
141
|
+
instrument.
|
|
142
|
+
|
|
143
|
+
-----------------------------------------------------------------------
|
|
144
|
+
args : none
|
|
145
|
+
-----------------------------------------------------------------------
|
|
146
|
+
returns
|
|
147
|
+
value : float or None
|
|
148
|
+
-----------------------------------------------------------------------
|
|
149
|
+
"""
|
|
150
|
+
response = common.atomic_send_command_read_response(
|
|
151
|
+
self._pipeline,
|
|
152
|
+
self._ser,
|
|
153
|
+
self._channel,
|
|
154
|
+
lexicon.instrument(self._channel.model, 'read value'),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
value = float(response)
|
|
159
|
+
except ValueError:
|
|
160
|
+
value = None
|
|
161
|
+
|
|
162
|
+
return value
|