Добрый день. Настраиваю modbus RTU для обмена данными приложения и PLC, но при отправке данных я получаю ошибку «Request timeout». При этом данные отправлены и получены контроллером (у меня стоит приложение на компьютере, которое может это отследить и показать). Я не могу понять, почему возникает эта ошибка. Сначала я думала увеличить время таймаута, но это ни на что не повлияло (при этом по ощущениям значение таймаута будто и не менялось вовсе). Потом я подумала, что, может, у меня посылается несколько раз пакет данных, когда первый нормально считывается, а второй выдает ошибку выхода времени, но при проверке через дебаггер часть кода, которая отвечает за полную передачу, даже не вызывается. Если у кого-нибудь будут предположения, что может быть не так, я буду рада проверить.
Код класса modbus:
modbus.h:
class QModbusClient;
class QModbusReply;
class Modbus : public QObject
{
Q_OBJECT
public:
Modbus(QObject *parent = nullptr);
~Modbus();
QModbusDataUnit readRequest() const;
QModbusDataUnit writeRequest() const;
private:
void init();
void on_writeButton_clickedRegisters(qint32 registers[], qint32 values[]);
QModbusClient *modbusDevice;
const int SERVER_ADDRESS = 1;
const int START_ADDRESS = 0;
const int AMOUNT = 24;
const int WRITE_SIZE = 24;
const int BAUDS = 9600;
const int STOP_BITS = 1;
const int DATA_BITS = 8;
const QString PORT = "ttyUSB0";
const int PARITY = QSerialPort::NoParity;
const int RESPONSE_TIME = 250;
};
#endif // MODBUS_H
modbus.cpp:
Modbus::Modbus(QObject *parent) :
QObject(parent),
modbusDevice(nullptr)
{
init();
}
void Modbus::init() {
modbusDevice = new QModbusRtuSerialMaster(this);
connect(modbusDevice, &QModbusClient::errorOccurred, [this](QModbusDevice::Error) {
emit sendData(modbusDevice->errorString());});
qDebug() << "Error message: " << modbusDevice->errorString();
if(modbusDevice) {
connect(modbusDevice, &QModbusClient::stateChanged,this, &Modbus::onStateChanged);
}
if (modbusDevice->state() != QModbusDevice::ConnectedState) {
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,PORT);
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,PARITY);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,BAUDS);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,DATA_BITS);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,STOP_BITS);
modbusDevice->setTimeout(RESPONSE_TIME);
modbusDevice->setNumberOfRetries(1);
if (!modbusDevice->connectDevice()) {
emit sendData(modbusDevice->errorString());
}
} else {
modbusDevice->disconnectDevice();
}
}
void Modbus::on_writeButton_clickedRegisters(qint32 registers[], qint32 values[])
{
<часть кода>
if (auto *lastRequest = modbusDevice->sendWriteRequest(writeUnit, SERVER_ADDRESS)) {
if (!lastRequest->isFinished()) {
connect(lastRequest, &QModbusReply::finished, this, [ lastRequest]() {
if (lastRequest->error() == QModbusDevice::ProtocolError) {
qDebug()<<"1"<<lastRequest->errorString();
} else if (lastRequest->error() != QModbusDevice::NoError) {
qDebug()<<"2"<<lastRequest->errorString();
//ошибка проходит через эту часть кода
}
lastRequest->deleteLater();
});
} else {
qDebug()<<"yes send"; //это не вызывается
lastRequest->deleteLater();
}
} else {
qDebug()<<lastRequest->errorString();
}
}
П.С. Особенности кода:
- У меня приложение, в котором много окон, взаимодействующих друг с другом и, соответственно, много файлов. Чтобы не создавать в каждом файле свой объект modbus, я создала класс, в котором обозначила глобальный объект класса Modbus, к которому обращается каждое окно, если ему это необходимо. Выглядит это так:
#ifndef GLOBALVARIABLE_H
#define GLOBALVARIABLE_H
#include "modbus.h"
inline Modbus connect_modbus = Modbus();
#endif // GLOBALVARIABLE_H
- Файлы не посылают одновременно запросы Modbus’у, так как у меня работает всего один поток, то есть запросы пересекаться не будут.