关于通过QTcpSocket和SCPI与信号发生器进行通信的经验

前言


第三年,我进入国内火箭和航天工业的一家企业实习。 我是一个雄心勃勃的实习生,并且非常活跃, 直到我看到一家俄罗斯国有企业的例行工作 ,并应我的要求被分配到涉及测试设备开发的部门(以下简称KPA )。 顺便说一下, CPA开发的很大一部分是编写设备的软件部分。 其中,为了检查正在开发的硬件,该部门拥有各种控制和测量设备 ,它们都连接到一个公共网络。 结果,作为我的首要任务之一,就是编写一个应用程序来控制信号发生器。

这将在本文中讨论。

开始


该部门中的所有应用程序都是使用C ++和Qt库开发的。 我对此框架有经验,因此在这方面没有困难。 此外,Qt有大量文档,您始终可以从StackOverflow复制粘贴代码以咨询策展人。

由于所有设备都连接到同一网络,因此如何快速连接它们的问题也得到了很快解决-我们以QTcpSocket的形式使用Qt的网络部分。

当我必须决定如何与这些设备通信,如何激活一个或另一个功能,传递一个或另一个值时,出现了最有趣的问题。 事实证明,这一切都是微不足道的:可编程仪器有一个标准命令协议-SCPI。 它允许使用标准命令来控制支持该标准的任何设备。

开始编码


头文件中的所有内容都是标准且无趣的:
#ifndef SIGGENCONTROL_H #define SIGGENCONTROL_H #include <QMainWindow> #include <QTcpSocket> #include <QString> namespace Ui { class sigGenControl; } class sigGenControl : public QMainWindow { Q_OBJECT public: explicit sigGenControl(QWidget *parent = 0); ~sigGenControl(); //      ,      QString host; //= "192.168.1.109"; ip   int port;// = 5025;   void clearErr(); //   bool rfOn; //    bool pset = false; bool hset = false; private: Ui::sigGenControl *ui; QTcpSocket* socket; private slots: //,     .cpp  void connectToHostSlot(); void sendToHostSlot(); void readyReadSlot(); void setFreq(); void setPow(); void activateRF(); void checkErrSlot(); void setPort(); void setHost(); void setDefault(); void dialValChangedSlot(); }; #endif // SIGGENCONTROL_H 


决定使接口如下所示:



这非常简单直观。 在两行编辑中,设备的主机和端口位于顶部。 也可以选择标准值,然后它们将采用以下形式:

 port = 5025; host = "192.168.1.109"; 

接下来是日志的文本框,来自设备的响应(错误将在此处发送,如果有的话)。 稍稍下方是用于连接设备,发送命令,检查错误的按钮。 在最后三行编辑中,您可以设置自己的命令并将其发送到设备,也可以分别设置频率和幅度。 右侧的单选按钮可打开/关闭RF输出。 取消选中此复选框时,微调器将调整频率,并在激活时调整幅度。

我们继续并完成


所有的乐趣都始于.cpp文件:
 #include "siggencontrol.h" #include "ui_siggencontrol.h" #include "qdebug.h" #include <QTime> sigGenControl::sigGenControl(QWidget *parent) : QMainWindow(parent), ui(new Ui::sigGenControl) { ui->setupUi(this); ui->history->setReadOnly(true); ui->history->setText("host : not set\nport : not set"); ui->history->append(QTime::currentTime().toString() + " : No connection"); socket = new QTcpSocket(this); //     //       -  //    ,       //           connect(ui->connPb,QPushButton::clicked,this,sigGenControl::connectToHostSlot); connect(ui->sendToHostPb,QPushButton::clicked,this,sigGenControl::sendToHostSlot); connect(ui->input,QLineEdit::returnPressed,this,sigGenControl::sendToHostSlot); connect(socket,QTcpSocket::readyRead,this,sigGenControl::readyReadSlot); connect(ui->freqEdit,QLineEdit::returnPressed,this,sigGenControl::setFreq); connect(ui->amptdEdit,QLineEdit::returnPressed,this,sigGenControl::setPow); connect(ui->radioButton,QRadioButton::clicked,this,sigGenControl::activateRF); connect(ui->errPb,QPushButton::clicked,this,sigGenControl::clearErr); connect(ui->hostEdit,QLineEdit::returnPressed,this,sigGenControl::setHost); connect(ui->portEdit,QLineEdit::returnPressed,this,sigGenControl::setPort); connect(ui->checkBox,QCheckBox::clicked,this,sigGenControl::setDefault); connect(ui->dial, QDial::valueChanged,this,sigGenControl::dialValChangedSlot); ui->hist->setReadOnly(true); QString deactRF = ":OUTP 0\n"; //  SCPI ,        socket->write(deactRF.toLocal8Bit()); //      this->rfOn = false; //   ui->input->setReadOnly(true); ui->freqEdit->setReadOnly(true); ui->amptdEdit->setReadOnly(true); ui->radioButton->setEnabled(false); ui->sendToHostPb->setEnabled(false); ui->errPb->setEnabled(false); ui->connPb->setDisabled(true); } sigGenControl::~sigGenControl() { delete ui; } void sigGenControl::connectToHostSlot(){ socket->connectToHost(host,port); //   //     qDebug()    if (socket->waitForConnected(1000)) qDebug("Connected!"); ui->history->append(QTime::currentTime().toString() + " : Connected"); //   ui->input->setReadOnly(false); ui->freqEdit->setReadOnly(false); ui->amptdEdit->setReadOnly(false); ui->radioButton->setEnabled(true); ui->sendToHostPb->setEnabled(true); ui->errPb->setEnabled(true); ui->input->setText("*IDN?"); //    } void sigGenControl::sendToHostSlot(){ //     socket->write(ui->input->text().toLocal8Bit()+"\n"); } void sigGenControl::readyReadSlot(){ //     qDebug("ready read!"); QByteArray dataArr; //    dataArr = socket->readAll(); //   ui->hist->append(QTime::currentTime().toString() + " " + dataArr); } void sigGenControl::clearErr(){ // ,   ,  ,   QString errTxt = ":SYST:ERR?\n"; socket->write(errTxt.toLocal8Bit()); } void sigGenControl::setFreq(){ QString fr = " kHz"; QString cmd = ":FREQ "; //    QString command = cmd+ui->freqEdit->text()+fr+"\n"; //  qDebug() << command; socket->write(command.toLocal8Bit()); //   } void sigGenControl::setPow(){ QString amp = " dBm"; QString cmd = ":POW "; //    socket->write(cmd.toLocal8Bit() + ui->amptdEdit->text().toLocal8Bit() + amp.toLocal8Bit() + "\n"); //  } void sigGenControl::activateRF(){ //       //   QString actRF = ":OUTP 1\n"; //   QString deactRF = ":OUTP 0\n"; //   if(this->rfOn == false){ socket->write(actRF.toLocal8Bit()); rfOn = true; }else{ socket->write(deactRF.toLocal8Bit()); rfOn = false; } } void sigGenControl::checkErrSlot(){ clearErr(); } void sigGenControl::setHost(){ //   this->host = ui->hostEdit->text(); ui->history->append("host: " + host); ui->checkBox->setEnabled(true); hset = true; //  if((pset && hset) == true){ ui->connPb->setEnabled(true); } } void sigGenControl::setPort(){ //   this->port = ui->portEdit->text().toInt(); ui->history->append("port: " + QString::number(port)); ui->checkBox->setEnabled(true); pset = true; //  if((pset && hset) == true){ ui->connPb->setEnabled(true); } } void sigGenControl::setDefault(){ //     port = 5025; host = "192.168.1.109"; ui->history->append(QTime::currentTime().toString() + " " + "host: " + host); ui->history->append(QTime::currentTime().toString() + " " + "port: " + QString::number(port)); ui->checkBox->setDisabled(true); ui->connPb->setEnabled(true); ui->hostEdit->setText(host); ui->portEdit->setText(QString::number(port)); } void sigGenControl::dialValChangedSlot(){ //   ,       qDebug()<< "value : " << ui->dial->value(); if(ui->amplCheckBox->isChecked() == false){ //  ,      ui->dial->setMinimum(100); ui->dial->setMaximum(20000000); QString fr = " kHz"; QString cmd = ":FREQ "; //    QString command = cmd+QString::number(ui->dial->value())+fr+"\n"; qDebug() << command; socket->write(command.toLocal8Bit()); ui->label->setText("FREQUENCY :" + QString::number(ui->dial->value()) + " kHz" ); }else if(ui->amplCheckBox->isChecked() == true){ //  ,       ui->dial->setMinimum(-130); ui->dial->setMaximum(15); QString pw = " dBm"; QString cmd = ":POW "; //    QString command = cmd+QString::number(ui->dial->value())+pw+"\n"; qDebug() << command; socket->write(command.toLocal8Bit()); ui->label->setText("AMPLITUDE :" + QString::number(ui->dial->value()) + " dBm" ); } } 


看完之后


我了解,对于许多读者来说,这篇文章似乎与现实和现实脱节了,但是工程领域的仪器仪表远程控制是一个相当普通的话题,它带来了很多好处和便利(例如,您无需运行设备和按钮) 。

对于其他内容,本文具有参考性和娱乐性,并且更可能面向发烧友以及涉及开发和测试板及其他硬件的人员。 我只想告诉我我为这种特定目的开发软件方面的一点经验。

Source: https://habr.com/ru/post/zh-CN435448/


All Articles