July 6, 2012

Dolbyz Dolbyz
Lab Rat
7 posts

QtSerialPort and CPU usage

Page  
1

Hi

I wrote simple application that reads and writes data from serial device. For some reason after sending and receiving just single packet, my application uses 100% of cpu time. The send-button in application still works (at least for some time) and I still can send and receive data, but otherwise the UI gets sluggish and stops working properly.

Sometimes sending second packet clears the situation. Sometimes application works normally for hundred messages or so.

I took the QtSerialPort from git yesterday and I compiled it with nmake. I’m using QtCreator 2.4.1 and Qt 4.8.0 on win7 64.

I’m using “ATEN usb to serial bridge” to connect to the serial device. Connection settings are 19200 / no parity / one stop bit.

When mainwindow is created:

  1. sp = new SerialPort();
  2.  
  3. connect(sp,SIGNAL(readyRead()), this, SLOT(readyRead()));

When connect is clicked

  1. void MainWindow::on_connectButton_clicked()
  2. {
  3.     qDebug()<< "on_connectButton_clicked";
  4.     if (!connected)
  5.     {
  6.         QIODevice::OpenMode mode = QIODevice::ReadWrite;
  7.  
  8.         sp->setPort(ui->comCB->currentText()); // e.g. COM13
  9.  
  10.         if (sp->open(mode))
  11.         {
  12.             ..setup other connection settings from ui here
  13.             // Set new settings
  14.             if (sp->setRate(rate) &&
  15.                 sp->setDataBits(SerialPort::Data8) &&
  16.                 sp->setParity(parity) &&
  17.                 sp->setStopBits(stopBits) &&
  18.                 sp->setFlowControl(SerialPort::NoFlowControl))
  19.             {
  20.                 ui->console->appendPlainText("Connection settings set successfully");
  21.                
  22.                 connected = true;
  23.                 ui->connectButton->setText("Close");
  24.             }
  25.             else
  26.             {
  27.                 ui->console->appendPlainText("Setting connection settings FAILED!");
  28.             }
  29.         }
  30.         else
  31.         {
  32.             ui->console->appendPlainText("Opening COM port FAILED!");
  33.         }
  34.     }
  35.     else
  36.     {
  37.         sp->close();
  38.         connected = false;
  39.         ui->connectButton->setText("Connect");
  40.     }
  41. }

When sending data (here I just tested taking the data in to member variable, previously I used the ‘data’ directly):

  1. void MainWindow::send(QByteArray data)
  2. {
  3.     delete iSendBuf;
  4.     iSendBuf = NULL;
  5.  
  6.     iSendBuf = new QByteArray(data);
  7.  
  8.     if (sp->write(*iSendBuf))
  9.     {
  10.         qDebug() << "Wrote data.";
  11.     }
  12.     else
  13.     {
  14.         qDebug() << "Write FAILED.";
  15.     }
  16. }

And receiving data:

  1. void MainWindow::readyRead()
  2. {    
  3.     QString str;
  4.     QByteArray* bytes = new QByteArray(sp->readAll());
  5.  
  6.     qDebug()<< "readyRead - len: " + QString::number(bytes->length());
  7.  
  8.     if (ui->showAsHexCHB->isChecked())
  9.     {
  10.         str = fromArray(*bytes); // converts bytes to hex string
  11.     }
  12.     else
  13.     {
  14.         str.append(*bytes);
  15.     }
  16.  
  17.     ui->console->appendPlainText("Received: "+str);
  18.     delete bytes;
  19.  
  20. }

Any ideas? I’m doing something wrong?

Dolbyz

17 replies

July 6, 2012

franku franku
Hobby Entomologist
132 posts

1. What about the bytes Array, is it zero terminated? 2. You may want to put a debug message into each send and readyRead function to figure out where the application hangs. 3. Comment out each line of code until you get it.

4. In Addition you could connect the serialPort with the Mainwindow asynchronous, using Qt::QueuedConnection, since there might be another thread working than the MainWindow thread (using QThread::currentThreadId() shows the current context’s thread id).

5. Besides, it is not advisable to write from an external thread into the UI nor read the data buffered from another thread without synching the threads as you did in readyByte as this can cause a reace condition. (Maybe I am wrong and someone can do this with QtSp.)

 Signature 

Keep in mind: This, Jen, is the internet.
.. frank

July 6, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

I’m doing something wrong?

Maybe this wrong:

  1. ...
  2. iSendBuf = new QByteArray(data);
  3. ...
  4. QByteArray* bytes = new QByteArray(sp->readAll());

No need to call operator new().

It is possible that your “ATEN usb to serial bridge” has a bad driver, try check on any other chip, such as FTDI or Prolific, but it’s better – the “native” serial port on the motherboard (if available).

July 6, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

2 franku,

What about the bytes Array, is it zero terminated?

So what?

Besides, it is not advisable to write from an external thread into the UI nor read the data buffered from another thread without synching the threads as you did in readyByte as this can cause a reace condition. (Maybe I am wrong and someone can do this with QtSp.)

Why are external threads? Here, they are not needed.

July 6, 2012

DerManu DerManu
Robot Herder
451 posts

1.) run in debug mode and stop execution a few times. Usually you land in the problematic section when having problems like these. (You’ll need the debug version of your serial library to find the problem inside it though).

2.) profile your application with valgrind and find out where the CPU-eater is.

July 7, 2012

Dolbyz Dolbyz
Lab Rat
7 posts

I’ll check do I have other usb to serial bridge-cables(on monday when I get back to work). I have only a laptop and it does not have any “native” serial ports.

My program is really simple. It has only the mainwindow-class which contains all the code. I don’t have there anything that could cause this cpu usage. I yesterday added debug prints to all slots (and other methods) in my program + I added prints also to QtSerialPort (all methods and to all while-loops). No prints were coming when cpu usage was 100%.

I’m using windows so I can’t use valgrind. I’ll have to check it with debugger, but I would need debug versions of the windows dll’s used in serial port connections?

I’m actually developing something in embedded device with c which uses serial port. Purpose of this Qt application was just to send few “hardcoded” messages (at least for now) to check the functionality and response messages.

Thanks for the advices.

July 7, 2012

franku franku
Hobby Entomologist
132 posts

QByteArray may not be zero terminated – forget this.

Some ideas, try harder to figure out where actually the cpu time is consumed. We can only see the code you’ve applied but in my opinion you should look into the send signal and (more possible) the receive slot. Try to remove the lines from the above code until it stops hanging. Maybe it is hanging in some procedure you don’t have the code for and you don’t see the while loop where it is cycling. You may also look into the rest of your code, sometimes someone programs a recursive statement unintended especially when you filled up everything into a single class.

good look!

 Signature 

Keep in mind: This, Jen, is the internet.
.. frank

July 7, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

2Dolbyz,

Previously had a similar problem with the CPU load, using the USB / Serial converter chip Prolific. The problem was that in a false fire notifier QWinEventNotifier at data receiving. Presumably the reason is the driver, although it is difficult to say. Previously, I seems to be fixed this problem, though .. I try will check again.

July 9, 2012

Dolbyz Dolbyz
Lab Rat
7 posts

My colleague found another usb-to-serial cable (USB-SERIAL CH340 wch.cn). It works perfectly.

When I debugged with the old cable it seemed to loop in qevendispatcher_win.cpp:770 for loop. With the old cable I got from two to eight readyRead-signals (message length about 16 bytes). With this “new” cable, just single signal with whole data.

Thanks for your help.

July 25, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

Please try to fix the code in the source code library QtSerialPort to test, as described here [bugreports.qt-project.org] and take there is an example of an attached [bugreports.qt-project.org] for testing.

July 25, 2012

Dolbyz Dolbyz
Lab Rat
7 posts

I tried this fix. The problem still occurs. I used my own code for testing.

For second try I put debug print to that event-function. I guess it was called “few” times, because then qt creator jammed too :)

July 25, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

Bad bad bad. I do not have ideas how to fix it.

July 25, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

UPD: Please try repeat test with new test tool CpuUsageTester [bugreports.qt-project.org]

July 26, 2012

Dolbyz Dolbyz
Lab Rat
7 posts

It works exactly same way with this test application.

July 26, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

Clear, thx

So, most likely a problem in the drivers.

August 6, 2012

kuzulis kuzulis
Hobby Entomologist
125 posts

2 Dolbyz,

Please check CPU load with a new concept from here [codereview.qt-project.org]

PS: If you have free time.

Page  
1

  ‹‹ direction problem      Insert new rows into database using QSqlTableModel ››

You must log in to post a reply. Not a member yet? Register here!