Skip to content

Commit dd573ed

Browse files
Done implementing dvg-devices. Bump version.
1 parent 75e2c3e commit dd573ed

12 files changed

+249
-1108
lines changed

Arduino_PyQt_demo_with_multithreading.py

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
__author__ = "Dennis van Gils"
77
__authoremail__ = "vangils.dennis@gmail.com"
88
__url__ = "https://github.com/Dennis-van-Gils/DvG_Arduino_PyQt_multithread_demo"
9-
__date__ = "01-07-2020"
10-
__version__ = "2.1"
9+
__date__ = "02-07-2020"
10+
__version__ = "3.0"
1111

1212
import os
1313
import sys
1414
from pathlib import Path
15+
import time
1516

1617
import numpy as np
1718
import psutil
@@ -24,19 +25,19 @@
2425
from DvG_pyqt_FileLogger import FileLogger
2526
from DvG_pyqt_ChartHistory import ChartHistory
2627
from DvG_pyqt_controls import create_Toggle_button, SS_GROUP
27-
from DvG_debug_functions import dprint, print_fancy_traceback as pft
28+
from dvg_debug_functions import dprint, print_fancy_traceback as pft
2829

29-
#import DvG_dev_Arduino__fun_serial as Arduino_functions
30-
from DvG_dev_Arduino__protocol_serial import Arduino # I.e. the `device
31-
from DvG_dev_Arduino__qdev import Arduino_qdev
32-
from DvG_QDeviceIO import QDeviceIO
30+
from dvg_devices.Arduino_protocol_serial import Arduino # I.e. the `device`
31+
32+
# from dvg_devices.Arduino_qdev import Arduino_qdev # Alternative approach as a mixed-in QDeviceIO class
33+
from dvg_qdeviceio import QDeviceIO
3334

3435

3536
# Constants
3637
# fmt: off
37-
DAQ_INTERVAL_ARDUINO = 10 # 10 [ms]
38-
DRAW_INTERVAL_CHART = 10 # 10 [ms]
39-
CHART_HISTORY_TIME = 10 # 10 [s]
38+
DAQ_INTERVAL_MS = 10 # 10 [ms]
39+
DRAW_INTERVAL_CHART = 10 # 10 [ms]
40+
CHART_HISTORY_TIME = 10 # 10 [s]
4041

4142
# Global variables for date-time keeping
4243
cur_date_time = QDateTime.currentDateTime()
@@ -54,11 +55,11 @@
5455

5556
class State(object):
5657
"""Reflects the actual readings, parsed into separate variables, of the
57-
Arduino(s). There should only be one instance of the State class.
58+
Arduino. There should only be one instance of the State class.
5859
"""
5960

6061
def __init__(self):
61-
self.time = np.nan # [ms]
62+
self.time = None # [s]
6263
self.reading_1 = np.nan
6364

6465
# Mutex for proper multithreading. If the state variables are not
@@ -153,9 +154,8 @@ def __init__(self, parent=None, **kwargs):
153154

154155
# Create ChartHistory and PlotDataItem and link them together
155156
PEN_01 = pg.mkPen(color=[0, 200, 0], width=3)
156-
num_samples = round(CHART_HISTORY_TIME * 1e3 / DAQ_INTERVAL_ARDUINO)
157+
num_samples = round(CHART_HISTORY_TIME * 1e3 / DAQ_INTERVAL_MS)
157158
self.CH_1 = ChartHistory(num_samples, self.pi_chart.plot(pen=PEN_01))
158-
self.CH_1.x_axis_divisor = 1000 # From [ms] to [s]
159159

160160
# 'Readings'
161161
p = {"readOnly": True}
@@ -279,7 +279,7 @@ def update_GUI():
279279
window.qlbl_cur_date_time.setText("%s %s" % (str_cur_date, str_cur_time))
280280
window.qlbl_update_counter.setText("%i" % qdev_ard.update_counter_DAQ)
281281
window.qlbl_DAQ_rate.setText("DAQ: %.1f Hz" % qdev_ard.obtained_DAQ_rate_Hz)
282-
window.qlin_reading_t.setText("%i" % state.time)
282+
window.qlin_reading_t.setText("%.3f" % state.time)
283283
window.qlin_reading_1.setText("%.4f" % state.reading_1)
284284

285285

@@ -291,13 +291,16 @@ def update_GUI():
291291
@QtCore.pyqtSlot()
292292
def update_chart():
293293
if DEBUG:
294-
tick = QDateTime.currentDateTime()
294+
tick = time.perf_counter()
295295

296296
window.CH_1.update_curve()
297297

298298
if DEBUG:
299-
tack = QDateTime.currentDateTime()
300-
dprint(" update_curve done in %d ms" % tick.msecsTo(tack))
299+
dprint(
300+
" update_curve done in %.2f ms"
301+
% (time.perf_counter() - tick)
302+
* 1000
303+
)
301304

302305

303306
# ------------------------------------------------------------------------------
@@ -323,7 +326,7 @@ def notify_connection_lost():
323326
window.qlbl_title.setText("%sLOST CONNECTION%s" % (excl, excl))
324327

325328
str_msg = (
326-
"%s %s\n" "Lost connection to Arduino(s).\n" " '%s', '%s': %salive"
329+
"%s %s\n" "Lost connection to Arduino.\n" " '%s', '%s': %salive"
327330
) % (
328331
str_cur_date,
329332
str_cur_time,
@@ -371,6 +374,7 @@ def DAQ_function():
371374
# Parse readings into separate state variables
372375
try:
373376
[state.time, state.reading_1] = tmp_state
377+
state.time /= 1000
374378
except Exception as err:
375379
pft(err, 3)
376380
dprint(
@@ -380,10 +384,9 @@ def DAQ_function():
380384
return False
381385

382386
# Use Arduino time or PC time?
383-
# Arduino time is more accurate, but rolls over ~49 days for a 32 bit timer.
384387
use_PC_time = True
385388
if use_PC_time:
386-
state.time = cur_date_time.toMSecsSinceEpoch()
389+
state.time = time.perf_counter()
387390

388391
# Add readings to chart histories
389392
window.CH_1.add_new_reading(state.time, state.reading_1)
@@ -404,7 +407,7 @@ def DAQ_function():
404407
file_logger.close_log()
405408

406409
if file_logger.is_recording:
407-
log_elapsed_time = (state.time - file_logger.start_time) / 1e3 # [sec]
410+
log_elapsed_time = state.time - file_logger.start_time
408411
file_logger.write("%.3f\t%.4f\n" % (log_elapsed_time, state.reading_1))
409412

410413
return True
@@ -438,7 +441,7 @@ def DAQ_function():
438441
if not (ard.is_alive):
439442
print("\nCheck connection and try resetting the Arduino.")
440443
print("Exiting...\n")
441-
sys.exit(0)
444+
sys.exit(1)
442445

443446
# --------------------------------------------------------------------------
444447
# Create application and main window
@@ -463,32 +466,35 @@ def DAQ_function():
463466
# --------------------------------------------------------------------------
464467

465468
"""
466-
# fmt: off
469+
# Alternative approach as a mixed-in QDeviceIO class
470+
# fmt: off
467471
qdev_ard = Arduino_qdev(
468-
dev = ard,
469-
DAQ_function = DAQ_function,
470-
DAQ_interval_ms = DAQ_INTERVAL_ARDUINO,
471-
critical_not_alive_count = 3,
472-
calc_DAQ_rate_every_N_iter=100,
473-
debug = DEBUG,
472+
dev = ard,
473+
DAQ_function = DAQ_function,
474+
DAQ_interval_ms = DAQ_INTERVAL_MS,
475+
critical_not_alive_count = 3,
476+
calc_DAQ_rate_every_N_iter = 100,
477+
debug = DEBUG,
474478
)
475-
"""
476479
# fmt: on
477-
480+
"""
481+
482+
# """
478483
# Create QDeviceIO
479484
qdev_ard = QDeviceIO(ard)
480485

481486
# Create workers
482487
# fmt: off
483488
qdev_ard.create_worker_DAQ(
484489
DAQ_function = DAQ_function,
485-
DAQ_interval_ms = DAQ_INTERVAL_ARDUINO,
490+
DAQ_interval_ms = DAQ_INTERVAL_MS,
486491
critical_not_alive_count = 3,
487492
debug = DEBUG,
488493
)
489494
# fmt: on
490495

491496
qdev_ard.create_worker_jobs(debug=DEBUG)
497+
# """
492498

493499
# Connect signals to slots
494500
qdev_ard.signal_DAQ_updated.connect(update_GUI)

Arduino_PyQt_demo_with_multithreading__LARGE_TEXT.py

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
__author__ = "Dennis van Gils"
77
__authoremail__ = "vangils.dennis@gmail.com"
88
__url__ = "https://github.com/Dennis-van-Gils/DvG_Arduino_PyQt_multithread_demo"
9-
__date__ = "24-06-2020"
10-
__version__ = "2.1"
9+
__date__ = "02-07-2020"
10+
__version__ = "3.0"
1111

1212
import os
1313
import sys
1414
from pathlib import Path
15+
import time
1516

1617
import numpy as np
1718
import psutil
@@ -24,16 +25,16 @@
2425
from DvG_pyqt_FileLogger import FileLogger
2526
from DvG_pyqt_ChartHistory import ChartHistory
2627
from DvG_pyqt_controls import create_Toggle_button
27-
from DvG_debug_functions import dprint, print_fancy_traceback as pft
28+
from dvg_debug_functions import dprint, print_fancy_traceback as pft
2829

29-
import DvG_dev_Arduino__fun_serial as Arduino_functions
30-
import DvG_QDeviceIO
30+
from dvg_devices.Arduino_protocol_serial import Arduino
31+
from dvg_qdeviceio import QDeviceIO
3132

3233
# Constants
3334
# fmt: off
34-
UPDATE_INTERVAL_ARDUINO = 10 # 10 [ms]
35-
UPDATE_INTERVAL_CHART = 10 # 10 [ms]
36-
CHART_HISTORY_TIME = 10 # 10 [s]
35+
DAQ_INTERVAL_MS = 10 # 10 [ms]
36+
DRAW_INTERVAL_CHART = 10 # 10 [ms]
37+
CHART_HISTORY_TIME = 10 # 10 [s]
3738

3839
# Global variables for date-time keeping
3940
cur_date_time = QDateTime.currentDateTime()
@@ -51,11 +52,11 @@
5152

5253
class State(object):
5354
"""Reflects the actual readings, parsed into separate variables, of the
54-
Arduino(s). There should only be one instance of the State class.
55+
Arduino. There should only be one instance of the State class.
5556
"""
5657

5758
def __init__(self):
58-
self.time = np.nan # [ms]
59+
self.time = None # [s]
5960
self.reading_1 = np.nan
6061

6162
# Mutex for proper multithreading. If the state variables are not
@@ -182,9 +183,8 @@ def __init__(self, parent=None, **kwargs):
182183

183184
# Create ChartHistory and PlotDataItem and link them together
184185
PEN_01 = pg.mkPen(color=[0, 200, 0], width=3)
185-
num_samples = round(CHART_HISTORY_TIME * 1e3 / UPDATE_INTERVAL_ARDUINO)
186+
num_samples = round(CHART_HISTORY_TIME * 1e3 / DAQ_INTERVAL_MS)
186187
self.CH_1 = ChartHistory(num_samples, self.pi_chart.plot(pen=PEN_01))
187-
self.CH_1.x_axis_divisor = 1000 # From [ms] to [s]
188188

189189
# 'Readings'
190190
p = {"readOnly": True}
@@ -299,6 +299,7 @@ def set_text_qpbt_record(self, text_str):
299299

300300

301301
# ------------------------------------------------------------------------------
302+
# update_GUI
302303
# ------------------------------------------------------------------------------
303304

304305

@@ -307,24 +308,28 @@ def update_GUI():
307308
window.qlbl_cur_date_time.setText("%s %s" % (str_cur_date, str_cur_time))
308309
window.qlbl_update_counter.setText("%i" % qdev_ard.update_counter_DAQ)
309310
window.qlbl_DAQ_rate.setText("DAQ: %.1f Hz" % qdev_ard.obtained_DAQ_rate_Hz)
310-
window.qlin_reading_t.setText("%i" % state.time)
311+
window.qlin_reading_t.setText("%.3f" % state.time)
311312
window.qlin_reading_1.setText("%.4f" % state.reading_1)
312313

313314

314315
# ------------------------------------------------------------------------------
316+
# update_chart
315317
# ------------------------------------------------------------------------------
316318

317319

318320
@QtCore.pyqtSlot()
319321
def update_chart():
320322
if DEBUG:
321-
tick = QDateTime.currentDateTime()
323+
tick = time.perf_counter()
322324

323325
window.CH_1.update_curve()
324326

325327
if DEBUG:
326-
tack = QDateTime.currentDateTime()
327-
dprint(" update_curve done in %d ms" % tick.msecsTo(tack))
328+
dprint(
329+
" update_curve done in %.2f ms"
330+
% (time.perf_counter() - tick)
331+
* 1000
332+
)
328333

329334

330335
# ------------------------------------------------------------------------------
@@ -350,7 +355,7 @@ def notify_connection_lost():
350355
window.qlbl_title.setText("%sLOST CONNECTION%s" % (excl, excl))
351356

352357
str_msg = (
353-
"%s %s\n" "Lost connection to Arduino(s).\n" " '%s', '%s': %salive"
358+
"%s %s\n" "Lost connection to Arduino.\n" " '%s', '%s': %salive"
354359
) % (
355360
str_cur_date,
356361
str_cur_time,
@@ -379,7 +384,7 @@ def about_to_quit():
379384
# ------------------------------------------------------------------------------
380385

381386

382-
def my_Arduino_DAQ_update():
387+
def DAQ_function():
383388
# Date-time keeping
384389
global cur_date_time, str_cur_date, str_cur_time
385390
cur_date_time = QDateTime.currentDateTime()
@@ -398,6 +403,7 @@ def my_Arduino_DAQ_update():
398403
# Parse readings into separate state variables
399404
try:
400405
[state.time, state.reading_1] = tmp_state
406+
state.time /= 1000
401407
except Exception as err:
402408
pft(err, 3)
403409
dprint(
@@ -407,10 +413,9 @@ def my_Arduino_DAQ_update():
407413
return False
408414

409415
# Use Arduino time or PC time?
410-
# Arduino time is more accurate, but rolls over ~49 days for a 32 bit timer.
411416
use_PC_time = True
412417
if use_PC_time:
413-
state.time = cur_date_time.toMSecsSinceEpoch()
418+
state.time = time.perf_counter()
414419

415420
# Add readings to chart histories
416421
window.CH_1.add_new_reading(state.time, state.reading_1)
@@ -431,7 +436,7 @@ def my_Arduino_DAQ_update():
431436
file_logger.close_log()
432437

433438
if file_logger.is_recording:
434-
log_elapsed_time = (state.time - file_logger.start_time) / 1e3 # [sec]
439+
log_elapsed_time = state.time - file_logger.start_time
435440
file_logger.write("%.3f\t%.4f\n" % (log_elapsed_time, state.reading_1))
436441

437442
return True
@@ -457,7 +462,7 @@ def my_Arduino_DAQ_update():
457462
# Connect to Arduino
458463
# --------------------------------------------------------------------------
459464

460-
ard = Arduino_functions.Arduino(name="Ard", baudrate=115200)
465+
ard = Arduino(name="Ard", baudrate=115200)
461466
ard.auto_connect(
462467
Path("last_used_port.txt"), match_identity="Wave generator"
463468
)
@@ -490,15 +495,16 @@ def my_Arduino_DAQ_update():
490495
# --------------------------------------------------------------------------
491496

492497
# Create QDeviceIO
493-
qdev_ard = DvG_QDeviceIO.QDeviceIO(ard)
498+
qdev_ard = QDeviceIO(ard)
494499

495500
# Create workers
496501
# fmt: off
497502
qdev_ard.create_worker_DAQ(
498-
DAQ_function = my_Arduino_DAQ_update,
499-
DAQ_interval_ms = UPDATE_INTERVAL_ARDUINO,
503+
DAQ_function = DAQ_function,
504+
DAQ_interval_ms = DAQ_INTERVAL_MS,
500505
critical_not_alive_count = 3,
501-
debug = DEBUG)
506+
debug = DEBUG,
507+
)
502508
# fmt: on
503509

504510
qdev_ard.create_worker_jobs(debug=DEBUG)
@@ -516,7 +522,7 @@ def my_Arduino_DAQ_update():
516522

517523
timer_chart = QtCore.QTimer()
518524
timer_chart.timeout.connect(update_chart)
519-
timer_chart.start(UPDATE_INTERVAL_CHART)
525+
timer_chart.start(DRAW_INTERVAL_CHART)
520526

521527
# --------------------------------------------------------------------------
522528
# Start the main GUI event loop

0 commit comments

Comments
 (0)