mmcb-rs232-avt 1.0.20__py3-none-any.whl → 1.1.38__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.38.dist-info/METADATA +210 -0
- mmcb_rs232_avt-1.1.38.dist-info/RECORD +26 -0
- {mmcb_rs232_avt-1.0.20.dist-info → mmcb_rs232_avt-1.1.38.dist-info}/WHEEL +1 -1
- mmcb_rs232_avt-1.1.38.dist-info/entry_points.txt +12 -0
- mmcb_rs232_avt-1.1.38.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 +40 -14
- {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
|
@@ -11,6 +11,7 @@ the return value can be used by the shell, e.g.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import argparse
|
|
14
|
+
import fcntl
|
|
14
15
|
import logging
|
|
15
16
|
import math
|
|
16
17
|
import sys
|
|
@@ -21,9 +22,9 @@ import types
|
|
|
21
22
|
import serial
|
|
22
23
|
import numpy as np
|
|
23
24
|
|
|
24
|
-
from
|
|
25
|
-
from
|
|
26
|
-
from
|
|
25
|
+
from mmcbrs232 import common
|
|
26
|
+
from mmcbrs232 import lexicon
|
|
27
|
+
from mmcbrs232 import sequence
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
##############################################################################
|
|
@@ -70,7 +71,7 @@ def check_settlingtime(val):
|
|
|
70
71
|
return val
|
|
71
72
|
|
|
72
73
|
|
|
73
|
-
def check_arguments(settings):
|
|
74
|
+
def check_arguments(settings, command=None):
|
|
74
75
|
"""
|
|
75
76
|
handle command line options
|
|
76
77
|
|
|
@@ -78,6 +79,7 @@ def check_arguments(settings):
|
|
|
78
79
|
args
|
|
79
80
|
settings : dictionary
|
|
80
81
|
contains core information about the test environment
|
|
82
|
+
command : str
|
|
81
83
|
--------------------------------------------------------------------------
|
|
82
84
|
returns : none
|
|
83
85
|
--------------------------------------------------------------------------
|
|
@@ -201,7 +203,12 @@ def check_arguments(settings):
|
|
|
201
203
|
action='store_true',
|
|
202
204
|
help='Minimal text output during normal operation')
|
|
203
205
|
|
|
204
|
-
|
|
206
|
+
if command is None:
|
|
207
|
+
args = parser.parse_args()
|
|
208
|
+
else:
|
|
209
|
+
args = parser.parse_args(
|
|
210
|
+
command.strip().partition(' ')[-1].split(' ')
|
|
211
|
+
)
|
|
205
212
|
|
|
206
213
|
settings['verbose'] = args.verbose
|
|
207
214
|
settings['quiet'] = args.quiet
|
|
@@ -364,7 +371,7 @@ def check_measured_voltage(settings, pipeline, ser, dev, set_voltage):
|
|
|
364
371
|
return success
|
|
365
372
|
|
|
366
373
|
|
|
367
|
-
def current_limit(settings, pipeline, ser, dev):
|
|
374
|
+
def current_limit(settings, pipeline, ser, dev, slow=True):
|
|
368
375
|
"""
|
|
369
376
|
Set and check current limit on Hameg HMP4040, Keithley 2614b and 2410.
|
|
370
377
|
|
|
@@ -387,6 +394,8 @@ def current_limit(settings, pipeline, ser, dev):
|
|
|
387
394
|
reference for serial port
|
|
388
395
|
dev : instance of class Channel
|
|
389
396
|
contains details of a device and its serial port
|
|
397
|
+
slow : bool
|
|
398
|
+
enable checking of set values
|
|
390
399
|
--------------------------------------------------------------------------
|
|
391
400
|
returns : none
|
|
392
401
|
--------------------------------------------------------------------------
|
|
@@ -405,6 +414,9 @@ def current_limit(settings, pipeline, ser, dev):
|
|
|
405
414
|
compliance, channel=dev.channel)
|
|
406
415
|
common.send_command(pipeline, ser, dev, command_string)
|
|
407
416
|
|
|
417
|
+
if not slow:
|
|
418
|
+
return
|
|
419
|
+
|
|
408
420
|
# read back current limit from PSU
|
|
409
421
|
command_string = lexicon.power(dev.model, 'get current limit', channel=dev.channel)
|
|
410
422
|
response = common.atomic_send_command_read_response(pipeline, ser, dev, command_string)
|
|
@@ -456,7 +468,7 @@ def hmp4040_constant_current(ser, pipeline, dev):
|
|
|
456
468
|
return retval
|
|
457
469
|
|
|
458
470
|
|
|
459
|
-
def configure_lvpsu(settings, pipeline, ser, dev):
|
|
471
|
+
def configure_lvpsu(settings, pipeline, ser, dev, slow=True):
|
|
460
472
|
"""
|
|
461
473
|
Set the power supply voltage and read back the value to confirm it has
|
|
462
474
|
been correctly set.
|
|
@@ -478,6 +490,8 @@ def configure_lvpsu(settings, pipeline, ser, dev):
|
|
|
478
490
|
reference for serial port
|
|
479
491
|
dev : instance of class Channel
|
|
480
492
|
contains details of a device and its serial port
|
|
493
|
+
slow : bool
|
|
494
|
+
enable checking of set values
|
|
481
495
|
--------------------------------------------------------------------------
|
|
482
496
|
returns
|
|
483
497
|
success : bool
|
|
@@ -500,7 +514,7 @@ def configure_lvpsu(settings, pipeline, ser, dev):
|
|
|
500
514
|
|
|
501
515
|
# set and verify current limit
|
|
502
516
|
if settings['current_limit'] is not None:
|
|
503
|
-
current_limit(settings, pipeline, ser, dev)
|
|
517
|
+
current_limit(settings, pipeline, ser, dev, slow)
|
|
504
518
|
|
|
505
519
|
# change output on/off if requested, otherwise do not change it
|
|
506
520
|
if settings['on'] is not None:
|
|
@@ -531,29 +545,34 @@ def configure_lvpsu(settings, pipeline, ser, dev):
|
|
|
531
545
|
else:
|
|
532
546
|
common.set_psu_voltage(settings, pipeline, voltage, ser, dev)
|
|
533
547
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
548
|
+
if slow:
|
|
549
|
+
# Agilent E3647A seems to require a minimum of half a second to apply
|
|
550
|
+
# the setting before any further RS232 interaction is reliable
|
|
551
|
+
time.sleep(0.5)
|
|
537
552
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
if not common.report_output_status(ser, pipeline, dev):
|
|
544
|
-
# allow a little time for the voltage to settle before reading
|
|
545
|
-
time.sleep(settings['settlingtime'])
|
|
553
|
+
# Arguably the voltage set for the channel should be read back too, so
|
|
554
|
+
# for the case where the channel output is off, some confirmation that
|
|
555
|
+
# the value has been set correctly can be given to the user.
|
|
556
|
+
#
|
|
557
|
+
# check measured voltage (can only be read back if output is on)
|
|
546
558
|
|
|
547
|
-
if
|
|
548
|
-
#
|
|
549
|
-
|
|
550
|
-
|
|
559
|
+
if not common.report_output_status(ser, pipeline, dev):
|
|
560
|
+
# allow a little time for the voltage to settle before reading
|
|
561
|
+
time.sleep(settings['settlingtime'])
|
|
562
|
+
|
|
563
|
+
if dev.manufacturer == 'hameg' and hmp4040_constant_current(ser, pipeline, dev):
|
|
564
|
+
# When configured as a constant current source, the measured
|
|
565
|
+
# voltage will not match the set voltage
|
|
566
|
+
success = True
|
|
567
|
+
else:
|
|
568
|
+
success = check_measured_voltage(settings, pipeline, ser, dev, voltage)
|
|
551
569
|
else:
|
|
552
|
-
|
|
570
|
+
message = 'with PSU output switched off, set voltage cannot be read back'
|
|
571
|
+
common.log_with_colour(logging.WARNING, message)
|
|
572
|
+
common.log_with_colour(logging.WARNING, 'assuming all is well')
|
|
573
|
+
success = True
|
|
553
574
|
else:
|
|
554
|
-
|
|
555
|
-
common.log_with_colour(logging.WARNING, message)
|
|
556
|
-
common.log_with_colour(logging.WARNING, 'assuming all is well')
|
|
575
|
+
# user elected to skip checks, assume successful outcome
|
|
557
576
|
success = True
|
|
558
577
|
|
|
559
578
|
return success
|
|
@@ -889,46 +908,59 @@ def main():
|
|
|
889
908
|
|
|
890
909
|
pipeline = Production()
|
|
891
910
|
|
|
892
|
-
|
|
893
|
-
# Check status of outputs and interlock (inhibit) on all power supplies
|
|
894
|
-
##########################################################################
|
|
911
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
895
912
|
|
|
896
|
-
|
|
913
|
+
# acquire the RS232 global lock
|
|
914
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
897
915
|
|
|
898
|
-
|
|
899
|
-
# display details of selected power supply
|
|
900
|
-
##########################################################################
|
|
916
|
+
# --------------------------------------------------------------------
|
|
901
917
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
918
|
+
######################################################################
|
|
919
|
+
# Check status of outputs and interlock (inhibit) on all power
|
|
920
|
+
# supplies
|
|
921
|
+
######################################################################
|
|
922
|
+
|
|
923
|
+
common.initial_power_supply_check(settings, pipeline, psus, channels, psuset=True)
|
|
924
|
+
|
|
925
|
+
######################################################################
|
|
926
|
+
# display details of selected power supply
|
|
927
|
+
######################################################################
|
|
928
|
+
|
|
929
|
+
try:
|
|
930
|
+
channel = channels[0]
|
|
931
|
+
except IndexError:
|
|
932
|
+
pass
|
|
933
|
+
else:
|
|
934
|
+
text = f'selected power supply: {channel.manufacturer} {channel.model}'
|
|
935
|
+
if channel.serial_number:
|
|
936
|
+
text += f' s.no. {channel.serial_number}'
|
|
937
|
+
if channel.channel:
|
|
938
|
+
text += f' channel {channel.channel}'
|
|
939
|
+
if settings['port'] is not None:
|
|
940
|
+
text += f' port {channel.port}'
|
|
941
|
+
common.log_with_colour(logging.INFO, text, quiet=settings['quiet'])
|
|
942
|
+
|
|
943
|
+
##################################################################
|
|
944
|
+
# set values on given power supply channel
|
|
945
|
+
##################################################################
|
|
946
|
+
|
|
947
|
+
setpsu = {'lvpsu': configure_lvpsu, 'hvpsu': configure_hvpsu}
|
|
948
|
+
|
|
949
|
+
with serial.Serial(port=channel.port) as ser:
|
|
950
|
+
ser.apply_settings(channel.config)
|
|
951
|
+
ser.reset_input_buffer()
|
|
952
|
+
ser.reset_output_buffer()
|
|
953
|
+
success = setpsu[channel.category](settings, pipeline, ser, channel)
|
|
954
|
+
if success:
|
|
955
|
+
common.log_with_colour(
|
|
956
|
+
logging.INFO, 'operation successful',
|
|
957
|
+
quiet=settings['quiet']
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
# --------------------------------------------------------------------
|
|
961
|
+
|
|
962
|
+
# release the RS232 global lock
|
|
963
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
932
964
|
|
|
933
965
|
return status.success if success else status.unreserved_error_code
|
|
934
966
|
|
|
@@ -9,24 +9,30 @@ All power supplies supported by detect.py are usable by this script.
|
|
|
9
9
|
import argparse
|
|
10
10
|
import collections
|
|
11
11
|
import contextlib
|
|
12
|
+
import fcntl
|
|
13
|
+
import json
|
|
14
|
+
import serial
|
|
12
15
|
import sys
|
|
13
16
|
import time
|
|
14
17
|
import threading
|
|
15
18
|
|
|
16
|
-
from
|
|
17
|
-
from
|
|
19
|
+
from mmcbrs232 import common
|
|
20
|
+
from mmcbrs232 import lexicon
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
##############################################################################
|
|
21
24
|
# command line option handler
|
|
22
25
|
##############################################################################
|
|
23
26
|
|
|
24
|
-
def check_arguments(settings):
|
|
27
|
+
def check_arguments(settings, command=None):
|
|
25
28
|
"""
|
|
26
29
|
handle command line options
|
|
27
30
|
|
|
28
31
|
--------------------------------------------------------------------------
|
|
29
|
-
args
|
|
32
|
+
args
|
|
33
|
+
settings : dictionary
|
|
34
|
+
contains core information about the test environment
|
|
35
|
+
command : str
|
|
30
36
|
--------------------------------------------------------------------------
|
|
31
37
|
returns : none
|
|
32
38
|
--------------------------------------------------------------------------
|
|
@@ -65,6 +71,14 @@ def check_arguments(settings):
|
|
|
65
71
|
not provide a serial number over RS232. A part of the serial may be\
|
|
66
72
|
supplied if it is unique amongst connected devices.',
|
|
67
73
|
default=None)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
'-z', '--zserv', action='store_true',
|
|
76
|
+
help=(
|
|
77
|
+
'ZeroMQ serial port server DEBUG option. '
|
|
78
|
+
'Enables experimental code path for certain HMP4040 read '
|
|
79
|
+
'(--sv and --mi) operations.'
|
|
80
|
+
),
|
|
81
|
+
)
|
|
68
82
|
|
|
69
83
|
group1 = parser.add_mutually_exclusive_group()
|
|
70
84
|
group1.add_argument(
|
|
@@ -86,7 +100,12 @@ def check_arguments(settings):
|
|
|
86
100
|
help='Read measured current. Only valid if the user has specified a PSU channel.',
|
|
87
101
|
)
|
|
88
102
|
|
|
89
|
-
|
|
103
|
+
if command is None:
|
|
104
|
+
args = parser.parse_args()
|
|
105
|
+
else:
|
|
106
|
+
args = parser.parse_args(
|
|
107
|
+
command.strip().partition(' ')[-1].split(' ')
|
|
108
|
+
)
|
|
90
109
|
|
|
91
110
|
if args.serial:
|
|
92
111
|
settings['serial'] = args.serial[0]
|
|
@@ -122,6 +141,7 @@ def check_arguments(settings):
|
|
|
122
141
|
settings['mv'] = args.mv
|
|
123
142
|
settings['si'] = args.si
|
|
124
143
|
settings['mi'] = args.mi
|
|
144
|
+
settings['zserv'] = args.zserv
|
|
125
145
|
|
|
126
146
|
|
|
127
147
|
##############################################################################
|
|
@@ -285,7 +305,7 @@ def simple_interlock_status(ser, pipeline, dev, tcolours):
|
|
|
285
305
|
returns : string
|
|
286
306
|
--------------------------------------------------------------------------
|
|
287
307
|
"""
|
|
288
|
-
assert dev.manufacturer not in {'agilent', 'hameg'}
|
|
308
|
+
assert dev.manufacturer not in {'agilent', 'hameg'}, \
|
|
289
309
|
'function not callable for Agilent or Hameg PSU'
|
|
290
310
|
|
|
291
311
|
status_categories = {
|
|
@@ -370,7 +390,121 @@ def simple_polarity_status(ser, pipeline, dev, tcolours):
|
|
|
370
390
|
return status_categories[polarity_positive]
|
|
371
391
|
|
|
372
392
|
|
|
373
|
-
|
|
393
|
+
###############################################################################
|
|
394
|
+
# For ZeroMQ server use only
|
|
395
|
+
###############################################################################
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def hmp4040_channel_cmp(id1, id2):
|
|
399
|
+
"""
|
|
400
|
+
Compare channel names
|
|
401
|
+
"""
|
|
402
|
+
id1 = f'{id1}'.lower()
|
|
403
|
+
id2 = f'{id2}'.lower()
|
|
404
|
+
lut = {
|
|
405
|
+
'1': ('1', 'a'),
|
|
406
|
+
'a': ('1', 'a'),
|
|
407
|
+
'2': ('2', 'b'),
|
|
408
|
+
'b': ('2', 'b'),
|
|
409
|
+
'3': ('3', 'c'),
|
|
410
|
+
'c': ('3', 'c'),
|
|
411
|
+
'4': ('4', 'd'),
|
|
412
|
+
'd': ('4', 'd'),
|
|
413
|
+
}
|
|
414
|
+
return id1 in lut[id2]
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def hmp4040_sv_fast(pipeline, channel):
|
|
418
|
+
"""
|
|
419
|
+
Read measured current from an HMP4040 PSU.
|
|
420
|
+
|
|
421
|
+
This function must only be called from the ZeroMQ serial port server,
|
|
422
|
+
which will have already performed the necessary serial port checks and
|
|
423
|
+
configuration.
|
|
424
|
+
|
|
425
|
+
Simplified version of read_psu_set_voltage().
|
|
426
|
+
|
|
427
|
+
--------------------------------------------------------------------------
|
|
428
|
+
args
|
|
429
|
+
pipeline : instance of class Production
|
|
430
|
+
contains all the queues through which the production pipeline
|
|
431
|
+
processes communicate
|
|
432
|
+
channel : instance of class Channel
|
|
433
|
+
contains details of a device and its serial port
|
|
434
|
+
--------------------------------------------------------------------------
|
|
435
|
+
returns
|
|
436
|
+
set_volt : float or None
|
|
437
|
+
--------------------------------------------------------------------------
|
|
438
|
+
"""
|
|
439
|
+
set_volt = None
|
|
440
|
+
|
|
441
|
+
with serial.Serial(port=channel.port) as ser:
|
|
442
|
+
ser.apply_settings(channel.config)
|
|
443
|
+
ser.reset_output_buffer()
|
|
444
|
+
ser.reset_input_buffer()
|
|
445
|
+
|
|
446
|
+
local_buffer = common.atomic_send_command_read_response(
|
|
447
|
+
pipeline, ser, channel,
|
|
448
|
+
lexicon.power(channel.model, 'read set voltage', channel=channel.channel)
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
with contextlib.suppress(ValueError):
|
|
452
|
+
set_volt = float(local_buffer)
|
|
453
|
+
|
|
454
|
+
return set_volt
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def hmp4040_mi_fast(pipeline, channel):
|
|
458
|
+
"""
|
|
459
|
+
Read measured current from an HMP4040 PSU.
|
|
460
|
+
|
|
461
|
+
This function must only be called from the ZeroMQ serial port server,
|
|
462
|
+
which will have already performed the necessary serial port checks and
|
|
463
|
+
configuration.
|
|
464
|
+
|
|
465
|
+
--------------------------------------------------------------------------
|
|
466
|
+
args
|
|
467
|
+
pipeline : instance of class Production
|
|
468
|
+
contains all the queues through which the production pipeline
|
|
469
|
+
processes communicate
|
|
470
|
+
channel : instance of class Channel
|
|
471
|
+
contains details of a device and its serial port
|
|
472
|
+
--------------------------------------------------------------------------
|
|
473
|
+
returns
|
|
474
|
+
mcurr : float or None
|
|
475
|
+
--------------------------------------------------------------------------
|
|
476
|
+
"""
|
|
477
|
+
with serial.Serial(port=channel.port) as ser:
|
|
478
|
+
ser.apply_settings(channel.config)
|
|
479
|
+
ser.reset_output_buffer()
|
|
480
|
+
ser.reset_input_buffer()
|
|
481
|
+
|
|
482
|
+
# ignore readings if output is off
|
|
483
|
+
output_status = common.atomic_send_command_read_response(
|
|
484
|
+
pipeline, ser, channel,
|
|
485
|
+
lexicon.power(channel.model, 'check output', channel=channel.channel)
|
|
486
|
+
)
|
|
487
|
+
if output_status == '0':
|
|
488
|
+
return None
|
|
489
|
+
|
|
490
|
+
measured_current = common.atomic_send_command_read_response(
|
|
491
|
+
pipeline, ser, channel,
|
|
492
|
+
lexicon.power(channel.model, 'read current', channel=channel.channel)
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
mcurr = None
|
|
496
|
+
try:
|
|
497
|
+
mcurr = float(measured_current)
|
|
498
|
+
except ValueError:
|
|
499
|
+
mcurr = None
|
|
500
|
+
|
|
501
|
+
return mcurr
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
###############################################################################
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def power_supply_channel_status(settings, pipeline, psus, channels, tcolours, verbose=True):
|
|
374
508
|
"""
|
|
375
509
|
Establishes RS232 communications with power supplies (as required).
|
|
376
510
|
Checks status of channel outputs and interlocks (inhibits).
|
|
@@ -390,12 +524,36 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
390
524
|
power supply channel
|
|
391
525
|
tcolours : class
|
|
392
526
|
contains ANSI colour escape sequences
|
|
527
|
+
verbose : bool
|
|
393
528
|
--------------------------------------------------------------------------
|
|
394
529
|
returns
|
|
395
530
|
channels : list
|
|
396
531
|
no explicit return, mutable type amended in place
|
|
397
532
|
--------------------------------------------------------------------------
|
|
398
533
|
"""
|
|
534
|
+
# ------------------------------------------------------------------------
|
|
535
|
+
# shortcut for HMP4040 for ZeroMQ server (DEBUG)
|
|
536
|
+
#
|
|
537
|
+
# remember that the caller needs to set the model otherwise this will not
|
|
538
|
+
# work
|
|
539
|
+
# ------------------------------------------------------------------------
|
|
540
|
+
|
|
541
|
+
if settings['zserv'] and settings['model'] == 'hmp4040' and (settings['sv'] or settings['mi']):
|
|
542
|
+
# select PSU channel
|
|
543
|
+
channel = next(
|
|
544
|
+
c for c in channels
|
|
545
|
+
if hmp4040_channel_cmp(c.channel, settings['channel'])
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
if settings['sv']:
|
|
549
|
+
value = hmp4040_sv_fast(pipeline, channel)
|
|
550
|
+
elif settings['mi']:
|
|
551
|
+
value = hmp4040_mi_fast(pipeline, channel)
|
|
552
|
+
|
|
553
|
+
return value
|
|
554
|
+
|
|
555
|
+
# ------------------------------------------------------------------------
|
|
556
|
+
|
|
399
557
|
port_used = collections.defaultdict(int)
|
|
400
558
|
|
|
401
559
|
# this function call may change the value of variable channels
|
|
@@ -403,6 +561,8 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
403
561
|
# which have been left open
|
|
404
562
|
spd = common.check_ports_accessible(psus, channels, close_after_check=False)
|
|
405
563
|
|
|
564
|
+
results = {}
|
|
565
|
+
|
|
406
566
|
for dev in channels:
|
|
407
567
|
read_values = []
|
|
408
568
|
|
|
@@ -457,7 +617,9 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
457
617
|
|
|
458
618
|
if settings['filter']:
|
|
459
619
|
if settings['sv']:
|
|
460
|
-
|
|
620
|
+
if verbose:
|
|
621
|
+
print(set_volt)
|
|
622
|
+
results['sv'] = set_volt
|
|
461
623
|
else:
|
|
462
624
|
print(f'output status: {out_stat}')
|
|
463
625
|
|
|
@@ -475,9 +637,10 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
475
637
|
if current_limit is not None:
|
|
476
638
|
if settings['filter']:
|
|
477
639
|
if settings['si']:
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
640
|
+
result = simple_current_limit(ser, pipeline, dev, eng_format=False)
|
|
641
|
+
if verbose:
|
|
642
|
+
print(result)
|
|
643
|
+
results['si'] = result
|
|
481
644
|
else:
|
|
482
645
|
print(f'current limit: {current_limit}')
|
|
483
646
|
|
|
@@ -494,9 +657,13 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
494
657
|
mvi_text = f'{common.si_prefix(mvolt)}V, {common.si_prefix(mcurr)}A'
|
|
495
658
|
else:
|
|
496
659
|
if settings['mi']:
|
|
497
|
-
|
|
660
|
+
if verbose:
|
|
661
|
+
print(mcurr)
|
|
662
|
+
results['mi'] = mcurr
|
|
498
663
|
elif settings['mv']:
|
|
499
|
-
|
|
664
|
+
if verbose:
|
|
665
|
+
print(mvolt)
|
|
666
|
+
results['mv'] = mvolt
|
|
500
667
|
|
|
501
668
|
if not settings['filter']:
|
|
502
669
|
read_values.append(f'measured: {mvi_text}')
|
|
@@ -537,6 +704,8 @@ def power_supply_channel_status(settings, pipeline, psus, channels, tcolours):
|
|
|
537
704
|
for serial_port in spd.values():
|
|
538
705
|
serial_port.close()
|
|
539
706
|
|
|
707
|
+
return next(iter(results.values())) if len(results) == 1 else json.dumps(results)
|
|
708
|
+
|
|
540
709
|
|
|
541
710
|
def read_psu_vi(pipeline, ser, dev):
|
|
542
711
|
"""
|
|
@@ -695,9 +864,21 @@ def main():
|
|
|
695
864
|
# Check status of outputs and interlock (inhibit) on all power supplies
|
|
696
865
|
##########################################################################
|
|
697
866
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
867
|
+
with open(common.RS232_LOCK_GLOBAL, 'a') as lock_file:
|
|
868
|
+
|
|
869
|
+
# acquire the RS232 global lock
|
|
870
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)
|
|
871
|
+
|
|
872
|
+
# --------------------------------------------------------------------
|
|
873
|
+
|
|
874
|
+
power_supply_channel_status(
|
|
875
|
+
settings, pipeline, psus, channels, common.ANSIColours
|
|
876
|
+
)
|
|
877
|
+
|
|
878
|
+
# --------------------------------------------------------------------
|
|
879
|
+
|
|
880
|
+
# release the RS232 global lock
|
|
881
|
+
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
|
701
882
|
|
|
702
883
|
|
|
703
884
|
##############################################################################
|
|
@@ -16,8 +16,8 @@ import time
|
|
|
16
16
|
|
|
17
17
|
import serial
|
|
18
18
|
|
|
19
|
-
from
|
|
20
|
-
from
|
|
19
|
+
from mmcbrs232 import common
|
|
20
|
+
from mmcbrs232 import lexicon
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
##############################################################################
|
|
@@ -156,6 +156,11 @@ def check_arguments(settings):
|
|
|
156
156
|
specified with either scientific (10e-12) or engineering notation\
|
|
157
157
|
(10p)',
|
|
158
158
|
type=common.check_current, default=(None, None))
|
|
159
|
+
parser.add_argument(
|
|
160
|
+
'--block_rs232', required=True, action='store_true',
|
|
161
|
+
help='Use this option to acknowledge that running this monitoring\
|
|
162
|
+
script will block RS232 access for other scripts in this suite.',
|
|
163
|
+
)
|
|
159
164
|
|
|
160
165
|
args = parser.parse_args()
|
|
161
166
|
|
|
@@ -350,9 +355,9 @@ def initial_power_supply_check(settings, pipeline, psus, channels, psuset=False)
|
|
|
350
355
|
channels.clear()
|
|
351
356
|
else:
|
|
352
357
|
message = '--debug: any connected power supplies will be ignored'
|
|
353
|
-
log_with_colour(logging.WARNING, message)
|
|
358
|
+
common.log_with_colour(logging.WARNING, message)
|
|
354
359
|
message = '--debug: IV data will generated internally'
|
|
355
|
-
log_with_colour(logging.WARNING, message)
|
|
360
|
+
common.log_with_colour(logging.WARNING, message)
|
|
356
361
|
|
|
357
362
|
|
|
358
363
|
def report_output_status(ser, pipeline, dev):
|
|
@@ -398,7 +403,7 @@ def report_output_status(ser, pipeline, dev):
|
|
|
398
403
|
|
|
399
404
|
if dev.manufacturer == 'iseg':
|
|
400
405
|
if '=ON' not in output:
|
|
401
|
-
# log_with_colour(logging.WARNING, f'{dev.ident}, output off')
|
|
406
|
+
# common.log_with_colour(logging.WARNING, f'{dev.ident}, output off')
|
|
402
407
|
fail = True
|
|
403
408
|
|
|
404
409
|
elif dev.manufacturer in {'agilent', 'hameg', 'keithley'}:
|
|
@@ -406,17 +411,17 @@ def report_output_status(ser, pipeline, dev):
|
|
|
406
411
|
outval = int(float(output))
|
|
407
412
|
except ValueError:
|
|
408
413
|
message = f'{dev.ident}, problem checking output'
|
|
409
|
-
log_with_colour(logging.ERROR, message)
|
|
414
|
+
common.log_with_colour(logging.ERROR, message)
|
|
410
415
|
fail = True
|
|
411
416
|
else:
|
|
412
417
|
if outval in {0, 1}:
|
|
413
418
|
if outval == 0:
|
|
414
419
|
# message = f'{dev.ident}, output off'
|
|
415
|
-
# log_with_colour(logging.WARNING, message)
|
|
420
|
+
# common.log_with_colour(logging.WARNING, message)
|
|
416
421
|
fail = True
|
|
417
422
|
else:
|
|
418
423
|
message = f'{dev.ident}, problem checking output'
|
|
419
|
-
log_with_colour(logging.ERROR, message)
|
|
424
|
+
common.log_with_colour(logging.ERROR, message)
|
|
420
425
|
fail = True
|
|
421
426
|
|
|
422
427
|
return fail
|
|
@@ -14,7 +14,7 @@ import operator as op
|
|
|
14
14
|
import os
|
|
15
15
|
import sys
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from mmcbrs232 import common
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
##############################################################################
|
|
@@ -329,8 +329,7 @@ def _entire_sequence(maxval, maxstep, ranges):
|
|
|
329
329
|
sys.exit()
|
|
330
330
|
|
|
331
331
|
# deliver results
|
|
332
|
-
|
|
333
|
-
yield voltage
|
|
332
|
+
yield from seqc
|
|
334
333
|
|
|
335
334
|
|
|
336
335
|
def _sequence_to_ranges(numseq):
|