QSerialPort issues - error signals, plugging/unplugging quickly, unable to do "open" ever
-
Hi everyone,
I'm running into the following issues with "QSerialPort 5.2":http://qt-project.org/doc/qt-5/qserialport.html while doing serial communication with a custom Arduio Lenoardo:
- If I unplug the USB cable exactly when__ the program is in the process of "open" call, I get an error back and I am never able to open that port with my timer retry approach. Even if I restart the app, I cannot open that port any more. If I plug the device back in another port, then it can open it. The only way to fix this state is if I am restart the app with the cable NOT plugged in that initial port.
On error, I am reattempting opening the serial port every 6 seconds. The QSerialPortInfo's list of ports actually finds the right serial port (with the right product ID and vendor ID) but it cannot open it. I also check "isOpen" to be false, before calling open again (after the cable is unplugged ie) but that call returns false. I also check if the QSerialPortInfo is busy but that check never turns true.
These checks can be seen in the function "initializeComm" below.
- If the USB cable is unplugged, the "error signal":http://qt-project.org/doc/qt-5/qserialport.html#error-prop is never emitted. I only get the error signal if I attempt to do a write operation AFTER the cable is unplugged. So the only way I can keep the UI updated is by having a timer and do some dummy write to the serial port (I am doing it every 3 seconds now); I get a error signal to my slot then.
The #1 issue here is definitely a big problem since #2 at least has a work around (al though, not ideal since it is not instant UI update).
I am running:
Qt Creator 3.0.1
Based on Qt 5.2.1 (MSVC 2010, 32 bit)
Built on Jan 31 2014 at 05:16:27
From revision 51af63bb9e
Windows 7 Professional 64bitFor reference, here is the code below. Any help would be greatly appreciated.
Thanks.
@
...
//Constructors and destructors...
// Note: calling "delete" (from the destructor) on the opened QSerialPort crashes the program. I do "deleteLater" to fix thatvoid onTimerEvent() {
// Try to connect to the serial port everytime
if (_serialPort == NULL || !_serialPort->isOpen()) {
// the port is either null or not open. So retry again with the timer logic
if (! this->initializeComm() ) {
} else {
_timer->setInterval(CHECK_SERIAL_INTERNAL); // since the serial connection is fine now, recheck this step with this internal
// the other error interval retry would be set from the error handler
}
} else {
// write something, just to detect the error if the cable is already unplugged (to clear items from the UI)
char dummyCharArray[1];
dummyCharArray[0] = DUMMY_CHAR_WRITE;
_serialPort->write(dummyCharArray);
}
_timer->start();
}
...bool initializeComm() {
QList<QSerialPortInfo> allPorts = QSerialPortInfo::availablePorts();
int numPorts = allPorts.size();QSerialPortInfo currPortInfo; for (int i=0; i<numPorts; i++) { currPortInfo = allPorts[i]; if ( currPortInfo.isBusy()) {//shows err msg here } else if ( currPortInfo.vendorIdentifier() == VENDOR_ID && currPortInfo.productIdentifier() == PRODUCT_ID ) { _serialPort = new QSerialPort(currPortInfo); connect(_serialPort, SIGNAL(readyRead()), this, SLOT(readData())); connect(_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError))); if ( _serialPort->isOpen()) { return false; } if ( !_serialPort->open(QIODevice::ReadWrite) ) { return false; } if ( !_serialPort->setBaudRate(BAUDRATE)) { return false; } return true; } } return false;
}
// Right now, only being invoked after an error comes through
void stopComm() {if ( _serialPort == NULL) { return; } if ( ! disconnect(_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError))) ) {
//ERR MSG
}
if (_serialPort->isOpen()) {
if ( _serialPort->clear()) {
//ERR MSG
}
}
if ( ! disconnect ( _serialPort, SIGNAL(readyRead()), this, SLOT(readData()) ) ) {
//ERR MSG
}
if (_serialPort->isOpen()) {
_serialPort->close();
}
_serialPort->deleteLater();
//delete _serialPort; // TODO: deleting _serialPort might be causing the crash, when usb is unplugged and we try to write to it. Investigate again
_serialPort = NULL; //setting it to NULL cause that is what we will be using to check if serial port communication is still valid
// Since the communication with the serial port is disabled by now, clear all the UI items
emit UIExtension::getSingletonInstance()->setClearItems(true);
}void handleError(QSerialPort::SerialPortError errorSent) {
if ( _serialPort != NULL ) {
//ERR MSG
}switch (errorSent) { case QSerialPort::NoError: // Don't do anything. For some reason, this is sent whenever the port is actually opened properly. NOT AN ERROR-- break; default: // For now, just close everything for any error // Since there is an error (possible usb cable unplugged), change the re-attempt interval accordingly _timer->setInterval(ERROR_RETRY_INTERVAL); // this is 6 seconds (6000 ms) this->stopComm(); break; }
}
@