飞凌嵌入式
直播中

华仔stm32

3年用户 2952经验值
擅长:嵌入式技术
私信 关注
[技术]

【飞凌RK3568开发板试用体验】2、QT界面——电机控制

电路原理图

image.png

搭建效果

将电机、驱动器、开发板连接好,如下图:

c4c66141491abf8c8157119b11dac8c.jpg

控制界面

8ac4f1d71d909923e9b5d6fea9305cb.jpg

程序

1、motor_demo.pro

#-------------------------------------------------
#
# Project created by QtCreator 2022-12-20T20:19:13
#
#-------------------------------------------------

QT       += core gui widgets

TARGET = motor_demo
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 += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

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

2、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTime>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void sleep(unsigned int msec);//延时功能
    static int period;
    static int duty_cycle;
    static int speed;
private slots:
    void on_btnOpen_clicked();

    void on_butClose_clicked();

    void on_btnStart_clicked();

    void on_btnBack_clicked();

    void on_btnFoward_clicked();

    void on_btnAddSpeed_clicked();

    void on_btnMinusSpeed_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

3、main.cpp

#include "mainwindow.h"
#include

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

return a.exec();

}

4、mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#define EN_GPIO_EXPORT    "echo 110 > /sys/class/gpio/export"

#define EN_DIR          "echo 'out' > /sys/class/gpio/gpio110/direction"
#define EN_DIR_ENABLE   "echo 0 > /sys/class/gpio/gpio110/value"
#define EN_DIR_DISABLE  "echo 1 > /sys/class/gpio/gpio110/value"

#define DIR_GPIO_EXPORT  "echo 108 > /sys/class/gpio/export"
#define DIR_DIR          "echo 'out' > /sys/class/gpio/gpio108/direction"
#define DIR_Forward      "echo 1 > /sys/class/gpio/gpio108/value"
#define DIR_Back         "echo 0 > /sys/class/gpio/gpio108/value"


#define PWM14_EXPORT            "echo 0 > /sys/class/pwm/pwmchip0/export"
#define PWM14_UNEXPORT          "echo 0 > /sys/class/pwm/pwmchip0/unexport"
#define PWM14_Period            "echo 500000 > /sys/class/pwm/pwmchip0/pwm0/period"
#define PWM14_Duty_cycle        "echo 0 >  /sys/class/pwm/pwmchip0/pwm0/duty_cycle"
#define PWM14_Polarity          "echo normal > /sys/class/pwm/pwmchip0/pwm0/polarity"
#define PWM14_Value_ENABLE      "echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable"
#define PWM14_Value_DISABLE     "echo 0 > /sys/class/pwm/pwmchip0/pwm0/enable"

int MainWindow::period = 5000000;
int MainWindow::duty_cycle = 2500000;
int MainWindow::speed = 0;

//延时功能
void MainWindow::sleep(unsigned int msec){
//currnentTime 返回当前时间 用当前时间加上我们要延时的时间msec得到一个新的时刻
    QTime reachTime = QTime::currentTime().addMSecs(msec);
    //用while循环不断比对当前时间与我们设定的时间
    while(QTime::currentTime()<reachTime){
    //如果当前的系统时间尚未达到我们设定的时刻,就让Qt的应用程序类执行默认的处理,
    //以使程序仍处于响应状态。一旦到达了我们设定的时刻,就跳出该循环,继续执行后面的语句。
        QApplication::processEvents(QEventLoop::AllEvents,100);
    }
}


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->lcdNumberSpeed->display(speed);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_btnOpen_clicked()
{
    system(EN_GPIO_EXPORT);
    system(EN_DIR);
    system(EN_DIR_DISABLE);

    system(DIR_GPIO_EXPORT);
    system(DIR_DIR);
    system(DIR_Forward);

    system(PWM14_UNEXPORT);
    system(PWM14_EXPORT);
    system(PWM14_Period);
    system(PWM14_Duty_cycle);
    system(PWM14_Polarity);
    system(PWM14_Value_DISABLE);
}

void MainWindow::on_butClose_clicked()
{

    QString cmdPeriod,cmdDutyCylce;
    while(period<2000000)
        {
            period = period + 15000;
            duty_cycle = duty_cycle + 7500;
            cmdPeriod = tr("echo %1 > /sys/class/pwm/pwmchip0/pwm0/period").arg(period);
            cmdDutyCylce = tr("echo %1 >  /sys/class/pwm/pwmchip0/pwm0/duty_cycle").arg(duty_cycle);
            system(cmdDutyCylce.toStdString().c_str());
            system(cmdPeriod.toStdString().c_str());
            sleep(1);
             ui->lcdNumberSpeed->display(10000000/period);
        }
    system(PWM14_Value_DISABLE);
    period = 5000000;
    duty_cycle = 2500000;
    ui->lcdNumberSpeed->display(0);
}

void MainWindow::on_btnStart_clicked()
{

    QString cmdPeriod,cmdDutyCylce;
    system(EN_DIR_ENABLE);
    system(PWM14_Value_ENABLE);
    do
        {
            period = period - 10000;
            duty_cycle = duty_cycle - 5000;
            cmdPeriod = tr("echo %1 > /sys/class/pwm/pwmchip0/pwm0/period").arg(period);
            cmdDutyCylce = tr("echo %1 >  /sys/class/pwm/pwmchip0/pwm0/duty_cycle").arg(duty_cycle);

            system(cmdDutyCylce.toStdString().c_str());
            system(cmdPeriod.toStdString().c_str());
            ui->lcdNumberSpeed->display(10000000/period);
            sleep(1);
        }
    while(period>200000);

}

void MainWindow::on_btnBack_clicked()
{
    system(EN_DIR_DISABLE);
    system(DIR_Back);

}


void MainWindow::on_btnFoward_clicked()
{
    system(EN_DIR_DISABLE);
    system(DIR_Forward);

}

void MainWindow::on_btnAddSpeed_clicked()
{
    QString cmdPeriod,cmdDutyCylce;

        period = period + 10000;
        duty_cycle = duty_cycle + 5000;
        if(period<5000000)
        {
            cmdPeriod = tr("echo %1 > /sys/class/pwm/pwmchip0/pwm0/period").arg(period);
            cmdDutyCylce = tr("echo %1 >  /sys/class/pwm/pwmchip0/pwm0/duty_cycle").arg(duty_cycle);
            system(cmdDutyCylce.toStdString().c_str());
            system(cmdPeriod.toStdString().c_str());
            sleep(1);

        }
        else
        {
            system(PWM14_Value_DISABLE);
            period = 5000000;
            duty_cycle = 2500000;

        }
         ui->lcdNumberSpeed->display(10000000/period);
}

void MainWindow::on_btnMinusSpeed_clicked()
{
    QString cmdPeriod,cmdDutyCylce;

        period = period - 10000;
        duty_cycle = duty_cycle - 5000;
        if(period>200000)
        {
            cmdPeriod = tr("echo %1 > /sys/class/pwm/pwmchip0/pwm0/period").arg(period);
            cmdDutyCylce = tr("echo %1 >  /sys/class/pwm/pwmchip0/pwm0/duty_cycle").arg(duty_cycle);
            system(cmdDutyCylce.toStdString().c_str());
            system(cmdPeriod.toStdString().c_str());
            sleep(1);
        }
        else
        {
            period = 200000;
            duty_cycle = 100000;
        }
         ui->lcdNumberSpeed->display(10000000/period);
}

5、mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1024</width>
    <height>800</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>240</x>
      <y>60</y>
      <width>611</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>36</pointsize>
     </font>
    </property>
    <property name="text">
     <string>电机控制系统</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnOpen">
    <property name="geometry">
     <rect>
      <x>140</x>
      <y>530</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>开机</string>
    </property>
   </widget>
   <widget class="QPushButton" name="butClose">
    <property name="geometry">
     <rect>
      <x>690</x>
      <y>530</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>关机</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnStart">
    <property name="geometry">
     <rect>
      <x>420</x>
      <y>530</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>启动</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnBack">
    <property name="geometry">
     <rect>
      <x>140</x>
      <y>230</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>反转</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnMinusSpeed">
    <property name="geometry">
     <rect>
      <x>680</x>
      <y>370</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>加速</string>
    </property>
   </widget>
   <widget class="QPushButton" name="btnAddSpeed">
    <property name="geometry">
     <rect>
      <x>140</x>
      <y>380</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>减速</string>
    </property>
   </widget>
   <widget class="QLCDNumber" name="lcdNumberSpeed">
    <property name="geometry">
     <rect>
      <x>410</x>
      <y>300</y>
      <width>171</width>
      <height>91</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>36</pointsize>
     </font>
    </property>
    <property name="value" stdset="0">
     <double>10.000000000000000</double>
    </property>
   </widget>
   <widget class="QPushButton" name="btnFoward">
    <property name="geometry">
     <rect>
      <x>680</x>
      <y>220</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="font">
     <font>
      <pointsize>24</pointsize>
     </font>
    </property>
    <property name="text">
     <string>正转</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1024</width>
     <height>48</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

技术要点

1、pwm调试,我原来是用pwm14,但是开了pwm14后显示有问题,后面改为pwm3来使用。详细的调试见我的帖子:
【新提醒】【飞凌RK3568开发板试用体验】调试硬件PWM记 - 飞凌嵌入式 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)

2、GPIO我选择了G3B6作做ENA+,G3B4作为DIR+。GPIO的调试见我上篇帖子:
【新提醒】【飞凌RK3568开发板试用体验】GPIO调试记 - 飞凌嵌入式 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)
3、启动电机的设计
因为步进电机不能一步把速度设置到指定的速度,需要从低频率往上调,所以起始速率以低的转速往上调。
4、电机的关机设计
同启动的设计,步进电机不能一下关死,也需要把频率慢慢调低再最后关断。
5、正反转的设计是搞制DIR的电平高低来确定方向。
【讨论】其实我还是第一次使用步进电机,原来的伺服电机有厂家的设计起动、停止调计,这次设计的起动与关停,花了不少时间。有经验的大佬希望可以指点我的一下。
后续将通过其他的方式,如CAN、MQTT等方式来实现控制。
效果请看视频。

电机控制

更多回帖

发帖
×
20
完善资料,
赚取积分