Я хочу запустить измерительную программу, которая получает измерения от двух разных устройств в течение одного и того же периода. Я хочу начать и остановить измерение в небольшом графическом интерфейсе. Поскольку мне нужен цикл while для измерения, построения и сохранения одного из измерений и запуска его до тех пор, пока я не прерву его кнопкой остановки, я подумал, что мне нужно вызвать его как другой поток, чтобы не замораживать графический интерфейс пользователя и иметь возможность использоватькнопка остановкиТакже я подумал, что не стоит использовать .join (), чтобы не заморозить графический интерфейс. Но почему-то мой графический интерфейс все еще зависает, и я не могу использовать кнопку остановки. Я уже читал подобные вопросы на форумах, но не могу понять, что я делаю неправильно. На самом деле это мой первый проект с использованием потоков, поэтому я не разбираюсь с опциями и событиями, но я также не вижу, как они мне помогут.
Итак, у меня есть класс для связи с моим arduino, один для связи с saleae (второе устройство) и один класс data_treatment для построения и сохранения данных из arduino.
Так что в моем основном у меня есть небольшой графический интерфейс с кнопкой запуска и остановки. Когда я нажимаю кнопку «Пуск», я хотел бы запустить измерение saleae (оно удобно выполняется в собственной программе) и вызвать функцию записи моего класса ardunio. Эта функция имеет цикл while, который считывает значения и передает их функции data_treatment. Когда я нажимаю start, он запускает измерение saleae и измерение arduino, и все работает как запланировано, но я не могу нажать stop, потому что кажется, что графический интерфейс ожидает другую угрозу, которая не заканчивается, пока я не нажму stop.
Итак, моя основная функция (cambine_func) - это просто функция, позволяющая вызывать несколько функций с помощью кнопки), а ниже - класс arduino:
if __name__ == '__main__':
window = gui.Window("Measurement")
start_button = window.add_button("Start")
start_button.pack(pady = 20)
gui.on("btnPress", start_button, lambda: combine_funcs(saleae.start_measurement(),
threading.Thread(target = arduino.record_values(300)).start()))
stop_button = window.add_button("Stopp")
stop_button.pack(pady = 20)
gui.on("btnPress", stop_button, lambda: combine_funcs(saleae.end_measurement(),
saleae.save_data(),
arduino.close_port(),
window.destroy()))
window.start()
import time
class Arduino_communication:
"""
reads what comes in from Arduino and transformes it into single values
"""
def __init__(self, arduino, data_treatment):
self.arduino = arduino
self.data_treatment = data_treatment
self.interrupted = False
def record_values(self, measurement_period):
"""
reads values from the Arduino and converts it into single values,
counts faulty lines received from Arduino
:return: array of 6 columns (roll, pitch, yaw, x-position, y-position, z-position)
"""
faulty_values = 0
data = [0, 0, 0, 0, 0, 0]
start_time = float(time.time())
time_vector = []
while self.interrupted == False:
self.arduino.flushInput() # delete what's in buffer
self.arduino.readline() # read a byte string and throw away (deleting buffer may lead to uncomplete line)
b = self.arduino.readline() # read next line
time_vector.append(float(time.time())-start_time)
try:
string_n = b.decode() # decode byte string into Unicode
except UnicodeDecodeError: # Arduino sometimes sends faulty lines
faulty_values += 1
string = string_n.rstrip() # remove \n and \r
single_strings = string.split('/')
try:
data = [float(j) for j in single_strings] # convert string to float
except (ValueError, UnicodeDecodeError): # Arduino sometimes sends faulty lines
faulty_values += 1
self.data_treatment.plot_new_data_line(time_vector[-1], data)
self.data_treatment.write_to_csv(time_vector[-1], data)
print('Es gab ', faulty_values, ' fehlerhafte Übertragungen.')
self.data_treatment.finish_plotting()
def close_port(self):
"""
stops measurement and closes arduino port
"""
self.interrupted = True
self.arduino.close()