Modbus TCP Client write holding registers
-
Hi,
I wrote simple Modbus TCP client to reading Input Registers cyclicly. It works Now I would like to write value to Holding Register form Modbus TCP Client, so I wrote
wr_redy
function to my thread, but I do not know how run it, any idea ?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,10); //define modbus write function auto wr_redy = [&](){ for(int i=0; i < 10; i++) wr.setValue(i, m_holdRegArray[i]); if (auto *replyWr = mc.sendWriteRequest(wr,255)){ if (!replyWr->isFinished()) { connect(replyWr, &QModbusReply::finished, this, [this, replyWr]() { if (replyWr->error() == QModbusDevice::ProtocolError) { qDebug() << "Modbus TCP Client write response error"; } else if (replyWr->error() != QModbusDevice::NoError) { qDebug() << "Modbus TCP Client write response error"; } replyWr->deleteLater(); }); } else { replyWr->deleteLater(); } } else { qDebug() << "Modbus TCP Client write error"; } }; //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)); }else{ exit(); } replyRd->deleteLater(); }; //define timer timeout function auto timeoutRd = [&](){ replyRd=mc.sendReadRequest(du,255); 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"; }else if(state==QModbusClient::UnconnectedState){ qDebug() << "ModbusTCPClient is disconnected"; exit(); } }; connect(&tim_event_timer, &QTimer::timeout,timeoutRd); connect(&mc, &QModbusClient::stateChanged,stateChange); mc.setConnectionParameter(QModbusDevice::NetworkAddressParameter, "192.168.1.18"); mc.setConnectionParameter(QModbusDevice::NetworkPortParameter, 5020); mc.setTimeout(500); if(!mc.connectDevice()){ exit(); return; } exec(); }
-
@jsulm How do I do that?
When I declare my function in *.h file :
void wr_redy();
And I will create definition this function outside my run() function , I do not have acces to variables defined in run()...
@Damian7546 If you want to connect a lambda to a signal then do it properly:
connect(this, ClientMachine1::holdRegArrayChanged, this, wr_redy);
wr_redy is NOT a member of your class, so simply do not prefix it with your class name.
-
How connect
wr_redy
to signal from ClientMachine1 , insiderun()
? -
How connect
wr_redy
to signal from ClientMachine1 , insiderun()
?@Damian7546 said in Modbus TCP Client write holding registers:
How connect wr_redy to signal from ClientMachine1 , inside run() ?
Using connect.
What exact problem do you have? -
Look..
I wold like callwr_ready
when QbyteArray (m_holdRegArray
) was changed, so I created code like below:void ClientMachine1::run() { ///my Modbus TCP Client code ///........ how connect wr_redy with signal holdRegArrayChanged } QByteArray ClientMachine1::holdRegArray() const { return m_holdRegArray; } void ClientMachine1::setHoldRegArray(const QByteArray &newHoldRegArray) { if (m_holdRegArray == newHoldRegArray) return; m_holdRegArray = newHoldRegArray; emit holdRegArrayChanged(); }
How connect
holdRegArrayChanged
withwr_ready
insiderun()
thread ? -
Look..
I wold like callwr_ready
when QbyteArray (m_holdRegArray
) was changed, so I created code like below:void ClientMachine1::run() { ///my Modbus TCP Client code ///........ how connect wr_redy with signal holdRegArrayChanged } QByteArray ClientMachine1::holdRegArray() const { return m_holdRegArray; } void ClientMachine1::setHoldRegArray(const QByteArray &newHoldRegArray) { if (m_holdRegArray == newHoldRegArray) return; m_holdRegArray = newHoldRegArray; emit holdRegArrayChanged(); }
How connect
holdRegArrayChanged
withwr_ready
insiderun()
thread ?@Damian7546 I still don't understand the problem. If wr_ready is a slot and holdRegArrayChanged a signal then simply connect them like any other signal/slot. Can you explain what exactly is not clear?
-
Because
wr_ready
is not visible in the constructor:ClientMachine1::ClientMachine1(QObject *parent) : QThread{parent} { connect(this, ClientMachine1::holdRegArrayChanged, this, ClientMachine1::wr_ready); }
In othe hand, the
holdRegArrayChanged
I can not connect insiderun()
because I have errors:Reference to non-static member function must be called; did you mean to call it with no arguments? (fix available) insert '()' No member named 'wr_redy' in 'ClientMachine1'
-
Because
wr_ready
is not visible in the constructor:ClientMachine1::ClientMachine1(QObject *parent) : QThread{parent} { connect(this, ClientMachine1::holdRegArrayChanged, this, ClientMachine1::wr_ready); }
In othe hand, the
holdRegArrayChanged
I can not connect insiderun()
because I have errors:Reference to non-static member function must be called; did you mean to call it with no arguments? (fix available) insert '()' No member named 'wr_redy' in 'ClientMachine1'
@Damian7546 said in Modbus TCP Client write holding registers:
Because wr_ready is not visible in the constructor
Of course it's not, because you defined it inside run().
Simply define it as normal member of ClientMachine1... -
Can you tell me how create definition in *.h file to my
wr_redy
lambda contruction andauto
type ? -
Can you tell me how create definition in *.h file to my
wr_redy
lambda contruction andauto
type ?@Damian7546 said in Modbus TCP Client write holding registers:
Can you tell me how create definition in *.h file to my wr_redy lambda contruction and auto type ?
Why does it have to be a lambda?
-
Can you tell me how create definition in *.h file to my
wr_redy
lambda contruction andauto
type ?@Damian7546 I'm also wondering why you use threads at all?
If you need to do something periodically then simply use QTimer. -
@Damian7546 said in Modbus TCP Client write holding registers:
Can you tell me how create definition in *.h file to my wr_redy lambda contruction and auto type ?
Why does it have to be a lambda?
@jsulm said in Modbus TCP Client write holding registers:
@Damian7546 said in Modbus TCP Client write holding registers:
Can you tell me how create definition in *.h file to my wr_redy lambda contruction and auto type ?
Why does it have to be a lambda?
I just want to know how to do it - for my own knowledge
-
@Damian7546 I'm also wondering why you use threads at all?
If you need to do something periodically then simply use QTimer.@jsulm said in Modbus TCP Client write holding registers:
@Damian7546 I'm also wondering why you use threads at all?
If you need to do something periodically then simply use QTimer.I would like to run Client on thread and test with several clients(threads) ... how will it be with stability and read/write speed,
So how definewr_redy
in *.h file ? -
@jsulm said in Modbus TCP Client write holding registers:
@Damian7546 I'm also wondering why you use threads at all?
If you need to do something periodically then simply use QTimer.I would like to run Client on thread and test with several clients(threads) ... how will it be with stability and read/write speed,
So how definewr_redy
in *.h file ?@Damian7546 said in Modbus TCP Client write holding registers:
So how define wr_redy in *.h file ?
Don't define it as lambda, but a normal method.
-
@Damian7546 said in Modbus TCP Client write holding registers:
So how define wr_redy in *.h file ?
Don't define it as lambda, but a normal method.
@jsulm How do I do that?
When I declare my function in *.h file :
void wr_redy();
And I will create definition this function outside my run() function , I do not have acces to variables defined in run()...
-
@jsulm How do I do that?
When I declare my function in *.h file :
void wr_redy();
And I will create definition this function outside my run() function , I do not have acces to variables defined in run()...
@Damian7546 If you want to connect a lambda to a signal then do it properly:
connect(this, ClientMachine1::holdRegArrayChanged, this, wr_redy);
wr_redy is NOT a member of your class, so simply do not prefix it with your class name.
-
@Damian7546 If you want to connect a lambda to a signal then do it properly:
connect(this, ClientMachine1::holdRegArrayChanged, this, wr_redy);
wr_redy is NOT a member of your class, so simply do not prefix it with your class name.
@jsulm said in Modbus TCP Client write holding registers:
@Damian7546 If you want to connect a lambda to a signal then do it properly:
connect(this, ClientMachine1::holdRegArrayChanged, this, wr_redy);
wr_redy is NOT a member of your class, so simply do not prefix it with your class name.
Right
-
@jsulm Unfortunetly my write function still doesn't work:/
auto wr_redy = [&](){ for(int i=0; i < m_holdRegArray.count(); i++){ qDebug() << "count: " << i; wr.setValue(i, m_holdRegArray[i]); } };
The application was crash when it
wr.setValue(i, m_holdRegArray[i]);
is called... -
@jsulm Unfortunetly my write function still doesn't work:/
auto wr_redy = [&](){ for(int i=0; i < m_holdRegArray.count(); i++){ qDebug() << "count: " << i; wr.setValue(i, m_holdRegArray[i]); } };
The application was crash when it
wr.setValue(i, m_holdRegArray[i]);
is called...@Damian7546 said in Modbus TCP Client write holding registers:
The application was crash when
So, did you use debugger to see why it crashes?
What is wr? -
@jsulm When I have status: "ModbusTCPClient is disconnected" my app crash when I try write registers..
-
@jsulm When I have status: "ModbusTCPClient is disconnected" my app crash when I try write registers..
@Damian7546 Then don't write registers if there is no connection...