Qt/C++ 通过 Modbus TCP 与 CMMO-ST-C5-1-LKP Festo 控制器通信
Qt/C++ communication with CMMO-ST-C5-1-LKP Festo controller over Modbus TCP
我正在尝试使用 Qt/C++ 通过 modbus 与电机控制器通信。
我使用主要从 Qt SerialBus adueditor 示例中获取的代码连接到它:
void Stepper::connect_device(){
if (ui.pb_connect->text() == "Connect"){
m_device = device;device->setParameters(0, 0x0000, 0x0000, 0x000F, 0x0000);
m_device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ui.tcpAddressEdit->text());
m_device->setConnectionParameter(QModbusDevice::NetworkPortParameter, ui.tcpPortEdit->text());
m_device->setTimeout(1000);
m_device->setNumberOfRetries(3);connect(m_device, &QModbusDevice::errorOccurred, this, [this](QModbusDevice::Error) {
qDebug().noquote() << QStringLiteral("Error: %1").arg(m_device->errorString());
reset();
/*QMessageBox msgBox;
msgBox.setWindowTitle("Modbus TCP Client");
msgBox.setText("Connection error !");
msgBox.exec();
emit ui.pb_connect->clicked();*/
return;
}, Qt::QueuedConnection);
connect(m_device, &QModbusDevice::stateChanged, [this](QModbusDevice::State state) {
switch (state) {
case QModbusDevice::UnconnectedState:
qDebug().noquote() << QStringLiteral("State: Entered unconnected state.");
ui.pb_connect->setEnabled(true);
ui.pb_connect->setText("Connect");
break;
case QModbusDevice::ConnectingState:
qDebug().noquote() << QStringLiteral("State: Entered connecting state.");
ui.pb_connect->setEnabled(false);
ui.pb_connect->setText("Trying to connect..");
break;
case QModbusDevice::ConnectedState:
qDebug().noquote() << QStringLiteral("State: Entered connected state.");
ui.pb_connect->setText("Disconnect");
ui.pb_connect->setEnabled(true);
break;
case QModbusDevice::ClosingState:
qDebug().noquote() << QStringLiteral("State: Entered closing state.");
ui.pb_connect->setEnabled(true);
ui.pb_connect->setText("Connect");
break;
case QModbusDevice::TimeoutError:
qDebug().noquote() << QStringLiteral("State: Time out error.");
QMessageBox msgBox;
msgBox.setWindowTitle("Modbus TCP Client");
msgBox.setText("Time out !");
msgBox.exec();
}
});
m_device->connectDevice();
}
else
{
disconnectAndDelete();
}}
建立连接后,我使用此 tcp pdu = "00000004084301000000000000" 调试驱动器,调试设备并出现代码 "E047" 的错误,因为通信中断。问题是当我尝试进行重置(这是重置位的上升沿)时,我发送了这两个连续的帧,但它不起作用,错误仍然存在。
void Stepper::reset(){
QModbusReply *reply = nullptr;
Data = "00000004084301000000000000";
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
connect(reply, &QModbusReply::finished, [reply, this]() {
qDebug() << "Receive: Asynchronous response PDU: " << reply->rawResult() << endl;
Data = "00000004084B01000000000000";
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
QModbusReply *reply = nullptr;
while (reply)
reply = m_device >sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
});}
我看了一下festo提供的这个模拟器"Modbus TCP Client V1.0.0.12"https://www.festo.com/net/cs_cz/SupportPortal/default.aspx?q=modbus&tab=4,
当我点击 "Start" 按钮时,帧被永久发送,然后我可以点击重置位,错误被消除。通信中断,只有点击"Stop"时才会出现错误。当通信是运行时我可以做其他的事情,比如点击停止按钮或更改功能代码,是否使用多线程?在这种情况下,我怎样才能像这个模拟器界面一样提供与控制器的持续通信?
终于成功了,这是代码:
void Stepper::reset(){
QTimer *timer1 = new QTimer(this);
timer1->setSingleShot(false);
timer1->start(100);
connect(timer1, &QTimer::timeout, [this]() {
send_packet("00000004084301000000000000");
});
QTimer *timer2 = new QTimer(this);
timer2->setSingleShot(false);
timer2->start(100);
connect(timer2, &QTimer::timeout, [this]() {
send_packet("00000004084B01000000000000");
});}
send_packet函数就是这个函数:
void Stepper::send_packet(QString Data){
QModbusReply *reply = nullptr;
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
if (reply)
return;}
我正在尝试使用 Qt/C++ 通过 modbus 与电机控制器通信。
我使用主要从 Qt SerialBus adueditor 示例中获取的代码连接到它:
void Stepper::connect_device(){
if (ui.pb_connect->text() == "Connect"){
m_device = device;device->setParameters(0, 0x0000, 0x0000, 0x000F, 0x0000);
m_device->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ui.tcpAddressEdit->text());
m_device->setConnectionParameter(QModbusDevice::NetworkPortParameter, ui.tcpPortEdit->text());
m_device->setTimeout(1000);
m_device->setNumberOfRetries(3);connect(m_device, &QModbusDevice::errorOccurred, this, [this](QModbusDevice::Error) {
qDebug().noquote() << QStringLiteral("Error: %1").arg(m_device->errorString());
reset();
/*QMessageBox msgBox;
msgBox.setWindowTitle("Modbus TCP Client");
msgBox.setText("Connection error !");
msgBox.exec();
emit ui.pb_connect->clicked();*/
return;
}, Qt::QueuedConnection);
connect(m_device, &QModbusDevice::stateChanged, [this](QModbusDevice::State state) {
switch (state) {
case QModbusDevice::UnconnectedState:
qDebug().noquote() << QStringLiteral("State: Entered unconnected state.");
ui.pb_connect->setEnabled(true);
ui.pb_connect->setText("Connect");
break;
case QModbusDevice::ConnectingState:
qDebug().noquote() << QStringLiteral("State: Entered connecting state.");
ui.pb_connect->setEnabled(false);
ui.pb_connect->setText("Trying to connect..");
break;
case QModbusDevice::ConnectedState:
qDebug().noquote() << QStringLiteral("State: Entered connected state.");
ui.pb_connect->setText("Disconnect");
ui.pb_connect->setEnabled(true);
break;
case QModbusDevice::ClosingState:
qDebug().noquote() << QStringLiteral("State: Entered closing state.");
ui.pb_connect->setEnabled(true);
ui.pb_connect->setText("Connect");
break;
case QModbusDevice::TimeoutError:
qDebug().noquote() << QStringLiteral("State: Time out error.");
QMessageBox msgBox;
msgBox.setWindowTitle("Modbus TCP Client");
msgBox.setText("Time out !");
msgBox.exec();
}
});
m_device->connectDevice();
}
else
{
disconnectAndDelete();
}}
建立连接后,我使用此 tcp pdu = "00000004084301000000000000" 调试驱动器,调试设备并出现代码 "E047" 的错误,因为通信中断。问题是当我尝试进行重置(这是重置位的上升沿)时,我发送了这两个连续的帧,但它不起作用,错误仍然存在。
void Stepper::reset(){
QModbusReply *reply = nullptr;
Data = "00000004084301000000000000";
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
connect(reply, &QModbusReply::finished, [reply, this]() {
qDebug() << "Receive: Asynchronous response PDU: " << reply->rawResult() << endl;
Data = "00000004084B01000000000000";
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
QModbusReply *reply = nullptr;
while (reply)
reply = m_device >sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
});}
我看了一下festo提供的这个模拟器"Modbus TCP Client V1.0.0.12"https://www.festo.com/net/cs_cz/SupportPortal/default.aspx?q=modbus&tab=4, 当我点击 "Start" 按钮时,帧被永久发送,然后我可以点击重置位,错误被消除。通信中断,只有点击"Stop"时才会出现错误。当通信是运行时我可以做其他的事情,比如点击停止按钮或更改功能代码,是否使用多线程?在这种情况下,我怎样才能像这个模拟器界面一样提供与控制器的持续通信?
终于成功了,这是代码:
void Stepper::reset(){
QTimer *timer1 = new QTimer(this);
timer1->setSingleShot(false);
timer1->start(100);
connect(timer1, &QTimer::timeout, [this]() {
send_packet("00000004084301000000000000");
});
QTimer *timer2 = new QTimer(this);
timer2->setSingleShot(false);
timer2->start(100);
connect(timer2, &QTimer::timeout, [this]() {
send_packet("00000004084B01000000000000");
});}
send_packet函数就是这个函数:
void Stepper::send_packet(QString Data){
QModbusReply *reply = nullptr;
QByteArray pduData = QByteArray::fromHex(Data.toLatin1());
reply = m_device->sendRawRequest(QModbusRequest(QModbusRequest::FunctionCode(0x0010), pduData), 0x01);
if (reply)
return;}