Serial Communication Problems



  • Hi all
    I am using QtSerialPort to communicate between my PC and hardware.
    I am using separate thread to send data periodically, Problem (a) is that I need to perform opening and closing of the port after each data sent which I don't want to do because I am also receiving data. Problem (b) is that I am unable to receive data. Minimum code for my application is as under:

    void QtSerialApp::initializeSerialPort()
    {
    	mySerialPort.setBaudRate(QSerialPort::Baud9600);
    	mySerialPort.setFlowControl(QSerialPort::NoFlowControl);
    	mySerialPort.setDataBits(QSerialPort::Data8);
    	mySerialPort.setStopBits(QSerialPort::OneStop);
    	mySerialPort.setParity(QSerialPort::NoParity);
    }
    
    void QtSerialApp::mySerialThread(void)
    {
    	while (threadRun)
    	{
    
    		Sleep(300);
    		mySerialPort.open(QIODevice::ReadWrite);
    		dataToWrite = QString("1").toLocal8Bit();
    		mySerialPort.write(dataToWrite);		
    		
    		qint64 bytesAvailable = 0;
    		bytesAvailable = mySerialPort.bytesAvailable();
    
    		if(true == mySerialPort.waitForReadyRead(200))
    		{
    			ui.label_Log->setText("ERROR");
    		}
    		
    		mySerialPort.clear(QSerialPort::AllDirections);
    		mySerialPort.close();
    	}
    }
    


  • I would do it something like this:

    void MySerialThread::run(void)       // MySerialThread is a subclass of QThread
    {
        mySerialPort.setBaudRate(QSerialPort::Baud9600);
        mySerialPort.setFlowControl(QSerialPort::NoFlowControl);    
        mySerialPort.setDataBits(QSerialPort::Data8);
        mySerialPort.setStopBits(QSerialPort::OneStop);
        mySerialPort.setParity(QSerialPort::NoParity);
    
        mySerialPort.open(QIODevice::ReadWrite);
    
        d_stop_requested = false;
    
        do
        {
            if(mySerialPort.getChar(&RxBuffer[ActualRead]))
            {
                ActualRead++;
                // do something with the data                
            }
            else if(TxBuffer.size())
            {
                mySerialPort.write(TxBuffer,TxBuffer.size());
            }
            else
            {
                 this->msleep(50);    // nothing to read or write.  might as well sleep. (maybe update feedback to parent).
            }
    
        }while(!d_stop_requested);    // set to true from parent thread to exit
    
        mySerialPort.clear(QSerialPort::AllDirections);
        mySerialPort.close();
    }
    

    There are different ways to use a thread. If it is something like a long calculation there is a way to do this without creating a sub class. There was a post about this a few years back. For serial this works pretty good (there are lots of utility functions you will probably need to add to this subclass in order to deal with things like no responses to commands, formatting data to write, ...).

    You should not have the close command inside your loop (if I understand your sample program).



  • Thank you for reply. But the problem is that I have to open and close the port within the thread for each thread cycle. If I don't do this, like you suggested, I can write data only for the first time. And next times time out is occurring. Please help.


  • Moderators

    @Engr-abxis Why do you have to initialize serial port every time? Isn't your thread running as long as your application is running? In the code from @Rondog the serial port is only initialized once when the thread is started (at the beginning of the run() method). So, how do you use the thread? Do you start it each time you want to do something, or is it running all the time?



  • It is running all the time.
    When I don't close and open the port at each thread cycle I get timeout.
    When I close and open the port at each thread cycle I could be able to send the data.
    Still in need of help.



    1. Problem is not in "serial communication"; problem is in your code.
    2. Do not use threads at all.
    3. Do not use blocking approach with waitFor(); use readyRead() signal instead.
    4. Using ui.label_Log->setText("ERROR"); from different thread it is a courageous course. :)


  • I created a separate thread like in the Blocking Slave example in Qt (Qt example also has a thread for serial communication). And I pasted my code in that example. My code works in that example but my code doesn't work in my own project.



  • Finally I figured out the problem. I was creating QSerialPort object in header file so that it will be accessible for every function in .cpp file. But when I closely looked through the Qt example for serial communication, although they created a separate thread, but they declared, initialized and did communication within that thread function. I did the same for my project. And IT WORKS!!!


Log in to reply
 

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