I want to run a measurment program which gets measurement from two different devices during the same period. I want to start and stop the measurement within a small gui. As I need a while loop to measure, plot and save one of the measurments and run it until I interrupt it with the stop button, I thought I need to call it as a different thread to not freeze the gui and be able to use the stop button. Also I thought that I should not use .join() to not freeze the gui. But somehow my gui still seems to freeze and I can't use the stop button. I already read similar questions in forums, but I can't figure out what I am doing wrong. It actually is my first project using threadings, so I don#t have any experiance with options and events, but I also couln't see how they would help me.
So I have a class to communicate with my arduino, one to communicate with saleae (second device) and one data_treatment class to plot and save the data from the arduino.
So in my main I have a small gui with a start and stop button. When I press the start button, I'd like to start the saleae measurment (it runs comfortably in its own program) and to call my record function of my ardunio class. That function has a while loop which reads the values and gives them to the function of data_treatment. When I press start, it starts the saleae measurement and the arduino measurement, and all works as planned, but I can't press stop, because the gui seems to wait for the other threat which doesn't end until I press stop.
So here is my main function (cambine_func) is just a function to be able to call several functions with the button), and below is the arduino class:
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()