-
Notifications
You must be signed in to change notification settings - Fork 0
/
pa273_v1_record.py
233 lines (197 loc) · 7.83 KB
/
pa273_v1_record.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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
import sys
import time
from main import setup_parser as sp
from Fake_Serial import Fake_Serial as fake_serial
"""pa273_v1.py
Created by Amit Sandhel on 2013-05-27. With contributions by Fredrick Leber.
Note: this script requires:
1) Python 2.7
2) matplotlib
3) PySerial
"""
TIMEDELAY = 0.3 # how long (in seconds) the exp_setup function sleeps for
# SETTING UP CSV FILE
FILENAME = "SingleVoltageDatarecord.csv"
NEWLINE = "\n"
# Change COM PORT as needed, used by MySerialPort.open_port() function.
# String variable with word COM in caplocks in front is a must!
# example: "COM4", "COM2", "COM1", etc...
# Defaulted to COM4 here
defaultCOM = "COM4"
class MySerialPort():
"""Potentiostat class that reads the command file, and runs the command
file from a serial port.
"""
# Passing in the egain, igain and bias settings in "real time" to the
# class directly for easier access
def __init__(self):
'''Initializing the variables so all functions can access the
self.s port and remain open.
'''
self.s = None
# these settings are needed to initalize the class so I can work with
# the class in the gui no choice must be here
def open_port(self, port=defaultCOM, baudrate=19200, bytesize=8,
parity='N', stopbits=1, timeout=1,
xonxoff=False, rtscts=False, writeTimeout=3, dsrdtr=False,
interCharTimeout=None):
'''Open a self.s port, explicitly define all values to be sure
they are set. Notes: I set a default read and write timeout of
3 seconds to get it to respond quickly.
'''
self.s = Serial(port, baudrate, bytesize, parity, stopbits, timeout,
xonxoff, rtscts, writeTimeout, dsrdtr,
interCharTimeout)
print('A serial port has been opened using ' + port + '.\n')
def send(self, str_to_send):
"""sending commands to the serial port """
chars_sent = self.s.write(str_to_send)
return chars_sent
def receive(self, max_chars):
'''Receive string with timeout and wait for end-of-message
character or error.
'''
data_string = ""
start_time = time.time()
MAXRECEIVETIMEOUT = 0.3
while True:
b = self.s.inWaiting()
if b > 0:
new_char = self.s.read(1)
if new_char == "*":
break
elif new_char == "\r" or new_char == "\n":
# Watch for other special characters like "\r \f".
pass
elif new_char == "?":
# should we break after an error?
break
else:
data_string = data_string + new_char
if time.time() - start_time > MAXRECEIVETIMEOUT:
print "Receive function timed out."
break
time.sleep(0.01)
return data_string
def close_port(self):
'''closes the self.s port'''
self.s.close()
def get_bias(self):
'''Setting the bias potential as soon as the cell is on.
Reference: PAGE 15 BIAS[]
'''
try:
# enter bias
x = input('Enter the Potential Bias to apply (mV) between -8000 mV\
and +8000 mV: ')
if x <= 8000 and x >= -8000:
self.bias_Val = x
print ""
else:
print "Please enter a value in the proper range."
self.get_bias()
except:
print 'Enter value again.'
self.get_bias()
def apply_voltage(self):
"""Actually applies the voltage BIAS"""
self.send('BIAS %s \n' % self.bias_Val)
reply = self.receive(25)
def measure_values(self):
'''Running the potentiostat to apply potential and measure the current,
and then return the value directly to the computer. Note that each
command is ran in single order due to ease and safety of command
processing. The data is then saved into a dictionary directly, no
if loop is required to check for error. However, note that two errors
do exist. Also, note that all these commands are READ commands only; no
writing is done in this function.
'''
self.send('READE \n')
v = self.receive(25)
self.measuredBIAS = v.strip()
self.send('READI \n')
i = self.receive(25)
self.reply_current = i.strip()
self.send('Q \n')
q = self.receive(17)
self.qval = q.strip()
def record_data(self):
'''Records the data output into a csv file with the timestamp'''
myfile = open(FILENAME, 'a')
newrow = time.strftime('%H:%M:%S,')
#newrow += str(self.bias_Val) + "," # applied potential
newrow += str(self.measuredBIAS) + "," # measured potential
newrow += str(self.reply_current) + "," # CURRENT
newrow += str(self.qval) # CHARGE
newrow += NEWLINE
myfile.write(newrow)
myfile.close()
def exp_setup(self):
self.measure_values()
self.record_data()
time.sleep(TIMEDELAY)
def run(self):
'''main while loop that controls, runs and executes all other commands
running everything in this main excution function.
'''
cycles = 1
#self.get_bias()
# change from 'a' to 'w' to overwrite file if desired
myfile = open(FILENAME, "a")
myfile.write("new data," + time.strftime("%d/%m/%Y") + NEWLINE)
myfile.write("Time,Measured Voltage,Current,CurrentExp,CHARGE(Q),\
Qexp" + NEWLINE)
myfile.close()
#self.apply_voltage()
while True:
# using a loop with a try and except to cancel and exit
# exit is only done via a ctrl-c loop
try:
cycles += 1
self.exp_setup()
print "cycle", cycles
print 'Eapp: %s Current: %s Charge: %s'%(self.measuredBIAS, self.reply_current, self.qval)
except (KeyboardInterrupt, SystemExit, ValueError):
print 'Closing software have a good day'
break
"""AMIT: Keep this module here, not at the top"""
module = sys.modules[__name__]
class Main():
"""Main class which executes the entire pa273_v1 script."""
def __init__(self, parser):
args = parser.parse_args()
self.sim = args.sim # sim parameter
self.com = 'COM' + str(args.com)
# opening the MySerialPort class with built in parameters
self.myfile = MySerialPort()
def fake_serial(self):
"""Runs the Fake_Serial() Class if the simulator parameter is True."""
setattr(module, "Serial", fake_serial)
# setting com parameter with open_port() function
self.myfile.open_port(self.com)
self.myfile.run()
# Closing serial port after run
self.myfile.close_port()
def run(self):
print 'Note: To Close program press "Ctrl-C"'
if self.sim is True:
# Running fake serial port
print 'Running simulator Mode: ', self.sim
self.fake_serial() # opening serial port in simulator class only
else:
# run real serial port:
print 'Running using real serial port.'
# Import real serial class
from serial import Serial
setattr(module, "Serial", Serial)
# open serial port, specifying comport choice
self.myfile.open_port(self.com)
self.myfile.run()
self.myfile.close_port()
print 'Closing Program'
print 'Thank you and Have a Good Day'
###############################################################################
if __name__ == '__main__':
parser = sp()
b = Main(parser)
b.run()