stm32 42步进电机 上位机示例

news/2024/7/23 11:23:00 标签: stm32, 嵌入式硬件, 单片机

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

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

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

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

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

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

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

思路就是stm32一直给步进电机发脉冲,然后通过驱动器驱动步进电机转动,这个项目多了一个qt发送串口消息给stm32stm32接收对应的命令然后执行不同的函数,但是这样无法实现步进电机的反馈,无法实现限位,回零等功能。
不过目前可以实现步进电机转动度数的控制,因为实物没负载也没测试有没有丢步的现象,还能实现正反转
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.niftyadmin.cn/n/5215939.html

相关文章

ps5ps4游戏室如何计时?计费系统怎么查看游戏时间以及收费如何管理

ps5ps4游戏室如何计时&#xff1f;计费系统怎么查看游戏时间以及收费如何管理 1、ps5ps4游戏室如何计时&#xff1f; 下图以佳易王计时计费软件V17.9为例说明 在开始计时的时候&#xff0c;只需点 开始计时按钮&#xff0c;那么开台时间和使用的时间长度项目显示在屏幕上&am…

【图像加密】Arnold置乱和混沌加密-MATLAB代码

Arnold Arnold.m function [img_new] Arnold(a,b,h,w,n,img) % h64; % w64;img_new zeros(h,w) ; %[h, w]size(img) % a 5; % b 6; % n 16; %n为置乱轮数N h;for i1:nfor y1:hfor x1:wxxmod((x-1)b*(y-1),N)1; %a,b可提前指定yymod(a*(x-1)(a*…

叠加原理(superposition principle)、线性系统

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

【数据结构】什么是队列?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;队列的定义 &#x1f4cc;队列的抽象数据类型 &#x1f4cc;队列的顺序存储结构 &#x1f4cc;队列的链式存储结构 结语 人生,是一个又一个小小的队列…

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

C/C++等级考试(1~8级)全部真题・点这里 第1题:数字字符求和 请编写一个程序实现以下功能:从一个字符串中,提取出所有的数字字符即0-9,并作为数求和。 时间限制:1000 内存限制:65536输入 一行字符串,长度不超过100,字符串中不含空格。输出 字符串中所有数字字符作为数…

【Linux】系统初始化配置

CentOS 7 的虚拟机安装后必须要做的几个操作&#xff0c;记录以下&#xff0c;网络配置修改、yum源安装、基础工具安装&#xff1a; 1、先修改权限&#xff0c;新建普通用户&#xff0c;并授权普通用户apps 的sudo权限&#xff1b; useradd apps password apps visudo apps A…

力控软件与多台PLC之间ModbusTCP/IP无线通信

Modbus TCP/IP 是对成熟的 Modbus 协议的改编&#xff0c; 因其开放性、简单性和广泛接受性而在工业自动化系统中发挥着举足轻重的作用。它作为连接各种工业设备的通用通信协议&#xff0c;包括可编程逻辑控制器 (PLC)、远程终端单元 (RTU) 和传感器。它提供标准化的 TCP 接口&…

洛谷P1047题 校门外的树

[NOIP2005 普及组] 校门外的树 题目描述 某校大门外长度为 l l l 的马路上有一排树&#xff0c;每两棵相邻的树之间的间隔都是 1 1 1 米。我们可以把马路看成一个数轴&#xff0c;马路的一端在数轴 0 0 0 的位置&#xff0c;另一端在 l l l 的位置&#xff1b;数轴上的每…