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. Reading/Writing Modbus TCP register in thread.
Forum Updated to NodeBB v4.3 + New Features

Reading/Writing Modbus TCP register in thread.

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 4 Posters 1.3k Views 1 Watching
  • 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.
  • D Offline
    D Offline
    Damian7546
    wrote on 24 Jan 2023, 10:09 last edited by
    #1

    Hi,
    To test I write simple thread with Modbus TCP Client. The reading InputRegisters works perfectly., but I have a problem with writing Holding register....
    Below is my run() function:

    void ClientMachine1::run()
    {
    
        QModbusTcpClient mc;
        QTimer tim_event_timer;
        tim_event_timer.setSingleShot(true);
        QModbusDataUnit du(QModbusDataUnit::InputRegisters,0,10);
        QModbusReply *replyRd;
        QModbusDataUnit wr(QModbusDataUnit::HoldingRegisters,0,6);
        QModbusReply *replyWr;
    
        //define modbus /write function
        auto wr_redy = [&](){
            if(!replyWr->error()){
                for(int i=0; i<m_holdRegArray.count(); i++)
                       wr.setValue(i, m_holdRegArray[i]);
            }else {
                exit();
                qDebug() << "Error Modbus TCP Client write: " << replyWr->error();
            }
            replyWr->deleteLater();
        };
        //define modbus reply function
        auto rpl_redy =[&](){
            if(!replyRd->error()){
                emit updateDataInReg(id, replyRd->result().value(0)
                                     , replyRd->result().value(1)
                                     , replyRd->result().value(2)
                                     , replyRd->result().value(3)
                                     , replyRd->result().value(4)
                                     , replyRd->result().value(5)
                                     , replyRd->result().value(6)
                                     , replyRd->result().value(7)
                                     , replyRd->result().value(8)
                                     , replyRd->result().value(9));
            tim_event_timer.start(2000);
            }else{
                exit();
                qDebug() << "Error Modbus TCP CLient read: " << replyRd->error();
            }
            replyRd->deleteLater();
        };
    
        //define event function
        auto eventWr = [&](){
           replyWr=mc.sendWriteRequest(wr,id);
             if(replyWr->isFinished()){
                delete replyWr;
            }else{
                connect(replyWr, &QModbusReply::finished,wr_redy );
            }
    
        };
    
        //define timer timeout function
        auto timeoutRd = [&](){
            replyRd=mc.sendReadRequest(du,id);
            if(replyRd->isFinished()){
                delete replyRd;
            }else{
                connect(replyRd, &QModbusReply::finished, rpl_redy);
            }
        };
    
        //define modbus device state change function
        auto stateChange = [&](QModbusClient::State state){
            if(state==QModbusClient::ConnectedState){
                tim_event_timer.start(1000);
                qDebug() << "ModbusTCPClient is connected";
                emit modbusTCPClientConnectedState(false);
            }else if(state==QModbusClient::UnconnectedState){
                qDebug() << "ModbusTCPClient is disconnected";
                emit modbusTCPClientConnectedState(true);
                exit();
            }else if(state==QModbusClient::ConnectingState){
                qDebug() << "ModbusTCP Client try to connect";
                emit modbusTCPClientConnectedState(true);
            }else{
                qDebug() << "ModbusTCPClient is disconnected";
                emit modbusTCPClientConnectedState(true);
                exit();
    
            }
        };
        connect(&tim_event_timer, &QTimer::timeout,timeoutRd);
        connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
    
        connect(&mc, &QModbusClient::stateChanged,stateChange);
    
        mc.setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
        mc.setConnectionParameter(QModbusDevice::NetworkPortParameter, 5020);
        mc.setTimeout(500);
    
        if(!mc.connectDevice()){
            exit();
            return;
        }
        exec();
    }
    

    When i try write some registers, I have error in line replyWr=mc.sendWriteRequest(wr,id); related with thread:/
    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread QObject: Cannot create children for a parent that is in a different thread. (Parent is QModbusTcpClient(0x4f0f9e0), parent's thread is ClientTicketMach(0x11da0c8), current thread is QThread(0x110a0d0) QObject::startTimer: Timers cannot be started from another thread Error Modbus TCP CLient read: QModbusDevice::TimeoutError QObject::killTimer: Timers cannot be stopped from another thread

    Where is problem in my code? How it possible that rpl_redy works , but wr_redy doesnt't works ?
    I would be rally gratefull for help to resolve my problem.

    P 1 Reply Last reply 24 Jan 2023, 11:24
    0
    • D Damian7546
      24 Jan 2023, 10:09

      Hi,
      To test I write simple thread with Modbus TCP Client. The reading InputRegisters works perfectly., but I have a problem with writing Holding register....
      Below is my run() function:

      void ClientMachine1::run()
      {
      
          QModbusTcpClient mc;
          QTimer tim_event_timer;
          tim_event_timer.setSingleShot(true);
          QModbusDataUnit du(QModbusDataUnit::InputRegisters,0,10);
          QModbusReply *replyRd;
          QModbusDataUnit wr(QModbusDataUnit::HoldingRegisters,0,6);
          QModbusReply *replyWr;
      
          //define modbus /write function
          auto wr_redy = [&](){
              if(!replyWr->error()){
                  for(int i=0; i<m_holdRegArray.count(); i++)
                         wr.setValue(i, m_holdRegArray[i]);
              }else {
                  exit();
                  qDebug() << "Error Modbus TCP Client write: " << replyWr->error();
              }
              replyWr->deleteLater();
          };
          //define modbus reply function
          auto rpl_redy =[&](){
              if(!replyRd->error()){
                  emit updateDataInReg(id, replyRd->result().value(0)
                                       , replyRd->result().value(1)
                                       , replyRd->result().value(2)
                                       , replyRd->result().value(3)
                                       , replyRd->result().value(4)
                                       , replyRd->result().value(5)
                                       , replyRd->result().value(6)
                                       , replyRd->result().value(7)
                                       , replyRd->result().value(8)
                                       , replyRd->result().value(9));
              tim_event_timer.start(2000);
              }else{
                  exit();
                  qDebug() << "Error Modbus TCP CLient read: " << replyRd->error();
              }
              replyRd->deleteLater();
          };
      
          //define event function
          auto eventWr = [&](){
             replyWr=mc.sendWriteRequest(wr,id);
               if(replyWr->isFinished()){
                  delete replyWr;
              }else{
                  connect(replyWr, &QModbusReply::finished,wr_redy );
              }
      
          };
      
          //define timer timeout function
          auto timeoutRd = [&](){
              replyRd=mc.sendReadRequest(du,id);
              if(replyRd->isFinished()){
                  delete replyRd;
              }else{
                  connect(replyRd, &QModbusReply::finished, rpl_redy);
              }
          };
      
          //define modbus device state change function
          auto stateChange = [&](QModbusClient::State state){
              if(state==QModbusClient::ConnectedState){
                  tim_event_timer.start(1000);
                  qDebug() << "ModbusTCPClient is connected";
                  emit modbusTCPClientConnectedState(false);
              }else if(state==QModbusClient::UnconnectedState){
                  qDebug() << "ModbusTCPClient is disconnected";
                  emit modbusTCPClientConnectedState(true);
                  exit();
              }else if(state==QModbusClient::ConnectingState){
                  qDebug() << "ModbusTCP Client try to connect";
                  emit modbusTCPClientConnectedState(true);
              }else{
                  qDebug() << "ModbusTCPClient is disconnected";
                  emit modbusTCPClientConnectedState(true);
                  exit();
      
              }
          };
          connect(&tim_event_timer, &QTimer::timeout,timeoutRd);
          connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
      
          connect(&mc, &QModbusClient::stateChanged,stateChange);
      
          mc.setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
          mc.setConnectionParameter(QModbusDevice::NetworkPortParameter, 5020);
          mc.setTimeout(500);
      
          if(!mc.connectDevice()){
              exit();
              return;
          }
          exec();
      }
      

      When i try write some registers, I have error in line replyWr=mc.sendWriteRequest(wr,id); related with thread:/
      QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread QObject: Cannot create children for a parent that is in a different thread. (Parent is QModbusTcpClient(0x4f0f9e0), parent's thread is ClientTicketMach(0x11da0c8), current thread is QThread(0x110a0d0) QObject::startTimer: Timers cannot be started from another thread Error Modbus TCP CLient read: QModbusDevice::TimeoutError QObject::killTimer: Timers cannot be stopped from another thread

      Where is problem in my code? How it possible that rpl_redy works , but wr_redy doesnt't works ?
      I would be rally gratefull for help to resolve my problem.

      P Offline
      P Offline
      Pl45m4
      wrote on 24 Jan 2023, 11:24 last edited by
      #2

      @Damian7546 said in Reading/Writing Modbus TCP register in thread.:

      QModbusTcpClient

      QModbusClient and it's subclasses are asynchronous. Why you want to put it in a thread anyway?


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Damian7546
        wrote on 24 Jan 2023, 11:42 last edited by Damian7546
        #3

        To test and knowledge.
        I found problem.

        This connect:
        connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
        run eventWr function in other threat no in run() where is defined.... How can I resolve this ? And run eventWr in my thread by change values in holdRegArray?

        Christian EhrlicherC 1 Reply Last reply 24 Jan 2023, 16:54
        0
        • D Damian7546
          24 Jan 2023, 11:42

          To test and knowledge.
          I found problem.

          This connect:
          connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
          run eventWr function in other threat no in run() where is defined.... How can I resolve this ? And run eventWr in my thread by change values in holdRegArray?

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 24 Jan 2023, 16:54 last edited by
          #4

          @Damian7546 said in Reading/Writing Modbus TCP register in thread.:

          How can I resolve this ?

          Use the worker thread approach as described in the documentation to make sure your object you're calling the slots is living in the correct thread instead the main thread as your ClientMachine1 instance in your example. Or even better - don't use thread because they are not needed here and only cause trouble when used wrong (as you did)

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          0
          • D Offline
            D Offline
            Damian7546
            wrote on 24 Jan 2023, 17:28 last edited by Damian7546
            #5

            @Christian-Ehrlicher I have a second problem. When I compile my code on Windows the Modbus TCP Client always connected to server. But when I compile my project on Linux I all the time have QModbusDevice::ConnectingState how it is possible?

            jsulmJ 1 Reply Last reply 25 Jan 2023, 05:50
            0
            • D Damian7546
              24 Jan 2023, 17:28

              @Christian-Ehrlicher I have a second problem. When I compile my code on Windows the Modbus TCP Client always connected to server. But when I compile my project on Linux I all the time have QModbusDevice::ConnectingState how it is possible?

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on 25 Jan 2023, 05:50 last edited by
              #6

              @Damian7546 said in Reading/Writing Modbus TCP register in thread.:

              how it is possible?

              Different network configuration on your Linux machine for example? Firewall?

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • D Offline
                D Offline
                Damian7546
                wrote on 25 Jan 2023, 06:33 last edited by
                #7

                @Christian-Ehrlicher @jsulm
                Thanks for all suggestions and helps. I rewrite my code and now don't use thread to Modbus TCP Client, and everything works ....
                Only I have thinking why when I plug out ethernet from my PC the state does not change from Connected to Disconnected ? It change only when I turn off server...

                void ClientTicketMach::onModbusStateChanged(int state)
                {
                    if (state == QModbusDevice::UnconnectedState){
                        qDebug() <<"Modbus TCP Client Disconnected";
                        tim_reconnect.start(10000);
                        tim_reading_inputRegisters.stop();
                        emit modbusTCPClientConnectedState(true);
                    }
                    else if (state == QModbusDevice::ConnectedState){
                       qDebug() <<"Modbus TCP Client Connected";
                       tim_reading_inputRegisters.start(1000);
                       emit modbusTCPClientConnectedState(false);
                    }
                    else if (state == QModbusDevice::ConnectingState){
                        qDebug() << "Modbus TCP Client Connecting";
                        emit modbusTCPClientConnectedState(true);
                    }
                }
                
                1 Reply Last reply
                0

                1/7

                24 Jan 2023, 10:09

                • Login

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