Intro
En troisième année, je suis venu pratiquer dans l'une des entreprises de l'industrie domestique des fusées et de l'espace. J'étais un stagiaire ambitieux et très actif
jusqu'à ce que je voie la routine dans une entreprise publique russe et, à ma demande, j'ai été affecté au département impliqué dans le développement
d'équipements de test (ci-après
KPA ). Soit dit en passant, une grande partie du développement du
CPA est en train d'écrire la partie logicielle de l'équipement. Notamment, pour vérifier le matériel en cours de développement, le département dispose de différents appareils de
contrôle et de mesure , tous connectés à un réseau commun. En conséquence, l'une de mes premières tâches a été d'écrire une application pour contrôler un générateur de signaux.
Cela sera discuté dans l'article.
Commencer
Toutes les applications du département sont développées à l'aide de C ++ et de la bibliothèque Qt. J'avais de l'expérience avec ce cadre, donc il n'y a eu aucune difficulté de ce côté. De plus, Qt possède une documentation complète et vous pouvez toujours
copier-coller le code de StackOverflow pour consulter un conservateur.
Étant donné que tous les appareils sont connectés au même réseau, la question de savoir comment s'y connecter a également été résolue très rapidement - nous utilisons la partie réseau de Qt sous la forme de QTcpSocket.
La question la plus intéressante s'est posée lorsque j'ai dû décider comment communiquer avec ces appareils, comment activer telle ou telle fonction, transférer telle ou telle valeur. Ensuite, il s'est avéré que tout est assez banal: il existe un protocole de commandes standard pour les instruments programmables - SCPI. Il permet d'utiliser des commandes standard pour contrôler tous les appareils qui prennent en charge cette norme.
Commencez à coder
Tout est standard et sans intérêt dans le fichier d'en-tête:#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
Il a été décidé de faire l'interface comme ceci:

C'est assez simple et intuitif. Dans les deux modifications de ligne, l'hôte et le port de l'appareil sont définis en haut. Il est également possible de sélectionner des valeurs standard, elles prendront alors la forme suivante:
port = 5025; host = "192.168.1.109";
Ensuite, la zone de texte du journal, la réponse de l'appareil (les erreurs y seront envoyées, le cas échéant). Un peu plus bas se trouvent les boutons pour se connecter à l'appareil, envoyer une commande, vérifier les erreurs. Dans les trois dernières modifications de ligne, vous pouvez soit définir votre propre commande et l'envoyer à l'appareil, soit définir séparément la fréquence et l'amplitude. Le bouton radio sur la droite active / désactive la sortie RF. Le spinner ajuste la fréquence lorsque la case est désactivée et l'amplitude lorsqu'elle est activée.
Nous continuons et finissons
Tout le plaisir commence dans le fichier .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" ); } }
Après avoir lu
Je comprends que l'article peut sembler séparé de la vie et de la réalité pour un grand nombre de lecteurs, mais la télécommande de l'instrumentation dans le domaine de l'ingénierie est un sujet assez courant qui apporte beaucoup d'avantages et de commodité (par exemple, vous n'avez pas besoin de courir sur des appareils et d'appuyer sur des boutons) .
Pour le reste, cet article est de nature informative et divertissante et s'adresse plus probablement aux passionnés et aux personnes impliquées dans le développement et le test de cartes et d'autres matériels. Je voudrais juste dire au reste de ma petite expérience dans le développement de logiciels à des fins spécifiques.