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:

    1. 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.

    1. 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 64bit

    For 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 that

    void 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;
    }
    

    }
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.