继上次PLC展厅,通过北辰网关的转Modbus功能,使用Qt写一个简单的S7-300的上位程序,可以查看正转时间,反转时间,还可以控制电机启停。
北辰网关的设置可以参考这篇文章西门子PLC实现modbusTCP通讯
我的设置如下图:
构造函数中
timer1 = new QTimer(this); //timer1为QTimer类型
connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
timer1->start(1000);
showTime()中
time=time.addSecs(60);//time为QTime类型
QString text = time.toString("hh:mm");
if ((time.second() % 2) == 0)
text[2] = ' ';
ui->lcdNumber->display(text);
modbus通讯可以参考我之前的文章QModbusClient
因为有正转时间,反转时间,停止时间三个时间需要计时
connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
connect(timer2, SIGNAL(timeout()), this, SLOT(showTime()));
connect(timer3, SIGNAL(timeout()), this, SLOT(showTime()));
它们都连接到槽showTime();因此,需要在showTime()中判断是哪个对象发出了timeout()信号,这个是通过QObject::sender()来实现的。
在showTime()中
QTimer *t=qobject_cast<QTimer *>(sender());
if(t==timer1)
ui->lcdNumber->display(text);
else if (t==timer2)
ui->lcdNumber_2->display(text);
else
ui->lcdNumber_3->display(text);
因为通过北辰的网关没有读出M区的变量,采取通过控制DB块来控制电机启停。
修改PLC起保停程序如下:
I0.0和I0.1是通过PLC按钮启停。在Qt上位中可以向DB3.DBX0.0写入1和0来控制PLC启停。为什么是DB3,因为在北辰网关的设置中,ModbusTcp映射DB号为3
mymodbus.h
#ifndef MYMODBUS_H
#define MYMODBUS_H
#include
#include
#include
#include
#include
#include
#include
class ModbusRly;
class QModbusTcpClient;
namespace Ui {
class MyModbus;
}
class MyModbus : public QWidget
{
Q_OBJECT
public:
explicit MyModbus(QWidget *parent = 0);
~MyModbus();
private:
QModbusTcpClient *client;
QTime time;
QString entry[5];
QTimer *timer1;
QTimer *timer2;
QTimer *timer3;
Ui::MyModbus *ui;
public slots:
void showTime();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void readReady();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
};
#endif // MYMODBUS_H
mymodbus.cpp
#include "mymodbus.h"
#include "ui_mymodbus.h"
MyModbus::MyModbus(QWidget *parent) :
QWidget(parent),client(nullptr),time(QTime(0,0,0)),
ui(new Ui::MyModbus)
{
ui->setupUi(this);
ui->pushButton_2->setEnabled(false);
ui->pushButton_5->setEnabled(false);
ui->pushButton_3->setEnabled(false);
ui->pushButton_4->setEnabled(false);
timer1 = new QTimer(this);
timer2=new QTimer(this);
timer3=new QTimer(this);
connect(timer1, SIGNAL(timeout()), this, SLOT(showTime()));
connect(timer2, SIGNAL(timeout()), this, SLOT(showTime()));
connect(timer3, SIGNAL(timeout()), this, SLOT(showTime()));
if (ui->lineEdit->text().isEmpty())
ui->lineEdit->setText(QLatin1Literal("192.168.1.99"));
}
void MyModbus::showTime()
{
QTimer *t=qobject_cast<QTimer *>(sender());
on_pushButton_2_clicked();
time=time.addSecs(60);
QString text = time.toString("hh:mm");
if ((time.second() % 2) == 0)
text[2] = ' ';
if(t==timer1)
ui->lcdNumber->display(text);
else if (t==timer2)
ui->lcdNumber_2->display(text);
//else
// ui->lcdNumber_3->display(text);
}
MyModbus::~MyModbus()
{
delete client;
delete ui;
}
void MyModbus::on_pushButton_clicked()
{
client=new QModbusTcpClient(this);
client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,ui->lineEdit->text());
client->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
if(!client->connectDevice())
{
qDebug("failed");
}
else
{
qDebug("successed");
ui->pushButton_2->setEnabled(true);
ui->pushButton_5->setEnabled(true);
ui->pushButton_3->setEnabled(true);
ui->pushButton_4->setEnabled(true);
}
}
void MyModbus::on_pushButton_2_clicked()
{
if(!client)
return;
QModbusDataUnit readUnit(QModbusDataUnit::Coils, 00000, 5);
if (auto *reply = client->sendReadRequest(readUnit, 2)) // client id 255
{
if (!reply->isFinished())
{
// connect the finished signal of the request to your read slot
connect(reply, &QModbusReply::finished, this, &MyModbus::readReady);
}
else
{
delete reply; // broadcast replies return immediately
qDebug("delete reply");
}
}
else
{
qDebug("request error"); // request error
}
}
void MyModbus::readReady()
{
auto *reply = qobject_cast<QModbusReply *>(sender());
if (!reply)
return;
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for (uint i = 0; i < unit.valueCount(); i++) {
entry[i] = QString::number(unit.value(i),
unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16);
qDebug()<if(entry[3].toInt()==1&&entry[2].toInt()==1)
{
timer1->start(1000);
timer2->stop();
timer3->stop();
}
else if(entry[3].toInt()==0&&entry[2].toInt()==1)
{
timer2->start(1000);
timer1->stop();
timer3->stop();
}
else if(entry[2].toInt()==0)
{
timer1->stop();
timer2->stop();
timer3->start(1000);
time.setHMS(0,0,0);
}
}
reply->deleteLater();
}
void MyModbus::on_pushButton_3_clicked()
{
if(!client)
return;
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // write 1 value in address 30000
writeUnit.setValue(0,256);
if (auto *reply = client->sendWriteRequest(writeUnit, 2))
{
if (!reply->isFinished())
{
connect(reply, &QModbusReply::finished, this, [this, reply]()
{
if (reply->error() != QModbusDevice::NoError)
// error in reply
qDebug("No Error");
reply->deleteLater();
});
}
else
{
if (reply->error() != QModbusDevice::NoError)
// error in reply
qDebug("No Error1");
// broadcast replies return immediately
reply->deleteLater();
}
}
else
{
// error in request
}
}
void MyModbus::on_pushButton_4_clicked()
{
if(!client)
return;
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters, 0, 1); // write 1 value in address 30001
writeUnit.setValue(0,0);
if (auto *reply = client->sendWriteRequest(writeUnit, 2))
{
if (!reply->isFinished())
{
connect(reply, &QModbusReply::finished, this, [this, reply]()
{
if (reply->error() != QModbusDevice::NoError)
// error in reply
qDebug("No Error");
reply->deleteLater();
});
}
else
{
if (reply->error() != QModbusDevice::NoError)
// error in reply
// broadcast replies return immediately
reply->deleteLater();
}
}
else
{
// error in request
}
}
void MyModbus::on_pushButton_5_clicked()
{
client->disconnectDevice();
ui->pushButton_5->setEnabled(false);
ui->pushButton_2->setEnabled(false);
ui->pushButton_3->setEnabled(false);
ui->pushButton_4->setEnabled(false);
timer1->stop();
timer2->stop();
timer3->stop();
}
main.cpp
#include "mymodbus.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyModbus w;
w.show();
return a.exec();
}