ESP32-S3 控制 步进电机

ESP32-S3 控制 28BYJ-48 步进电机实验

一、实验简介

28BYJ-48 是一种常见的减速步进电机,配合 ULN2003 驱动模块使用,能够精确控制转动的角度与速度。

本实验中,我们使用 ESP32-S3 通过按键实现以下功能:

  • 按下 KEY1:切换电机旋转方向
  • 按下 KEY2:电机加速
  • 按下 KEY3:电机减速

二、硬件准备

  • ESP32-S3 开发板 × 1
  • ULN2003 驱动模块 × 1
  • 28BYJ-48 步进电机 × 1
  • 按键模块 × 1(4 个独立按键)
  • 杜邦线若干
  • USB 数据线 × 1

1. ULN2003 驱动模块

ULN2003是高耐压、大电流复合晶体管阵列,由七个硅NPN 复合晶体管组成,每一对达林顿都串联一个2.7K 的基极电阻,在5V 的工作电压下它能与TTL 和CMOS 电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。

LN2003也是一个7路反向器电路:

  • 即当输入端为高电平时,ULN2003输出端为低电平;
  • 当输入端为低电平时,ULN2003输出端为高电平。

ULN2003是一个非门电路,包含7个单元,单独每个单元驱动电流最大可达500mA,9脚可以悬空。比如1脚输入,16脚输出,你的负载接在VCC与16脚之间,不用9脚。

根据上面的原理,ULN2003的驱动应用电路的基本示例图,各个引脚的功能都标注在上面:

ULN2003示意图

一个实际例程的ULN2003的驱动应用电路:

ULN2003的驱动应用电路

整体看下来,一共接了四个负载:

  1. 继电器(1个IO口)
  2. 步进电机(4个IO口)
  3. 喇叭(1个IO口)
  4. 直流电机(1个IO口)

引脚1-7是输入信号;引脚10-16是输出信号,引脚8接地,引脚9接VCC。
引脚1输入RL信号,相对应的输出引脚16控制的是一个继电器。当引脚1输入高电平,引脚16输出低电平,继电器开启;
引脚2-5输入D、C、B、A信号,相对应的输出引脚15、14、13、12作为四相来控制四相五线步进电机;
引脚6输入SPK信号,相对应的输出引脚11控制的是一个喇叭。当引脚6输入高电平,引脚11输出低电平,喇叭开启;
引脚7输入M0T信号,相对应的输出引脚10控制的是一个直流电机。当引脚6输入高电平,引脚10输出低电平,直流电机启动。

2. 28BYJ-48 5V步进电机

上张 28BYJ-48 步进电机 的图

28BYJ-48步进电机

在这个步进电机内部有个 真正的步进马达转子。
每一个脉冲能使这个真正的转子转动5.625°;
看下图的数据表格中的减速比是1:64,意思是这个真正的步进马达转子转动64周才能让输出轴转动1周;
因此下图的表格中步距角度才写的是5.625°/64,表明的意思是一个脉冲可以让输出轴转动5.625°/64的角度。
所以要让马达转一周(360°), 则需要360/5.625*64=4096个脉冲。
脉冲(或拍)的数量决定转动的角度,单位时间内脉冲(或拍)的数量决定转动的速度。

28BYJ-48步进电机参数

步进电机是一种将电脉冲转化为角位移的执行机构。

通俗一点讲:当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。
可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;
同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

步进电机28BYJ48型 四相八拍电机,电压为DC5V—DC12V。
当对步进电机施加一系列连续不断的控制脉冲时,它可以连续不断地转动。
每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。
当通电状态的改变完成一个循环时,转子转过一个齿距。

3. 步进电机工作方式

五线四相步进电机内部原理图

五线四相步进电机内部原理图

四相步进电机可以在不同的通电方式下运行,常见的通电方式有如下三种:

  1. 工作方式1:单相4拍
  2. 工作方式2:双相4拍
  3. 工作方式3:一二相8拍

3种工作方式的脉冲图:

四相步进电机3种工作方式

3.1 工作方式1:单相4拍

单相4拍:1相通电,4种位置状态。
单相4拍工作方式,步进电机的输出信号为单相,每拍输出一个正弦波。

单相4拍工作方式

3.2 工作方式2:双相4拍

双相4拍:2相通电,4种位置状态。
双相4拍工作方式,步进电机的输出信号为双相,每拍输出一个正弦波。

双相4拍工作方式

3.3 工作方式3:一二相8拍

一二相8拍:1相通电、2相通电交替,8种位置状态。
一二相8拍工作方式,步进电机的输出信号为1相2相交替,每拍输出一个正弦波。

一二相8拍工作方式


三、接线说明

1. ESP32-S3 → ULN2003(步进电机驱动模块)

驱动模块引脚 ESP32-S3 引脚
IN1 GPIO9
IN2 GPIO10
IN3 GPIO11
IN4 GPIO12
VCC 5V
GND GND

2. ULN2003 → 28BYJ-48 步进电机

驱动模块引脚 电机线颜色
VCC 红线
O1~O4 蓝/粉/黄/橙

3. ESP32-S3 → 按键模块

按键名称 ESP32-S3 引脚
KEY1 GPIO1
KEY2 GPIO38
KEY3 GPIO39
KEY4 GPIO40

接线示意:

ESP32-S3 GPIO9  → IN1
ESP32-S3 GPIO10 → IN2
ESP32-S3 GPIO11 → IN3
ESP32-S3 GPIO12 → IN4
ESP32-S3 GPIO1  → KEY1
ESP32-S3 GPIO38 → KEY2
ESP32-S3 GPIO39 → KEY3
ESP32-S3 GPIO40 → KEY4

四、程序代码

代码由三个模块组成:

  • 主程序(控制流程)
  • key.cpp / key.h(按键扫描)
  • step_motor.cpp / step_motor.h(步进电机控制)

1. 主程序

#include "public.h"
#include "key.h"
#include "step_motor.h"

// 定义全局变量
u8 g_key = 0;
u8 g_dir = 0; // 默认逆时针方向
u8 g_speed = STEPMOTOR_MAXSPEED; // 默认最大速度
u8 g_step = 0;

void setup() {
  key_init();
  step_motor_init();
}

void loop() {
  g_key = key_scan(0);
  
  if(g_key == KEY1_PRESS) { // 换向
    g_dir = !g_dir;    
  }
  else if(g_key == KEY2_PRESS) { // 加速
    if(g_speed > STEPMOTOR_MAXSPEED)
      g_speed -= 1;     
  }
  else if(g_key == KEY3_PRESS) { // 减速
    if(g_speed < STEPMOTOR_MINSPEED)
      g_speed += 1;     
  }
  
  // 发送脉冲控制步进电机
  step_motor_28BYJ48_send_pulse(g_step++, g_dir);
  if(g_step == 8) g_step = 0;    
  
  delay(g_speed);
}

2. 按键模块(key.h / key.cpp)

key.h

#ifndef _key_H
#define _key_H

#include "public.h"

// 定义按键引脚
#define key1_pin  1
#define key2_pin  38
#define key3_pin  39
#define key4_pin  40

// 按键值定义
#define KEY1_PRESS  1
#define KEY2_PRESS  2
#define KEY3_PRESS  3
#define KEY4_PRESS  4
#define KEY_UNPRESS 0 

void key_init(void);
u8 key_scan(u8 mode);

#endif

key.cpp

#include "key.h"

void key_init(void) {
  pinMode(key1_pin, INPUT_PULLUP);
  pinMode(key2_pin, INPUT_PULLUP);
  pinMode(key3_pin, INPUT_PULLUP);
  pinMode(key4_pin, INPUT_PULLUP);
}

u8 key_scan(u8 mode) {
  static u8 key = 1;
  if(mode) key = 1; // 连续扫描
  
  if(key == 1 && (digitalRead(key1_pin) == 0 || digitalRead(key2_pin) == 0 || 
                  digitalRead(key3_pin) == 0 || digitalRead(key4_pin) == 0)) {
    delay(10); // 消抖
    key = 0;
    if(digitalRead(key1_pin) == 0) return KEY1_PRESS;
    else if(digitalRead(key2_pin) == 0) return KEY2_PRESS;
    else if(digitalRead(key3_pin) == 0) return KEY3_PRESS;
    else if(digitalRead(key4_pin) == 0) return KEY4_PRESS;
  }
  else if(digitalRead(key1_pin) == 1 && digitalRead(key2_pin) == 1 &&
          digitalRead(key3_pin) == 1 && digitalRead(key4_pin) == 1) {
    key = 1; // 按键释放
  }
  
  return KEY_UNPRESS;
}

3. 步进电机模块(step_motor.h / step_motor.cpp)

step_motor.h

#ifndef _step_motor_H
#define _step_motor_H

#include "public.h"

#define ina_pin  9
#define inb_pin  10
#define inc_pin  11
#define ind_pin  12

#define STEPMOTOR_MAXSPEED  1  
#define STEPMOTOR_MINSPEED  5 

void step_motor_init(void);
void step_motor_28BYJ48_send_pulse(u8 step,u8 dir);

#endif

step_motor.cpp

#include "step_motor.h"

void step_motor_init(void) {
  pinMode(ina_pin, OUTPUT);
  pinMode(inb_pin, OUTPUT);
  pinMode(inc_pin, OUTPUT);
  pinMode(ind_pin, OUTPUT);
}

void step_motor_28BYJ48_send_pulse(u8 step,u8 dir) {
  u8 temp = step;
  if(dir == 0) temp = 7 - step; // 逆时针调换节拍
  
  switch(temp) {
    case 0: digitalWrite(ina_pin,1); digitalWrite(inb_pin,0); digitalWrite(inc_pin,0); digitalWrite(ind_pin,0); break;
    case 1: digitalWrite(ina_pin,1); digitalWrite(inb_pin,1); digitalWrite(inc_pin,0); digitalWrite(ind_pin,0); break;
    case 2: digitalWrite(ina_pin,0); digitalWrite(inb_pin,1); digitalWrite(inc_pin,0); digitalWrite(ind_pin,0); break;
    case 3: digitalWrite(ina_pin,0); digitalWrite(inb_pin,1); digitalWrite(inc_pin,1); digitalWrite(ind_pin,0); break;
    case 4: digitalWrite(ina_pin,0); digitalWrite(inb_pin,0); digitalWrite(inc_pin,1); digitalWrite(ind_pin,0); break;
    case 5: digitalWrite(ina_pin,0); digitalWrite(inb_pin,0); digitalWrite(inc_pin,1); digitalWrite(ind_pin,1); break;
    case 6: digitalWrite(ina_pin,0); digitalWrite(inb_pin,0); digitalWrite(inc_pin,0); digitalWrite(ind_pin,1); break;
    case 7: digitalWrite(ina_pin,1); digitalWrite(inb_pin,0); digitalWrite(inc_pin,0); digitalWrite(ind_pin,1); break;
    default: digitalWrite(ina_pin,0); digitalWrite(inb_pin,0); digitalWrite(inc_pin,0); digitalWrite(ind_pin,0); break;
  }     
}

五、实验现象

  1. 程序烧录到 ESP32-S3 后,步进电机开始旋转。
  2. KEY1:切换旋转方向(顺时针 / 逆时针)。
  3. KEY2:加快转速。
  4. KEY3:减慢转速。

六、注意事项

  • 电机电源建议使用独立 5V 供电,避免 ESP32-S3 供电不足导致复位。
  • 步进电机速度不能过快,否则会丢步或停转。
  • 按键模块需接地,并使用 INPUT_PULLUP 模式。

七、总结

通过本实验,我们掌握了 ESP32-S3 控制步进电机的基本方法,并实现了按键换向、加减速等功能。
在实际应用中,还可以加入:

  • 位置计数(实现精准角度控制)
  • PWM 微步驱动(提高运行平稳度)
  • 限位开关(实现自动回零)
posted @ 2025-08-16 09:38  jeikerxiao  阅读(345)  评论(0)    收藏  举报