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. QtSerialPort weird behaviours on MacOSX

QtSerialPort weird behaviours on MacOSX

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 4 Posters 728 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.
  • J Offline
    J Offline
    JorgeMaker
    wrote on last edited by
    #1

    Hi, I'm trying to make an application that uses the serial port and I can't get it to work. To try to see where the problem comes from, I am testing with this simple application.

    What I observed are behaviors that do not make much sense or I am not able to understand.

    The application most of the time detects the serial port as occupied by another application when no other application is using it and the few times that it manages to detect it as free it does not produce any output, it seems that it sends data but does not send anything.

    Does anyone know what he could be doing wrong or how he can debug the cause of the error?

    Greetings and thanks in advance for the help.

    #include <QDebug>
    #include <unistd.h>
    #include <QtSerialPort/QSerialPort>
    
    int main(int argc, char *argv[])
    {
          QSerialPort* serial = new QSerialPort();
          serial->setPortName("/dev/cu.usbserial-14130");
    
           serial->open(QSerialPort::ReadOnly);
           serial->setBaudRate(QSerialPort::Baud9600);
           serial->setDataBits(QSerialPort::Data8);
           serial->setFlowControl(QSerialPort::NoFlowControl);
           serial->setParity(QSerialPort::NoParity);
           serial->setStopBits(QSerialPort::OneStop);
    
          if (serial->open(QIODevice::ReadWrite))
           {
               QString hex = "command\r";
               QByteArray test = QByteArray::fromHex(hex.toLatin1());
    
               while(true){
                   if (serial->isWritable()){
                       serial->write(test.data());
                       qDebug() << "Sending data";
                   }
                   else{
                       qDebug() << "I can not write ";
                   }
    
                  sleep(10/1000);
                  qDebug("Another Loop") ;
              }
           }
           else
           {
              qDebug("Failed to open Serial Port") ;
              qDebug() << "Port Name : " << serial->portName();
              qDebug() << "Serial port eror: " << serial->errorString() ;
              serial->close();
              return -1;
           }
    }
    

    Obtained output

    Failed to open Serial Port
    Port Name :  "cu.usbserial-14130"
    Serial port eror:  "Device is already open"
    
    J.HilkJ 1 Reply Last reply
    0
    • J JorgeMaker

      @J-Hilk said in QtSerialPort weird behaviours on MacOSX:

      t doesn't wri

      Hi @J-Hilk thanks for your answer ,

      May be I do not understand how QtSerialPort works. Could you suggest an alternative implementation on how to send a ""command\r" each N milliseconds to a devices connected to, in this case, "/dev/cu.usbserial-14130" ?

      Best regards and thanks in advance :)

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

      @JorgeMaker said in QtSerialPort weird behaviours on MacOSX:

      May be I do not understand how QtSerialPort works

      It's not just about QtSerialport it is how Qt (or any other event driven framework) works.
      Simple rule: never block Qt event loop with long lasting loops, or even worse using sleep().
      Use a QTimer with appropriate timeout and send what you need in the slot connected to the https://doc.qt.io/qt-5/qtimer.html#timeout slot.

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

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

        Hi and welcome to devnet,

        Which version of macOS are you running ?
        Which type of serial port is it ? FTDI ?
        Which version of Qt are you using ?

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

        J 1 Reply Last reply
        2
        • SGaistS SGaist

          Hi and welcome to devnet,

          Which version of macOS are you running ?
          Which type of serial port is it ? FTDI ?
          Which version of Qt are you using ?

          J Offline
          J Offline
          JorgeMaker
          wrote on last edited by JorgeMaker
          #3

          Hi @SGaist thank you very much for your quick answer :)

          Here there is the information you requested:

          Which version of macOS are you running ? :

          • MacOS BigSur version11.4

          Which type of serial port is it ? FTDI ?

          • Is a USB to TTL converter based on CH340C . I scoped both Tx and RX pins with an oscilloscope and no activity is detected ..... both lines remain pulled up and the oscilloscope never triggers. I have tested this device using other applications and works without any problem using the same /dev/cu.usbserial-14130 serial port .

          Which version of Qt are you using ?

          • Qt 5.12.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by Clang 10.0.0 (clang-1000.11.45.2) (Apple)) on "cocoa"
            OS: macOS 10.16 [darwin version 20.5.0]

          Observations:

          • 1.- Something that I do not understand is why serial->setPortName is printed as "cu.usbserial-14130" while I am initializing it with "/dev/cu.usbserial-14130" ... Does it could be a sign that something is going wrong?
          • 2.- I installed QtCreator a while time ago, .... I don't know if it makes sense to uninstall it and install a newer version to see if this solves my issue.

          Regards :)

          1 Reply Last reply
          0
          • J JorgeMaker

            Hi, I'm trying to make an application that uses the serial port and I can't get it to work. To try to see where the problem comes from, I am testing with this simple application.

            What I observed are behaviors that do not make much sense or I am not able to understand.

            The application most of the time detects the serial port as occupied by another application when no other application is using it and the few times that it manages to detect it as free it does not produce any output, it seems that it sends data but does not send anything.

            Does anyone know what he could be doing wrong or how he can debug the cause of the error?

            Greetings and thanks in advance for the help.

            #include <QDebug>
            #include <unistd.h>
            #include <QtSerialPort/QSerialPort>
            
            int main(int argc, char *argv[])
            {
                  QSerialPort* serial = new QSerialPort();
                  serial->setPortName("/dev/cu.usbserial-14130");
            
                   serial->open(QSerialPort::ReadOnly);
                   serial->setBaudRate(QSerialPort::Baud9600);
                   serial->setDataBits(QSerialPort::Data8);
                   serial->setFlowControl(QSerialPort::NoFlowControl);
                   serial->setParity(QSerialPort::NoParity);
                   serial->setStopBits(QSerialPort::OneStop);
            
                  if (serial->open(QIODevice::ReadWrite))
                   {
                       QString hex = "command\r";
                       QByteArray test = QByteArray::fromHex(hex.toLatin1());
            
                       while(true){
                           if (serial->isWritable()){
                               serial->write(test.data());
                               qDebug() << "Sending data";
                           }
                           else{
                               qDebug() << "I can not write ";
                           }
            
                          sleep(10/1000);
                          qDebug("Another Loop") ;
                      }
                   }
                   else
                   {
                      qDebug("Failed to open Serial Port") ;
                      qDebug() << "Port Name : " << serial->portName();
                      qDebug() << "Serial port eror: " << serial->errorString() ;
                      serial->close();
                      return -1;
                   }
            }
            

            Obtained output

            Failed to open Serial Port
            Port Name :  "cu.usbserial-14130"
            Serial port eror:  "Device is already open"
            
            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #4

            @JorgeMaker said in QtSerialPort weird behaviours on MacOSX:

            while(true){
            if (serial->isWritable()){
            serial->write(test.data());
            qDebug() << "Sending data";
            }
            else{
            qDebug() << "I can not write ";
            }

                      sleep(10/1000);
                      qDebug("Another Loop") ;
                  }
            

            It doesn't write, when you're connected because of your while loop.
            And its also the reason why you get the port not open error. It switches internally from attemotToConnect state to connected state once the EventLoop is running, it's a queued connection.

            The data will be passed to the OS when the event queue is processed, that doesn't happen while looping.


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            J 1 Reply Last reply
            3
            • J.HilkJ J.Hilk

              @JorgeMaker said in QtSerialPort weird behaviours on MacOSX:

              while(true){
              if (serial->isWritable()){
              serial->write(test.data());
              qDebug() << "Sending data";
              }
              else{
              qDebug() << "I can not write ";
              }

                        sleep(10/1000);
                        qDebug("Another Loop") ;
                    }
              

              It doesn't write, when you're connected because of your while loop.
              And its also the reason why you get the port not open error. It switches internally from attemotToConnect state to connected state once the EventLoop is running, it's a queued connection.

              The data will be passed to the OS when the event queue is processed, that doesn't happen while looping.

              J Offline
              J Offline
              JorgeMaker
              wrote on last edited by
              #5

              @J-Hilk said in QtSerialPort weird behaviours on MacOSX:

              t doesn't wri

              Hi @J-Hilk thanks for your answer ,

              May be I do not understand how QtSerialPort works. Could you suggest an alternative implementation on how to send a ""command\r" each N milliseconds to a devices connected to, in this case, "/dev/cu.usbserial-14130" ?

              Best regards and thanks in advance :)

              jsulmJ J.HilkJ 2 Replies Last reply
              0
              • J JorgeMaker

                @J-Hilk said in QtSerialPort weird behaviours on MacOSX:

                t doesn't wri

                Hi @J-Hilk thanks for your answer ,

                May be I do not understand how QtSerialPort works. Could you suggest an alternative implementation on how to send a ""command\r" each N milliseconds to a devices connected to, in this case, "/dev/cu.usbserial-14130" ?

                Best regards and thanks in advance :)

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

                @JorgeMaker said in QtSerialPort weird behaviours on MacOSX:

                May be I do not understand how QtSerialPort works

                It's not just about QtSerialport it is how Qt (or any other event driven framework) works.
                Simple rule: never block Qt event loop with long lasting loops, or even worse using sleep().
                Use a QTimer with appropriate timeout and send what you need in the slot connected to the https://doc.qt.io/qt-5/qtimer.html#timeout slot.

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

                1 Reply Last reply
                2
                • J JorgeMaker

                  @J-Hilk said in QtSerialPort weird behaviours on MacOSX:

                  t doesn't wri

                  Hi @J-Hilk thanks for your answer ,

                  May be I do not understand how QtSerialPort works. Could you suggest an alternative implementation on how to send a ""command\r" each N milliseconds to a devices connected to, in this case, "/dev/cu.usbserial-14130" ?

                  Best regards and thanks in advance :)

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #7

                  @JorgeMaker

                  this should get you started, hopefully

                  #include <QCoreApplication>
                  #include <QSerialPort>
                  #include <QTimer>
                  int main(int argc, char *argv[])
                  {
                  
                      QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                      QCoreApplication::setOrganizationName("MyCompany");
                      QCoreApplication::setOrganizationDomain("MyApplication");
                      QCoreApplication app(argc, argv);
                  
                      QSerialPort* serial = new QSerialPort();
                      serial->setPortName("/dev/cu.usbserial-14130");
                  
                      serial->open(QSerialPort::ReadOnly);
                      serial->setBaudRate(QSerialPort::Baud9600);
                      serial->setDataBits(QSerialPort::Data8);
                      serial->setFlowControl(QSerialPort::NoFlowControl);
                      serial->setParity(QSerialPort::NoParity);
                      serial->setStopBits(QSerialPort::OneStop);
                  
                  
                      QObject::connect(serial, &QSerialPort::errorOccurred, [serial](QSerialPort::SerialPortError error)->void{
                          qDebug() << "Serialport had an error" << error << serial->errorString();
                      });
                  
                      QObject::connect(serial, &QSerialPort::readyRead, [serial]()->void{
                          QByteArray ba = serial->readAll();
                          qDebug() << "Response over serial" << ba.toHex((' '));
                      });
                  
                      QTimer timer;
                      QObject::connect(&timer, &QTimer::timeout, serial, [serial]()->void{
                          qDebug() << "Attempt to write";
                          QString hex = "command\r";
                          QByteArray test = QByteArray::fromHex(hex.toLatin1());
                          serial->write(test);
                      });
                  
                  
                      if (serial->open(QIODevice::ReadWrite))
                      {
                          timer.start(100); // 10/1000 is inteneger division -> results in 0, 100 = 100 ms
                      }
                  
                      return app.exec();
                  }
                  
                  #include "main.moc"
                  

                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  J 1 Reply Last reply
                  3
                  • J.HilkJ J.Hilk

                    @JorgeMaker

                    this should get you started, hopefully

                    #include <QCoreApplication>
                    #include <QSerialPort>
                    #include <QTimer>
                    int main(int argc, char *argv[])
                    {
                    
                        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                        QCoreApplication::setOrganizationName("MyCompany");
                        QCoreApplication::setOrganizationDomain("MyApplication");
                        QCoreApplication app(argc, argv);
                    
                        QSerialPort* serial = new QSerialPort();
                        serial->setPortName("/dev/cu.usbserial-14130");
                    
                        serial->open(QSerialPort::ReadOnly);
                        serial->setBaudRate(QSerialPort::Baud9600);
                        serial->setDataBits(QSerialPort::Data8);
                        serial->setFlowControl(QSerialPort::NoFlowControl);
                        serial->setParity(QSerialPort::NoParity);
                        serial->setStopBits(QSerialPort::OneStop);
                    
                    
                        QObject::connect(serial, &QSerialPort::errorOccurred, [serial](QSerialPort::SerialPortError error)->void{
                            qDebug() << "Serialport had an error" << error << serial->errorString();
                        });
                    
                        QObject::connect(serial, &QSerialPort::readyRead, [serial]()->void{
                            QByteArray ba = serial->readAll();
                            qDebug() << "Response over serial" << ba.toHex((' '));
                        });
                    
                        QTimer timer;
                        QObject::connect(&timer, &QTimer::timeout, serial, [serial]()->void{
                            qDebug() << "Attempt to write";
                            QString hex = "command\r";
                            QByteArray test = QByteArray::fromHex(hex.toLatin1());
                            serial->write(test);
                        });
                    
                    
                        if (serial->open(QIODevice::ReadWrite))
                        {
                            timer.start(100); // 10/1000 is inteneger division -> results in 0, 100 = 100 ms
                        }
                    
                        return app.exec();
                    }
                    
                    #include "main.moc"
                    
                    J Offline
                    J Offline
                    JorgeMaker
                    wrote on last edited by JorgeMaker
                    #8

                    Hi @J-Hilk , @jsulm , @SGaist

                    Issue solved :) It works perfectly, The solution proposed by @J-Hilk worked perfectly ... finally data on the screen after a couple of afternoons hitting my head against the screen.

                    DS1Z_QuickPrint1.png

                    I also implemented a solution based on the use of QTimer as @jsulm suggested. I copy it here just in case It can help anyone else having the same issue/misunderstanding.

                    • main.cpp:
                    #include <QCoreApplication>
                    #include "mytimer.h"
                    
                    int main(int argc, char *argv[])
                    {
                        QCoreApplication a(argc, argv);
                    
                        // Create MyTimer instance
                        // QTimer object will be created in the MyTimer constructor
                        MyTimer timer;
                    
                        return a.exec();
                    }
                    
                    • timer.h
                    #ifndef MYTIMER_H
                     #define MYTIMER_H
                    
                    #include <QTimer>
                    #include <QtSerialPort/QSerialPort>
                    
                      class MyTimer : public QObject
                      {
                          Q_OBJECT
                      public:
                          MyTimer();
                          QTimer *timer;
                          QSerialPort* serialPort;
                    
                    
                      public slots:
                          void MyTimerSlot();
                      };
                    
                      #endif // MYTIME
                    
                    • timer.cpp
                    #include "mytimer.h"
                    #include <QDebug>
                    MyTimer::MyTimer()
                    {
                        // create a timer
                        timer = new QTimer(this);
                        serialPort = new QSerialPort(this);
                    
                         serialPort->setPortName("/dev/cu.usbserial-14130");
                    
                         serialPort->setBaudRate(QSerialPort::Baud9600);
                         serialPort->setDataBits(QSerialPort::Data8);
                         serialPort->setFlowControl(QSerialPort::NoFlowControl);
                         serialPort->setParity(QSerialPort::NoParity);
                         serialPort->setStopBits(QSerialPort::OneStop);
                    
                         if (!serialPort->open(QIODevice::ReadWrite)){
                             qDebug("Failed to open Serial Port") ;
                             qDebug() << "Port Name : " << serialPort->portName();
                             qDebug() << "Serial port eror: " << serialPort->errorString() ;
                         }
                        // setup signal and slot
                        connect(timer, SIGNAL(timeout()), this, SLOT(MyTimerSlot()));
                        // msec
                        timer->start(100);
                    }
                    
                    void MyTimer::MyTimerSlot()
                    {
                        qDebug() << "One Loop...";
                        if (serialPort->isWritable()){
                            serialPort->write("Command");
                            qDebug() << "Sending data";
                        }
                        else{
                            qDebug() << "I can not write ";
                        }
                    }
                    
                    

                    Thanks again for your help ;))

                    1 Reply Last reply
                    1

                    • Login

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