USB <=> Serial Test Bug



  • Hello once again,

    based on the Terminal example i tried a stripped down version, where are existing two
    buttons and a lable on a ui-File. The buttons are triggering a send process on a QSerialPort instance. One button sends a string "String 1", the other "String 2", both terminated with "\0".
    I use one of these "cable-build-in" FTDI adapter cables and shortcutted RX and TX.

    When i press the button a few times, it happens, that bytes get lost. What i´m doing wrong?

    best regards,
    Moe

    Project is based on QWidget template project, i didn´t do anything to main.cpp.

    widget.h:
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>
    #include <QtSerialPort/QSerialPort>

    namespace Ui {
    class Widget;
    }

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    private:
    Ui::Widget *ui;
    QSerialPort serial;
    QString s1;
    QString s2;

    private slots:
    void NewSerialData();
    void s1Slot();
    void s2Slot();
    };

    #endif // WIDGET_H

    //******************************************

    widget.cpp:
    #include "widget.h"
    #include "ui_widget.h"

    Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
    {
    ui->setupUi(this);

    serial.setPortName("COM11");
    serial.setBaudRate(QSerialPort::Baud9600);
    serial.setDataBits(QSerialPort::Data8);
    serial.setParity(QSerialPort::NoParity);
    serial.setStopBits(QSerialPort::OneStop);
    serial.setFlowControl(QSerialPort::NoFlowControl);
    serial.open(QIODevice::ReadWrite);
    connect(ui->s1, SIGNAL(clicked()), this, SLOT(s1Slot()));
    connect(ui->s2, SIGNAL(clicked()), this, SLOT(s2Slot()));
    connect(&serial, SIGNAL(readyRead()), this, SLOT(NewSerialData()));
    s1 = "String 1";
    s2 = "String 2";
    

    }

    Widget::~Widget()
    {
    delete ui;
    }

    void Widget::s1Slot()
    {
    serial.write(s1.toLocal8Bit()+"\0");
    }

    void Widget::s2Slot()
    {
    serial.write(s2.toLocal8Bit()+"\0");
    }

    void Widget::NewSerialData()
    {
    ui->label->setText(serial.readAll());
    }

    //**************************************
    widget.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
    <class>Widget</class>
    <widget class="QWidget" name="Widget">
    <property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>477</width>
    <height>114</height>
    </rect>
    </property>
    <property name="windowTitle">
    <string>Widget</string>
    </property>
    <widget class="QPushButton" name="s2">
    <property name="geometry">
    <rect>
    <x>360</x>
    <y>40</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>String 2</string>
    </property>
    </widget>
    <widget class="QLabel" name="label">
    <property name="geometry">
    <rect>
    <x>40</x>
    <y>30</y>
    <width>141</width>
    <height>31</height>
    </rect>
    </property>
    <property name="font">
    <font>
    <pointsize>12</pointsize>
    </font>
    </property>
    <property name="text">
    <string/>
    </property>
    </widget>
    <widget class="QPushButton" name="s1">
    <property name="geometry">
    <rect>
    <x>250</x>
    <y>40</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>String 1</string>
    </property>
    </widget>
    </widget>
    <layoutdefault spacing="6" margin="11"/>
    <resources/>
    <connections/>
    </ui>

    //************************************************

    .pro:

    QT += core gui
    QT += widgets serialport

    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

    TARGET = USB_SERIAL_Test
    TEMPLATE = app

    SOURCES += main.cpp
    widget.cpp

    HEADERS += widget.h

    FORMS += widget.ui



  • What i´m doing wrong?

    Why are you think that this:

    void Widget::NewSerialData()
    {
        ui->label->setText(serial.readAll());
    }
    

    will display whole your string? This is not true.

    You should do something:

    void Widget::NewSerialData()
    {
        if (serial.bytesAvailable() == expected)
            ui->label->setText(serial.readAll());
    }
    

    where 'expected' - is an expected size of your string, in bytes



  • Yes, this way it works.
    Thanks for answer!

    The point is, i don´t know what happens behind the scenes. I "think" the Qt will trigger "readyRead()" Signal the moment the first byte arives? But until the moment the OS goes to get them, there allready arived an unkown ammount of new bytes. I think this can vary by time elapsing from Signal to Service wich is unpredictable for a non RT-OS.
    Plus what happens when reading the Serial driver? Is it a linear or circular buffer? Are the amount of incoming and read out bytes are counted?
    When i have serial slaves which are sending a random amount of bytes per burst, i don´t know the amount in advance, so how would i handle that?



  • Signal the moment the first byte arives?

    No. For one or several bytes (in reality in FIFO can be several bytes in current moment)!

    But until the moment the OS goes to get them, there allready arived an unkown ammount of new bytes. I think this can vary by time elapsing from Signal to Service wich is unpredictable for a non RT-OS.

    Yes, it is.

    Plus what happens when reading the Serial driver?

    Reads all available data from the FIFO into own internal buffer.

    Is it a linear or circular buffer?

    Linear, unlimited by default.

    Are the amount of incoming and read out bytes are counted?

    For the user it is has sense only bytesAvailable() which defines a count of bytes that are stored in internal buffer of the class and available to reading for the user.

    When i have serial slaves which are sending a random amount of bytes per burst, i don´t know the amount in advance, so how would i handle that?

    I don't know, it depends on you.

    For this purpose it is necessary to develop the appropriate communication protocol between a master and slave. Where the slave sends a frame, which containd a field in which described the size of whole frame.

    Or, you can use the QTimer to handle a timeout of frame. The timer should be re-started on each readyRead(), but the data reading should be happens only by the timeout() signal from the timer.



  • Ah, more clear now.

    Something itches me.

    Are the amount of incoming and read out bytes are counted?
    

    For the user it is has sense only bytesAvailable() which defines a count of bytes that are stored in internal buffer of the class and available to reading for the user.

    From the moment "bytesAvailable()" return the amount to the moment the if clause performs the descision; following Murphy, this is the exact moment a new byte arives and the returned amount is wrong.
    Is this scenario handled by the OS or framework?

    And much more important:
    How do i get the information you gave me on my own next time in order to help myself?



  • Is this scenario handled by the OS or framework?

    • The readyRead() is emitted when the new data has been appended into the internal buffer of class.
    • The bytesAvailable() returns the size of the internal buffer of class
    • The read()/readAll() reads data from the internal buffer of class.

    So, I do not understand what is difficulties for you.

    How do i get the information you gave me on my own next time in order to help myself?

    I do not understand what you mean.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.