Reading/Writing Modbus TCP register in thread.
-
wrote on 24 Jan 2023, 10:09 last edited by
Hi,
To test I write simple thread with Modbus TCP Client. The readingInputRegisters
works perfectly., but I have a problem with writingHolding register.
...
Below is myrun()
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 , butwr_redy
doesnt't works ?
I would be rally gratefull for help to resolve my problem. -
Hi,
To test I write simple thread with Modbus TCP Client. The readingInputRegisters
works perfectly., but I have a problem with writingHolding register.
...
Below is myrun()
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 , butwr_redy
doesnt't works ?
I would be rally gratefull for help to resolve my problem.wrote on 24 Jan 2023, 11:24 last edited by@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? -
wrote on 24 Jan 2023, 11:42 last edited by Damian7546
To test and knowledge.
I found problem.This connect:
connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
runeventWr
function in other threat no inrun()
where is defined.... How can I resolve this ? And runeventWr
in my thread by change values inholdRegArray
? -
To test and knowledge.
I found problem.This connect:
connect(this, &ClientMachine1::holdRegArrayChanged,eventWr);
runeventWr
function in other threat no inrun()
where is defined.... How can I resolve this ? And runeventWr
in my thread by change values inholdRegArray
?@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)
-
wrote on 24 Jan 2023, 17:28 last edited by Damian7546
@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? -
@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?@Damian7546 said in Reading/Writing Modbus TCP register in thread.:
how it is possible?
Different network configuration on your Linux machine for example? Firewall?
-
wrote on 25 Jan 2023, 06:33 last edited by
@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/7