مقدمة
في السنة الثالثة ، بدأت أمارس التدريب في إحدى شركات صناعة الصواريخ والفضاء المحلية. كنت متدربًا طموحًا ونشطًا
إلى حد بعيد
حتى رأيت العمل الروتيني في مؤسسة روسية مملوكة للدولة ، وبناءً على طلبي ، تم تعييني في القسم المعني بتطوير
معدات الاختبار (المشار إليها فيما يلي باسم
KPA ). بالمناسبة ، جزء كبير من تطوير
اتفاق السلام الشامل هو كتابة جزء البرنامج للمعدات. بما في ذلك ، للتحقق من الأجهزة التي يجري تطويرها ، لدى القسم
أجهزة تحكم وقياس متنوعة ، كلها متصلة بشبكة مشتركة. كنتيجة لذلك ، كان من بين أول مهامي كتابة تطبيق للتحكم في مولد الإشارات.
سوف نناقش هذا في المقال.
ابدأ
يتم تطوير جميع التطبيقات في القسم باستخدام C ++ ومكتبة Qt. لقد واجهت هذا الإطار ، لذلك لم تكن هناك صعوبات في هذا الجانب. بالإضافة إلى ذلك ، لدى Qt وثائق مستفيضة ، ويمكنك دائمًا
نسخ الشفرة من لصق StackOverflow لاستشارة أمين المعرض.
نظرًا لأن جميع الأجهزة متصلة بنفس الشبكة ، تم حل مسألة كيفية الاتصال بها أيضًا بسرعة كبيرة - نستخدم جزء شبكة Qt في شكل QTcpSocket.
نشأ السؤال الأكثر إثارة للاهتمام عندما اضطررت إلى اتخاذ قرار بشأن كيفية التواصل مع هذه الأجهزة ، وكيفية تنشيط وظيفة أو وظيفة أخرى ، لنقل قيمة واحدة أو أخرى. ثم اتضح أن كل شيء تافه للغاية: هناك بروتوكول للأوامر القياسية للأدوات القابلة للبرمجة - 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" ); } }
بعد القراءة
أتفهم أن المقالة قد تبدو منفصلة عن الحياة والواقع بالنسبة لعدد كبير من القراء ، ولكن التحكم عن بعد في الأجهزة في مجال الهندسة هو موضوع شائع إلى حد كبير يجلب الكثير من الفوائد والراحة (على سبيل المثال ، لا تحتاج إلى تشغيل إلى الأجهزة والضغط على أزرار) .
بالنسبة للباقي ، تتميز هذه المقالة بطابع إعلامي وترفيهي وتهدف على الأرجح إلى المتحمسين والأشخاص المشاركين في تطوير واختبار اللوحات والأجهزة الأخرى. أود فقط أن أخبر الباقي عن تجربتي الصغيرة في تطوير البرامج لأغراض محددة.