汇川伺服电机位置控制模式QT程序Demo实现

0.实现效果

1.工程文件

#-------------------------------------------------
#
# Project created by QtCreator 2022-11-30T09:37:26
#
#-------------------------------------------------

QT       += core gui
QT       += serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = SerialServo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        console.cpp \
        main.cpp \
        mainwindow.cpp \
        settingsdialog.cpp

HEADERS += \
        console.h \
        mainwindow.h \
        settingsdialog.h

FORMS += \
        mainwindow.ui \
        settingsdialog.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    serialservo.qrc

2. 接受显示区

#ifndef CONSOLE_H
#define CONSOLE_H

#include <QPlainTextEdit>

class Console : public QPlainTextEdit
{
    Q_OBJECT

signals:
    void getData(const QByteArray &data);

public:
    explicit Console(QWidget *parent = nullptr);

    void putData(const QByteArray &data);
    void setLocalEchoEnabled(bool set);

protected:
    void keyPressEvent(QKeyEvent *e) override;
    void mousePressEvent(QMouseEvent *e) override;
    void mouseDoubleClickEvent(QMouseEvent *e) override;
    void contextMenuEvent(QContextMenuEvent *e) override;

private:
    bool m_localEchoEnabled = false;
};

#endif // CONSOLE_H

实现文件

#include "console.h"

#include <QScrollBar>

Console::Console(QWidget *parent) :
    QPlainTextEdit(parent)
{
    document()->setMaximumBlockCount(100);
    QPalette p = palette();
    p.setColor(QPalette::Base, Qt::black);
    p.setColor(QPalette::Text, Qt::green);
    setPalette(p);
}

void Console::putData(const QByteArray &data)
{
    insertPlainText(data);

//    QScrollBar *bar = verticalScrollBar();
//    bar->setValue(bar->maximum());
}

void Console::setLocalEchoEnabled(bool set)
{
    m_localEchoEnabled = set;
}

void Console::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_Backspace:
    case Qt::Key_Left:
    case Qt::Key_Right:
    case Qt::Key_Up:
    case Qt::Key_Down:
        break;
    default:
        if (m_localEchoEnabled)
            QPlainTextEdit::keyPressEvent(e);
        emit getData(e->text().toLocal8Bit());
    }
}

void Console::mousePressEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
    setFocus();
}

void Console::mouseDoubleClickEvent(QMouseEvent *e)
{
    Q_UNUSED(e)
}

void Console::contextMenuEvent(QContextMenuEvent *e)
{
    Q_UNUSED(e)
}

3. 主程序

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

4. 主窗体程序

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>

QT_BEGIN_NAMESPACE

class QLabel;

namespace Ui {
class MainWindow;
}

QT_END_NAMESPACE

class Console;
class SettingsDialog;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    QByteArray hexString2ByteArray(QString HexString);
    uint16_t comCrcValue(const uint8_t* data, uint16_t length);

signals:
    void VDI1cmd(const QString &s);
    void VDI2cmd(const QString &s);
    void VDO1cmd(const QString &s);
    void Modelcmd(const QString &s);
    void ComVDIcmd(const QString &s);
    void ComVDOcmd(const QString &s);
    void ComVDIDefaultcmd(const QString &s);
    void DI5Funccmd(const QString &s);
    void CmdSourcecmd(const QString &s);
    void MulStageModcmd(const QString &s);
    void Displacementcmd(const QString &s);
    void PosAbsLinearcmd(const QString &s);
    void RunMotorcmd(const QString &s);

    void FillDisplacementcmd(const QString &s);

private slots:
    void openSerialPort();
    void closeSerialPort();
    void about();
    void writeData(const QByteArray &data);
    void readData();
    void saveSettings();

    void handleError(QSerialPort::SerialPortError error);

    void on_pushButtonRun_clicked();

    void on_pushButtonEnable_clicked();

    void on_pushButtonDisable_clicked();

    void sendCommands(QString strcommands);
    void fillDisplacement(QString strcommands);

private:
    void initActionsConnections();
    void initCommandsConnections();

private:
    void showStatusMessage(const QString &message);

    Ui::MainWindow *m_ui = nullptr;
    QLabel *m_status = nullptr;
    Console *m_console = nullptr;
    SettingsDialog *m_settings = nullptr;
    QSerialPort *m_serial = nullptr;

    long m_displacement;
};

#endif // MAINWINDOW_H


实现文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "console.h"
#include "settingsdialog.h"

#include <QLabel>
#include <QMessageBox>

#include <QDebug>
#include <QThread>

const int SLEEPMS = 50;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_ui(new Ui::MainWindow),
    m_status(new QLabel),
    m_console(new Console),
    m_settings(new SettingsDialog),
    m_serial(new QSerialPort(this))
   ,m_displacement(0)
{
    m_ui->setupUi(this);

    setWindowTitle(tr("Servo Motor Demo"));

//    m_console->setEnabled(false);
//    setCentralWidget(m_console);

    m_ui->actionConnect->setEnabled(true);
    m_ui->actionDisconnect->setEnabled(false);
    m_ui->actionQuit->setEnabled(true);
    m_ui->statusBar->addWidget(m_status);

    initActionsConnections();
    initCommandsConnections();

    connect(m_serial, &QSerialPort::errorOccurred, this, &MainWindow::handleError);
    connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
//    connect(m_console, &Console::getData, this, &MainWindow::writeData);
}

MainWindow::~MainWindow()
{
    delete m_ui;
    delete m_settings;
}

void MainWindow::openSerialPort()
{
    const SettingsDialog::Settings p = m_settings->settings();
    m_serial->setPortName(p.name);
    m_serial->setBaudRate(p.baudRate);
    m_serial->setDataBits(p.dataBits);
    m_serial->setParity(p.parity);
    m_serial->setStopBits(p.stopBits);
    m_serial->setFlowControl(p.flowControl);
    if(m_serial->open(QIODevice::ReadWrite)){
//        m_console->setEnabled(true);
//        m_console->setLocalEchoEnabled(p.localEchoEnabled);
        m_ui->actionConnect->setEnabled(false);
        m_ui->actionDisconnect->setEnabled(true);
        m_ui->actionConfigure->setEnabled(false);

        showStatusMessage(tr("Connect to %1 :%2, %3, %4, %5, %6")
                          .arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits)
                          .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl));
    } else {
        QMessageBox::critical(this, tr("Error"), m_serial->errorString());
        showStatusMessage(tr("Open error"));
    }
}

void MainWindow::closeSerialPort()
{
    if(m_serial->isOpen())
    {
        m_serial->close();
    }
//    m_console->setEnabled(false);
    m_ui->actionConnect->setEnabled(true);
    m_ui->actionDisconnect->setEnabled(false);
    m_ui->actionConfigure->setEnabled(true);
    showStatusMessage(tr("Disconnected"));
}

void MainWindow::about()
{
    QMessageBox::about(this, "About Serial Servo",
                       tr("Serial Servo Demo"));
}

uint16_t MainWindow::comCrcValue(const uint8_t* data, uint16_t length)
{
    uint16_t crcValue = 0xffff;
    int i;
    while (length--)
    {
        crcValue ^= *data++;
        for (i = 0; i < 8; i++)
        {
            if (crcValue & 0x0001)
            {
                crcValue = (crcValue >> 1) ^ 0xA001;
            }
            else
            {
                crcValue = crcValue >> 1;
            }
        }
    }
    return (crcValue);
}

void MainWindow::saveSettings()
{
    QString strVDI1cmd =  QString("01 06 17 00 00 01 4D BE");
    QString strVDI2cmd =  QString("01 06 17 02 00 1C 2C 77");
    QString strVDO1cmd =  QString("01 06 17 21 00 05 1C 77");
    QString strModelcmd =  QString("01 06 02 00 00 01 49 B2");
    QString strComVDIcmd =  QString("01 06 0C 09 00 01 9B 58");
    QString strComVDOcmd =  QString("01 06 0C 0B 00 01 3A 98");
    QString strComVDIDefaultcmd =  QString("01 06 0C 0A 00 01 6B 58");
    QString strDI5Funccmd =  QString("01 06 03 0A 00 00 A9 8C");
    QString strCmdSourcecmd =  QString("01 06 05 00 00 02 08 C7");
    QString strMulStageModcmd =  QString("01 06 11 00 00 00 8C F6");
    QString strDisplacementcmd =  QString("01 10 11 0C 00 02 04 C3 50 00 00 0F FF");
    QString strPosAbsLinearcmd =  QString("01 06 02 01 00 01 18 72");

    if(m_ui->checkBoxVDI1->checkState() == Qt::Checked)
    {
        emit VDI1cmd(strVDI1cmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxVDI2->checkState() == Qt::Checked)
    {
        emit VDI2cmd(strVDI2cmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxVDO1->checkState() == Qt::Checked)
    {
        emit VDO1cmd(strVDO1cmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxModel->checkState() == Qt::Checked)
    {
        emit Modelcmd(strModelcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxComVDI->checkState() == Qt::Checked)
    {
        emit ComVDIcmd(strComVDIcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxComVDO->checkState() == Qt::Checked)
    {
        emit ComVDOcmd(strComVDOcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxComVDIDefault->checkState() == Qt::Checked)
    {
        emit ComVDIDefaultcmd(strComVDIDefaultcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxDI5Func->checkState() == Qt::Checked)
    {
        emit DI5Funccmd(strDI5Funccmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxCmdSource->checkState() == Qt::Checked)
    {
        emit CmdSourcecmd(strCmdSourcecmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxMulStageMod->checkState() == Qt::Checked)
    {
        emit MulStageModcmd(strMulStageModcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxDisplacement->checkState() == Qt::Checked)
    {
        emit Displacementcmd(strDisplacementcmd);
        QThread::msleep(SLEEPMS);
    }

    if(m_ui->checkBoxPosAbsLinear->checkState() == Qt::Checked)
    {
        emit PosAbsLinearcmd(strPosAbsLinearcmd);
        QThread::msleep(SLEEPMS);
    }
}

void MainWindow::sendCommands(QString strcommands)
{
    QByteArray settingCmd;
    settingCmd = hexString2ByteArray(strcommands);
    writeData(settingCmd);
}

void MainWindow::writeData(const QByteArray &data)
{
    m_serial->write(data);
    m_serial->waitForBytesWritten(1000);
}

void MainWindow::readData()
{
    const QByteArray data = m_serial->readAll();
//    m_console->putData(data);
}

void MainWindow::handleError(QSerialPort::SerialPortError error)
{
    if(error == QSerialPort::ResourceError){
        QMessageBox::critical(this, tr("Critical Error"), m_serial->errorString());
        closeSerialPort();
    }
}

void MainWindow::initActionsConnections()
{
    connect(m_ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort);
    connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort);
    connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close);
    connect(m_ui->actionConfigure, &QAction::triggered, m_settings, &SettingsDialog::show);
//    connect(m_ui->actionClear, &QAction::triggered, m_console, &Console::clear);
    connect(m_ui->actionAbout, &QAction::triggered, this, &MainWindow::about);
    connect(m_ui->actionSaveSetting, &QAction::triggered, this, &MainWindow::saveSettings);
}

void MainWindow::initCommandsConnections()
{
    connect(this, &MainWindow::VDI1cmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::VDI2cmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::VDO1cmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::Modelcmd, this, &MainWindow::sendCommands);

    connect(this, &MainWindow::ComVDIcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::ComVDOcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::ComVDIDefaultcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::DI5Funccmd, this, &MainWindow::sendCommands);

    connect(this, &MainWindow::CmdSourcecmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::MulStageModcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::Displacementcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::PosAbsLinearcmd, this, &MainWindow::sendCommands);

    connect(this, &MainWindow::RunMotorcmd, this, &MainWindow::sendCommands);
    connect(this, &MainWindow::FillDisplacementcmd, this, &MainWindow::fillDisplacement);
}

void MainWindow::showStatusMessage(const QString &message)
{
    m_status->setText(message);
}

QByteArray MainWindow::hexString2ByteArray(QString HexString)
{
    bool ok;
    QByteArray ret;
    HexString = HexString.trimmed();
    HexString = HexString.simplified();
    QStringList sl = HexString.split(" ");

    foreach (QString s, sl) {
        if(!s.isEmpty())
        {
            char c = s.toInt(&ok,16) & 0xFF;
            if(ok){
                ret.append(c);
            }else{
                qDebug()<<"invalid hex string"<<s;
            }
        }
    }
    return ret;
}

void MainWindow::fillDisplacement(QString strcommands)
{
//   QString strDisplacement = m_ui->lineEditDisplacement->text();
   QString strDisplacement = strcommands;
   long ldisplacement = strDisplacement.toLong();
   if((ldisplacement < 10000) || (ldisplacement > 100000))
   {
       QMessageBox::warning(this,"Warning","Please enter the value between 10000 and 100000");
       qDebug() << "invalid value: should be between 10000 and 100000" << endl;
       return;
   }

   QByteArray runCmd;

   uint16_t a;
   uint16_t dataLow;
   uint16_t dataHigh;
   uint8_t data[13];
   data[0] = 0x01;
   data[1] = 0x10;
   data[2] = 0x11;
   data[3] = 0x0C;

   data[4] = 0x00;
   data[5] = 0x02;
   data[6] = 0x04;

   dataLow = ldisplacement & 0xffff;
   dataHigh = (ldisplacement >> 16) & 0xffff;

   data[7] = (dataLow >> 8) & 0xff;
   data[8] = dataLow & 0xff;
   data[9] = (dataHigh >> 8) & 0xff;
   data[10] = dataHigh & 0xff;

   a = comCrcValue(data, 11);
   data[11] = a & 0xff;
   data[12] = (a >> 8) & 0xff;

   QString request= QString("");
   for (int i=0; i<13;i++) {
       request += QString("%1 ").arg(data[i],2,16,QChar('0'));
   }

   runCmd = hexString2ByteArray(request);
   writeData(runCmd);

}

void MainWindow::on_pushButtonRun_clicked()
{
       long longTemp = m_ui->lineEditDisplacement->text().toLong();
       if (m_displacement != longTemp)
       {
           m_displacement = longTemp;
           emit FillDisplacementcmd(m_ui->lineEditDisplacement->text());
           QThread::msleep(SLEEPMS);
       }


       QString strRunMotorcmd =  QString("01 06 31 00 00 03 C7 37");
       emit RunMotorcmd(strRunMotorcmd);
       QThread::msleep(SLEEPMS);
}

void MainWindow::on_pushButtonEnable_clicked()
{
    QString strEnableMotorcmd =  QString("01 06 31 00 00 01 46 F6");

    QByteArray runCmd;
    runCmd = hexString2ByteArray(strEnableMotorcmd);
    writeData(runCmd);
}

void MainWindow::on_pushButtonDisable_clicked()
{
    QString strDisableMotorcmd =  QString("01 06 31 00 00 00 87 36");

    QByteArray runCmd;
    runCmd = hexString2ByteArray(strDisableMotorcmd);
    writeData(runCmd);
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt是一种跨平台的应用程序开发框架,可以方便地进行图形化界面设计和串口通信。在使用Qt实现串口控制电机的功能时,我们需要编写一些源码来实现相应的功能。 首先,我们需要使用Qt提供的串口类,打开并配置串口。可以使用如下代码来实现: ```cpp QSerialPort serial; serial.setPortName("COM1"); // 设置串口名字 serial.setBaudRate(QSerialPort::Baud115200); // 设置波特率 serial.setDataBits(QSerialPort::Data8); // 设置数据位 serial.setParity(QSerialPort::NoParity); // 设置校验位 serial.setStopBits(QSerialPort::OneStop); // 设置停止位 serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 if (serial.open(QIODevice::ReadWrite)) { // 串口打开成功 } else { // 串口打开失败 } ``` 然后,我们可以使用串口类的`write()`函数写入数据到串口中,控制电机的运动。例如,下面的代码将给串口发送一个字节的数据来控制电机: ```cpp char data = 0x01; QByteArray sendData; sendData.append(data); serial.write(sendData); ``` 接下来,我们可以使用串口类的`readyRead()`信号来读取从串口接收到的数据。例如,下面的代码将读取从串口接收到的所有数据: ```cpp connect(&serial, &QSerialPort::readyRead, [&]() { QByteArray receivedData = serial.readAll(); // 对接收到的数据进行处理 }); ``` 最后,在程序结束时,记得关闭串口: ```cpp serial.close(); ``` 通过以上的源码实现,我们就可以使用Qt控制电机了。需要注意的是,以上的代码只是简单示例,实际使用时需要根据具体需求进行修改和完善。 ### 回答2: Qt 是一种跨平台的应用程序开发框架,提供了丰富的库和工具来开发各种类型的应用程序,包括串口通信。串口通信是一种用于与其他设备进行数据交互的通信方式,而控制电机是其中常见的一种应用场景。 在 Qt 中,可以使用 QSerialPort 类来实现串口通信。它提供了一组函数来配置串口参数、打开和关闭串口、发送和接收数据等操作。要控制电机,可以先将串口与电机连接,并使用相应的串口协议向电机发送控制指令。 以下是一个简单的示例,演示了如何使用 Qt 进行串口控制电机: 1. 首先,需要在程序中包含串口相关的头文件: ```cpp #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> ``` 2. 创建一个 QSerialPort 类的对象,并打开串口: ```cpp QSerialPort serialPort; serialPort.setPortName("COM1"); // 设置串口名 serialPort.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serialPort.setDataBits(QSerialPort::Data8); // 设置数据位 serialPort.setParity(QSerialPort::NoParity); // 设置校验位 serialPort.setStopBits(QSerialPort::OneStop); // 设置停止位 if (serialPort.open(QIODevice::ReadWrite)) { // 串口打开成功 } else { // 串口打开失败 } ``` 3. 发送控制指令到串口: ```cpp QByteArray command = "MOTOR_ON"; serialPort.write(command); // 向串口发送数据 ``` 4. 接收串口返回的数据: ```cpp QObject::connect(&serialPort, &QSerialPort::readyRead, [&](){ QByteArray data = serialPort.readAll(); // 处理接收到的数据 }); ``` 5. 在程序结束时,关闭串口: ```cpp serialPort.close(); ``` 以上是一个基本的串口控制电机的 Qt 源码示例,具体的实现方式和串口协议要根据具体的硬件设备和通信协议来确定。注意在实际应用中,还需要进行异常处理、错误处理和数据解析等工作,以保证串口通信的稳定和正确性。 ### 回答3: QT串口控制电机的源码实现如下: 首先,在QT的工程中,需要引入QtSerialPort模块,以便实现串口通信功能。可以通过在.pro文件中添加`QT += serialport`来引入该模块。 其次,需要创建一个串口对象,并进行相关的配置,如波特率、数据位、校验位等。 然后,在界面中设置相应的按钮和文本框,以便用户可以输入命令或者控制电机的运动。通过将按钮的clicked信号与相关的槽函数相连,可以响应按钮的点击事件。 接下来,实现相应的槽函数。当按钮被点击时,槽函数会被调用,从而执行相应的串口操作。例如,可以通过串口对象的write函数将命令写入串口。 最后,可以通过串口对象的readyRead信号来接收串口传来的数据。可以通过readAll函数读取数据,并将接收到的数据显示在文本框中,用来实时监测串口的返回结果。 总结起来,QT串口控制电机的源码实现主要包括串口对象的创建和配置、按钮的点击事件响应、串口操作的实现以及接收串口数据的处理。通过这些步骤,可以实现通过串口控制电机的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值