我想运行一个测量程序,该程序可以在同一时期从两个不同的设备获取测量值。我想在一个小gui中开始和停止测量。由于我需要一个while循环来测量,绘制和保存其中一项测量,然后运行它,直到用“停止”按钮中断它为止,所以我认为我需要将其作为另一个线程来调用,以免冻结gui并能够使用停止按钮。我还认为我不应该使用.join()来冻结gui。但是不知何故,我的GUI仍然似乎死机了,我无法使用停止按钮。我已经在论坛上阅读过类似的问题,但是我无法弄清楚自己在做什么错。 实际上,这是我第一个使用线程的项目,因此我对选项和事件没有任何经验,但是我也看不出它们对我有什么帮助。
因此,我有一个与arduino通信的类,一个与Saleae(第二设备)通信的类,以及一个data_processing类,用于绘制和保存来自arduino的数据。
所以在我的主菜单中,我有一个带有启动和停止按钮的小GUI。当我按下开始按钮时,我想启动saleae测量(在自己的程序中舒适地运行)并调用ardunio类的记录函数。该函数有一个while循环,该循环读取值并将其提供给data_treatment函数。当我按下开始键时,它会开始测量saleae和arduino,并且一切都按计划进行,但是我无法按一下Stop,因为gui似乎正在等待其他威胁,直到我按下Stop为止。 / p>
所以这是我的主要功能(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()
答案 0 :(得分:0)
您有:
threading.Thread(target = arduino.record_values(300)).start()
这将调用该方法,然后启动一个以结果为目标的线程。
您想要的地方:
threading.Thread(target=arduino.record_values, args=[300]).start()
这将从目标arduino.record_values
和参数300
开始线程。
您可能希望保留该线程,以防止在录制线程正在录制时启动按钮启动另一个录制线程。
答案 1 :(得分:0)
我不知道自己认为可行的解决方案,但是我发现了这个answer可以适应我的项目,现在它可以按我的意愿工作了。