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. QModbus in a Thread
Forum Updated to NodeBB v4.3 + New Features

QModbus in a Thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
3 Posts 1 Posters 658 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.
  • H Offline
    H Offline
    hkottmann
    wrote on 24 Apr 2020, 13:32 last edited by
    #1

    On my programm I have a worker thread (QThread) that is independent from the GUI-thread which is collecting data from an RS232 device and a modbus (RS485) device. While RS232 is easy to handle, I have a problem with the modbus device since QModbus is obviously running in a separate thread. I have programmed it like the modbus example that comes with the QT installation, so I send a read request and connect the reply with a slot which takes care of picking up the data. Currently I'm waiting for the answer using this code:

    do
        {
            QEventLoop(this).processEvents();
        } while (!answerReceived);
    

    But this seems to be an ugly hack, so I get tons of such error messages in QTCreator:

    QBasicTimer::start: Timers cannot be started from another thread
    

    What would be the proper way to implement this?

    1 Reply Last reply
    0
    • H Offline
      H Offline
      hkottmann
      wrote on 26 Apr 2020, 10:15 last edited by
      #2

      I've tried these two suggestions from here, but I still get tons of these timer errors:

      https://stackoverflow.com/questions/5610785/how-to-tell-qthread-to-wait-until-work-is-done-and-then-finish

      1 Reply Last reply
      0
      • H Offline
        H Offline
        hkottmann
        wrote on 27 Apr 2020, 06:24 last edited by
        #3

        Here the full code of the involved functions:

        void Worker::requestValue(int address, int length)
        {
            answerReceived = false;
            qDebug() << "Read values";
            read(address, length);
            do
            {
                QEventLoop(this).processEvents();
            } while (!answerReceived);
        }
        
        void Worker::read(int address, int length)
        {
            if (!modbusDevice)
                return;
            if (auto *reply = modbusDevice->sendReadRequest(readRequest(address, length), 10)) {
                if (!reply->isFinished())
                    connect(reply, &QModbusReply::finished, this, &Worker::onReceiveValues);
                else
                    delete reply; // broadcast replies return immediately
            } else {
                qDebug() << tr("Read error: ") + modbusDevice->errorString();
            }
        }
        
        void Worker::onReceiveValues()
        {
            auto reply = qobject_cast<QModbusReply *>(sender());
            if (!reply)
                return;
        
        if (reply->error() == QModbusDevice::NoError) {
            const QModbusDataUnit unit = reply->result();
            QVector<quint16> receivedValues = unit.values();
            switch(answerType)
            {
            case AnswerType::Flow:
            {
                prominentPumvValues.flow = processFloatValue(receivedValues);
            }
                break;
            case AnswerType::Stroke:
            {
                prominentPumvValues.stroke = processFloatValue(receivedValues);
            }
                break;
            case AnswerType::Frequency:
                prominentPumvValues.frequency = receivedValues.at(0);
                break;
            case AnswerType::SerialNumber:
            {
                prominentPumvValues.serialNumber = processString(receivedValues);
            }
            default:
                break;
            }
        } else if (reply->error() == QModbusDevice::ProtocolError) {
            qDebug() << tr("Read response error: %1 (Mobus exception: 0x%2)").
                                        arg(reply->errorString()).
                                        arg(reply->rawResult().exceptionCode(), -1, 16);
        } else {
            qDebug() << tr("Read response error: %1 (code: 0x%2)").
                                        arg(reply->errorString()).
                                        arg(reply->error(), -1, 16);
        }
        
        reply->deleteLater();
        answerReceived = true;
        }
        

        I've found this thread here: https://forum.qt.io/topic/82819/qbasictimer-start-timers-cannot-be-started-from-another-thread-issue/10 and modified the read function as follows:

        void Worker::read(int address, int length)
        {
            if (!modbusDevice)
                return;
            if (auto *reply = modbusDevice->sendReadRequest(readRequest(address, length), 10)) {
                if (!reply->isFinished())
                {
                    qDebug() << "Reply not finished";
                    qDebug() << "Connect: " << connect(reply, &QModbusReply::finished, [reply, this]() {
                        qDebug() << "connect";
                        if(reply->error() == QModbusClient::NoError)
                        {
                            const QModbusDataUnit unit = reply->result();
                            receivedValues = unit.values();
                            qDebug() << "Lambda: " << receivedValues.length();
                        }
                        else
                            qDebug() << "Reply error";
                        reply->deleteLater();
                        qDebug() << "Bye";
                    });
                    qDebug() << "Ade";
                }
                else
                {
                    qDebug() << "Reply finished";
                    delete reply; // broadcast replies return immediately
                }
            } else {
                qDebug() << tr("Read error: ") + modbusDevice->errorString();
            }
            qDebug() <<receivedValues[0] << receivedValues[1];
        }
        

        The answer of connect is true but so it looks the code inside the lambda is not executed, there is no output of the qDebug() functions inside the lambda

        1 Reply Last reply
        0

        1/3

        24 Apr 2020, 13:32

        • Login

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