将电机、驱动器、开发板连接好,如下图:
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等方式来实现控制。
效果请看视频。
更多回帖