I have an interface which has button for the read serial line.
class MainWindow(QMainWindow):
def __init__(self,parent = None):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
########################################################################
# APPLY JSON STYLESHEET
########################################################################
# self = QMainWindow class
# self.ui = Ui_MainWindow / user interface class
loadJsonStyle(self, self.ui)
########################################################################
QSizeGrip(self.ui.size_grip)
self.connection = SerialConnection()
self.Rs232 = RS232_Data()
self.ui.propertyListBtn.clicked.connect(self.get_property_list)
self.show()
def get_property_list(self):
self.Rs232.read(46,0,self.propertyDataArray) #Read Request
self.getAllByte = self.connection.serial_read_byte(236)
print(list(self.getAllByte))
# self.connection.connection_close()
#self.connection.connection_start()
This is the SerialConnection class:
import time
import serial
# serialPort = serial.Serial(port = "COM4", baudrate=115200,
# bytesize=8, timeout=2, stopbits=serial.STOPBITS_ONE)
import serial.tools.list_ports
class SerialConnection():
def __init__(self):
portList = serial.tools.list_ports.comports()
for p in portList:
if p.pid == 12345:
print("Confirmed")
self.getPortName = p.device
print(self.getPortName)
self.serialPort = serial.Serial(port=self.getPortName, baudrate=230400, bytesize=8, timeout=5,
stopbits=serial.STOPBITS_ONE)
break
else:
## Show dialog
print("There is no device on the line")
def connection_start(self):
try:
self.serialPort.open()
except Exception:
print("Port is already open")
def connection_close(self):
self.serialPort.close()
def serial_write(self, data):
self.data = data
self.serialPort.write(self.data)
def serial_read_string(self):
readData = self.serialPort.readline()
return readData
def serial_read_byte(self,size):
readData = self.serialPort.read(size)
return readData
RS232 Class:
class RS232_Data():
def __init__(self):
self.startOfTheFrame = "0x2621"
self.endOfTheFrame = "0x0D0A"
self.startOfTheFrameL = 0x26
self.startOfTheFrameH = 0x21
self.endOfTheFrameL = 0x0D
self.endOfTheFrameH = 0x0A
self.connection = SerialConnection()
def read(self,length,type,propertyData = []):
self.datagram = []
self.datagram.extend([startOfTheFrameL,startOfTheFrameH])
self.connection.serial_write(self.dataGram)
When I press the button only one time. I get correct value. But If I press second-three-third.. time I get wrong values.
But if I add below lines:
self.connection.connection_close()
self.connection.connection_start()
end of the get_property_list function, I get correct value everytime.
Is there any other way to do this? Do I have to close and open the connection every time?
Related
I want to create and maintain multiple non-blocking serial connections with some peripherals over UART. Truthfully, this is an expansion of this question about tkinter and multithreading
Domarm suggests the following as a solution to the original question of creating a new thread to handle receiving serial data without blocking the main script. (In the code below I left out the Raw data reader class for simplicity here).
import tkinter as tk
from serial import Serial
from serial.threaded import ReaderThread, Protocol, LineReader
class SerialReaderProtocolLine(LineReader):
tk_listener = None
TERMINATOR = b'\n\r'
def connection_made(self, transport):
"""Called when reader thread is started"""
if self.tk_listener is None:
raise Exception("tk_listener must be set before connecting to the socket!")
super().connection_made(transport)
print("Connected, ready to receive data...")
def handle_line(self, line):
"""New line waiting to be processed"""
# Execute our callback in tk
self.tk_listener.after(0, self.tk_listener.on_data, line)
class MainFrame(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.listbox = tk.Listbox(self)
self.listbox.pack()
self.pack()
def on_data(self, data):
print("Called from tk Thread:", data)
self.listbox.insert(tk.END, data)
if __name__ == '__main__':
app = tk.Tk()
main_frame = MainFrame()
# Set listener to our reader
SerialReaderProtocolLine.tk_listener = main_frame
# Initiate serial port
serial_port = Serial("/dev/ttyUSB0")
# Initiate ReaderThread
reader = ReaderThread(serial_port, SerialReaderProtocolLine)
# Start reader
reader.start()
app.mainloop()
This solution works well for a single connection, but what if I want to expand this so I can manage multiple connections at once?
Since this code structure is using the SerialReaderProtocolLine class variable tk_listener, I am unsure of how to go about making this modular so that I can create multiple ReaderThreads with each their own listeners.
Here is an example of me trying to move the class variable tk_listener into a constructor to allow for the creation of a new instance of SerialReaderProtocolLine, which I then try to pass into a new ReaderThread. From that, I get a type error, "TypeError: 'SerialReaderProtocolLine' object is not callable". This error is thrown when I try to pass an instance of SerialReaderProtocolLine to ReaderThread.
import tkinter as tk
from serial import Serial
from serial.threaded import ReaderThread, LineReader
class SerialReaderProtocolLine(LineReader):
def __init__(self, listener, *args, **kwargs):
super().__init__(*args, **kwargs)
self.tk_listener = listener
self.TERMINATOR = b'\n\r'
def connection_made(self, transport):
"""Called when reader thread is started"""
if self.tk_listener is None:
raise Exception("tk_listener must be set before connecting to the socket!")
super().connection_made(transport)
print("Connected, ready to receive data...")
def handle_line(self, line):
"""New line waiting to be processed"""
# Execute our callback in tk
self.tk_listener.after(0, self.tk_listener.on_data, line)
class MainFrame(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.listbox = tk.Listbox(self)
self.listbox.pack()
self.pack()
def on_data(self, data):
print("Called from tk Thread:", data)
self.listbox.insert(tk.END, data)
if __name__ == '__main__':
app = tk.Tk()
main_frame1 = MainFrame()
main_frame2 = MainFrame()
# Set listener to our reader
reader_listener1 = SerialReaderProtocolLine(main_frame1)
reader_listener2 = SerialReaderProtocolLine(main_frame2)
# Initiate serial port
serial_port1 = Serial("/dev/ttyUSB0")
serial_port2 = Serial("/dev/ttyUSB1")
# Initiate ReaderThread
reader1 = ReaderThread(serial_port1, reader_listener1)
reader2 = ReaderThread(serial_port2, reader_listener2)
# Start reader
reader1.start()
reader2.start()
app.mainloop()
So because it looks like ReaderThread is trying to create a new instance of SerialProtocolLine, I now try a different approach where I pass the SerialProtocolLine class twice to two different ReaderThread constructors. I reassign the tk_listener class variable inbetween ReaderThread instantiation calls...and this bluescreens my computer upon the first receipt of data!
if __name__ == '__main__':
app = tk.Tk()
main_frame0 = MainFrame()
main_frame1 = MainFrame()
# Set listener to our reader
SerialReaderProtocolLine.tk_listener = main_frame0
serial_port0 = Serial("/dev/ttyUSB0")
reader0 = ReaderThread(serial_port0, SerialReaderProtocolLine)
# Initiate serial port
SerialReaderProtocolLine.tk_listener = main_frame1
serial_port1 = Serial("/dev/ttyUSB1")
reader1 = ReaderThread(serial_port1, SerialReaderProtocolLine)
# Start reader
reader0.start()
reader1.start()
app.mainloop()
Any suggestions on how to go about making this modular?
You can pass the instance of MainFrame to SerialReaderProtocolLine class and use functools.partial to pass this extra argument in ReaderThread(...).
Below is the updated code (note that my platform is Windows, so the com ports used are "COM1" and "COM3", change them to the com ports in your platform):
from functools import partial
import tkinter as tk
from serial import Serial
from serial.threaded import ReaderThread, LineReader
class SerialReaderProtocolLine(LineReader):
def __init__(self, tk_listener):
super().__init__()
self.tk_listener = tk_listener
def connection_made(self, transport):
super().connection_made(transport)
self.handle_line(f"Connected {self.tk_listener}, ready to receive data ...")
def handle_line(self, line):
self.tk_listener.after(1, self.tk_listener.on_data, line)
class MainFrame(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.listbox = tk.Listbox(self, width=60)
self.listbox.pack()
#self.pack() # it is not recommended to pack itself, let the parent do it
def on_data(self, data):
print("Called from tk Thread:", data)
self.listbox.insert(tk.END, data)
if __name__ == "__main__":
app = tk.Tk()
main_frame1 = MainFrame(app, name="listener1")
main_frame2 = MainFrame(app, name="listener2")
main_frame1.pack(side="left")
main_frame2.pack(side="left")
serial_port1 = Serial("COM1") # change to your required port name
serial_port2 = Serial("COM3") # change to your required port name
reader1 = ReaderThread(serial_port1, partial(SerialReaderProtocolLine, main_frame1))
reader2 = ReaderThread(serial_port2, partial(SerialReaderProtocolLine, main_frame2))
reader1.start()
reader2.start()
app.mainloop()
The result:
I am trying to make an Uart Class in python which can receive data and send it. The meaning for my program is so that I can just use it as a driver and put it in the constructor and get the data I want, for example: Uart = uart(arg1, arg2) where arg1 sends a number or a string for what kind of data I need, FX. Temperature or water level, and arg2 is the data I receive.
import serial
import time
class uart():
uart = serial.Serial('/dev/serial0', baudrate=9600)
def __init__(self, write, read):
self.read = read
self.write = write
def read(self, read):
if uart.isopen():
try:
while True:
self.value = uart.readline()
return self.value
except:
print("failed to recive data")
def write(self, write):
if uart.isopen():
try:
self.uart.write()
finally:
print("sent")
time.sleep(1)
if __name__ == '__main__':
myPh = uart("22",'')
Okay, i tried something more easy and i got the read def running, but the write wont work like i want i too..
import serial
import time
class uart(object):
uart = serial.Serial('/dev/serial0', baudrate=9600)
# def __init__(self, write, read):
# self.read = read()
# self.write = write()
def write(self):
self.uart.write()
print("sent")
time.sleep(3)
def read(self):
while True:
self.value = uart.readline()
time.sleep(2)
print(self.value)
return self.value
if __name__ == '__main__':
while True:
myTemp = uart()
myTemp.write('hello')
myTemp.read()
I have been trying to Inherit the self.Arduino from the GetData Class to the GUI class. So in order to do this I simply added this line of code.
class GUI(QMainWindow, Ui_MainWindow, GetData):
I thought it would inherit the self.Arduino but it did not.Obviously I am doing something wrong but I don't understand what.
Here is my code
class GetData(QThread):
ChangedData = pyqtSignal(float, float, float, float)
def __init__(self, parent=None):
QThread.__init__(self, parent)
arduino_ports = [ # automatically searches for an Arduino and selects the port it's on
p.device
for p in serial.tools.list_ports.comports()
if 'Arduino' in p.description
]
if not arduino_ports:
raise IOError("No Arduino found - is it plugged in? If so, restart computer.")
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
self.Arduino = serial.Serial(arduino_ports[0], 9600, timeout=1)
def __del__(self): # part of the standard format of a QThread
self.wait()
def run(self): # also a required QThread func tion, the working part
import time
self.Arduino.close()
self.Arduino.open()
self.Arduino.flush()
self.Arduino.reset_input_buffer()
start_time = time.time()
while True:
while self.Arduino.inWaiting() == 0:
pass
try:
data = self.Arduino.readline()
dataarray = data.decode().rstrip().split(',')
self.Arduino.reset_input_buffer()
Pwm = round(float(dataarray[0]), 3)
Distance = round(float(dataarray[1]), 3)
ArduinoTime = round(float(dataarray[2]), 3)
RunTime = round(time.time() - start_time, 3)
print(Pwm, 'Pulse', ",", Distance, 'CM', ",", ArduinoTime, "Millis", ",", RunTime, "Time Elasped")
self.ChangedData.emit(Pwm, Distance, ArduinoTime , RunTime)
except (KeyboardInterrupt, SystemExit, IndexError, ValueError):
pass
class GUI(QMainWindow, Ui_MainWindow, GetData):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.Run_pushButton.setEnabled(True)
self.Run_pushButton.clicked.connect(self.btn_run)
def Display_data(self):
self.thread = GetData(self)
self.thread.ChangedData.connect(self.onDataChanged)
self.thread.start()
self.Stop_pushButton.setEnabled(True)
self.Stop_pushButton.clicked.connect(self.btn_stop)
def onDataChanged(self, Pwm, Distance, ArduinoTime, RunTime):
self.Humid_lcdNumber_2.display(Pwm)
self.Velocity_lcdNumber_3.display(Distance)
self.Pwm_lcdNumber_4.display(ArduinoTime)
self.Pressure_lcdNumber_5.display(RunTime)
self.widget_2.update_plot(Pwm, RunTime)
def btn_run(self):
p1 = 1
p2 = self.InputPos_Slider.value()
the_bytes = bytes(f'<{p1},{p2}>\n', 'utf-8')
a = self.Arduino.write(the_bytes)
def btn_stop(self):
p1 = 0
p2 = 0
the_bytes = bytes(f'<{p1},{p2}>\n', 'utf-8')
a = self.Arduino.write(the_bytes)
It gave me this error , I thought I can simply inherit self.arduino but failed to do so.
Traceback (most recent call last):
File "C:\Users\Emman\Desktop\5th year\1THESIS\Python Program\C2_Final_PID.py", line 373, in btn_run
self.Arduino.write(the_bytes)
AttributeError: 'GUI' object has no attribute 'Arduino'
Looks like you have forgotten to initialize GetData:
class GUI(QMainWindow, Ui_MainWindow, GetData):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
GetData.__init__(self, parent) # this is the missing line
self.setupUi(self)
self.Run_pushButton.setEnabled(True)
self.Run_pushButton.clicked.connect(self.btn_run)
(Note you may need to do the same for Ui_MainWindow.)
I'm not quite sure why my application does not receive the message that is being sent to it. It appears the message is being sent. I looked at this example as reference.
how to listen to a specific port in qt using QTcpSocket?
I tried converting this c++ example as well and it didn't seem to send any messages as expected: QTcpSocket: reading and writing
The message being received should be printed to the console, however the bytes received always return 0.
import sys
from PyQt4 import QtNetwork, QtCore, QtGui
class Messenger(object):
def __init__(self):
super(Messenger, self).__init__()
self.TCP_HOST = '127.0.0.1' # QtNetwork.QHostAddress.LocalHost
self.TCP_SEND_TO_PORT = 7011
self.pSocket = None
self.listenServer = None
def slotSendMessage(self):
self.pSocket = QtNetwork.QTcpSocket();
self.pSocket.readyRead.connect(self.slotReadData)
self.pSocket.connectToHost(self.TCP_HOST, self.TCP_SEND_TO_PORT)
if not (self.pSocket.waitForConnected(1000)): # one second
print 'Unable to send data to port: "{}"'.format(self.TCP_SEND_TO_PORT)
return
cmd = "Hi there!"
print 'Command Sent:', cmd
ucmd = unicode(cmd, "utf-8")
self.pSocket.write(ucmd)
self.pSocket.waitForBytesWritten(1000)
# Do something with readData
self.pSocket.disconnectFromHost()
self.pSocket.waitForDisconnected(1000)
def slotReadData(self):
print 'Reading data:', self.pSocket.readAll()
# QByteArray data = pSocket->readAll();
class Client(QtCore.QObject):
def __init__(self, parent=None):
QtCore.QObject.__init__(self)
def SetSocket(self, Descriptor):
self.socket = QtNetwork.QTcpSocket(self)
self.connect(self.socket, QtCore.SIGNAL("connected()"), QtCore.SLOT(self.connected()))
self.connect(self.socket, QtCore.SIGNAL("disconnected()"), QtCore.SLOT(self.disconnected()))
self.connect(self.socket, QtCore.SIGNAL("readyRead()"), QtCore.SLOT(self.readyRead()))
self.socket.setSocketDescriptor(Descriptor)
print "Client Connected from IP %s" % self.socket.peerAddress().toString()
def connected(self):
print "Client Connected Event"
def disconnected(self):
print "Client Disconnected"
def readyRead(self):
msg = self.socket.readAll()
print type(msg), msg.count()
print "Client Message:", msg
class Server(QtCore.QObject):
def __init__(self, parent=None):
QtCore.QObject.__init__(self)
self.TCP_LISTEN_TO_PORT = 7011
def incomingConnection(self, handle):
print "Incoming Connection..."
self.client = Client(self)
self.client.SetSocket(handle)
def StartServer(self):
self.server = QtNetwork.QTcpServer()
self.server.incomingConnection = self.incomingConnection
if self.server.listen(QtNetwork.QHostAddress.Any, self.TCP_LISTEN_TO_PORT):
print "Server is listening on port: {}".format(self.TCP_LISTEN_TO_PORT)
else:
print "Server couldn't wake up"
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.setWindowTitle('TCP/Server')
self.resize(300, 300)
self.uiConnect =QtGui.QPushButton('Connect')
# layout
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.uiConnect)
self.widget = QtGui.QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
# Connections
self.uiConnect.clicked.connect(self.setup)
def setup(self):
server = Server()
server.StartServer()
tcp = Messenger()
tcp.slotSendMessage()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You make the following mistakes:
You should not use the waitForXXX methods since they are blocking, preventing the eventloop from executing and consequently the slots connected to the signals are not invoked.
It is not necessary to do self.server.incomingConnection = self.incomingConnection, it is like overwriting the class without using inheritance so you can generate problems, instead use the signal newConnection that indicates when there is a new connection and use nextPendingConnection() to get the socket.
Considering the above, the solution is:
import sys
from PyQt4 import QtCore, QtGui, QtNetwork
class Messenger(object):
def __init__(self):
super(Messenger, self).__init__()
self.TCP_HOST = "127.0.0.1" # QtNetwork.QHostAddress.LocalHost
self.TCP_SEND_TO_PORT = 7011
self.pSocket = None
self.listenServer = None
self.pSocket = QtNetwork.QTcpSocket()
self.pSocket.readyRead.connect(self.slotReadData)
self.pSocket.connected.connect(self.on_connected)
self.pSocket.error.connect(self.on_error)
def slotSendMessage(self):
self.pSocket.connectToHost(self.TCP_HOST, self.TCP_SEND_TO_PORT)
def on_error(self, error):
if error == QtNetwork.QAbstractSocket.ConnectionRefusedError:
print(
'Unable to send data to port: "{}"'.format(
self.TCP_SEND_TO_PORT
)
)
print("trying to reconnect")
QtCore.QTimer.singleShot(1000, self.slotSendMessage)
def on_connected(self):
cmd = "Hi there!"
print("Command Sent:", cmd)
ucmd = unicode(cmd, "utf-8")
self.pSocket.write(ucmd)
self.pSocket.flush()
self.pSocket.disconnectFromHost()
def slotReadData(self):
print("Reading data:", self.pSocket.readAll())
# QByteArray data = pSocket->readAll();
class Client(QtCore.QObject):
def SetSocket(self, socket):
self.socket = socket
self.socket.connected.connect(self.on_connected)
self.socket.disconnected.connect(self.on_connected)
self.socket.readyRead.connect(self.on_readyRead)
print(
"Client Connected from IP %s" % self.socket.peerAddress().toString()
)
def on_connected(self):
print("Client Connected Event")
def on_disconnected(self):
print("Client Disconnected")
def on_readyRead(self):
msg = self.socket.readAll()
print(type(msg), msg.count())
print("Client Message:", msg)
class Server(QtCore.QObject):
def __init__(self, parent=None):
QtCore.QObject.__init__(self)
self.TCP_LISTEN_TO_PORT = 7011
self.server = QtNetwork.QTcpServer()
self.server.newConnection.connect(self.on_newConnection)
def on_newConnection(self):
while self.server.hasPendingConnections():
print("Incoming Connection...")
self.client = Client(self)
self.client.SetSocket(self.server.nextPendingConnection())
def StartServer(self):
if self.server.listen(
QtNetwork.QHostAddress.Any, self.TCP_LISTEN_TO_PORT
):
print(
"Server is listening on port: {}".format(
self.TCP_LISTEN_TO_PORT
)
)
else:
print("Server couldn't wake up")
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.setWindowTitle("TCP/Server")
self.resize(300, 300)
self.uiConnect = QtGui.QPushButton("Connect")
# layout
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.uiConnect)
self.widget = QtGui.QWidget()
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
# Connections
self.uiConnect.clicked.connect(self.setup)
def setup(self):
self.server = Server()
self.server.StartServer()
self.tcp = Messenger()
self.tcp.slotSendMessage()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
For a few weeks I'm stuck with, how to open a serial COM port from a thread,
to be able to write/read it from another thread. In my example, when I write to the port from another thread, there is access denied.
When I open the port from Main GUI, it works fine, I can write it from the thread, but I need to give a user possibility to choose the COM number.
This is my code, if anybody could take a look and help, it would be great...
class Connect(QThread):
connectResult = QtCore.pyqtSignal(str)
position1 = QtCore.pyqtSignal(str)
actuPosResult = QtCore.pyqtSignal(str)
def __init__(self, myvar, parent=None):
QThread.__init__(self, parent)
self.myvar = str(myvar) # value from spinbox
def run(self):
self.pserial = serial.Serial()
try:
COMnumber= self.myvar
self.pserial = serial.Serial('COM'+COMnumber, 115200,timeout=None)
r='COM '+COMnumber+' connected.'
self.pserial.write("c".encode('ascii')+"\n".encode('ascii'))
incomingByte = self.pserial.read()
decodedByte = incomingByte.decode("utf-8")
if decodedByte == ('c'):
r='Atmega On-Line'
self.connectResult.emit(r)
pos1='---'
self.position1.emit(pos1)
else :
r=' No answer from Atmega.'
self.connectResult.emit(r)
def stop(self):
self.terminate()
class ReadingEncoder(QThread):
actuPosResult = QtCore.pyqtSignal(str)
def __init__(self, mojazmienna, parent=None):
QThread.__init__(self, parent)
self.mojazmienna = str(mojazmienna)
def run(self):
Try:
self.pserial = serial.Serial()
self.pserial = serial.Serial('COM3', 115200,timeout=1)
self.pserial.write("p".encode('ascii')+"\n".encode('ascii'))
incomingByte = self.pserial.read()
decodedByte = incomingByte.decode("utf-8")
actualPos = ''
if decodedByte == ('a'):
while decodedByte != ('\n'):
incomingByte = self.pserial.read()
decodedByte = incomingByte.decode("utf-8")
actualPos = actualPos + decodedByte
pos= actualPos.rstrip('\n')# pozycja w formacie string
print(pos)
self.actuPosResult.emit(pos)
except (EOFError, OSError, IOError, ValueError, RuntimeError, BrokenPipeError, InterruptedError, TimeoutError):
print('Thread readingEncoder error')
self.pserial.close()
You just open the serial port and start the thread.
import atexit
class SerialPort(QThread):
connectResult = QtCore.pyqtSignal(str)
position1 = QtCore.pyqtSignal(str)
actuPosResult = QtCore.pyqtSignal(str)
def __init__(self, port=None, baud=115200, timeout=1):
super().__init__()
self.ser = serial.Serial()
self.ser.port = port
self.ser.baudrate = baud
self.ser.timeout = timeout
self.running = False
atexit.register(self.ser.close) # Make sure the serial port closes when you quit the program.
def set_port(port_num):
self.ser.port = "COM"+str(port_num)
def start(self, *args, **kwargs):
self.running = True
self.ser.open()
super().start()
self.ser.write("c\n".encode("ascii"))
def run(self):
while self.running:
try:
incomingByte = self.ser.read()
decodedByte = incomingByte.decode("utf-8")
if decodedByte == ('c'):
r='Atmega On-Line'
self.connectResult.emit(r)
pos1='---'
self.position1.emit(pos1)
else:
r=' No answer from Atmega.'
self.connectResult.emit(r)
except:
pass
# time.sleep(0.01) # You may want to sleep or use readline
You use this class by having a button call the start method.
serial = SerialPort("COM3")
btn = QtGui.QPushButton("Connect")
btn.clicked.connect(serial.start)
You can typically only open a serial port once unless you know that you have both ends available to you.
The serial port exists on the main thread and exists the entire time. You don't need to continuously open and close the serial port. All of the reading happens in the thread. To write just call serial.write(b"c\n"). You shouldn't need the writing to happen in the thread.
To have the user select the com port just use a QLineEdit.
myserial = QtGui.QLineEdit("3")
myserial.textChanged.connect(serial.set_port)
You're trying to open the port multiple times.
Instead of doing that, you have a couple of alternatives;
Create a Serial object once, and pass it to the thread that has to work with it.
Provide the name of the serial port to use to the the thread that has to work with it, and let it open the port.
In both cases make sure that your thread closes the port properly when it exits!