[SOLVED]Possible? Multiple QSerialPort Threads Simultaneously Independently



  • Hi,

    I am a newbie working on multi-sensors control, with each sensor passing data to one Serial Port independently.
    The aim is to retrieve data as fast as possible, which means I want to control multi-Sensors through multi-SerialPorts simultaneously and independently, instead of merging data into one Serial Port or processing the serial communications in only one loop.

    Here is my Question: is that possible in Qt to do multiple serial-threads simultaneously and independently?

    It keeps telling me
    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread
    whenever I tried to open or close a QSerialPort if it happens in a new thread, and of course data are not received successfully.

    There must be one micro-controller between COM and sensor, while one MCU controlling multi-sensors will definitely slow down the communication speed; the best way is to realize multi-SerialPort control in Qt.

    Could anyone give me some ideas about my problem?


  • Lifetime Qt Champion

    Hi,

    How are you creating your QSerialPort objects ?
    Do you haven on sensor per physical serial port ?



  • @SGaist
    Hi,

    Here is my QObject for QSerialPort control, with openSerial, closeSerial, and algorithm to control how to read data.
    When I put SenSerialControlAlgorithmObject into a thread, it keeps telling me
    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread
    whenever it comes to the openSerial or closeSerial command, and the serial communication doesn't work.

    One Serial Port connects with one MCU to control one sensor.

    #include <QObject>
    #include <QtSerialPort/QSerialPort>
    #include <QTime>
    #include <QElapsedTimer>
    
    class SenSerialControlAlgorithmObject : public QObject
    {
        Q_OBJECT
    public:
        explicit SenSerialControlAlgorithmObject(QObject *parent = 0);
    
        QSerialPort *mySerialPort;
        QByteArray SenMotionByteArray;
        bool motionReadBegun;
        QElapsedTimer *myElapsedTimer;
    
    signals:
        void emitSerialCloseSetting();
        void emitSerialOpenedSetting();
        void emitSerialDataToConsole(QByteArray);
    
        void emitMotionTrackingStart();
        void emitMotionTrackingStop(qint64);
        void emitMotionUpdateSignal(QByteArray SenMotionByteArray, int);
    
    public slots:
        void openSerialPort(Settings mySettingInfo);
        void closeSerialPort();
        void readData();
        void handleError(QSerialPort::SerialPortError error);
    
    private:
        int motionReadBytes, delta_X, delta_Y;
    };
    #endif // SENSERIALCONTROLALGORITHMOBJECT_H

  • Lifetime Qt Champion

    How are you putting SenSerialControlAlgorithmObject in a QThread ?



  • @SGaist

    In the constructor in MainWindow of Terminal.
    The MainWindow has ui for Serial Info Setting.

        mySerialThread = new QThread();
    //    SenSerialControlAlgorithmObject ->moveToThread(mySerialThread );
        mySerialThread ->start();


  • @SGaist
    MainWindow:

    #include <QMainWindow>
    #include <QtSerialPort/QSerialPort>
    #include "SenConsole.h"
    #include "SenSettingsDialog.h"
    #include "SenSerialControlAlgorithmObject.h"
    
    class SenOpticalFlowSensorsMainWindow : public QMainWindow
    {
    private slots:
        void writeData(const QByteArray &data);
        void showDataInConsole(QByteArray data);
    
    signals:
        void emitOpenSerialOrder(SenSettingsDialog::Settings);
    
    private:
        Ui::SenOpticalFlowSensorsMainWindow *myMainWindow_ui;
        SenConsole *mySenConsole;
        SenSettingsDialog *mySenSettingsDialog;
    
        SenSettingsDialog::Settings mySettingInfo;
        SenSerialControlAlgorithmObject *myDefaulSerialObject;
    
        QThread *mySerialThread;
    };
    

    Constructor:

    SenOpticalFlowSensorsMainWindow::SenOpticalFlowSensorsMainWindow(QWidget *parent) :    QMainWindow(parent),
        myMainWindow_ui(new Ui::SenOpticalFlowSensorsMainWindow)
    {
        myMainWindow_ui->setupUi(this);
        mySenConsole = new SenConsole;
        setCentralWidget(mySenConsole);
    ////
        myDefaulSerialObject = new SenSerialControlAlgorithmObject();
    ////
        mySenSettingsDialog = new SenSettingsDialog;
        initActionsConnections();
    
        mySerialThread = new QThread();
    //    myDefaulSerialObject ->moveToThread(mySerialThread );
        mySerialThread ->start();
    }


  • Just do not use the threads if you don't know how to do it.



  • @kuzulis
    So is it impossible to do multi-Terminal in Qt?


  • Lifetime Qt Champion

    No it's not impossible, however thread programming is a complex matter where it's very very very easy to shoot yourself in the foot.

    One guess: your actual QSerialPort doesn't have a parent, so when your move myDefaultSerialObject, the serial port itself is not moved.



  • @SGaist

    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread

    I appreciate your guessing, however the application output reminder is telling something failed in another thread, which means the command of

        if (mySerialPort->open(QIODevice::ReadWrite)) {//Here is when the hint comes out
            emit emitSerialOpenedSetting();
            syncNumMotionsCount = 0;
            SenMotionByteArray.clear();
            debugError = false;
        } else {
            emit emitSerialOpenErrorSetting(mySerialPort->errorString());
        }
    

    failed in another thread instead of main thread.



  • Although it is not allowed to open/close QSerialPort in a new thread, I can open/close it in the main thread, and push it into the new thread after it is opened.



  • Although it is not allowed to open/close QSerialPort in a new thread,

    It is not true. There are no differences in from what a thread to do open/close. A main things is that the QSerialPort should be moved into another thread before than opened/closed/read/write on it and so on. Besides, this should be called in that thread to which the QSerialPort was moved (not from the main thread or any others).

    And I do not understand what is reason to use a more than one thread.. Because you can handle a data from the several serial ports (sensors) from the one main thread "simultaneous".



  • @kuzulis

    That is also what I do not understand.

    However, the truth is:
    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread

    and how will you explain this when it comes to open/close QSerialPort?



  • It seems that, there is no way to push the Object, which contains QSerialPort, back to main thread and then close QSerialPort.



  • That is also what I do not understand.

    What do you don't understand?

    I once again will repeat: simply don't use the threads, if no reason for this! (in your case there are is no any reason)

    QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread

    Obviously, you do something wrong: all methods of QSerialPort shall be called from the same thread in which an QSerialPort lives.

    It seems that, there is no way to push the Object, which contains QSerialPort, back to main thread and then close QSerialPort.

    WTF?



  • @kuzulis
    I don't understand what's wrong with my codes; it doesn't work anyway to open/close QSerialPort in a new thread.

    I made it in main thread, no problem without putting the Serial Communication Control in a new thread; however, is that possible to do multiple serial threads?

    Two reasons to do threads:

    1. To make it as fast as possible;
    2. Learn my bug in programming: I do not want to encounter the same bug again.

  • Lifetime Qt Champion

    @Sen-Li

    Threads are not always the way to make a program go faster. In some cases performance can be worse with threads. Qt's asynchronous nature allows to avoid usage of thread for most of the cases and generally serial port can be handled in the GUI thread without problem.



  • @SGaist

    Thank you very much for your tips!
    I probably should give up on the serial thread. It is beyond my ability to play with that problem.



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