Skip to content
  • 0 Votes
    3 Posts
    916 Views
    BeaverShallBurnB

    Hi, @J-Hilk!

    Looks like i found desired method in QModbusDataUnit class docs. Don't know how i missed it being mentioned in List of All Members for QModbusRtuSerialMaster. I guess digging into Qt docs about Modbus was a proper way to solve this :)

    QModbusDataUnit::QModbusDataUnit(QModbusDataUnit::RegisterType type, int address, const QVector<quint16> &data)

    In my case this will be:

    QModbusDataUnit input(QModbusDataUnit::InputRegisters, 3001, data);

    Thanks for joining my journey!

  • 0 Votes
    7 Posts
    1k Views
    A

    Hi @Chai18 Did you find any solution ? I have a similar issue but in the client side (QModbusClient) , this is my function to write data to the holding registers , but I'm all the time getting the response timeout, and master is actually handling incoming requests and send appropriate responses automatically.

    void Serial::writeData(int start, const QList<quint16> &holdingRegisters) { if (!modbusDevice) return; startAddress = start; numberOfEntries = holdingRegisters.size(); // Switch to Transmit Mode switchGPIO->setValue(true); // enables TX QModbusDataUnit writeUnit = writeRequest(); QModbusDataUnit::RegisterType table = writeUnit.registerType(); for (qsizetype i = 0, total = writeUnit.valueCount(); i < total; ++i) { const auto addr = i + writeUnit.startAddress(); if (table == QModbusDataUnit::Coils) writeUnit.setValue(i, m_coils[addr]); else writeUnit.setValue(i, holdingRegisters[addr]); } if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, serverAddress)) { if (!reply->isFinished()) { QModbusDevice::connect( reply, &QModbusReply::finished, this, [this, reply]() { // Switch back to Receive Mode usleep(1000); // Small delay before switching switchGPIO->setValue(false); // Enable RX mode const auto error = reply->error(); if (error == QModbusDevice::ProtocolError) { qDebug() << "Write response error:" << reply->errorString() << "(Modbus exception:" << reply->rawResult().exceptionCode() << ")"; } else if (error != QModbusDevice::NoError) { qDebug() << "Write response error:" << reply->errorString() << "(code: 0x" << QString::number(error, 16) << ")"; } reply->deleteLater(); }); } else { qDebug() << "Write error: " << reply->errorString(); reply->deleteLater(); } } else { qDebug() << "Write error: " << modbusDevice->errorString(); switchGPIO->setValue(false); // Ensure RX mode is enabled on failure } }

    Thanks in advance

  • 0 Votes
    3 Posts
    1k Views
    R

    Thank you very much!
    Using the "finished"-signal everything works fine :-)

  • 0 Votes
    3 Posts
    3k Views
    J.HilkJ

    @tangxinzhou I'm afraid I do not have a solid solutions. I'm running a workaround now.

    Let me post it for you:

    void connectDevice(bool connect) { if(connect){ switch (mDevice->state()) { case QModbusDevice::ClosingState: case QModbusDevice::ConnectedState: case QModbusDevice::ConnectingState: mDevice->deleteLater(); mDevice = new QModbusRtuSerialMaster(this); setupSignalSlots(); QTimer::singleShot(100,this, [=]{setConnectParamter(m_port,m_paramter);}); break; case QModbusDevice::UnconnectedState: default: if(!mDevice->connectDevice()){ emit signalModbusError(mDevice->errorString()); mDevice->disconnectDevice(); } break; } }else{ stopPoll(); mDevice->disconnectDevice(); QTimer::singleShot(200,this,[=]{checkDisconnected();}); } } void checkDisconnected() { if(mDevice->state() != QModbusDevice::UnconnectedState){ mDevice->deleteLater(); mDevice = new QModbusRtuSerialMaster(this); setupSignalSlots(); } }