I cannot write more than one line of data from a file to a virtual com port (com0com) using pyserial. I am attempting to write the file line-by-line so I can simultaneously update a progress bar in Tkinter. I am running on Windows and have attempted to put the write operation in its own thread (per UART Controller with Tkinter and Python GUI ). My program hangs after writing one line.
Relevant Code:
import os
import sys
from functools import partial
import re
import time
import threading
import serial
import serial.tools.list_ports
import tkinter as tk
from tkinter import ttk, filedialog
class MainApp(tk.Tk):
def __init__(self,
parent,
title = 'Main Application',
*args,
**kwargs):
self.parent = parent
#Set window title and size
self.parent.title(title)
#Create widget container
container = tk.Frame(self.parent)
#Add widgets
# --> Create load program widgets
load_frame = tk.LabelFrame(container,
text = 'Load Program',
width = 400,
height = 100)
port_dropdown = DropDown(load_frame,
label = 'Port:',
row = 0)
file_browser = Browser(load_frame,
path_type = 'file',
label = 'File:',
row = 1)
program_downloader = Downloader(load_frame,
port_dropdown,
file_browser,
row = 2)
# --> Layout load program widgets
load_frame.grid(row = 0,
column= 0,
padx = (5,5),
pady = (5,5))
#Layout widget container
container.pack(fill = tk.BOTH,
padx = 10,
pady = 5,
expand = True)
.
.
.
class Downloader(tk.Frame):
def __init__(self,
parent,
port_dropdown,
file_browser,
row = 0):
self.port_dropdown = port_dropdown
self.file_browser = file_browser
#Instantiate serial port object
self.serial_port = None
self.progress_bar = ttk.Progressbar(parent,
orient = 'horizontal',
mode = 'determinate')
self.progress_bar.grid(row = row,
column = 0,
columnspan = 2,
padx = (5,5),
pady = (5,5),
sticky = 'WE')
self.button = tk.Button(parent,
text = 'Download',
command = self.download_program)
self.button.grid(row = row,
column = 2,
padx = (5,5),
pady = (5,5),
sticky = 'W')
def download_program(self):
port_full_name = self.port_dropdown.combobox.get()
port_name = re.match('([^\s]+)', port_full_name).group(0)
baud_rate = 9600
program_path = self.file_browser.text.get()
self.connect(port_name,
baud_rate,
program_path)
def connect(self,
port_name,
baud_rate,
program_path):
self.serial_port = serial.Serial(port_name,
baud_rate,
timeout=1)
t1 = threading.Thread(target = self.transfer_data,
args = (program_path,))
t1.daemon = True
t1.start()
def transfer_data(self,
program_path):
line = 1
self.progress_bar['value'] = line
with open(program_path, 'r') as program:
max_lines = len(program.readlines())
self.progress_bar['maximum'] = max_lines
with open(program_path, 'r') as program:
while line < max_lines:
command = program.readline().replace('\n','\r\n')
print(str(line) + ': ' + repr(command))
self.serial_port.write(command.encode('ascii'))
line += 1
self.progress_bar['value'] = line
self.serial_port.flush()
print('done')
self.disconnect()
def disconnect(self):
self.serial_port.close()
if __name__ == '__main__':
#Initialize Tkinter
root = tk.Tk()
#Create GUI
gui = MainApp(root,
'Main Application')
#Run program
root.mainloop()
GUI Hangs:
Terminal Output:
1: '@01\r\n'
2: '@02\r\n'
The fact that I'm able to read from program.txt
the second time around in the loop tells me the program might be hanging because the port is still stuck on the first write.
Any help would be appreciated.
Set timeout
and write_timeout
to 0
prevents blocking, which seems to fix the problem.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.