stm32 42步进电机 上位机示例

news2024/11/28 8:40:33

脉冲到底是个啥东西?步进电机一直说发脉冲
步进电机通过接收脉冲信号来实现精确的位置控制。脉冲是一种短暂的电信号,它的变化可以触发步进电机转动一定的角度或步进。步进电机控制系统会根据输入的脉冲信号来精确定位和控制步进电机的转动,每个脉冲信号通常对应步进电机转动的一个固定的步进角度。

简单来说,当步进电机需要转动时,控制系统会发送一系列脉冲信号给步进电机,每个脉冲信号对应步进电机转动的一个步进角度。通过控制脉冲信号的频率和数量,可以精确地控制步进电机的转动,从而实现精准的位置控制和运动控制。

步进电机的相数是干嘛的,比如;两相是啥意思
步进电机的相数指的是步进电机的驱动方式中使用的线圈数量。常见的步进电机有两相、三相、四相和五相等不同的相数。

在两相步进电机中,驱动方式包含两个线圈(也称为相),每个线圈独立控制一个电机极性。两相步进电机通过交替激活这两个线圈来实现转动。具体来说,当一个线圈通电时,它会产生一个磁场,将电机转子吸引到对应位置;当另一个线圈通电时,前一个线圈的磁场会减弱,电机转子会被吸引到新的位置。通过交替激活两个线圈,可以实现步进电机的转动。

两相步进电机相对简单,结构紧凑,成本较低,广泛应用于一些低要求的应用领域。然而,由于只有两个线圈,步进角度较大,精度相对较低。

其他相数的步进电机,如三相、四相和五相步进电机,通过增加线圈的数量来提高步进角度的精度。随着相数的增加,步进电机的转动变得更加平滑和精确,但同时也增加了电机结构的复杂性和成本。

实物图:
在这里插入图片描述
上位机Qt软件图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路就是stm32一直给步进电机发脉冲,然后通过驱动器驱动步进电机转动,这个项目多了一个qt发送串口消息给stm32,stm32接收对应的命令然后执行不同的函数,但是这样无法实现步进电机的反馈,无法实现限位,回零等功能。
不过目前可以实现步进电机转动度数的控制,因为实物没负载也没测试有没有丢步的现象,还能实现正反转
stm32主要代码:
Motor.h:

#ifndef __MOTOR_H
#define __MOTOR_H

void Motor_Init(void);
void Motor_Run(uint32_t dir,uint32_t num,uint32_t speed);
void Motor_RunDegree(uint32_t dir,uint32_t degree,uint32_t speed);

#endif

Motor.cpp:

#include "stm32f10x.h"
#include "Delay.h"

void Motor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
	
	GPIO_InitTypeDef  GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4 | GPIO_Pin_3;  //PA5->EN;PA4->DIR;PA3->PWM
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_4| GPIO_Pin_3);	
}


void Motor_Run(uint32_t dir,uint32_t num,uint32_t speed)  
{
	if(dir==1)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_4);		
	}
	
	if(dir==0)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_4);			
	}
	
	for(uint32_t i=0;i<=(num*3200);i++) 
	{		
		Delay_us(speed);                   
		GPIOA->ODR ^= GPIO_Pin_3;  				
	}	
}


void Motor_RunDegree(uint32_t dir,uint32_t degree,uint32_t speed)  
{
	if(dir==1)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_4);		
	}
	
	if(dir==0)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_4);			
	}
	
	for(uint32_t i=0;i<=degree;i++) 
	{		
		Delay_us(speed);                   
		GPIOA->ODR ^= GPIO_Pin_3;  				
	}	
}


main.c:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Serial.h"
#include "string.h"
#include "Motor.h"

int main(void){
	Serial_Init();
	Motor_Init();
	while (1)
	{
		if (Serial_RxFlag == 1){
			if (strcmp(Serial_RxPacket, "1") == 0)
			{
				GPIO_SetBits(GPIOA, GPIO_Pin_5);
			}
			else if (strcmp(Serial_RxPacket, "3") == 0)
			{
					Motor_RunDegree(1,800,360);
			}else if (strcmp(Serial_RxPacket, "4") == 0)
			{
					Motor_RunDegree(0,800,360);
			}else if (strcmp(Serial_RxPacket, "5") == 0)
			{
					Motor_Run(1,1,300);
			}else if (strcmp(Serial_RxPacket, "6") == 0)
			{
					Motor_Run(0,1,300);
			}else if (strcmp(Serial_RxPacket, "7") == 0)
			{
					Motor_Run(1,1,400);
			}else if (strcmp(Serial_RxPacket, "8") == 0)
			{
					Motor_Run(0,1,400);
			}else if (strcmp(Serial_RxPacket, "9") == 0)
			{
					Motor_Run(1,1,500);
			}else if (strcmp(Serial_RxPacket, "10") == 0)
			{
					Motor_Run(0,1,500);
			}else if (strcmp(Serial_RxPacket, "11") == 0)
			{
					Motor_Run(1,2,300);
			}else if (strcmp(Serial_RxPacket, "12") == 0)
			{
					Motor_Run(0,2,300);
			}
			else if (strcmp(Serial_RxPacket, "2") == 0)
			{
				GPIO_ResetBits(GPIOA, GPIO_Pin_5);    
			}
			Serial_RxFlag = 0;
		}
	}
}

Qt的主要代码:

#include "widget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>

//角度实时波形显示
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    portSteepr=new Port(this);
    InitWidget();
    InitSignalAndSlot();
    ButtonDisabled();
}

Widget::~Widget(){

}

void Widget::InitWidget()
{
    setFixedSize(QSize(1200,800));
    LabelStatus=new QLabel(this);
    LabelStatus->move(100,200);

    PushButtonOpenDevice=new QPushButton(this);
    PushButtonOpenDevice->setText(tr("open device"));
    PushButtonOpenDevice->setFixedSize(120,60);

    PushButtonCloseDevice=new QPushButton(this);
    PushButtonCloseDevice->setText(tr("close device"));
    PushButtonCloseDevice->setFixedSize(120,60);


    PushButtonAdvance=new QPushButton(this);
    PushButtonAdvance->setText(tr("advance"));
    PushButtonAdvance->setFixedSize(120,60);



    PushButtonBackOff=new QPushButton(this);
    PushButtonBackOff->setText(tr("backoff"));
    PushButtonBackOff->setFixedSize(120,60);


    PushButton11300=new QPushButton(this);
    PushButton11300->setText(tr("pushbutton11300"));
    PushButton11300->setFixedSize(120,60);
    PushButton01300=new QPushButton(this);
    PushButton01300->setText(tr("pushbutton01300"));
    PushButton01300->setFixedSize(120,60);
    PushButton11400=new QPushButton(this);
    PushButton11400->setText(tr("pushbutton11400"));
    PushButton11400->setFixedSize(120,60);
    PushButton01400=new QPushButton(this);
    PushButton01400->setText(tr("pushbutton01400"));
    PushButton01400->setFixedSize(120,60);
    PushButton11500=new QPushButton(this);
    PushButton11500->setText(tr("pushbutton11500"));
    PushButton11500->setFixedSize(120,60);
    PushButton01500=new QPushButton(this);
    PushButton01500->setText(tr("pushbutton01500"));
    PushButton01500->setFixedSize(120,60);
    PushButton12300=new QPushButton(this);
    PushButton12300->setText(tr("pushbutton12300"));
    PushButton12300->setFixedSize(120,60);
    PushButton02300=new QPushButton(this);
    PushButton02300->setText(tr("pushbutton02300"));
    PushButton02300->setFixedSize(120,60);

    QVBoxLayout* vlayout1=new QVBoxLayout;
    QHBoxLayout* hlayout1=new QHBoxLayout;
    hlayout1->addWidget(PushButtonOpenDevice);
    hlayout1->addWidget(PushButtonCloseDevice);
    QHBoxLayout* hlayout2=new QHBoxLayout;
    hlayout2->addWidget(PushButtonAdvance);
    hlayout2->addWidget(PushButtonBackOff);
    QHBoxLayout* hlayout3=new QHBoxLayout;
    hlayout3->addWidget(PushButton01300);
    hlayout3->addWidget(PushButton11300);
    QHBoxLayout* hlayout4=new QHBoxLayout;
    hlayout4->addWidget(PushButton01400);
    hlayout4->addWidget(PushButton11400);
    QHBoxLayout* hlayout5=new QHBoxLayout;
    hlayout5->addWidget(PushButton01500);
    hlayout5->addWidget(PushButton11500);
    QHBoxLayout* hlayout6=new QHBoxLayout;
    hlayout6->addWidget(PushButton02300);
    hlayout6->addWidget(PushButton12300);
    vlayout1->addLayout(hlayout1);
    vlayout1->addLayout(hlayout2);
    vlayout1->addLayout(hlayout3);
    vlayout1->addLayout(hlayout4);
    vlayout1->addLayout(hlayout5);
    vlayout1->addLayout(hlayout6);
    setLayout(vlayout1);

}

void Widget::InitSignalAndSlot()
{
    connect(PushButtonOpenDevice,&QPushButton::clicked,this,&Widget::slotOpenDevice);
    connect(PushButtonCloseDevice,&QPushButton::clicked,this,&Widget::slotCloseDevice);
    connect(PushButtonAdvance,&QPushButton::clicked,this,&Widget::slotDriverSteeprAdvance);
    connect(PushButtonBackOff,&QPushButton::clicked,this,&Widget::slotDriverSteeprBackOff);

    connect(PushButton01300,&QPushButton::clicked,[=]{

        portSteepr->DriverSteeprMotor01300();

    });
    connect(PushButton11300,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor11300();
    });
    connect(PushButton01400,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor01400();
    });
    connect(PushButton11400,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor11400();
    });
    connect(PushButton01500,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor01500();
    });
    connect(PushButton11500,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor11500();
    });
    connect(PushButton02300,&QPushButton::clicked,[=]{
        ButtonDisabled();
        portSteepr->DriverSteeprMotor02300();
        ButtonEnabled();
    });
    connect(PushButton12300,&QPushButton::clicked,[=]{
        portSteepr->DriverSteeprMotor12300();
    });
}

void Widget::slotOpenDevice()
{
    ButtonEnabled();
    portSteepr->EnableSteepr();
}

void Widget::slotCloseDevice()
{
    ButtonDisabled();
    portSteepr->DisEnableSteepr();
}

void Widget::slotDriverSteeprAdvance()
{
    portSteepr->DriverSteeprAdvance();
}


void Widget::slotDriverSteeprBackOff()
{
    portSteepr->DriverSteeprBackOff();
}


void Widget::ButtonDisabled()
{
    PushButtonAdvance->setEnabled(false);
    PushButtonBackOff->setEnabled(false);
    PushButton01300->setEnabled(false);
    PushButton11300->setEnabled(false);
    PushButton01400->setEnabled(false);
    PushButton11400->setEnabled(false);
    PushButton01500->setEnabled(false);
    PushButton11500->setEnabled(false);
    PushButton02300->setEnabled(false);
    PushButton12300->setEnabled(false);
}


void Widget::ButtonEnabled()
{
    PushButtonAdvance->setEnabled(true);
    PushButtonBackOff->setEnabled(true);
    PushButton01300->setEnabled(true);
    PushButton11300->setEnabled(true);
    PushButton01400->setEnabled(true);
    PushButton11400->setEnabled(true);
    PushButton01500->setEnabled(true);
    PushButton11500->setEnabled(true);
    PushButton02300->setEnabled(true);
    PushButton12300->setEnabled(true);

}

然后是接线:
采用共阳极接线法:
PUL+ ENA+ DIR+接3.3V,ENA-接A5 DIR-接A4 PUL-接A3 然后USB转TTL接线 RX接A9 TX接A10
在这里插入图片描述
注意事项:
电机如果发热严重记得调节拨码开关的电流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1254383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android平台GB28181设备接入模块开发填坑指南

技术背景 为什么要开发Android平台GB28181设备接入模块&#xff1f;这个问题不再赘述&#xff0c;在做Android平台GB28181客户端的时候&#xff0c;媒体数据这块&#xff0c;我们已经有了很好的积累&#xff0c;因为在此之前&#xff0c;我们就开发了非常成熟的RTMP推送、轻量…

rsyslog出现Unit rsyslog.service is masked不可用问题解决

博主在测试将日志发送到日志服务器的功能时遇到了rsyslog服务不可用的问题&#xff0c;具体来说&#xff0c;就是执行systemctl restart rsyslog或者 service rsyslog restart命令时&#xff0c;出现了标题中所述的Unit rsyslog.service is masked问题。网上查找了很多资料&…

云服务器上部署 Web 项目及端口异常处理

文章目录 1. 在云服务器的 MySQL(MariaDB) 中, 建库建表2. 微调代码3. 打包4. 把 war 包 拷贝到云服务器上端口被占用处理 1. 在云服务器的 MySQL(MariaDB) 中, 建库建表 在云服务器中进入 MySQL mysql -u root -p把之前本地写好的 SQL 代码一粘贴即可 例如: -- 这个文件主要…

【Python】用三种方法创建tkinter桌面窗口

Python的tkinter是Python的标准GUI库之一&#xff0c;它是一个开源的、跨平台的GUI工具包&#xff0c;可以用于创建桌面应用程序。 tkinter提供了许多常见的GUI组件&#xff0c;例如按钮、文本框、标签、列表框等等&#xff0c;可以轻松地创建各种类型的桌面应用程序。它还支持…

go atexit源码分析

文章目录 atexit源码解析UML类图样例一: 程序退出之前执行注册函数1.1 流程图1.2 代码分析 样例二&#xff1a;使用cancel取消注册函数2.1 cancel流程图2.2 代码分析 样例三&#xff1a;使用Fatal/Fatalln/Fatal执行注册函数3.1 Fatal/Fatalln/Fatal流程图3.2 代码分析 atexit源…

什么是LASSO回归,怎么看懂LASSO回归的结果

随着机器学习的发展&#xff0c;越来越多SCI文章都使用了更多有趣、高效的统计方法来进行分析&#xff0c;LASSO回归就是其中之一。很多小伙伴听说过LASSO&#xff0c;但是对于LASSO是什么&#xff0c;有什么用&#xff0c;怎么才能实现&#xff0c;大家可能一头雾水。今天的文…

每日一题2023.11.26——个位数统计【PTA】

题目要求&#xff1a; 输入格式&#xff1a; 每个输入包含 1 个测试用例&#xff0c;即一个不超过 1000 位的正整数 N。 输出格式&#xff1a; 对 N 中每一种不同的个位数字&#xff0c;以 D:M 的格式在一行中输出该位数字 D 及其在 N 中出现的次数 M。要求按 D 的升序输出。…

【华为数通HCIP | 网络工程师】821-IGP高频题、易错题之OSPF(7)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

blender 3D眼球结构

角膜&#xff08;Cornea&#xff09;&#xff1a;眼球的前部&#xff0c;透明的曲面&#xff0c;负责折射光线。虹膜&#xff08;Iris&#xff09;&#xff1a;眼睛的颜色部分&#xff0c;控制瞳孔大小以调整进入眼睛的光量。瞳孔&#xff08;Pupil&#xff09;&#xff1a;虹膜…

S25FL系列FLASH读写的FPGA实现

文章目录 实现思路具体实现子模块实现top模块 测试Something 实现思路 建议读者先对 S25FL-S 系列 FLASH 进行了解&#xff0c;我之前的博文中有详细介绍。 笔者的芯片具体型号为 S25FL256SAGNFI00&#xff0c;存储容量 256Mb&#xff0c;增强高性能 EHPLC&#xff0c;4KB 与 6…

快速幂算法详解(C++实现)

文章目录 1. 什么是快速幂2. 暴力求解代码实现缺陷分析 3. 优化一&#xff1a;取模运算的性质4. 优化二&#xff1a;快速幂算法的核心思想5. 终极优化&#xff1a;位运算优化6. 源码 这篇文章我们来一起学习一个算法——快速幂算法。 1. 什么是快速幂 顾名思义&#xff0c;快速…

中海油“海安杯”一站到底知识竞赛真的很有特色

中海油“海安杯”一站到底知识竞赛规格高&#xff0c;赛制复杂&#xff0c;天纵知识竞赛系统为此次知识竞赛提供了软件支持。本次竞赛设置选手区和擂台区两个区域。比赛共分为五个轮次&#xff0c;五个轮次选手区所有参赛选手均需答题。 第一轮&#xff1a;“脱颖而出” 所有参…

叠加原理(superposition principle)

叠加原理&#xff08;superposition principle&#xff09;指对线性系统而言&#xff0c;两个或多个输入产生的输出&#xff0c;等于这几个输入单独引起的输出的和&#xff0c;即输入的叠加等于各输入单独引起的输出的叠加。 例如&#xff0c;如果输入产生的输出是&#xff0c;…

B树与B+树的对比

B树&#xff1a; m阶B树的核心特性&#xff1a; 树中每个节点至多有m棵子树&#xff0c;即至多含有m-1个关键字根节点的子树数属于[2, m]&#xff0c;关键字数属于[1, m-1]&#xff0c;其他节点的子树数属于 [ ⌈ m 2 ⌉ , m ] [\lceil \frac{m}{2}\rceil, m] [⌈2m​⌉,m]&am…

Spring的依赖注入,依赖注入的基本原则,依赖注入的优势

文章目录 Spring的依赖注入依赖注入的基本原则依赖注入有什么优势查找定位操作与应用代码完全无关。有哪些不同类型的依赖注入实现方式&#xff1f;构造器依赖注入和 Setter方法注入的区别 Spring的依赖注入 控制反转IoC是一个很大的概念&#xff0c;可以用不同的方式来实现。…

电子学会C/C++编程等级考试2022年09月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:统计误差范围内的数 统计一个整数序列中与指定数字m误差范围小于等于X的数的个数。 时间限制:5000 内存限制:65536输入 输入包含三行: 第一行为N,表示整数序列的长度(N <= 100); 第二行为N个整数,整数之间以一个空格分…

【教学类-06-12】20231126 (一)如何让加减乘除题目从小到大排序(以1-20之间加法为例,做正序排列用)

结果展示 优化后 优化前 背景需求&#xff1a; 生成列表 单独抽取显示题目排序方法 存在问题: 我希望 00 01 02……这样排序&#xff0c;但是实际上&#xff0c;除了第一个加数会从小到大排序&#xff0c;第二个被加数的第十位数和个位数都会从小到大排序&#xff0c;也就是…

定长子网划分和变长子网划分问题_二叉树解法_通俗易懂_配考研真题

引入:定长子网划分和变长子网划分的基本概念 定长子网划分和变长子网划分的基本概念 目前常用的子网划分&#xff0c;是基于CIDR的子网划分&#xff0c;也就是将给定的CIDR地址块划分为若干个较小的CIDR地址块。 定长子网划分: 使用同一个子网掩码来划分子网&#xff0c;因…

使用VC++设计程序对一幅256级灰度图像进行全局固定阈值分割、自适应阈值分割

图像分割–全局固定阈值分割、自适应阈值分割 获取源工程可访问gitee可在此工程的基础上进行学习。 该工程的其他文章&#xff1a; 01- 一元熵值、二维熵值 02- 图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像以及图像的旋转 03-邻域平均平滑算法、中值滤波算法、…

线性表,也是Java中数组的知识点!

线性表定义&#xff1a; 由n (n≥0)个数据特性相同的元素构成的有限序列称为线性表&#xff0c;(n0)的时候被称为空表。 线性表的顺序表示 线性表的顺序存储又被称为顺序表 优点 无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以随意读取任意位置的元素 缺点 插入…