-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpsup.py
104 lines (93 loc) · 3 KB
/
psup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from __future__ import division
import serial
import glob
import time
import decimal
def _str2num(num, factor=10):
"""Takes a number in the supply's format, which always has one
decimal place, and returns a decimal number reflecting it.
"""
return decimal.Decimal(num) / factor
def _num2str(s, length=3, factor=10):
"""Turns a number, which may be a decimal, integer, or float,
and turns it into a supply-formatted string.
"""
dec = decimal.Decimal(s)
return ('%0' + str(length) + 'i') % int(dec * factor)
def _numfields(s, fields, factor=10):
"""Generates numbers of the given lengths in the string.
"""
pos = 0
for field in fields:
yield _str2num(s[pos:pos+field], factor)
pos += field
class Supply(object):
def __init__(self, ident=None):
if not ident:
# Discover a device.
devices = glob.glob('/dev/tty.PL*') # Mac OS X
devices += glob.glob('/dev/ttyUSB*') # Linux
ident = devices[0]
self.ser = serial.Serial(ident, 9600, 8, 'N', 1)
def command(self, code, param='', address='00'):
# Put this communication in an isolated little transaction.
self.ser.flushInput()
self.ser.flushOutput()
self.ser.write(code + address + param + "\r")
self.ser.flush()
out = None
while True:
# Read until CR.
resp = ''
while True:
char = self.ser.read()
resp += char
if char == '\r':
break
if resp == 'OK\r':
return out
if out is not None:
print 'received more than one line of output without OK!'
return resp
out = resp
def start(self):
self.command('SESS')
def close(self):
self.command('ENDS')
def voltage(self, volts):
self.command('VOLT', _num2str(volts))
def reading(self):
resp = self.command('GETD')
volts, amps = _numfields(resp, (4, 4), 1)
return volts/100, amps/1000
def maxima(self):
resp = self.command('GMAX')
return tuple(_numfields(resp, (3, 3)))
def settings(self):
resp = self.command('GETS')
return tuple(_numfields(resp, (3, 3)))
def enable(self):
"""Enable output."""
self.command('SOUT', '0')
def disable(self):
"""Disable output."""
self.command('SOUT', '1')
# Context manager.
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
# Just some tests to show it's working.
if __name__ == '__main__':
with Supply() as sup:
time.sleep(0.5)
sup.voltage(1.3)
sup.enable()
time.sleep(0.5)
print 'Reading', sup.reading()
print 'Maxima', sup.maxima()
print 'Settings', sup.settings()
sup.disable()
print 'Disabled; reading', sup.reading()
time.sleep(0.5)