Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. QSerialPort transmit errors while sending 0xff
QtWS25 Last Chance

QSerialPort transmit errors while sending 0xff

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
6 Posts 2 Posters 506 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.
  • T Offline
    T Offline
    tobias423412
    wrote on 26 Oct 2019, 19:11 last edited by tobias423412
    #1

    Hello,

    i try to implement a communication between an embedded device and my computer. During development, i observed that i get a lot errors during the communication, when the byte array contains magic bytes like 0xff.
    It got more strange when i tried to send only characters like 0xff. On my serial adapter i can see, that the TX LED stars stuttering. If i send other bytes like 0x55 or something like that, the LED is smoothly flashing and i have no errors during transmit.
    It is really easy to reproduce and to prove that my target has no influence. I disconnected my target and i can still see that the LED stutters during 0xff and not during other characters on my serial adapter.
    To make it more confusing: The majority of bytes is transmitted correctly. Just a small percentage of 0xff's is not transmitted correctly.
    I am using Mac OS Mojave and tried it with Qt 5.6 and 5.12. Both show exactly the same behavior.

    Has someone an idea from where this is coming and how i can fix this?

    Greetings
    Tobias

    A 1 Reply Last reply 27 Oct 2019, 05:55
    0
    • T tobias423412
      26 Oct 2019, 19:11

      Hello,

      i try to implement a communication between an embedded device and my computer. During development, i observed that i get a lot errors during the communication, when the byte array contains magic bytes like 0xff.
      It got more strange when i tried to send only characters like 0xff. On my serial adapter i can see, that the TX LED stars stuttering. If i send other bytes like 0x55 or something like that, the LED is smoothly flashing and i have no errors during transmit.
      It is really easy to reproduce and to prove that my target has no influence. I disconnected my target and i can still see that the LED stutters during 0xff and not during other characters on my serial adapter.
      To make it more confusing: The majority of bytes is transmitted correctly. Just a small percentage of 0xff's is not transmitted correctly.
      I am using Mac OS Mojave and tried it with Qt 5.6 and 5.12. Both show exactly the same behavior.

      Has someone an idea from where this is coming and how i can fix this?

      Greetings
      Tobias

      A Offline
      A Offline
      aha_1980
      Lifetime Qt Champion
      wrote on 27 Oct 2019, 05:55 last edited by
      #2

      Hi @tobias423412

      I'm using QtSerialPort to transmit binary data to one of my self-built embedded devices using FTDI serial adapters - without problems.

      So there are three possible things that could be wrong on your side:

      1. Your hardware - which is that?
      2. Your code - can you show it?
      3. Are you using a software protocol like XON/XOFF?

      Regards

      Qt has to stay free or it will die.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        tobias423412
        wrote on 27 Oct 2019, 08:23 last edited by tobias423412
        #3

        Hi,

        this is not the most clean code, but it does the job:

        #include "serialportwriter.h"
        
        #include <QCoreApplication>
        #include <QDebug>
        #include <QThread>
        QT_USE_NAMESPACE
        #define TEST_BYTE ((uint8_t)0xff)
        #define END_ADDR 0xf
        
        SerialPortWriter::SerialPortWriter(QSerialPort *serialPort, QObject *parent)
            : QObject(parent)
            , m_serialPort(serialPort)
            , m_standardOutput(stdout)
            , m_bytesWritten(0)
            , m_testByte(TEST_BYTE)
        {
            m_timer.setSingleShot(false);
            connect(m_serialPort, &QSerialPort::bytesWritten, this, &SerialPortWriter::handleBytesWritten);
            connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
                    this, &SerialPortWriter::handleError);
            connect(&m_timer, &QTimer::timeout, this, &SerialPortWriter::handleTimeout);
            connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortWriter::readReady);
            m_timer.start(35);
        }
        
        SerialPortWriter::~SerialPortWriter()
        {
        }
        
        void SerialPortWriter::handleBytesWritten(qint64 bytes)
        {
        
        }
        
        void SerialPortWriter::handleTimeout()
        {
            static bool read = false;
            static uint32_t readCycle = 0;
            static uint32_t writeCycle = 0;
            static uint16_t addr = 0;
            if (read)
            {
                QByteArray readData;
                readData.push_back((char)0x1); // Read Command
                readData.push_back((char)(addr >> 8)); // 23:16
                readData.push_back((char)(addr & 0xff)); // 15:8
                readData.push_back((char)0x0); // 7:0
                readData.push_back((char)0x40); // Size in DWord
        
        
                if (addr < END_ADDR)
                {
                    write(readData);
                    addr++;
                }
                else
                {
                    addr = 0;
                    read = false;
                    qDebug() << "Read cylce" << readCycle++;
                }
            }
            else
            {
                QByteArray writeData;
                writeData.push_back((char)0x2); // Write Command
                writeData.push_back((char)(addr >> 8)); // 23:16
                writeData.push_back((char)(addr & 0xff)); // 15:8
                writeData.push_back((char)0x0); // 7:0
                writeData.push_back((char)0x40); // Size in DWord
        
                // Payload
                for (int i = 0; i < 0x40; i++)
                {
                    writeData.push_back((char)m_testByte);
                    writeData.push_back((char)m_testByte);
                    writeData.push_back((char)m_testByte);
                    writeData.push_back((char)m_testByte);
                }
        
                if (addr < END_ADDR)
                {
                    write(writeData);
                    addr++;
                }
                else
                {
                    qDebug() << "Write cylce" << writeCycle++;
                    addr = 0;
                    read = true;
                }
            }
        }
        
        void SerialPortWriter::handleError(QSerialPort::SerialPortError serialPortError)
        {
            if (serialPortError == QSerialPort::WriteError) {
                m_standardOutput << QObject::tr("An I/O error occurred while writing the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                QCoreApplication::exit(1);
            }
        }
        
        void SerialPortWriter::readReady()
        {
            QByteArray r = m_serialPort->readAll();
            for (int i = 0; i < r.size(); i++)
            {
                if ((uint8_t)(r.at(i)) != m_testByte)
                {
                    qDebug() << "Read Error actual:" << QString::number((uint8_t)(r.at(i))).toInt() << "should:" << QString::number(m_testByte).toInt();
                }
            }
        }
        
        void SerialPortWriter::write(const QByteArray &writeData)
        {
            m_writeData = writeData;
        
            qint64 bytesWritten = m_serialPort->write(writeData);
        
            if (bytesWritten == -1) {
                m_standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                QCoreApplication::exit(1);
            } else if (bytesWritten != m_writeData.size()) {
                m_standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                QCoreApplication::exit(1);
            }
            //m_serialPort->flush();
        }
        

        What i am doing here? I write 0xff in some memory and when i am done with this, i try to read it back. And that is what i am doing forever.
        If i am using for TEST_BYTE 0xAA or something like that, everything works fine. If it is 0xff than something goes wrong. If i read the memory back, i get errors on random places.
        The error outputs like this

        Read Error actual: 251 should: 255
        Read Error actual: 254 should: 255
        Read Error actual: 251 should: 255
        Read Error actual: 254 should: 255
        Read Error actual: 251 should: 255
        

        As a serial converter i am using an ordinary FT232.

        Greetings
        Tobias

        A 1 Reply Last reply 27 Oct 2019, 08:39
        0
        • T tobias423412
          27 Oct 2019, 08:23

          Hi,

          this is not the most clean code, but it does the job:

          #include "serialportwriter.h"
          
          #include <QCoreApplication>
          #include <QDebug>
          #include <QThread>
          QT_USE_NAMESPACE
          #define TEST_BYTE ((uint8_t)0xff)
          #define END_ADDR 0xf
          
          SerialPortWriter::SerialPortWriter(QSerialPort *serialPort, QObject *parent)
              : QObject(parent)
              , m_serialPort(serialPort)
              , m_standardOutput(stdout)
              , m_bytesWritten(0)
              , m_testByte(TEST_BYTE)
          {
              m_timer.setSingleShot(false);
              connect(m_serialPort, &QSerialPort::bytesWritten, this, &SerialPortWriter::handleBytesWritten);
              connect(m_serialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
                      this, &SerialPortWriter::handleError);
              connect(&m_timer, &QTimer::timeout, this, &SerialPortWriter::handleTimeout);
              connect(m_serialPort, &QSerialPort::readyRead, this, &SerialPortWriter::readReady);
              m_timer.start(35);
          }
          
          SerialPortWriter::~SerialPortWriter()
          {
          }
          
          void SerialPortWriter::handleBytesWritten(qint64 bytes)
          {
          
          }
          
          void SerialPortWriter::handleTimeout()
          {
              static bool read = false;
              static uint32_t readCycle = 0;
              static uint32_t writeCycle = 0;
              static uint16_t addr = 0;
              if (read)
              {
                  QByteArray readData;
                  readData.push_back((char)0x1); // Read Command
                  readData.push_back((char)(addr >> 8)); // 23:16
                  readData.push_back((char)(addr & 0xff)); // 15:8
                  readData.push_back((char)0x0); // 7:0
                  readData.push_back((char)0x40); // Size in DWord
          
          
                  if (addr < END_ADDR)
                  {
                      write(readData);
                      addr++;
                  }
                  else
                  {
                      addr = 0;
                      read = false;
                      qDebug() << "Read cylce" << readCycle++;
                  }
              }
              else
              {
                  QByteArray writeData;
                  writeData.push_back((char)0x2); // Write Command
                  writeData.push_back((char)(addr >> 8)); // 23:16
                  writeData.push_back((char)(addr & 0xff)); // 15:8
                  writeData.push_back((char)0x0); // 7:0
                  writeData.push_back((char)0x40); // Size in DWord
          
                  // Payload
                  for (int i = 0; i < 0x40; i++)
                  {
                      writeData.push_back((char)m_testByte);
                      writeData.push_back((char)m_testByte);
                      writeData.push_back((char)m_testByte);
                      writeData.push_back((char)m_testByte);
                  }
          
                  if (addr < END_ADDR)
                  {
                      write(writeData);
                      addr++;
                  }
                  else
                  {
                      qDebug() << "Write cylce" << writeCycle++;
                      addr = 0;
                      read = true;
                  }
              }
          }
          
          void SerialPortWriter::handleError(QSerialPort::SerialPortError serialPortError)
          {
              if (serialPortError == QSerialPort::WriteError) {
                  m_standardOutput << QObject::tr("An I/O error occurred while writing the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                  QCoreApplication::exit(1);
              }
          }
          
          void SerialPortWriter::readReady()
          {
              QByteArray r = m_serialPort->readAll();
              for (int i = 0; i < r.size(); i++)
              {
                  if ((uint8_t)(r.at(i)) != m_testByte)
                  {
                      qDebug() << "Read Error actual:" << QString::number((uint8_t)(r.at(i))).toInt() << "should:" << QString::number(m_testByte).toInt();
                  }
              }
          }
          
          void SerialPortWriter::write(const QByteArray &writeData)
          {
              m_writeData = writeData;
          
              qint64 bytesWritten = m_serialPort->write(writeData);
          
              if (bytesWritten == -1) {
                  m_standardOutput << QObject::tr("Failed to write the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                  QCoreApplication::exit(1);
              } else if (bytesWritten != m_writeData.size()) {
                  m_standardOutput << QObject::tr("Failed to write all the data to port %1, error: %2").arg(m_serialPort->portName()).arg(m_serialPort->errorString()) << endl;
                  QCoreApplication::exit(1);
              }
              //m_serialPort->flush();
          }
          

          What i am doing here? I write 0xff in some memory and when i am done with this, i try to read it back. And that is what i am doing forever.
          If i am using for TEST_BYTE 0xAA or something like that, everything works fine. If it is 0xff than something goes wrong. If i read the memory back, i get errors on random places.
          The error outputs like this

          Read Error actual: 251 should: 255
          Read Error actual: 254 should: 255
          Read Error actual: 251 should: 255
          Read Error actual: 254 should: 255
          Read Error actual: 251 should: 255
          

          As a serial converter i am using an ordinary FT232.

          Greetings
          Tobias

          A Offline
          A Offline
          aha_1980
          Lifetime Qt Champion
          wrote on 27 Oct 2019, 08:39 last edited by
          #4

          @tobias423412

          Your code still looks a bit complicated and is missing important pieces, like the serial port set up. Which baud rate are you using? Am I right that you repeat that cycle every 35 ms?

          On my serial adapter i can see, that the TX LED stars stuttering.

          Ok, then I'd start with a simple program that only transmits a fixed frame, containing 0xff. Does that work? If yes, then do it from a timer with a timeout large enough that the previous frame is completely transmitted (to avoid buffer overflows).

          I really can't see why transmitting arbitrary data should lead to problems like you described.

          Regards

          Qt has to stay free or it will die.

          1 Reply Last reply
          1
          • T Offline
            T Offline
            tobias423412
            wrote on 27 Oct 2019, 09:05 last edited by
            #5

            Hi,

            yes, the init

            #include "serialportwriter.h"
            
            #include <QtSerialPort/QSerialPort>
            #include <QCoreApplication>
            
            #include <QString>
            #include <QDebug>
            
            QT_USE_NAMESPACE
            
            int main(int argc, char *argv[])
            {
            
                QCoreApplication coreApplication(argc, argv);
                int argumentCount = QCoreApplication::arguments().size();
                QStringList argumentList = QCoreApplication::arguments();
            
                QTextStream standardOutput(stdout);
            
                if (argumentCount != 3) {
                    standardOutput << "Version 1.0.0 (Compile date: " << __DATE__ << " " << __TIME__ << ")" << endl;
                    standardOutput << QObject::tr("Usage: %1 <serialportname> <baudrate>").arg(argumentList.first()) << endl;
                    return 1;
                }
            
                QSerialPort serialPort;
                QString serialPortName = argumentList.at(1);
                serialPort.setPortName(serialPortName);
            
                int serialPortBaudRate = argumentList.at(2).toInt();
                serialPort.setBaudRate(serialPortBaudRate);
            
                serialPort.open(QIODevice::ReadWrite);
                serialPort.setParity(QSerialPort::NoParity);
                serialPort.setStopBits(QSerialPort::OneStop);
                serialPort.setFlowControl(QSerialPort::NoFlowControl);
                serialPort.setDataBits(QSerialPort::Data8);
            
                SerialPortWriter serialPortWriter(&serialPort);
                return coreApplication.exec();
            }
            
            

            I am using 115200 baud.

            I use that timer to periodically send one frame of data. After every 15 timer shots i switch from sending payload to reading payload. Theoretically i can send around 500 bytes within this 35ms and currently sending around 261.

            I tried also now to just send a byte array containing only 0xff. I also increased the time of the timer. The TX LED on the FT232 is still stuttering.

            Greetings
            Tobias

            1 Reply Last reply
            0
            • T Offline
              T Offline
              tobias423412
              wrote on 27 Oct 2019, 09:23 last edited by
              #6

              I guess i found a solution which i don't like.

              I observed also two crashes of my USB stack on my Mac which are (obviously) related to this stuff. Sometimes when i start this program all my USB ports are dying and the kernel tasks runs with 100% load. I can only resurrect the USB ports by a reboot of my computer. If i connect the serial adapter on a nativ USB port, it works as intended without any errors.

              The USB Hub should have enough power. It is a Hub which is powered from an external power plug.

              For sure, i would be really thankful if anyone know a better workaround to this bug instead of utilizing one of the very rare native USB ports on a Mac, but in this case, i guess, it is an Apple problem and not an Qt related one.

              Thank you very much for your help

              Greetings
              Tobias

              1 Reply Last reply
              0

              1/6

              26 Oct 2019, 19:11

              • Login

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