pvblocks 0.1.1__tar.gz → 0.1.2__tar.gz
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.
Potentially problematic release.
This version of pvblocks might be problematic. Click here for more details.
- {pvblocks-0.1.1 → pvblocks-0.1.2}/PKG-INFO +1 -1
- {pvblocks-0.1.1 → pvblocks-0.1.2}/pyproject.toml +1 -1
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks/__init__.py +1 -1
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks/pvblocks_system.py +2 -4
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks.egg-info/PKG-INFO +1 -1
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks.egg-info/SOURCES.txt +2 -1
- {pvblocks-0.1.1 → pvblocks-0.1.2}/tests/test.py +14 -1
- pvblocks-0.1.2/tests/testui.py +395 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/LICENSE +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/README.md +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/setup.cfg +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks/__main__.py +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks/constants.py +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks/exceptions.py +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks.egg-info/dependency_links.txt +0 -0
- {pvblocks-0.1.1 → pvblocks-0.1.2}/src/pvblocks.egg-info/top_level.txt +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
VERSION = '0.1.
|
|
1
|
+
VERSION = '0.1.2'
|
|
2
2
|
__version__ = VERSION
|
|
@@ -183,7 +183,7 @@ class IvMpp(PvBlock):
|
|
|
183
183
|
voltage = 0.0;
|
|
184
184
|
self.open()
|
|
185
185
|
bytes = list(((int)(1000 * voltage)).to_bytes(4, "little"))
|
|
186
|
-
self.uart.write(serial.to_bytes([2, constants.
|
|
186
|
+
self.uart.write(serial.to_bytes([2, constants.VOLTAGE_COMMAND, bytes[0], bytes[1], bytes[2], bytes[3]]))
|
|
187
187
|
sleep(0.5)
|
|
188
188
|
self.close()
|
|
189
189
|
|
|
@@ -191,7 +191,7 @@ class IvMpp(PvBlock):
|
|
|
191
191
|
self.open()
|
|
192
192
|
bytes = list(((int)(1000 * voltage)).to_bytes(4, "little"))
|
|
193
193
|
self.uart.write(
|
|
194
|
-
serial.to_bytes([2, constants.
|
|
194
|
+
serial.to_bytes([2, constants.VOLTAGE_COMMAND, bytes[0], bytes[1], bytes[2], bytes[3]]))
|
|
195
195
|
sleep(0.5)
|
|
196
196
|
self.close()
|
|
197
197
|
|
|
@@ -217,7 +217,6 @@ class IvMpp(PvBlock):
|
|
|
217
217
|
status = self.read_statusbyte()
|
|
218
218
|
|
|
219
219
|
self.close()
|
|
220
|
-
|
|
221
220
|
points_measured = status.statusbytes[0]
|
|
222
221
|
curve = self.transfer_curve(points_measured)
|
|
223
222
|
|
|
@@ -239,7 +238,6 @@ class IvMpp(PvBlock):
|
|
|
239
238
|
voltages = []
|
|
240
239
|
currents = []
|
|
241
240
|
|
|
242
|
-
print(availablebytes)
|
|
243
241
|
for i in range(1, int((availablebytes - 1)/8)):
|
|
244
242
|
index = (i * 8) + 1
|
|
245
243
|
voltages.append(int.from_bytes(bts[index:(index+4)], "little") / 10000.0)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from pvblocks import pvblocks_system
|
|
2
2
|
from time import sleep
|
|
3
|
+
from pvlib.ivtools.utils import rectify_iv_curve
|
|
4
|
+
import numpy as np
|
|
3
5
|
|
|
4
6
|
print("PV-Blocks version: " + pvblocks_system.show_version())
|
|
5
7
|
|
|
6
8
|
pvblocks = pvblocks_system.PvBlocks('COM16')
|
|
7
|
-
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
8
10
|
|
|
9
11
|
if pvblocks.init_system():
|
|
10
12
|
print("init ok")
|
|
@@ -38,5 +40,16 @@ if len(pvblocks.IvMppBlocks) > 0:
|
|
|
38
40
|
ivpoint = iv_mpp.read_ivpoint()
|
|
39
41
|
print(ivpoint)
|
|
40
42
|
curve = iv_mpp.measure_ivcurve(100, 20, 0)
|
|
43
|
+
(v, i) = rectify_iv_curve(curve['voltages'], curve['currents'])
|
|
44
|
+
p = v * i
|
|
45
|
+
voc = v[-1]
|
|
46
|
+
isc = i[0]
|
|
47
|
+
index_max = np.argmax(p)
|
|
48
|
+
impp = i[index_max]
|
|
49
|
+
vmpp = v[index_max]
|
|
50
|
+
pmax = p[index_max]
|
|
51
|
+
ff = pmax/(voc * isc)
|
|
52
|
+
pmax = p[index_max]
|
|
53
|
+
|
|
41
54
|
|
|
42
55
|
pvblocks.close_system()
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import pathlib
|
|
3
|
+
import ttkbootstrap as ttk
|
|
4
|
+
from ttkbootstrap.constants import *
|
|
5
|
+
from ttkbootstrap import utility
|
|
6
|
+
from matplotlib.figure import Figure
|
|
7
|
+
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
|
|
8
|
+
import serial.tools.list_ports
|
|
9
|
+
import pickle
|
|
10
|
+
import os
|
|
11
|
+
from pvblocks import pvblocks_system
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MainApp(ttk.Frame):
|
|
15
|
+
|
|
16
|
+
def __init__(self, master):
|
|
17
|
+
super().__init__(master, padding=15)
|
|
18
|
+
self.pack(fill=BOTH, expand=YES)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
self.master = master
|
|
22
|
+
|
|
23
|
+
self.online = False
|
|
24
|
+
self.is_active = False
|
|
25
|
+
self.voltages = []
|
|
26
|
+
self.currents = []
|
|
27
|
+
self.pvblocks = None
|
|
28
|
+
self.iv_mpp = None
|
|
29
|
+
self.load_settings()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
self.fig = Figure((6, 4), dpi=100)
|
|
34
|
+
# application variables
|
|
35
|
+
self.points_var = ttk.StringVar(value=self.settings['points'])
|
|
36
|
+
self.delay_var = ttk.StringVar(value=self.settings['delay_ms'])
|
|
37
|
+
self.mode_var = ttk.StringVar(value='voc')
|
|
38
|
+
self.sweepstyle_var = ttk.StringVar(value=self.settings['sweepstyle'])
|
|
39
|
+
self.ivpoint_var = ttk.StringVar(value='(,)')
|
|
40
|
+
|
|
41
|
+
self.isc_var = ttk.StringVar(value='0.000')
|
|
42
|
+
self.voc_var = ttk.StringVar(value='0.000')
|
|
43
|
+
self.impp_var = ttk.StringVar(value='0.000')
|
|
44
|
+
self.vmpp_var = ttk.StringVar(value='0.000')
|
|
45
|
+
self.ff_var = ttk.StringVar(value='0.000')
|
|
46
|
+
self.power_var = ttk.StringVar(value='0.000')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
self.create_menu()
|
|
50
|
+
# header and labelframe option container
|
|
51
|
+
option_text = "IV/MPP Load control"
|
|
52
|
+
self.option_lf = ttk.Labelframe(self, text=option_text, padding=15)
|
|
53
|
+
self.option_lf.pack(fill=X, expand=YES, anchor=N)
|
|
54
|
+
|
|
55
|
+
data_text = "Measurement"
|
|
56
|
+
self.data_lf = ttk.Labelframe(self, text=data_text, padding=15)
|
|
57
|
+
self.data_lf.pack(fill=X, expand=YES, anchor=N)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
self.create_mode_row()
|
|
61
|
+
self.create_curveinput_row()
|
|
62
|
+
self.create_ivpoint_row()
|
|
63
|
+
|
|
64
|
+
self.create_graph()
|
|
65
|
+
self.create_parameters_table('Isc:', self.isc_var)
|
|
66
|
+
self.create_parameters_table('Voc:', self.voc_var)
|
|
67
|
+
self.create_parameters_table('Impp:', self.impp_var)
|
|
68
|
+
self.create_parameters_table('Vmpp:', self.vmpp_var)
|
|
69
|
+
self.create_parameters_table('Power:', self.power_var)
|
|
70
|
+
self.create_parameters_table('FF:', self.ff_var)
|
|
71
|
+
self.create_save_button()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
self.draw_empty_figure()
|
|
75
|
+
self.update_controls()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def create_menu(self):
|
|
81
|
+
self.menu = ttk.Menu(self.master)
|
|
82
|
+
self.master.config(menu=self.menu)
|
|
83
|
+
self.connect_menu = ttk.Menu(self.menu)
|
|
84
|
+
self.menu.add_cascade(label='File', menu=self.connect_menu)
|
|
85
|
+
self.connect_menu.add_command(label='Connect...', command=self.connect)
|
|
86
|
+
self.connect_menu.add_command(label='Disconnect...', command=self.disconnect, state='disabled')
|
|
87
|
+
self.connect_menu.add_separator()
|
|
88
|
+
self.connect_menu.add_command(label='Exit', command=self.exit_app)
|
|
89
|
+
self.configmenu = ttk.Menu(self.menu)
|
|
90
|
+
self.menu.add_cascade(label='Configure', menu=self.configmenu)
|
|
91
|
+
self.configmenu.add_command(label='Select serialport', command=self.open_comport_window)
|
|
92
|
+
self.helpmenu = ttk.Menu(self.menu)
|
|
93
|
+
self.menu.add_cascade(label='Help', menu=self.helpmenu)
|
|
94
|
+
self.helpmenu.add_command(label='About')
|
|
95
|
+
|
|
96
|
+
def create_parameters_table(self, caption, variable):
|
|
97
|
+
isc_row = ttk.Frame(self.data_lf)
|
|
98
|
+
isc_row.pack(side=TOP, expand=YES, pady=1)
|
|
99
|
+
lbl = ttk.Label(master=isc_row, text=caption, width=10)
|
|
100
|
+
lbl.pack(side=LEFT, padx=5)
|
|
101
|
+
isc_ent = ttk.Entry(master=isc_row, textvariable=variable)
|
|
102
|
+
isc_ent.pack(side=LEFT, padx=5, fill=X, expand=YES)
|
|
103
|
+
|
|
104
|
+
def create_save_button(self):
|
|
105
|
+
isc_row = ttk.Frame(self.data_lf)
|
|
106
|
+
isc_row.pack(side=TOP, fill=X, pady=1)
|
|
107
|
+
self.save_btn = ttk.Button(
|
|
108
|
+
master=isc_row,
|
|
109
|
+
text="Save data",
|
|
110
|
+
command=self.save_data
|
|
111
|
+
)
|
|
112
|
+
self.save_btn.pack(side=TOP, fill=X, padx=5)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def create_ivpoint_row(self):
|
|
117
|
+
"""Add path row to labelframe"""
|
|
118
|
+
ivpoint_row = ttk.Frame(self.option_lf)
|
|
119
|
+
ivpoint_row.pack(fill=X, expand=YES)
|
|
120
|
+
ivpoint_lbl = ttk.Label(ivpoint_row, text="IV-Point", width=8)
|
|
121
|
+
ivpoint_lbl.pack(side=LEFT, padx=(15, 0))
|
|
122
|
+
ivpoint_ent = ttk.Entry(ivpoint_row, textvariable=self.ivpoint_var)
|
|
123
|
+
ivpoint_ent.pack(side=LEFT, fill=X, expand=YES, padx=5)
|
|
124
|
+
self.measure_ivpoint_btn = ttk.Button(
|
|
125
|
+
master=ivpoint_row,
|
|
126
|
+
text="Measure point",
|
|
127
|
+
command = self.measure_ivpoint,
|
|
128
|
+
width=18
|
|
129
|
+
)
|
|
130
|
+
self.measure_ivpoint_btn.pack(side=LEFT, padx=5)
|
|
131
|
+
|
|
132
|
+
def create_curveinput_row(self):
|
|
133
|
+
"""Add term row to labelframe"""
|
|
134
|
+
term_row = ttk.Frame(self.option_lf)
|
|
135
|
+
term_row.pack(fill=X, expand=YES, pady=15)
|
|
136
|
+
points_lbl = ttk.Label(term_row, text="Points", width=8)
|
|
137
|
+
points_lbl.pack(side=LEFT, padx=(15, 0))
|
|
138
|
+
points_ent = ttk.Entry(term_row, textvariable=self.points_var)
|
|
139
|
+
points_ent.pack(side=LEFT, fill=X, expand=YES, padx=5)
|
|
140
|
+
delay_lbl = ttk.Label(term_row, text="Delay [ms]", width=8)
|
|
141
|
+
delay_lbl.pack(side=LEFT, padx=(15, 0))
|
|
142
|
+
delay_ent = ttk.Entry(term_row, textvariable=self.delay_var)
|
|
143
|
+
delay_ent.pack(side=LEFT, fill=X, expand=YES, padx=5)
|
|
144
|
+
|
|
145
|
+
sweepstyle_ent = ttk.Combobox(term_row, state="readonly", textvariable=self.sweepstyle_var,
|
|
146
|
+
values=("Isc to Voc", "Voc to Isc", "Isc to Voc to Isc", "Voc to Isc to Voc"))
|
|
147
|
+
sweepstyle_ent.pack(side=LEFT, fill=X, expand=YES)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
self.measureCurveBtn = ttk.Button(
|
|
152
|
+
master=term_row,
|
|
153
|
+
text="Measure Curve",
|
|
154
|
+
command = self.system_measure_curve,
|
|
155
|
+
width=18
|
|
156
|
+
)
|
|
157
|
+
self.measureCurveBtn.pack(side=LEFT, padx=5)
|
|
158
|
+
|
|
159
|
+
def create_mode_row(self):
|
|
160
|
+
"""Add type row to labelframe"""
|
|
161
|
+
type_row = ttk.Frame(self.option_lf)
|
|
162
|
+
type_row.pack(fill=X, expand=YES, pady=15)
|
|
163
|
+
type_lbl = ttk.Label(type_row, text="Mode", width=8)
|
|
164
|
+
type_lbl.pack(side=LEFT, padx=(15, 0))
|
|
165
|
+
|
|
166
|
+
voc_opt = ttk.Radiobutton(
|
|
167
|
+
master=type_row,
|
|
168
|
+
text="Voc mode",
|
|
169
|
+
variable=self.mode_var,
|
|
170
|
+
value="voc"
|
|
171
|
+
)
|
|
172
|
+
voc_opt.pack(side=LEFT)
|
|
173
|
+
|
|
174
|
+
isc_opt = ttk.Radiobutton(
|
|
175
|
+
master=type_row,
|
|
176
|
+
text="Isc mode",
|
|
177
|
+
variable=self.mode_var,
|
|
178
|
+
value="isc"
|
|
179
|
+
)
|
|
180
|
+
isc_opt.pack(side=LEFT, padx = 5)
|
|
181
|
+
voc_opt.invoke()
|
|
182
|
+
|
|
183
|
+
self.apply_btn = ttk.Button(
|
|
184
|
+
master=type_row,
|
|
185
|
+
text="Apply",
|
|
186
|
+
command=self.on_apply,
|
|
187
|
+
width=8
|
|
188
|
+
)
|
|
189
|
+
self.apply_btn.pack(side=LEFT, padx=5)
|
|
190
|
+
|
|
191
|
+
def create_graph(self):
|
|
192
|
+
print("Create graph")
|
|
193
|
+
canvas = FigureCanvasTkAgg(self.fig, master=self.data_lf)
|
|
194
|
+
canvas.get_tk_widget().pack(side=LEFT)
|
|
195
|
+
|
|
196
|
+
def on_apply(self):
|
|
197
|
+
print(self.mode_var.get())
|
|
198
|
+
if self.mode_var.get() == 'isc':
|
|
199
|
+
self.iv_mpp.ApplyIsc()
|
|
200
|
+
else:
|
|
201
|
+
self.iv_mpp.ApplyVoc()
|
|
202
|
+
|
|
203
|
+
def system_measure_curve(self):
|
|
204
|
+
|
|
205
|
+
print('measure curve')
|
|
206
|
+
self.save_btn.configure(state=ttk.DISABLED)
|
|
207
|
+
self.is_active = True
|
|
208
|
+
self.update_controls()
|
|
209
|
+
self.voltages = []
|
|
210
|
+
self.currents = []
|
|
211
|
+
self.draw_empty_figure()
|
|
212
|
+
self.master.update()
|
|
213
|
+
self.save_settings()
|
|
214
|
+
|
|
215
|
+
sweepstl = 0
|
|
216
|
+
|
|
217
|
+
if self.sweepstyle_var.get() == 'Isc to Voc':
|
|
218
|
+
sweepstl = 0
|
|
219
|
+
if self.sweepstyle_var.get() == 'Voc to Isc':
|
|
220
|
+
sweepstl = 1
|
|
221
|
+
if self.sweepstyle_var.get() == 'Isc to Voc to Isc':
|
|
222
|
+
sweepstl = 8
|
|
223
|
+
if self.sweepstyle_var.get() == 'Voc to Isc to Voc':
|
|
224
|
+
sweepstl = 4
|
|
225
|
+
|
|
226
|
+
curve = self.iv_mpp.measure_ivcurve(int(self.points_var.get()), int(self.delay_var.get()), sweepstl)
|
|
227
|
+
|
|
228
|
+
self.voltages = curve['voltages']
|
|
229
|
+
self.currents = curve['currents']
|
|
230
|
+
self.refresh_figure()
|
|
231
|
+
self.is_active = False
|
|
232
|
+
self.update_controls()
|
|
233
|
+
self.save_btn.configure(state=ttk.NORMAL)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def measure_ivpoint(self):
|
|
237
|
+
print('measure point')
|
|
238
|
+
self.is_active = True
|
|
239
|
+
self.update_controls()
|
|
240
|
+
ivpoint = self.iv_mpp.read_ivpoint()
|
|
241
|
+
voltage = ivpoint.voltage
|
|
242
|
+
current = ivpoint.current
|
|
243
|
+
self.ivpoint_var.set('Voltage: %f V, Current: %f A, Power: %f W' % (voltage, current, voltage * current))
|
|
244
|
+
self.is_active = False
|
|
245
|
+
self.update_controls()
|
|
246
|
+
pass
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def system_connect(self):
|
|
250
|
+
if self.online:
|
|
251
|
+
self.disconnect()
|
|
252
|
+
else:
|
|
253
|
+
self.connect()
|
|
254
|
+
|
|
255
|
+
def exit_app(self):
|
|
256
|
+
print('exit app')
|
|
257
|
+
if self.online:
|
|
258
|
+
self.disconnect()
|
|
259
|
+
self.master.quit()
|
|
260
|
+
|
|
261
|
+
def connect(self):
|
|
262
|
+
self.online = False
|
|
263
|
+
print('connect pvblocks using: ' + self.settings['serialport'])
|
|
264
|
+
self.pvblocks = pvblocks_system.PvBlocks(self.settings['serialport'])
|
|
265
|
+
if self.pvblocks.init_system():
|
|
266
|
+
print("init ok")
|
|
267
|
+
print("scanning available blocks")
|
|
268
|
+
|
|
269
|
+
if self.pvblocks.scan_blocks():
|
|
270
|
+
print("scan_blocks returns ok")
|
|
271
|
+
self.iv_mpp = None
|
|
272
|
+
if len(self.pvblocks.IvMppBlocks) > 0:
|
|
273
|
+
self.iv_mpp = self.pvblocks.IvMppBlocks[0]
|
|
274
|
+
self.online = True
|
|
275
|
+
print("Found IV-MPP block")
|
|
276
|
+
else:
|
|
277
|
+
print("scan_blocks failed")
|
|
278
|
+
|
|
279
|
+
else:
|
|
280
|
+
print("failed")
|
|
281
|
+
|
|
282
|
+
self.update_controls()
|
|
283
|
+
|
|
284
|
+
def disconnect(self):
|
|
285
|
+
print('disconnect pvblocks')
|
|
286
|
+
self.pvblocks.close_system()
|
|
287
|
+
self.online = False
|
|
288
|
+
self.update_controls()
|
|
289
|
+
|
|
290
|
+
def refresh_figure(self):
|
|
291
|
+
self.fig.clear()
|
|
292
|
+
ax = self.fig.add_subplot(111)
|
|
293
|
+
ax.scatter(self.voltages, self.currents)
|
|
294
|
+
self.fig.canvas.draw_idle()
|
|
295
|
+
|
|
296
|
+
def draw_empty_figure(self):
|
|
297
|
+
y = []
|
|
298
|
+
x = []
|
|
299
|
+
ax = self.fig.add_subplot(111)
|
|
300
|
+
ax.scatter(x, y)
|
|
301
|
+
self.fig.canvas.draw()
|
|
302
|
+
|
|
303
|
+
def save_data(self):
|
|
304
|
+
pass
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def open_comport_window(self):
|
|
308
|
+
# Create a new top-level window
|
|
309
|
+
comport_window = ttk.Toplevel(self.master)
|
|
310
|
+
comport_window.title("Select Serial Port")
|
|
311
|
+
comport_window.geometry("300x150")
|
|
312
|
+
|
|
313
|
+
# Make the window modal
|
|
314
|
+
comport_window.grab_set()
|
|
315
|
+
|
|
316
|
+
# Label instructing the user
|
|
317
|
+
label = ttk.Label(comport_window, text="Select a serial port:")
|
|
318
|
+
label.pack(pady=10)
|
|
319
|
+
|
|
320
|
+
# List of COM ports - customizable
|
|
321
|
+
com_ports = []
|
|
322
|
+
for c in serial.tools.list_ports.comports():
|
|
323
|
+
com_ports.append(c.device)
|
|
324
|
+
|
|
325
|
+
# Variable to hold the selected port
|
|
326
|
+
selected_port = ttk.StringVar()
|
|
327
|
+
|
|
328
|
+
# Combobox for selecting COM port
|
|
329
|
+
combo = ttk.Combobox(comport_window, values=com_ports, textvariable=selected_port)
|
|
330
|
+
combo.pack(pady=5)
|
|
331
|
+
combo.current(0) # Set default selection
|
|
332
|
+
|
|
333
|
+
# Function to handle selection
|
|
334
|
+
def select_port():
|
|
335
|
+
self.settings['serialport'] = selected_port.get()
|
|
336
|
+
self.save_settings()
|
|
337
|
+
comport_window.grab_release()
|
|
338
|
+
comport_window.destroy()
|
|
339
|
+
|
|
340
|
+
# Button to confirm selection
|
|
341
|
+
select_button = ttk.Button(comport_window, text="Select", command=select_port)
|
|
342
|
+
select_button.pack(pady=10)
|
|
343
|
+
|
|
344
|
+
def update_controls(self):
|
|
345
|
+
if self.online:
|
|
346
|
+
self.connect_menu.entryconfig(0, state=ttk.DISABLED)
|
|
347
|
+
self.connect_menu.entryconfig(1, state=ttk.NORMAL)
|
|
348
|
+
else:
|
|
349
|
+
self.connect_menu.entryconfig(0, state=ttk.NORMAL)
|
|
350
|
+
self.connect_menu.entryconfig(1, state=ttk.DISABLED)
|
|
351
|
+
self.save_btn.configure(state=ttk.DISABLED)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
if self.is_active:
|
|
355
|
+
self.measureCurveBtn.configure(state=ttk.DISABLED)
|
|
356
|
+
self.measure_ivpoint_btn.configure(state=ttk.DISABLED)
|
|
357
|
+
self.apply_btn.configure(state=ttk.DISABLED)
|
|
358
|
+
else:
|
|
359
|
+
if self.online:
|
|
360
|
+
self.measureCurveBtn.configure(state=ttk.NORMAL)
|
|
361
|
+
self.measure_ivpoint_btn.configure(state=ttk.NORMAL)
|
|
362
|
+
self.apply_btn.configure(state=ttk.NORMAL)
|
|
363
|
+
else:
|
|
364
|
+
self.measureCurveBtn.configure(state=ttk.DISABLED)
|
|
365
|
+
self.measure_ivpoint_btn.configure(state=ttk.DISABLED)
|
|
366
|
+
self.apply_btn.configure(state=ttk.DISABLED)
|
|
367
|
+
|
|
368
|
+
self.master.update()
|
|
369
|
+
|
|
370
|
+
def save_settings(self):
|
|
371
|
+
self.settings['points'] = self.points_var.get()
|
|
372
|
+
self.settings['delay_ms'] = self.delay_var.get()
|
|
373
|
+
self.settings['sweepstyle'] = self.sweepstyle_var.get()
|
|
374
|
+
with open('settings.pkl', 'wb') as f:
|
|
375
|
+
pickle.dump(self.settings, f)
|
|
376
|
+
|
|
377
|
+
def load_settings(self):
|
|
378
|
+
self.settings = {'serialport': 'COM1', 'points': '100', 'delay_ms': '20', 'sweepstyle': 'Isc to Voc'}
|
|
379
|
+
|
|
380
|
+
if os.path.isfile('settings.pkl'):
|
|
381
|
+
with open('settings.pkl', 'rb') as f:
|
|
382
|
+
self.settings = pickle.load(f)
|
|
383
|
+
else:
|
|
384
|
+
with open('settings.pkl', 'wb') as f:
|
|
385
|
+
pickle.dump(self.settings, f)
|
|
386
|
+
|
|
387
|
+
for key in self.settings.keys():
|
|
388
|
+
print(self.settings[key])
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
if __name__ == '__main__':
|
|
392
|
+
|
|
393
|
+
app = ttk.Window("PVBlocks IV/MPP Control", "journal")
|
|
394
|
+
MainApp(app)
|
|
395
|
+
app.mainloop()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|