Home > Software engineering >  pressing button tkinter blocks execution of a part of the software
pressing button tkinter blocks execution of a part of the software

Time:05-14

I've a program in python that reads my serial port for data. I'm writing a new part where, with the click of a button, on the same serial port, I send specific data.

Below part of the code I'm using

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):

        # def sch_plus_callback():
        #     self.ser.reset_input_buffer()
        #     self.ser.reset_output_buffer()
        #     self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x42\x33\x04')
        #     logging.info("write on serial")
        #     self.ser.reset_input_buffer()
        #     self.ser.reset_output_buffer()

        tk.Tk.__init__(self, *args, **kwargs)
        # self.insert_lengh_text_label = tk.Label(self, text="Max Packet Length")
        # self.insert_lengh_text_label.pack()
        # self.insert_lengh_text = tk.Entry(self, width=2)
        # self.insert_lengh_text.pack()
        self.serial_text_label = tk.Label(self, text="String")
        self.serial_text_label.pack()
        self.serial_text = tk.Text(self, height=1, width=50)
        self.serial_text.pack()

        self.port = 'COM3'
        self.baud = 38400

        self.ser = serial.Serial(self.port, self.baud, timeout=None)
        if self.ser.isOpen():
            self.ser.close()
            self.ser.open()

        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()

        logging.info("created serial port")

        # self.sch_plus_button = tk.Button(self, text="S ", command=sch_plus_callback)
        # self.sch_plus_button.pack()

        # start the serial_text_label "ticking"
        self._update_scheduled = threading.Condition()
        self._terminating = threading.Event()
        self.update_screen()

    def mainloop(self):
        with ThreadPoolExecutor() as executor:
            future = executor.submit(self._do_update_screen_loop)
            try:
                return super().mainloop()
            finally:
                # letting the thread to know we're done
                self._terminating.set()
                with self._update_scheduled:
                    self._update_scheduled.notify_all()

    def update_screen(self):
        with self._update_scheduled:
            self._update_scheduled.notify_all()
        self.after(500, self.update_screen)

    def _do_update_screen_loop(self):
        while True:
            with self._update_scheduled:
                self._update_scheduled.wait()
            if self._terminating.is_set():
                return
            self._do_data_screen()

    def _do_data_screen(self):
        self.serial_text.delete('1.0', tk.END)
        # dimension = self.insert_lengh_text.get()
        # if dimension == "":
        #     dimension = 1

    data = ""
    data_raw = self.ser.read(1)
    if data_raw == b'\x02':
        data_raw = self.ser.read_until(b'\x03')
        data = "02-"   str(data_raw.hex('-'))
        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()

    hex_list = [int(x, 16) for x in data.split('-')]

    check = checksum_calculation(hex_list)
    if hex_list[4] == check[0] and hex_list[5] == check[1]:
        logging.debug("Checksum correct")
    logging.debug(str(hex_list))

    self.serial_text.insert(tk.END, data)
    # self.serial_text_label.configure(text=data)

I'm writing to the serial port with the button

self.sch_plus_button = tk.Button(self, text="S ", command=sch_plus_callback)
self.sch_plus_button.pack()

that calls

        def sch_plus_callback():
            self.ser.reset_input_buffer()
            self.ser.reset_output_buffer()
            self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x42\x33\x04')
            logging.info("write on serial")
            self.ser.reset_input_buffer()
            self.ser.reset_output_buffer()

And it works as the data is sent to the serial port. The only issue is that at some random moment in time, after having press the button at least one time, the program stops reading the port.

Any idea why?

CodePudding user response:

It seemed that the solution was to bring sch_plus_callback outside the init and calling

self.sch_plus_button = tk.Button(self, text="S ", command=self.sch_plus_callback)

function outside init

def __init__(self, *args, **kwargs):

    tk.Tk.__init__(self, *args, **kwargs)
    # all my other code

def sch_plus_callback(self):
    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()
    self.ser.write(b'\x02\x56\x81\x80\x80\x80\x80\x80\x39\x35\x04')
    logging.info("write on serial")
    self.ser.reset_input_buffer()
    self.ser.reset_output_buffer()
  • Related