Не отрабатывает сигнал readyRead() в QSerialPort



  • Всем привет, товарищи форумчане!
    Столкнулся с такой проблемой (баг Qt или нет - не знаю):
    У меня есть слот, который по приходу пакета - получает его.
    Мой connect();

    connect(serial, &QSerialPort::readyRead, this, &eq_systems::readData);
    

    Кнопки "Подключиться к порту" у меня нету. Есть только кнопка "Write", по её нажатию я подключаюсь к порту, отправляю пакет, жду несколько секунд ответ от устройства. В любом случае, будет ответ или нет, я отключаюсь от порта.

    Так вот: если устройство ответит, то сигнал QSerialPort::readyRead(); исправно отработает. Но! Если устройство ответит больше одного раза, то при следующей отправки пакета и получения ответа - сигнал QSerialPort::readyRead(); не отработает никогда.

    Если устройство будет отвечать исправно по одному ответу на пакет, то всё будет нормально. Но вдруг баг и будет 2 ответа, то сигнал QSerialPort::readyRead(); не отработает

    Что делать в таких ситуациях?

    Слот, который принимает ответ с устройства по сигналу QSerialPort::readyRead();

    void eq_systems::readData()
    {
    	packet = serial->readAll();
    	qDebug() << "DATA: " << packet;
    }
    

    Буду очень признательный.



  • Дополню:

    У меня есть таймер и слот. Совсем другой слот. Он нужен для того, чтобы отсчитать время ожидания пакета и вывести ошибку, если пакет с ответом не пришел. Также есть слот, который работает по сигналу QSerialPort::readyRead(); вызывается он тогда, когда приходит ответ от устройства.

    Нажимаю на кнопку - подключаюсь к порту, шлю пакет, запускаю таймер. Таймер обновляет слот до тех пор, пока не придет пакет с ответом от устройства. Если пакет с ответом не пришел, значит сигнал не отработал, а значит, по логике вещей, пакет до устройства не дошел или на конце линии устройства вообще нету. Но если приходит ответ, то по сигналу QSerialPort::readyRead(); я попадаю в другой слот, где я отключаю таймер, отключаюсь от порта и пишу в статусе что всё "ок".

    Сам баг происходит тогда, когда от порта произошло отключение и я (со стороны устройства) начинаю просто слать пакеты либо куда. И вот тут самое интересное. Когда снова я отправляю пакет с программы на устройство, а устройство мне отвечает, то сигнал не отрабатывается вообще.

    Что делать, подскажите?



  • Та же самая проблема. На Qt5.7 никаких проблем, после переходя на Qt5.10 перестал получать данные с порта.
    Явно видно, что не приходит сигнал readyRead, переполняется буфер порта и висит. Программа даже не знает, что какие-то данные есть. Делать таймером глупо, если есть сигнал для этой цели - явно баг, жду когда пофиксят.



  • @Renewer said in Не отрабатывает сигнал readyRead() в QSerialPort:

    явно баг, жду когда пофиксят.

    Какой баг? У меня нет никаких багов, все работает.



  • @kuzulis said in Не отрабатывает сигнал readyRead() в QSerialPort:

    Какой баг? У меня нет никаких багов, все работает.

    Гражданин хороший, если у вас всё работает - это не значит, что у остальных тоже. Баг заключается в отсутствии сигнала readyRead(), когда он ДОЛЖЕН быть передан и некорректная работа программы вследствие. На Qt5.7 такого поведения не наблюдается при абсолютно идентичном коде. Надеюсь, вы понимаете смысл написанных повторно фраз?


  • Moderators

    @Renewer Zachem takoj ton?
    Esli vy schitaete chto v Qt oshibka to sdelajte soobshenie v https://bugreports.qt.io/secure/Dashboard.jspa inache vy dolgo budete zhdat'.



  • @jsulm said in Не отрабатывает сигнал readyRead() в QSerialPort:

    Esli vy schitaete chto v Qt oshibka to sdelajte soobshenie v https://bugreports.qt.io/secure/Dashboard.jspa inache vy dolgo budete zhdat'.

    Спасибо, сейчас попробую.
    Может вы знаете, нужно ли ковырять сам код библиотек, или достаточно сообщить о проблемном поведении?


  • Moderators

    @Renewer Dostatochno soobshit' o probleme. Mozhno pribavit' programku kotoraja demonstriruet problemu.



  • @Renewer said in Не отрабатывает сигнал readyRead() в QSerialPort:

    Надеюсь, вы понимаете смысл написанных повторно фраз?

    Намек был на то, что описание всей перечисленной выше проблемы не имеет смысла без конкретного минимального проекта, который воспроизводит проблему, где сразу было бы видно что и как. А гадать и разбираться что автор имеет ввиду ну нет никакого смысла. Да и непонятно о какой ОС речь, какой тип уар-та используется (какой чип), и воспроизводится ли это на Qt 5.8. Изменений особых между Qt 5.7 и Qt 5.10 в модуле QtSerialPort не было.

    PS: Если данные пришли уже после закрытия порта, то, естественно, они будут потеряны, и при следующем открытии никакого readyRead() не будет.

    PS2: И не важно по сколько пакетов у-во отвечает, хоть по 100500. Для QSP нет такого понятия как пакет, он оперирует байтовым потоком.

    PS3: И желателен пример как можно проще (без всяких там CRC и парсингов пакета), что-то вроде эхо, можно также попробовать с loopback воспроизвести (замкнуть Rx/Tx) дабы исключить весь лапша-код пользователя.



  • Я вас понял. Опишу максимально подробно.

    Да и непонятно о какой ОС речь, какой тип уар-та используется (какой чип), и воспроизводится ли это на Qt 5.8.

    ОС Win 7x86, в качестве устройства используется конвертер rs485-usb ftdi. Для того чтобы данные с порта могли читать сразу несколько программ используется VirtualSerialPortEmulator (предупреждая вопрос, без него ничего не меняется).
    На Qt5.8 не проверял.

    Изменений особых между Qt 5.7 и Qt 5.10 в модуле QtSerialPort не было.

    Если изменился размер библиотеки и точки входа - значит изменения хоть какие-то, но были. Кроме того возможно дело в QIODevice, потому что readyRead() наследуется от него.

    PS: Если данные пришли уже после закрытия порта, то, естественно, они будут потеряны, и при следующем открытии никакого readyRead() не будет.

    coreThread = new QThread(this);
    serialTranciever = new CSerialTranciever();
    serialTranciever->moveToThread(coreThread);
    connect(coreThread, &QThread::started, serialTranciever, &CSerialTranciever::portConnect);
    connect(coreThread, &QThread::finished, serialTranciever, &QObject::deleteLater);
    connect(coreThread, &QThread::finished, coreThread, &QObject::deleteLater);
    connect(serialTranciever, &QObject::destroyed, coreThread, &QThread::quit);
    coreThread->start();
    
    CSerialTranciever::CSerialTranciever(QObject *parent)
        : QSerialPort(parent)
    {
    -//-
        connect(this, QSerialPort::readyRead, this, CSerialTranciever::readBuffer);
    }
    
    void CSerialTranciever::portConnect()
    {-//-
        if (this->open(QSerialPort::ReadOnly))    emit connected();
        else         emit connectionError(0);
    -//-}
    
    void CSerialTranciever::readBuffer()
    {
        incomingArray.append(this->readAll());
       -//-
    }
    

    Порт открывается однократно и не закрывается, я говорю про свой случай. Данные читаются по сигналу:
    connect(this, QSerialPort::readyRead, this, CSerialTranciever::readBuffer);
    После подключения порта слот readBuffer не вызывается. Эмулятор говорит, что буфер заполнен.

    PS лапша-код полностью исключен, только главное
    Вполне возможно, что я просто не улавливаю суть правильной работы с портом. Сейчас в качестве временного решения работает так: connect(timer, QTimer::timeout, this, CSerialTranciever::readBuffer); учитывая, что за время таймера буфер не забьется.


  • Moderators

    @Renewer Vy ne probovali bes QThread? Prosto chtoby iskljuchit' problemy s multithreading.
    "Если изменился размер библиотеки и точки входа - значит изменения хоть какие-то, но были." - ne objazatelno. Prosto ispolsovali drugoj compiler.



  • У меня этот код работает:

    #include <QCoreApplication>
    #include <QSerialPort>
    #include <QThread>
    #include <QDebug>
    
    class Worker : public QSerialPort
    {
        Q_OBJECT
    public:
        explicit Worker(QObject *parent = nullptr)
            : QSerialPort(parent)
        {
            connect(this, &QSerialPort::readyRead, [this]() {
                qDebug() << "Rx:" << readAll();
            });
        }
    
        void initialize()
        {
            setPortName("COM3");
            const auto result = open(QIODevice::ReadOnly);
            qDebug() << "Opened:" << result;
        }
    
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        QThread thread;
        Worker worker;
        worker.moveToThread(&thread);
        QCoreApplication::connect(&thread, &QThread::started,
                                  &worker, &Worker::initialize);
        thread.start();
        return a.exec();
    }
    
    #include "main.moc"
    

    Windows 10, Qt 5.9.3/5.10.1: как с com0com так и с USB/Serial PL2303.

    PS: С FTDI вообще никаких проблем быть не должно, они отлично себя зарекомендовали.



  • @razorqhex

    1. С какими настройками откр. порт? (Parity, FlowControl и тд)
    2. QThread используется?
    3. Елси 2 да, то в каком месте соединяется readyRead?


  • @bohdan said in Не отрабатывает сигнал readyRead() в QSerialPort:

    С какими настройками откр. порт? (Parity, FlowControl и тд)

    setParity(QSerialPort::NoParity);
    setFlowControl(QSerialPort::NoFlowControl);
    

    QThread используется?
    Елси 2 да, то в каком месте соединяется readyRead?

    Используется. Соединяется в конструкторе. Порт открывается уже после передачи QSerialPort в другой поток по сигналу started.


Log in to reply
 

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