Results 1 to 6 of 6

Thread: No readyRead() signal from SerialPort, but (seemingly) same code works in another app

  1. #1
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    I've been using the QtSerialPort add-on with no issues for about 9 months in one application. But, when I use what I think is the same code in another application, I don't get the readyRead() signal when bytes have been sent to the serial port.

    I'm stuck on how to debug why it's not firing.

    No message is issued when the connect statement is executed. When I have a typo in a signal or slot name, I've seen error messages. So, I think that means the connect was ok.

    The open on the port succeeds along with configuration of the communication parameters, but a breakpoint on the first line of readData is never hit. Here's the relevant code:

    in main.h:
    Qt Code:
    1. class MainWindow : public QMainWindow, public Ui_MainWindow
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. MainWindow(QWidget *parent=0);
    7. SerialPort *serial;
    8. ...
    9. private slots:
    10. void writeData(const QByteArray &data);
    11. void readData();
    12. ...
    13. }
    To copy to clipboard, switch view to plain text mode 

    in main.cpp:
    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent)
    3. {
    4. setupUi(this);
    5.  
    6. ....
    7. serial = new SerialPort(this);
    8.  
    9.  
    10. if (serial_port_settings->setCurrentPort("COM47"))
    11. openSerialPort();
    12.  
    13. QObject::connect(serial, SIGNAL(readyRead()), this, SLOT(readData()));
    14.  
    15. }
    16. void MainWindow::openSerialPort()
    17. {
    18.  
    19. SettingsDialog::Settings p = serial_port_settings->settings();
    20.  
    21. serial->setPort(p.name);
    22. if (serial->open(QIODevice::ReadWrite)) {
    23. if (serial->setRate(p.rate)
    24. && serial->setDataBits(p.dataBits)
    25. && serial->setParity(p.parity)
    26. && serial->setStopBits(p.stopBits)
    27. && serial->setFlowControl(p.flowControl)) {
    28.  
    29.  
    30. statusbar->showMessage(tr("Connected to %1 : %2, %3, %4, %5, %6")
    31. .arg(p.name).arg(p.stringRate).arg(p.stringDataBits)
    32. .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl));
    33.  
    34. } else {
    35. serial->close();
    36. QMessageBox::critical(this, tr("Error"),
    37. tr("Can't configure the serial port: %1,\n"
    38. "error code: %2")
    39. .arg(p.name).arg(serial->error()));
    40.  
    41. statusbar->showMessage(tr("Open error"));
    42. }
    43. } else {
    44. QMessageBox::critical(this, tr("Error"),
    45. tr("Can't opened the serial port: %1,\n"
    46. "error code: %2")
    47. .arg(p.name).arg(serial->error()));
    48.  
    49. statusbar->showMessage(tr("Configure error"));
    50. }
    51. }
    52.  
    53.  
    54. void MainWindow::readData()
    55. {
    56. ...
    57. }
    To copy to clipboard, switch view to plain text mode 

    I can run the old application that has the same code fragments and use the same method to send characters to the serial port. It still works fine.

    More info--

    The new application uses openCv with a Qt enhancement. cvWaitKey() is called periodically instead of entering an event loop using exec().

    This has worked fine. The GUI is still responsive when the serial port should have received characters, yet no readyRead signal is generated. Is the fact that the GUI is still responsive (and my widget to widget signal/slots are working) sufficient to conclude the event loop isn't "broken", or is the mechanism somehow different for SerialPort?

    Any suggestions would be greatly appreciated!

    Windows 7

    Thanks,

    Dave Thomas


    Added after 21 minutes:


    I did a hack to my code and inserted a call to exec() before the main thread executed the loop with the cvWaitKey(10) command in it. The readyRead signal is issued!

    So, it's definitely has something to do with the eventLoop processing.

    Eventually, I need to rewrite the application to not use the Qt bolt-on that's and "experimental" bolt-on to openCv, but that's a big effort. Meanwhile, I'd like to get the SerialPort stuff working while using cvWaitKey().

    So, I guess the question becomes what's magic about exec() that's not under cvWaitKey(). I'll try finding source for both.

    Dave Thomas
    Last edited by davethomaspilot; 24th September 2013 at 16:24.

  2. #2
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    Added a call to QApplication:rocessEvents() right after the cvWaitKey(10) and everything works fine!

    I thought that's what the cvWaitKey did (among other things). And I don't understand why all my widgets were working fine, if the cvWaitkey wasn't calling processEvents or doing something equivalent.

    It works, but I want to understand better. So, I need to find the cvWaitKey source (with the Qt bolt experimental stuff), I guess unless someone smarter than me has a clue.

    Dave Thomas

  3. #3
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    cvWaitKey() does exactly that, it waits for up to x milliseconds for a keypress, then continues. cvWaitKey is part of OpenCV, it has nothing to do with Qt's event processing (or Qt at all). If you want the source for cvWaitKey() OpenCV is where you need to look.

    If Qt's event processing code is never executed then nothing is checking for bytes received, timers expired, and other events before translating these things into Qt events and signals. You can probably dispense with cvWaitKey() altogether using the Qt key press events on approrpiate widgets.

  4. #4
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    it has nothing to do with Qt's event processing (or Qt at all).
    I don't think that's true, when you build OpenCv with Qt support ( the symbolic HAVE_QT is defined) to get this function:

    http://docs.opencv.org/modules/highg...functions.html

    Before I really got "on board" with Qt, I was using openCv with their simple Gui functionality. This was a big enhancement, so I used it. I needed a much better Gui, and this enhancement got me looking at Qt. Later, I got better at Qt and have done many widgets and dialogs. All work fine--I think the only way events could get processed are calls to the cvWaitKey() function, since QApplication::exec() never gets called.

    I think I read that when you build OpenCv with Qt support, cvWaitKey() causes the event processing to occur. I'm still looking for where I read that, but certainly all the widgets work just fine without running an exec and only calling the cvWaitKey. And the gui becomes non-responsive if cvWaitKey is not executed periodically. Also, still trying to find the source for cvWaitKey() in openCv. I'll update the thread when I find it, for the benefit of anyone else who's gone down this path. But the trhead probably belongs on the OpenCv forum, not here, because if my guess is correct, cvWaitKey() at least sometimes doesn't seem to cause Qt events to be processed.

    Dave Thomas


    Added after 11 minutes:


    Here's the source for cvWaitKey in the openCV tree (higui/src/window_Qt.cpp) Note the call to processEvents()



    Qt Code:
    1. CV_IMPL int cvWaitKey(int delay)
    2. {
    3. int result = -1;
    4.  
    5. if (!guiMainThread)
    6. return result;
    7.  
    8. unsigned long delayms = delay <= 0 ? ULONG_MAX : delay; //in milliseconds
    9.  
    10. if (multiThreads)
    11. {
    12. mutexKey.lock();
    13. if (key_pressed.wait(&mutexKey, delayms)) //false if timeout
    14. {
    15. result = last_key;
    16. }
    17. last_key = -1;
    18. mutexKey.unlock();
    19. }
    20. else
    21. {
    22. //cannot use wait here because events will not be distributed before processEvents (the main eventLoop is broken)
    23. //so I create a Thread for the QTimer
    24.  
    25. if (delay > 0)
    26. guiMainThread->timer->start(delay);
    27.  
    28. //QMutex dummy;
    29.  
    30. while (!guiMainThread->bTimeOut)
    31. {
    32. qApp->processEvents(QEventLoop::AllEvents);
    33.  
    34. if (!guiMainThread)//when all the windows are deleted
    35. return result;
    36.  
    37. mutexKey.lock();
    38. if (last_key != -1)
    39. {
    40. result = last_key;
    41. last_key = -1;
    42. guiMainThread->timer->stop();
    43. //printf("keypressed\n");
    44. }
    45. mutexKey.unlock();
    46.  
    47. if (result!=-1)
    48. {
    49. break;
    50. }
    51. else
    52. {
    53. /*
    54.   * //will not work, I broke the event loop !!!!
    55.   dummy.lock();
    56.   QWaitCondition waitCondition;
    57.   waitCondition.wait(&dummy, 2);
    58.   */
    59.  
    60. //to decrease CPU usage
    61. //sleep 1 millisecond
    62. #if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
    63. Sleep(1);
    64. #else
    65. usleep(1000);
    66. #endif
    67. }
    68. }
    69.  
    70. guiMainThread->bTimeOut = false;
    71. }
    72.  
    73. return result;
    74. }
    To copy to clipboard, switch view to plain text mode 

    I'll have to figure out how to step into the cvWaitKey function while under the debugger to see if the processEvents() method gets called.
    Last edited by davethomaspilot; 25th September 2013 at 13:34. Reason: updated contents

  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    Well it certainly won't be called if the global "multiThreads" is true. Perhaps that is easier to check?

  6. #6
    Join Date
    Jun 2012
    Posts
    219
    Thanks
    28
    Thanked 3 Times in 3 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: No readyRead() signal from SerialPort, but (seemingly) same code works in another

    Good suggestion, but the debugger doesn't know about multiThreads:

    multiThreads CXX0017: Error: symbol "multiThreads" not found

    Unfortunately, VS2010 can't find the .pdb it needs for source line debugging:

    "Loaded 'C:\OpenCV\builds\install\bin\opencv_highgui240d.d ll', Cannot find or open the PDB file"

    I guess it needs that file for globals too. I found the pdb and copied it to the same directory as the dll, but VS still couldn't find it. So, I'll need to figure out where it needs to be or how to tell VS to look in the right directory.

    It is a multi-threaded application. However, all GUI interaction is on the main thread. There are separate threads for each of two cameras and windows thread sync mechanisms like WaitForMultipleObjects, ReleaseSemaphore, and ReleaseMutex are used to keep everything thread safe (I didn't know enough Qt to use the framework supplied threading objects when I wrote the code).

    But, I think processEvents must be getting called at least some of the time, since everything but the SerialPort signal/slot worked and still works fine without the the added processEvents call. The Qt widgets and dialog remain responsive if and only if cvWaitKey is called periodically. Adding the "extra" processEvents() makes the SerialPort code work too.

    That's why I'm so confused.

    Dave Thomas


    Added after 53 minutes:


    VS doesn' thing my pdb file matches the dll:

    Under Modules Symbol load information:
    C:\OpenCV\builds\bin\Debug\opencv_highgui240d.pdb: PDB does not match image.

    No clue why. I see the timestamp is about 5 hours later on 5/23 2012 for the pdb. That's way too long ago to remember the bizillion steps it took to build openCv.

    I think I'll have to rebuild to step into the OpenCV code and/or see its symbols. I want to do that, since where there's smoke...

    I just don't have time to do right now--need to get more code done.

    Thanks for the replies.

    Dave THomas
    Last edited by davethomaspilot; 26th September 2013 at 07:54.

Similar Threads

  1. QSslSocket readyRead() signal problem
    By JaroMast in forum Qt Programming
    Replies: 2
    Last Post: 19th February 2013, 17:39
  2. QUdpSocket readyRead() signal not triggered
    By deionut in forum Newbie
    Replies: 2
    Last Post: 26th October 2010, 18:19
  3. QNetworkReply & delayed readyRead(() signal
    By dmini in forum Qt Programming
    Replies: 1
    Last Post: 6th November 2009, 13:47
  4. Replies: 10
    Last Post: 9th July 2009, 12:05
  5. readyRead signal too slow or what?
    By Morea in forum Qt Programming
    Replies: 1
    Last Post: 6th July 2007, 19:11

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.