Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. 2 thread send data To serial port
QtWS25 Last Chance

2 thread send data To serial port

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 4 Posters 492 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bassem84
    wrote on last edited by
    #1

    Good morning all
    I am a new user of Qt creator and new to C ++
    I wanted to make an application that sends a UART frame on the serial port every 100ms and another frame every 200ms I used an example code for the multithreaded I created 3 tasks to run at the same time and send different UART frames on the serial port but I manage to send just once at the start of the task i.e. if I run the task 1 at the start of the application it sends the UART frames
    if I run task 2 when starting the application it sends the UART frames
    each time the data I send the first time does not change even if I run the other task the goal is to send different data to each selected task.

    I share with you the code that I use and if you have any modifications to help me please tell me how to do it because I am a beginner

    worker1.h

    #ifndef WORKER1_H
    #define WORKER1_H
    
    #include <QObject>
    #include <QMutex>
    
    class Worker1 : public QObject
    {
        Q_OBJECT
    public:
        explicit Worker1(QObject *parent = nullptr);
    
    
        /**
         * @brief Requests the process to start
         *
         * It is thread safe as it uses #mutex to protect access to #_working variable.
         */
        void requestWork1();
        /**
         * @brief Requests the process to abort
         *
         * It is thread safe as it uses #mutex to protect access to #_abort variable.
         */
        void abort1();
    
    
    private:
        /**
         * @brief Process is aborted when @em true
         */
        bool _abort1;
        /**
         * @brief @em true when Worker is doing work
         */
        bool _working1;
        /**
         * @brief Protects access to #_abort
         */
        QMutex mutex1;
    
    
    signals:
    
    
        /**
         * @brief This signal is emitted when the Worker request to Work
         * @sa requestWork()
         */
        void workRequested1();
        /**
         * @brief This signal is emitted when counted value is changed (every sec)
         */
        void valueChanged1(const QString &value1);
        void moyenne();
    
    
    
        /**
         * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
         */
        void finished1();
    
    
    public slots:
        /**
         * @brief Does something
         *
         * Counts 60 sec in this example.
         * Counting is interrupted if #_aborted is set to true.
         */
        void doWork1();
    
    
    };
    
    #endif // WORKER1_H
    
    
    

    worker1.cpp

    #include "worker1.h"
    #include <QTimer>
    #include <QEventLoop>
    #include <QThread>
    #include <QDebug>
    #include "global.h"
    #include <windows.h>
    #include <qdebug.h>
    #include <QApplication>
    #include <QTextEdit>
    #include <QFile>
    #include <QString>
    #include <QTextStream>
    #include <QInputDialog>
    #include <QIODevice>
    #include <QMessageBox>
    #include <QtGui>
    #include <QTextEdit>
    #include <QLineEdit>
    #include <QThread>
    #include <QtWidgets>
    #include <QDir>
    #include <QCoreApplication>
    #include <cmath>
    #include <cstdio>
    #include <stdio.h>
    #include <QWidget>
    #include <QPaintEvent>
    #include <QPixmap>
    #include <QPainter>
    #include <QTimer>
    #include <QtCore>
    #include <QLabel>
    #include <QComboBox>
    #include <QVBoxLayout>
    #include <QSerialPort>
    
    
    QByteArray Worker1_array;
    
    
    Worker1::Worker1(QObject *parent) : QObject(parent)
    {
        _working1 =false;
        _abort1 = false;
    }
    
    
    void Worker1::requestWork1()
    {
        mutex1.lock();
        _working1 = true;
        _abort1 = false;
        qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
        mutex1.unlock();
    
        emit workRequested1();
    }
    
    void Worker1::abort1()
    {
        mutex1.lock();
        if (_working1) {
            _abort1 = true;
            qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
        }
        mutex1.unlock();
    }
    
    void Worker1::doWork1()
    {
        qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
    
        for (int i1 = 0; i1 < 60; i1 ++) {
    
            // Checks if the process should be aborted
            mutex1.lock();
            bool abort1 = _abort1;
            mutex1.unlock();
    
            if (abort1) {
                qDebug()<<"Aborting worker process in Thread "<<thread()->currentThreadId();
                break;
            }
    
            // This will stupidly wait 1 sec doing nothing...
            QEventLoop loop1;
            QTimer::singleShot(100, &loop1, SLOT(quit()));
            loop1.exec();
    
            // Once we're done waiting, value is updated
            emit valueChanged1(QString::number(i1));
    
    
            Worker1_array[0] = 0x01;
            Worker1_array[1] = 0x01;
            Worker1_array[2] = 0x01;
            Worker1_array[3] = 0x01;
            Worker1_array[4] = 0x01;
            Worker1_array[5] = 0x01;
            Worker1_array[6] = 0x01;
            Worker1_array[7] = 0x01;
            Worker1_array[8] = 0x01;
            Worker1_array[9] = 0x01;
            Worker1_array[10] = 0x01;
            Worker1_array[11] = 0x01;
            Worker1_array[12] = 0x01;
            Worker1_array[13] = 0x01;
            Worker1_array[14] = 0x01;
            Worker1_array[15] = 0x01;
    
            serial_Main.write(Worker1_array,16);
    
    
        }
    
        // Set _working to false, meaning the process can't be aborted anymore.
        mutex1.lock();
        _working1 = false;
        mutex1.unlock();
    
    //    qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
    
        //Once 60 sec passed, the finished signal is sent
        emit finished1();
    }
    
    

    worker2.h

    #ifndef WORKER2_H
    #define WORKER2_H
    
    #include <QObject>
    #include <QMutex>
    
    class Worker2 : public QObject
    {
        Q_OBJECT
    public:
        explicit Worker2(QObject *parent = nullptr);
    
        /**
         * @brief Requests the process to start
         *
         * It is thread safe as it uses #mutex to protect access to #_working variable.
         */
        void requestWork2();
        /**
         * @brief Requests the process to abort
         *
         * It is thread safe as it uses #mutex to protect access to #_abort variable.
         */
        void abort2();
    
    private:
        /**
         * @brief Process is aborted when @em true
         */
        bool _abort2;
        /**
         * @brief @em true when Worker is doing work
         */
        bool _working2;
        /**
         * @brief Protects access to #_abort
         */
        QMutex mutex2;
    
    
    signals:
    
    
        /**
         * @brief This signal is emitted when the Worker request to Work
         * @sa requestWork()
         */
        void workRequested2();
        /**
         * @brief This signal is emitted when counted value is changed (every sec)
         */
        void valueChanged2(const QString &value2);
        /**
         * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
         */
        void finished2();
    
    public slots:
        /**
         * @brief Does something
         *
         * Counts 60 sec in this example.
         * Counting is interrupted if #_aborted is set to true.
         */
        void doWork2();
    
    
    
    };
    
    #endif // WORKER2_H
    
    

    worker2.cpp

    #include "worker2.h"
    
    #include <QTimer>
    #include <QEventLoop>
    
    #include <QThread>
    #include <QDebug>
    
    
    #include <windows.h>
    #include <qdebug.h>
    #include <QApplication>
    #include <QTextEdit>
    #include <QFile>
    #include <QString>
    #include <QTextStream>
    #include <QInputDialog>
    #include <QIODevice>
    #include <QMessageBox>
    #include <QtGui>
    #include <QTextEdit>
    #include <QLineEdit>
    #include <QThread>
    #include <QtWidgets>
    #include <QDir>
    #include <QCoreApplication>
    #include <cmath>
    #include <cstdio>
    #include <stdio.h>
    #include <QWidget>
    #include <QPaintEvent>
    #include <QPixmap>
    #include <QPainter>
    #include <QTimer>
    #include <QtCore>
    #include <QLabel>
    #include <QComboBox>
    #include <QVBoxLayout>
    #include <QSerialPort>
    
    
    #include "global.h"
    
    QByteArray Worker2_array;
    
    
    Worker2::Worker2(QObject *parent) : QObject(parent)
    {
        _working2 =false;
        _abort2 = false;
    }
    
    void Worker2::requestWork2()
    {
        mutex2.lock();
        _working2 = true;
        _abort2 = false;
        qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
        mutex2.unlock();
    
        emit workRequested2();
    }
    
    void Worker2::abort2()
    {
        mutex2.lock();
        if (_working2) {
            _abort2 = true;
            qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
        }
        mutex2.unlock();
    }
    
    void Worker2::doWork2()
    {
        qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
    
        for (int i2 = 0; i2 < 60; i2 ++) {
    
            // Checks if the process should be aborted
            mutex2.lock();
            bool abort2 = _abort2;
            mutex2.unlock();
    
            if (abort2) {
                qDebug()<<"Aborting worker process in Thread "<<thread()->currentThreadId();
                break;
            }
    
            // This will stupidly wait 1 sec doing nothing...
            QEventLoop loop1;
            QTimer::singleShot(1000, &loop1, SLOT(quit()));
            loop1.exec();
    
            // Once we're done waiting, value is updated
            emit valueChanged2(QString::number(i2));
    
    
            Worker2_array[0] = 0x02;
            Worker2_array[1] = 0x02;
            Worker2_array[2] = 0x02;
            Worker2_array[3] = 0x02;
            Worker2_array[4] = 0x02;
            Worker2_array[5] = 0x02;
            Worker2_array[6] = 0x02;
            Worker2_array[7] = 0x02;
            Worker2_array[8] = 0x02;
            Worker2_array[9] = 0x02;
            Worker2_array[10] = 0x02;
            Worker2_array[11] = 0x02;
            Worker2_array[12] = 0x02;
            Worker2_array[13] = 0x02;
            Worker2_array[14] = 0x02;
            Worker2_array[15] = 0x02;
    
    
            serial_Main.write(Worker2_array,16);
    
    
    
        }
    
        // Set _working to false, meaning the process can't be aborted anymore.
        mutex2.lock();
        _working2 = false;
        mutex2.unlock();
    
    //    qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
    
        //Once 60 sec passed, the finished signal is sent
        emit finished2();
    }
    
    
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThread>
    
    #include "global.h"
    #include "worker1.h"
    #include "worker2.h"
    #include "worker3.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    
    
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
        QThread *thread1;
        QThread *thread2;
        QThread *thread3;
        /**
         * @brief Object which contains methods that should be runned in another thread
         */
        Worker1 *worker1;
        Worker2 *worker2;
        Worker3 *worker3;
    
    
            /**
             * @brief Object which contains methods that should be runned in another thread
             */
    
    
    
    private slots:
        void on_pushButton_clicked();
    
    
        void on_pushButton_2_clicked();
        void on_pushButton_3_clicked();
        void on_pushButton_4_clicked();
        void on_pushButton_5_clicked();
        void on_pushButton_6_clicked();
    };
    #endif // MAINWINDOW_H
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "global.h"
    #include <windows.h>
    #include <qdebug.h>
    #include <QApplication>
    #include <QTextEdit>
    #include <QFile>
    #include <QString>
    #include <QTextStream>
    #include <QInputDialog>
    #include <QIODevice>
    #include <QMessageBox>
    #include <QtGui>
    #include <QTextEdit>
    #include <QLineEdit>
    #include <QThread>
    #include <QtWidgets>
    #include <QDir>
    #include <QCoreApplication>
    #include <cmath>
    #include <cstdio>
    #include <stdio.h>
    #include <QWidget>
    #include <QPaintEvent>
    #include <QPixmap>
    #include <QPainter>
    #include <QTimer>
    #include <QtCore>
    #include <QLabel>
    #include <QComboBox>
    #include <QVBoxLayout>
    #include <QSerialPort>
    
    
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // The thread and the worker are created in the constructor so it is always safe to delete them.
    
    
    
        serial_Main.setPortName("COM8");
        serial_Main.setBaudRate(115200);
        serial_Main.setDataBits(QSerialPort::Data8);
        serial_Main.setParity(QSerialPort::NoParity);
        serial_Main.setStopBits(QSerialPort::OneStop);
        serial_Main.setFlowControl(QSerialPort::NoFlowControl);
        serial_Main.open(QIODevice::ReadWrite);
    
    
    
    
        thread1 = new QThread();
        worker1 = new Worker1();
    
        thread2 = new QThread();
        worker2 = new Worker2();
    
        thread3 = new QThread();
        worker3 = new Worker3();
    
        worker1->moveToThread(thread1);
        connect(worker1, SIGNAL(valueChanged1(QString)), ui->label, SLOT(setText(QString)));
        connect(worker1, SIGNAL(workRequested1()), thread1, SLOT(start()));
        connect(thread1, SIGNAL(started()), worker1, SLOT(doWork1()));
        connect(worker1, SIGNAL(finished1()), thread1, SLOT(quit()), Qt::DirectConnection);
    
        worker2->moveToThread(thread2);
        connect(worker2, SIGNAL(valueChanged2(QString)), ui->label_2, SLOT(setText(QString)));
        connect(worker2, SIGNAL(workRequested2()), thread2, SLOT(start()));
        connect(thread2, SIGNAL(started()), worker2, SLOT(doWork2()));
        connect(worker2, SIGNAL(finished2()), thread2, SLOT(quit()), Qt::DirectConnection);
    
        worker3->moveToThread(thread3);
        connect(worker3, SIGNAL(valueChanged3(QString)), ui->label_3, SLOT(setText(QString)));
        connect(worker3, SIGNAL(workRequested3()), thread3, SLOT(start()));
        connect(thread3, SIGNAL(started()), worker3, SLOT(doWork3()));
        connect(worker3, SIGNAL(finished3()), thread3, SLOT(quit()), Qt::DirectConnection);
    
    }
    
    MainWindow::~MainWindow()
    {
    
        worker1->abort1();
        thread1->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread1;
        delete worker1;
    
        worker2->abort2();
        thread2->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread2;
        delete worker2;
    
        worker3->abort3();
        thread3->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread3;
        delete worker3;
    
        delete ui;
    }
    
    
    void MainWindow::on_pushButton_clicked()
    {
    
        worker1->abort1();
        thread1->wait(); // If the thread is not running, this will immediately return.
        worker1->requestWork1();
    
    }
    
    void MainWindow::on_pushButton_2_clicked()
    {
    
        worker2->abort2();
        thread2->wait(); // If the thread is not running, this will immediately return.
        worker2->requestWork2();
    
    }
    
    void MainWindow::on_pushButton_3_clicked()
    {
    
        worker3->abort3();
        thread3->wait(); // If the thread is not running, this will immediately return.
        worker3->requestWork3();
    
    }
    
    void MainWindow::on_pushButton_4_clicked()
    {
        worker1->abort1();
        thread1->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread1;
        delete worker1;
    
    }
    
    void MainWindow::on_pushButton_5_clicked()
    {
        worker2->abort2();
        thread2->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread2;
        delete worker2;
    
    }
    
    void MainWindow::on_pushButton_6_clicked()
    {
        worker3->abort3();
        thread3->wait();
        qDebug()<<"Deleting thread and worker in Thread "<<this->QObject::thread()->currentThreadId();
        delete thread3;
        delete worker3;
    }
    
    

    Thank you for Help

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      Hi @bassem84, and welcome.

      My advice is: Don't use threads for this at all. Just use QTimer.

      • 1 timer should timeout every 100ms.
      • 1 timer should timeout every 200ms.

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      7
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        Beside @JKSH good point, you seem to be using a global object QSerialPort object that you are accessing from your various threads without any protections. This is wrong on several levels.

        I also noted that you have tons of includes related to GUI elements in your workers code which might indicate that you are about to try and change GUI elements from secondary threads. This is also a no go.

        If you really need these threads, then you should design a proper controller class for the serial port communication that will be shared between the workers and serialize/protect the access to the serial port.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        6
        • B Offline
          B Offline
          bassem84
          wrote on last edited by
          #4

          Hi JKSH

          Thank you for you support

          /* I try to use qtimer but he dont' work correctly and i dont now whay

          jsulmJ JKSHJ 2 Replies Last reply
          0
          • B bassem84

            Hi JKSH

            Thank you for you support

            /* I try to use qtimer but he dont' work correctly and i dont now whay

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @bassem84 said in 2 thread send data To serial port:

            I try to use qtimer but he dont' work correctly and i dont now whay

            We neither as you did not provide any code and no error messages...

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            3
            • B bassem84

              Hi JKSH

              Thank you for you support

              /* I try to use qtimer but he dont' work correctly and i dont now whay

              JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote on last edited by
              #6

              @bassem84 said in 2 thread send data To serial port:

              I try to use qtimer but he dont' work correctly and i dont now whay

              Start by writing very simple code. First, try to use a QTimer to print a message to your console every 500ms. If you can't get it to work, post your code here like @jsulm said.

              Notes:

              • The code that you originally posted is quite complex. It is easier to help you when you post simple code.
              • Threads are difficult to use correctly in C++. I recommend that beginners stay away from them.

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              3

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved