-
Notifications
You must be signed in to change notification settings - Fork 0
/
keithleyDevice.py
194 lines (147 loc) · 5.85 KB
/
keithleyDevice.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import keithleyInterface
import ConfigParser
import time
import math
from threading import Thread
class keithleyDevice(keithleyInterface.keithleyInterface, Thread):
def __init__(self,name,config, hotStart=False):
Thread.__init__(self)
self.isKilled = False
self.name = name
self.config = config
self.keithley = None
self.port = self.config.get(self.name,'address')
self.ramp = float(self.config.get(self.name,'ramp'))
self.targetBias = float(self.config.get(self.name,'bias'))
self.minBias = float(self.config.get(self.name,'minBias'))
self.maxBias = float(self.config.get(self.name,'maxBias'))
self.maxStep = float(self.config.get(self.name,'maxStep'))
if self.config.has_option(self.name,'baudrate'):
baudrate = self.config.get_option(self.name,'baudrate')
else:
baudrate = 57600
self.isBusy = False
self.maxTime = 20
if hotStart:
keithleyInterface.keithleyInterface.__init__(self,
self.port,
baudrate=baudrate,
hotStart=True)
self.status = 1
self.updateVoltageCurrent()
u = self.get_bias()
print u
self.immidiateVoltage = u
self.targetBias = u
self.biasNow = u
else:
keithleyInterface.keithleyInterface.__init__(self,
self.port,
immidiateVoltage = 0,
baudrate=baudrate)
self.biasNow = 0
self.status = 0
compliance = self.config.get(self.name,'compliance')
# make sure bias is consistent
if self.maxBias < self.minBias:
raise Exception("Invalid config file (maxBias < minBias)")
if self.targetBias < self.minBias:
raise Exception("Invalid config file (bias < minBias)")
if self.targetBias > self.maxBias:
raise Exception("Invalid config file (bias > maxBias)")
# last time the actual voltage was changed
self.lastUChange = time.time()
self.currentNow = 0
self.powering_down = False
self.lastUpdate = time.time()
self.manual = False
def set_manual(self,status):
if status == False:
self.write(':SYST:REM')
target = self.getAnswerForQuery(':SOUR:VOLT?')
target = float(target)
self.set_target_bias(target)
else:
self.write(':SYST:LOCAL')
self.manual = status
def get_current(self):
return self.currentNow
def get_bias(self):
return self.biasNow
def get_target_bias(self):
return self.targetBias
def set_target_bias(self,target):
self.targetBias = target
self.lastUChange = time.time()
def get_status(self):
return self.status
def get_update_time(self):
return self.lastUpdate
def is_ramping(self):
return abs( self.biasNow - self.targetBias)> 0.1
def power_down(self):
self.set_target_bias(0)
self.powering_down = True
def run(self):
now = time.time()
while not self.isKilled:
time.sleep(.5)
if time.time()-now>1 and not self.manual:
self.updateVoltageCurrent()
self.doRamp()
self.updateVoltageCurrent()
now = time.time()
def wait_for_device(self):
now = time.time()
while time.time()-now < self.maxTime and self.isBusy:
time.sleep(.2)
def updateVoltageCurrent(self):
self.wait_for_device()
self.isBusy=True
self.status = self.getOutputStatus()
if self.status:
try:
[voltage, current,rest] = self.readIV()
self.biasNow = voltage
self.currentNow = current
self.lastUpdate = time.time()
# print 'readIV',voltage,current,self.targetBias,rest
except Exception as inst:
print 'Could not read valid iv',type(inst),inst
self.isBusy=False
pass
def doRamp(self):
# Try to update voltage (we remember the measurement from the last loop)
# (the step we can make in voltage is the ramp-speed times
# how many seconds passed since last change)
if not self.status:
return
deltaU = self.targetBias - self.biasNow
Ustep = abs(self.ramp * (time.time() - self.lastUChange))
# Limit the maximal voltage step size
if Ustep > self.maxStep:
Ustep = self.maxStep
#print 'delta U ',deltaU,Ustep
newtime = time.time()
if abs(deltaU) > 0.1:
if abs(deltaU) <= Ustep:
newBias = self.targetBias
else:
newBias = self.biasNow + math.copysign( Ustep, deltaU )
#print self.biasNow, Ustep,deltaU
self.isBusy=True
self.setVoltage(newBias)
if newBias == self.targetBias and not self.powering_down:
print '%s is done with ramping to %d'%(self.name,self.targetBias)
self.lastUChange = newtime
self.isBusy=False
if self.powering_down and abs(self.biasNow) <.1:
self.setOutput(0)
self.powering_down = False
print '%s has ramped down and turned off'%self.name
# End of ramp
if __name__ == '__main__':
config = ConfigParser.ConfigParser()
config.read('keithley.cfg')
keithley = keithleyDevice('Keithley1',config)
keithley.setOutput(1)