Russian Qt Forum

Qt => Вопросы новичков => Тема начата: bv7 от Февраль 24, 2023, 17:58



Название: Modbus RTU. Запись в modbus регистр.
Отправлено: bv7 от Февраль 24, 2023, 17:58
Доброго всем времени суток.
qt5.15
Из приложения должен формироваться запрос — "01 06 00 00 00 05 49 C9", по факту же формируется "00 06 00 00 00 00 88 1B". Пробовал вместо spinBox->value() прописывать другие значения, например 100 или 5, все равно в запросе отправляется 0, судя по трафику. Т.к. реального контроллера нет все эксперименты провожу на виртуальных com портах. Виртуальные порты работают корректно, т.к. mobusPull и modbusSlave данные передают нормально. В чем причина? Как исправить?
Запись в регистр:
Код:
void MainWindow::write_registr(int num_device, int reg, quint16 data){
    if (!modbusDevice) return;
    QModbusDataUnit writeUnit;
    writeUnit.setRegisterType(QModbusDataUnit::HoldingRegisters);
    writeUnit.setStartAddress(reg);
    writeUnit.setValueCount(1);
    writeUnit.setValue(0,data);
    if (QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device)){
        if(!lastRequest->isFinished()){
        connect(lastRequest, &QModbusReply::finished, this, [=](){
            if(lastRequest->error() == QModbusDevice::ProtocolError){
    //ошибка протокола
                ui->statusBar->showMessage("Ошибка протокола");
            }else if(lastRequest->error() == QModbusDevice::TimeoutError){
    //превышено время ожидания
                ui->statusBar->showMessage("Превышено время ожидания", 5000);
            }else if (lastRequest->error() != QModbusDevice::NoError){
    //прочие ошибки
                    ui->statusBar->showMessage("Ошибка");
                }else if(lastRequest->error() == QModbusDevice::NoError){
    //успешно
                ui->statusBar->showMessage("Успешно",5000);
                };
            lastRequest->deleteLater();
        });
        } else lastRequest->deleteLater();
    } else {
    //ошибка записи
        ui->statusBar->showMessage("Ошибка записи", 5000);
    };
};
    //Примечание: write_registr функция для записи регистра
Вызов функции записи:
Код:
void MainWindow::on_pushButton_write_clicked()
{
    write_registr(ui->spinBox_reg->value(), ui->spinBox_reg->value(), ui->spinBox_writedata->value());
}
Во вложении проект приложения


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: sergek от Февраль 24, 2023, 20:10
Ошибка здесь:
Код:
    if (QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device)){
Надо исправить на:
Код
C++ (Qt)
   QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device);
   if (lastRequest){
 
То же самое и в read_registr.


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: bv7 от Февраль 25, 2023, 11:26
Ошибка здесь:
Код:
    if (QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device)){

Надо исправить на:
Код
C++ (Qt)
   QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device);
   if (lastRequest){
 
То же самое и в read_registr.

Спасибо, но не помогло :( должен отправлять 01 06 00 01 00 05 18 09. А отправляет 01 06 00 01 00 00 D8 0A


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: kambala от Февраль 25, 2023, 15:27
Ошибка здесь:
Код:
    if (QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device)){
Надо исправить на:
Код
C++ (Qt)
   QModbusReply *lastRequest = modbusDevice->sendWriteRequest(writeUnit, num_device);
   if (lastRequest){
 
То же самое и в read_registr.
и в чем тут ошибка? :)


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: kambala от Февраль 25, 2023, 15:29
я не знаю что такое Modbus, но случайно нет ошибки в on_pushButton_write_clicked()? в функцию подается одно и то же значение (ui->spinBox_reg->value()) в двух разных параметрах


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: sergek от Февраль 25, 2023, 16:28
и в чем тут ошибка? :)
Согласен, был не прав, погорячился))


Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: sergek от Февраль 25, 2023, 17:21
Спасибо, но не помогло :( должен отправлять 01 06 00 01 00 05 18 09. А отправляет 01 06 00 01 00 00 D8 0A
Это из-за особенности (или ошибки?) QModbusDataUnit, фрагмент
Код
C++ (Qt)
   QModbusDataUnit writeUnit;
   writeUnit.setRegisterType(QModbusDataUnit::HoldingRegisters);
   writeUnit.setStartAddress(reg);
   writeUnit.setValueCount(1);
   writeUnit.setValue(0,data);
Нужно заменить на
Код
C++ (Qt)
   QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, reg, 1);
   writeUnit.setValue(0,data);
 
Почему так, не вникал, но можете почитать здесь: https://forum.qt.io/topic/90552/qmodbusdataunit-bug/4 (https://forum.qt.io/topic/90552/qmodbusdataunit-bug/4)

Еще есть ошибка в слоте on_pushButton_write_clicked (там у вас вместо адреса устройства передается стартовый регистр). Нужно
Код
C++ (Qt)
void MainWindow::on_pushButton_write_clicked()
{
   write_registr(ui->spinBox_addr->value(), ui->spinBox_reg->value(), ui->spinBox_writedata->value());//ui->spinBox_writedata->value()
}
 



Название: Re: Modbus RTU. Запись в modbus регистр.
Отправлено: bv7 от Февраль 26, 2023, 08:55
Это из-за особенности (или ошибки?) QModbusDataUnit, фрагмент
Код
C++ (Qt)
   QModbusDataUnit writeUnit;
   writeUnit.setRegisterType(QModbusDataUnit::HoldingRegisters);
   writeUnit.setStartAddress(reg);
   writeUnit.setValueCount(1);
   writeUnit.setValue(0,data);
Нужно заменить на
Код
C++ (Qt)
   QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, reg, 1);
   writeUnit.setValue(0,data);
 
Почему так, не вникал, но можете почитать здесь: https://forum.qt.io/topic/90552/qmodbusdataunit-bug/4 (https://forum.qt.io/topic/90552/qmodbusdataunit-bug/4)

Еще есть ошибка в слоте on_pushButton_write_clicked (там у вас вместо адреса устройства передается стартовый регистр). Нужно
Код
C++ (Qt)
void MainWindow::on_pushButton_write_clicked()
{
   write_registr(ui->spinBox_addr->value(), ui->spinBox_reg->value(), ui->spinBox_writedata->value());//ui->spinBox_writedata->value()
}
 
1. Сделал по аналогии как с подключением к порту, но видимо не все подход одинаково полезны.
Код:
...
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,port_name);
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,parity);
...
2. Похоже глаз замылился, не заметил, что передаю не то. Оно скомпилировалось, ошибок нет. А вот данные не те.

В справке qt посмотрел, есть у класса QModbusDataUnit несколько конструкторов, буду внимательнее.
Спасибо за помощь. Теперь все работает,  как и положено.

P.S. говорила мама, читай инструкцию, а я все методом тыка. Вот и натыкал.