0

I have a Button in gui to take data from serial port.

here is my code:

def takeRead():
    ser = serial.Serial()
    ser.baudrate = 115200
    ser.port = "COM7" # "COM#" this must match with connected port
    ser.open() #opening serial port
    while True:
        global data, x, y0
        y0 = []
        data = []
        x = []
        for j in range(8000):
            line = ser.readline() # read a byte string
            if line:
                string = line.decode() # convert the byte string to a unicode string
                res = [int(i) for i in string.split() if i.isdigit()] #saperating integer from string
                data.append(res) #append readings to store 
                # print(res)
                x0= j*0.9
                x.append(x0)
                # print(x0)
                if j<4000:
                    y = (5/4000)*j
                else:
                    y = (-5/4000)*j + 10
                y0.append(y)
        data = [val for sublist in data for val in sublist]
        # ax.plot(x,y0,color='r')
        break
    # print(y0)
    ser.close()

takeread = Button(graph_frame,
                  text="Take Readings",
                  command=threading.Thread(target=takeRead).start,
                  font=20,
                  width=20)
takeread.pack(side=BOTTOM)

when I use this code then i can only run it one time as 'thread can only be started once'.

So, I tried another approach, that to run a thread and inside the thread one conditional statement to take data.

I want that, when the button is clicked then the data is taken. if button is pressed multiple time then function should work multiple time.

def takeRead():
    global takereadings
    def takereadings():
        takereading = True
        while takereading == True:
            ser = serial.Serial()
            ser.baudrate = 115200
            ser.port = "COM7" # "COM#" this must match with connected port
            ser.open() #opening serial port
            global data, x, y0
            y0 = []
            data = []
            x = []
            for j in range(8000):
                line = ser.readline() # read a byte string
                if line:
                    string = line.decode() # convert the byte string to a unicode string
                    res = [int(i) for i in string.split() if i.isdigit()] #saperating integer from string
                    data.append(res) #append readings to store 
                    # print(res)
                    x0= j*0.9
                    x.append(x0)
                    # print(x0)
                    if j<4000:
                        y = (5/4000)*j
                    else:
                        y = (-5/4000)*j + 10
                    y0.append(y)
            data = [val for sublist in data for val in sublist]
            # ax.plot(x,y0,color='r')
            break
        # print(y0)
        ser.close()
        takereading = False

threading.Thread(target=takeRead).start()
takeread = Button(graph_frame,
                  text="Take Readings", 
                  command=takereadings,
                  font=20,
                  width=20)
takeread.pack()

I am using thread to stop GUI from freezing.

IMI
  • 13
  • 4
  • have you had a look at https://stackoverflow.com/questions/53525746/trying-to-fix-tkinter-gui-freeze-ups-using-threads ? – CarlosSR Jul 21 '22 at 08:21
  • yes, but did not understand much. – IMI Jul 21 '22 at 08:50
  • For the first approach, it should be `command=lambda: threading.Thread(target=takeRead).start()`. – acw1668 Jul 21 '22 at 08:50
  • @acw1668 thanks to you. it works but i wonder about to kill thread after taking readings. Also i dont understand how the problem for "thread started only once" solved by "lambda". can you please explain me? – IMI Jul 21 '22 at 09:08
  • Without `lambda`, you create *only one instance of the thread* and pass the `start` function reference to `command` option. Whereas using `lambda`, the `lambda` is executed which it will create *new instance of the thread* and call its `start` function. – acw1668 Jul 21 '22 at 09:13
  • @acw1668 hmm.. I understand about lambda. thanks for the explanation. and what about to kill/join the thread?? is there any need to join/kill the thread? – IMI Jul 21 '22 at 09:46
  • The `threading` module does not have function to kill a thread. You need to design how to break the while loop in the threaded function. There is a `.join()` function on the instance of the thread object returned by `threading.Thread()`. – acw1668 Jul 21 '22 at 09:52
  • @acw1668 Thanks for you precious time and efforts. – IMI Jul 21 '22 at 10:00

0 Answers0