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 blocking write in raspberry pi(raspbian pixel)
QtWS25 Last Chance

QtSerialPort blocking write in raspberry pi(raspbian pixel)

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 2.7k 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.
  • V Offline
    V Offline
    Vasily S
    wrote on last edited by
    #1

    Hi guys, I'm asking for your help.

    I'm writing an application for interaction of the raspberry pi with the device using the RS485 interface using the QtSerialPort(Qt 5.3).
    I do not have the ability to organize a blocking write operation, because by the RS485 standard it is necessary to specify the direction of transmission (high pin s$

    My code

    gpio->writeState(Gpio::IOEnable, Gpio::Set);
    serial.write(data);
    if (serial.waitForBytesWritten(500))
    {
        qDebug() << "Success";
    }
    else
    {
        qDebug() << "Timeout";
        return;
    }
    gpio->writeState(Gpio::IOEnable, Gpio::Reset);
    

    This code is executed successfully. When viewed with an oscilloscope, the pin becomes a unit not for the entire transmission time, as required by the interface standard. However, waitForBytesWritten returns after 5-10 milliseconds.

    Any thoughts on this?

    V 1 Reply Last reply
    0
    • V Vasily S

      Hi guys, I'm asking for your help.

      I'm writing an application for interaction of the raspberry pi with the device using the RS485 interface using the QtSerialPort(Qt 5.3).
      I do not have the ability to organize a blocking write operation, because by the RS485 standard it is necessary to specify the direction of transmission (high pin s$

      My code

      gpio->writeState(Gpio::IOEnable, Gpio::Set);
      serial.write(data);
      if (serial.waitForBytesWritten(500))
      {
          qDebug() << "Success";
      }
      else
      {
          qDebug() << "Timeout";
          return;
      }
      gpio->writeState(Gpio::IOEnable, Gpio::Reset);
      

      This code is executed successfully. When viewed with an oscilloscope, the pin becomes a unit not for the entire transmission time, as required by the interface standard. However, waitForBytesWritten returns after 5-10 milliseconds.

      Any thoughts on this?

      V Offline
      V Offline
      Vasily S
      wrote on last edited by
      #2

      Sorry, I did not add it - high pin state during transmission, low when receiving

      1 Reply Last reply
      0
      • aha_1980A Offline
        aha_1980A Offline
        aha_1980
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Vasily-S: Hi, and welcome to the Qt Forum!

        I guess your problem is buffering. The Linux Kernel is likely to keep a bunch of serial data in an internal buffer and sending it in background. Normally this is useful, but in your case it's a problem :)

        I see three possibilities for a proper solution:

        1. Use a microcontroller without operating system, where you have full control over the registers. I do similar tasks on 16 bit microcontrollers every day.
        2. Search for an existing or write your own Linux Kernel driver. The driver knows when the last character has been sent and can change the pin state.
        3. Use feedback of sent characters to know when sending is completed. You need to connect the UART TX pin to the (same or another) UART RX pin (if you use the same UART RX, you will need to decouple the pins with a diode, of course). With that change, you can "hear what you sent". This will allow you to easily do your task in user space (i.e. Qt)

        Qt has to stay free or it will die.

        1 Reply Last reply
        0
        • aha_1980A Offline
          aha_1980A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on last edited by
          #4

          One more note "Mobile and Embedded" would have been a better sub-forum for this question.

          Qt has to stay free or it will die.

          V 1 Reply Last reply
          0
          • aha_1980A aha_1980

            One more note "Mobile and Embedded" would have been a better sub-forum for this question.

            V Offline
            V Offline
            Vasily S
            wrote on last edited by
            #5

            @aha_1980 Thanks for the answer!

            Unfortunately, I do not have access to the microcontroller of this device.
            Therefore, in addition to writing the driver, I do not see another solution.

            1 Reply Last reply
            0
            • aha_1980A Offline
              aha_1980A Offline
              aha_1980
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @Vasily-S What you could also try is to flush the send buffer as far as possible.

              First, insert serial.flush() after your serial.write(data); [1]

              If that is not enough (I guess so), you can try flushing the Kernel buffers [2]. You will need the serial port handle for that [3]

              [1] http://doc.qt.io/qt-5/qserialport.html#flush
              [2] https://stackoverflow.com/questions/16398588/flush-linux-os-serial-buffer
              [3] http://doc.qt.io/qt-5/qserialport.html#handle

              Qt has to stay free or it will die.

              V 1 Reply Last reply
              2
              • aha_1980A aha_1980

                @Vasily-S What you could also try is to flush the send buffer as far as possible.

                First, insert serial.flush() after your serial.write(data); [1]

                If that is not enough (I guess so), you can try flushing the Kernel buffers [2]. You will need the serial port handle for that [3]

                [1] http://doc.qt.io/qt-5/qserialport.html#flush
                [2] https://stackoverflow.com/questions/16398588/flush-linux-os-serial-buffer
                [3] http://doc.qt.io/qt-5/qserialport.html#handle

                V Offline
                V Offline
                Vasily S
                wrote on last edited by
                #7

                @aha_1980 Many thanks, everything turned out. The problem was in the kernel buffer.

                It works

                #include <termios.h>
                ...
                void SerialTransport485::write(const QByteArray & msg)
                {
                    mGPIO.writeState(GPIO::IOEnable, GPIO::Set);
                    mPort->write(msg);
                    mPort->flush();
                
                    int serialHandle = mPort->handle();
                    tcdrain(serialHandle);
                
                    mGPIO.writeState(GPIO::IOEnable, GPIO::Reset);
                }
                
                1 Reply Last reply
                2
                • K Offline
                  K Offline
                  kuzulis
                  Qt Champions 2020
                  wrote on last edited by kuzulis
                  #8

                  Also you can try to use the bytesWritten(qint64 bytes) signal to know, how much bytes are written. And after this signal fired, to do reset the pin. It is preferrable unblocking way (also you can add tcdrain() here if need).

                  1 Reply Last reply
                  0

                  • Login

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