Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

problem with writing on serial port



  • This post is deleted!

  • Lifetime Qt Champion

    @nanor said in problem with writing on serial port:

    while(1)
    {
    serial->write("ok");

              }
    

    Please don't do such things in event driven applications! You block Qt event loop!
    Write once, connect a slot to https://doc.qt.io/qt-5/qiodevice.html#bytesWritten and write again in that slot if you need to write "OK" more than once.



  • This post is deleted!

  • Lifetime Qt Champion

    @nanor Please show your code. The warning actually tells you something.
    Also, please post warnings/errors as text, not screen-shots.



  • @jsulm This is the updated code:

    widget.cpp:

    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>
    #include <QtSerialPort/QSerialPort>
    #include <QSerialPortInfo>
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
            ui->setupUi(this);
    
            serial = new QSerialPort(this);
    
            serial->setPortName("COM1");
    
            for(const auto &serialPortInfo : QSerialPortInfo::availablePorts())
            {
                    qDebug() << "find serial port: " << serialPortInfo.portName() ;
            }
    
            serial->open(QIODevice::ReadWrite);
    
            if(serial->isOpen())
            {
                serial->setBaudRate(QSerialPort::Baud9600);
                serial->setDataBits(QSerialPort::Data8);
                serial->setParity(QSerialPort::NoParity);
                serial->setStopBits(QSerialPort::OneStop);
                serial->setFlowControl(QSerialPort::NoFlowControl);
    
    
               serial->write("ok");
               connect(serial, SIGNAL(bytesWritten(qint64)), this, SLOT(Write(qint64)));
                /*while(1)
                  {
                     serial->write("ok");
    
                  }*/
    
    
    
            }
    
            else
            {
              qDebug() << "can't open the port";
            }
    
    }
    
    Widget::~Widget()
    {
        delete ui;
        serial->close();
    }
    
    void Widget::on_pushButton_clicked()
    {
        qDebug() << "salam";
    }
    
    void Widget::Write(qint64)
    {
        while(1)
        {
            serial->write("ok");
        }
    }
    
    

    this is the error:

    07:22:37: Starting C:\Users\nanor\OneDrive\Desktop\qt codes\build-SerialPortReading-Desktop_Qt_5_12_2_MinGW_32_bit-Debug\debug\SerialPortReading.exe...
    find serial port: "COM1"
    find serial port: "COM6"
    terminate called after throwing an instance of 'std::bad_alloc'
    what(): std::bad_alloc
    07:23:15: C:/Users/nanor/OneDrive/Desktop/qt codes/build-SerialPortReading-Desktop_Qt_5_12_2_MinGW_32_bit-Debug/debug/SerialPortReading.exe exited with code 3


  • Lifetime Qt Champion

    @nanor said in problem with writing on serial port:

    while(1)
    {
    serial->write("ok");
    }

    I already told you to not to block the event loop! Why do you do it again? Why do you think you need this while(1) loop?



  • @jsulm I was asked to do this. I was asked to send a text in while(1) loop.



  • @jsulm In the last uploaded code, I have commented the while loop inside the constructor and move this while loop to the slot


  • Lifetime Qt Champion

    @nanor said in problem with writing on serial port:

    I have commented the while loop inside the constructor and move this while loop to the slot

    So, you're again blocking the event loop.
    Is this an exercise, or who asked you to use a loop?
    If you have to do so, then you will need to move your serial port code to a thread.



  • @jsulm Yes this is an exercise. Thank you so much for your suggestion.


  • Lifetime Qt Champion

    @nanor You could keep your loop and call https://doc.qt.io/qt-5/qcoreapplication.html#processEvents inside the loop. But warning: this is dirty work-around and probably not what the teacher wants to see :-)



  • @jsulm Thank you. You mentioned that if I want to do write my code in a while loop, I have to use thread. I have read about qthread class, but I don't know how to use this class in my project. Could you please give suggestions about the steps I have to take?
    The question is:
    read data continuously and byte by byte from a serial port and if data equals to something special that is defined in code (like"hi"), then write to serial port something.
    I would appreciate if you guide me how to use threads in solving this question


  • Lifetime Qt Champion

    @nanor This example does exactly what you need: https://doc.qt.io/qt-5/qtserialport-blockingmaster-example.html
    It uses blocking QSerialPort API in a worker thread.
    Take a look.



  • @jsulm Thank you so much.
    For the firt step (I want to continuesly read data byte by byte) I have written the following code. But it crashes. Could you please guide me how to fix this?

    mainwindow.h:

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QtSerialPort/QSerialPort>
    #include "mythread.h"
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
        QSerialPort *serial;
    
        QThread *myThread;
    
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    

    mythread.h:

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    
    #include <QObject>
    #include <QThread>
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>
    #include <QDebug>
    
    class MyThread : public QThread
    {
        Q_OBJECT
    public:
        explicit MyThread(QObject *parent = nullptr);
    
        void run();
    
        QSerialPort *serial;
    
    signals:
    
    public slots:
    };
    
    #endif // MYTHREAD_H
    
    

    mainwindow.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QtSerialPort/QSerialPort>
    #include <QtSerialPort/QSerialPortInfo>
    #include <QDebug>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        myThread->start();
    
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        qDebug() << "salam";
    }
    

    mythread.cpp:

    #include "mythread.h"
    
    MyThread::MyThread(QObject *parent) : QThread(parent)
    {
    
    }
    
    void MyThread::run()
    {
        serial = new QSerialPort(this);
        serial->setPortName("COM1");
    
        for(const auto &serialPortInfo : QSerialPortInfo::availablePorts())
        {
           qDebug() << "find serial port: " << serialPortInfo.portName() ;
        }
    
        serial->open(QIODevice::ReadWrite);
    
    
        if(serial->isOpen())
        {
            serial->setBaudRate(QSerialPort::Baud9600);
            serial->setDataBits(QSerialPort::Data8);
            serial->setParity(QSerialPort::NoParity);
            serial->setStopBits(QSerialPort::OneStop);
            serial->setFlowControl(QSerialPort::NoFlowControl);
    
             while(1)
            {
                serial->read(1);
    
           }
    
        }
    
        else
        {
          qDebug() << "can't open the port";
        }
    
    }
    
    

    the error:

    10:33:50: Starting C:\Users\nanor\OneDrive\Desktop\qt codes\build-serialportreading3-Desktop_Qt_5_12_2_MinGW_32_bit-Debug\debug\serialportreading3.exe...
    ASSERT: "timeout >= 0" in file thread\qmutex.cpp, line 582
    10:33:52: The program has unexpectedly finished.
    10:33:52: The process was ended forcefully.
    10:33:52: C:/Users/nanor/OneDrive/Desktop/qt codes/build-serialportreading3-Desktop_Qt_5_12_2_MinGW_32_bit-Debug/debug/serialportreading3.exe crashed.


  • Lifetime Qt Champion

    @nanor said in problem with writing on serial port:

    serial = new QSerialPort(this);

    Remove "this".
    If it is still crashing then please use the debugger to see where exactly and post the stack trace after crash.



  • This post is deleted!

  • Lifetime Qt Champion

    @nanor Please build in debug mode before running in debugger!



  • This post is deleted!

  • Lifetime Qt Champion

    @nanor Please post the stack trace (as text). It's in the middle of your screen-shot, in "Debugger" section.



  • This post is deleted!

  • Lifetime Qt Champion

    @nanor Please post what is in level 2 and 3, else I'm out of this thread as I do not want to guess what is wrong...
    It is your job to find out where your app is crashing.



  • @jsulm inside the mainwindow.cpp I didn't initialize the thread (myThread = new QThread();) . I added this and it got fixed.



  • @jsulm Sorry again. I have another question. inside the while loop, I have to constantly read data from the port and store them inside an array adn then debug them . I have written the following line. but nothing is printed

    while(1)
            {
                QByteArray data = serial->read(1);
                for(int i=0; i<data.size(); i++)
                {
                    qDebug() << data[i];
                }
    
    
            }
    


  • @nanor
    Absolutely not! Since it's while(1) how is it ever going to exit the loop?? while (1) is "always" wrong in Qt....

    You have now changed your code...

    but nothing is printed

    So either it never enters the loop, or it never has anything to read.



  • @JonB I removed the while loop and mythread.cpp is now:

    #include "mythread.h"
    
    MyThread::MyThread(QObject *parent) : QThread(parent)
    {
    
    }
    
    void MyThread::run()
    {
        serial = new QSerialPort();
        serial->setPortName("COM1");
    
        for(const auto &serialPortInfo : QSerialPortInfo::availablePorts())
        {
           qDebug() << "find serial port: " << serialPortInfo.portName() ;
        }
    
        serial->open(QIODevice::ReadWrite);
    
    
        if(serial->isOpen())
        {
            serial->setBaudRate(QSerialPort::Baud9600);
            serial->setDataBits(QSerialPort::Data8);
            serial->setParity(QSerialPort::NoParity);
            serial->setStopBits(QSerialPort::OneStop);
            serial->setFlowControl(QSerialPort::NoFlowControl);
    
    
    
            QByteArray data = serial->read(1);
            for(int i=0; i<data.size(); i++)
             {
                    qDebug() << data[i];
             }
    
    
    
    
        }
    
        else
        {
          qDebug() << "can't open the port";
        }
    
    }
    
    

    But still I can't get the messages. I send data from hercules.



  • @nanor
    Start by putting in qDebug() statements to see for yourself where you are actually getting to, plus more error checking.

    I don't know if any serial data is available to read at the instant you open the port. And you only try to read one byte once.



  • @JonB Thank you for mentioning using debug. I added the line qDebug() << "inside the run function"; inside the run function, but after running, this message isn't shown. But I have started the thread inside the mainwindow class. I can't understand why this is happened!



  • @nanor
    My own view, often times expressed, is why are you going anywhere near QThread at all? Every time it causes posters problems. Qt framework is asynchronous, so why do you need any threads when you have signals?


  • Lifetime Qt Champion

    @nanor I gave you a link to an example which uses the synchronous API. Apparently you did not really read it carefully, did you? In your loop you should use waitForReadyRead(...) as is done in the example. This makes sure that the event loop can actually do its job.

    if (serial.waitForReadyRead(currentWaitTimeout)) {
        QByteArray responseData = serial.readAll();
    

  • Lifetime Qt Champion

    @JonB I asked already why threads. Seems to be an exercise.


  • Moderators

    @jsulm said in problem with writing on serial port:

    I asked already why threads. Seems to be an exercise.

    possibly, but the OP only states the while loop as a task. Not threads specifically.

    @nanor can you word exactly, what you want to do ?



  • @J-Hilk Hi
    I have a button that when a user pushes it, "salam" is printed. At the same time, I want to constantly read from and write to a port (I want to read byte by byte and print them(debug them)). Now I know that I have to declare a class inheritted from qThread class and inside its run function, read and write. But I don't know if I have to declare while loop inside the run function in order to read constantly or not. In the code I posted, I have:

    
            QByteArray data = serial->read(1);
            for(int i=0; i<data.size(); i++)
            {
                    qDebug() << data[i];
            }
    

    Is this part reading the datas byte by byte and store them inside an array and print the datas?



  • @nanor said in problem with writing on serial port:

    Now I know that I have to declare a class inheritted from qThread class and inside its run function,

    Why? Is this a required exercise to use a thread, or are you just doing it because you think you need to??

    Oh, now I see

    @jsulm I was asked to do this. I was asked to send a text in while(1) loop.

    EDIT OK, I have seen now you have answered that you must do it this way. Seems terrible to me! But OK :)



  • @JonB This is a required exersize


  • Moderators

    @nanor said in problem with writing on serial port:

    I want to constantly read from and write to a port (

    is it specified how you have to constantly read from and write to a port or is that implementation detail up to you?

    because while- loops and threads I the least optimal way to do it



  • @J-Hilk It is specified to use while(1) loop


Log in to reply