【28BYJ-48步进电机:开启你的创新之旅】

1.28BYJ-48步进电机的控制

自带减速器,五线四相单极性,直径为28mm。一般有五根线。红色是公共的VCC(5v),A相蓝色,B相粉色,C相黄色,D相橙色。如果采用单双拍如图所示:

第一步:先D相导通接GND,其他接高电平。第二部:D,C相导通接GND其他接高电平。一次走完8步。如果对应MCU那么红色接VCC(5V),其他四相接MCU的普通I/o并且选择推挽输出。如果让电机反转则把步数反过来。注意每一步的切换都要延时一段时间。

2.28BYJ-48步进电机的主要参数

首先相电阻就是公共端与每相之间的电阻。 步距角有两种情况。没有加减速比的时候。5.625度。

加减速比就是5.625/ 64。 因为减速比是1:64。启动频率>=500。

一个脉冲电机转5.625度。一圈(360)= 360/ 5.625 = 64个脉冲。那么减速后轴转一圈需要64 *64  = 4096.当然减速比不可能精确1:64.总有误差存在。28BYJ-48步进电机实际上是:减速齿轮+步进电机组成。内部减速齿轮如下

 由于MCU的端口的电流很小对于驱动电流大的外设需要驱动板(放大电流)。

电机需要驱动的电流 VCC/ 相电阻 = 5 / 300 =16.7mA。

ULN2003是大电流达林顿晶体管阵列系列产品,具有电流增益高、工作电压高、温度范围宽、带负载能力强等特点,适应于各类要求高速大功率驱动的系统。ULN2003A由7组达林顿晶体管阵列和相应的电阻网络以及钳位二极管网络构成,具有同时驱动7组负载的能力,为单片双极型大功率高速集成电路。ULN2003可用于小型步进电机驱动。

 

 下面如图接线方法:

 ULN2003_IN1, ULN2003_IN2,ULN2003_IN3,ULN2003_IN4左边接MCU的I/o口,经过ULN2003AD后电流就放大了从而去驱动电机。

3.28BYJ-48步进电机转动。

1.28BYJ-48步进电机基本转动

uln2003.h

#ifndef __BSP_ULN2003_H__
#define __BSP_ULN2003_H__

#include "stm32f4xx_hal.h"

#define ULN2003_RCC_CLK_ENABLE()         __HAL_RCC_GPIOF_CLK_ENABLE()
#define ULN2003_GPIO_PIN                 (GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6)
#define ULN2003_GPIO_PORT                GPIOF

#define A_ON                             HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_3,GPIO_PIN_SET)
#define A_OFF                            HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_3,GPIO_PIN_RESET)
#define B_ON                             HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_4,GPIO_PIN_SET)
#define B_OFF                            HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_4,GPIO_PIN_RESET)
#define C_ON                             HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_5,GPIO_PIN_SET)
#define C_OFF                            HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_5,GPIO_PIN_RESET)
#define D_ON                             HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_6,GPIO_PIN_SET)
#define D_OFF                            HAL_GPIO_WritePin(ULN2003_GPIO_PORT,GPIO_PIN_6,GPIO_PIN_RESET)


void ULN2003_GPIO_Init(void);

#endif  // __BSP_ULN2003_H__

uln2003.c

#include "StepMotor/bsp_uln2003.h"

void ULN2003_GPIO_Init(void)
{
   /* 定义IO硬件初始化结构体变量 */
  GPIO_InitTypeDef GPIO_InitStruct;
	
	/* 使能(开启)端口时钟 */  
  ULN2003_RCC_CLK_ENABLE();
  
  /* 一开始设置为低电平 */
  HAL_GPIO_WritePin(ULN2003_GPIO_PORT,ULN2003_GPIO_PIN,GPIO_PIN_RESET);
  
  /* 设定引脚IO编号 */
  GPIO_InitStruct.Pin = ULN2003_GPIO_PIN;
  /* 设定引脚IO为输出模式 */
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;   // 推挽输出
  /* 设定引脚IO操作速度 */
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  /* 初始化引脚IO */
  HAL_GPIO_Init(ULN2003_GPIO_PORT, &GPIO_InitStruct);
}

main.c

#include "stm32f4xx_hal.h"
#include "StepMotor/bsp_uln2003.h"

#define STEPMOTOR_SPEED           10     // 定义步进电机速度,值越小,速度越快

void SystemClock_Config(void);



/**
  * 函数功能: 系统时钟配置
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
  __HAL_RCC_PWR_CLK_ENABLE();                                     // 使能PWR时钟

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);  // 设置调压器输出电压级别1

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;      // 外部晶振,8MHz
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;                        // 打开HSE 
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                    // 打开PLL
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;            // PLL时钟源选择HSE
  RCC_OscInitStruct.PLL.PLLM = 8;                                 // 8分频MHz
  RCC_OscInitStruct.PLL.PLLN = 336;                               // 336倍频
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                     // 2分频,得到168MHz主时钟
  RCC_OscInitStruct.PLL.PLLQ = 7;                                 // USB/SDIO/随机数产生器等的主PLL分频系数
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:168MHz
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟: 168MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;               // APB1时钟:42MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;               // APB2时钟:84MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

  HAL_RCC_EnableCSS();                                            // 使能CSS功能,优先使用外部晶振,内部时钟源为备用
  
 	// HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
	// HAL_RCC_GetHCLKFreq()/100000	 10us中断一次
	// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);                 // 配置并启动系统滴答定时器
  /* 系统滴答定时器时钟源 */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* 系统滴答定时器中断优先级配置 */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{  
  uint8_t i=0;
  
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();
  
  ULN2003_GPIO_Init();
  
  /* 无限循环 */
  while (1)
  {
    // 8个节拍控制:A->AB->B->BC->C->CD->D->DA 正转  如果反过来可以反转   2.这个可以控制方向
    switch(i)
    {
      case 0:
        A_ON;  B_OFF; C_OFF; D_OFF;
      break;
      case 1:
        A_ON;  B_ON;  C_OFF; D_OFF;
      break;
      case 2:
        A_OFF; B_ON;  C_OFF; D_OFF;
      break;
      case 3:
        A_OFF; B_ON;  C_ON;  D_OFF;
      break;
      case 4:
        A_OFF; B_OFF; C_ON;  D_OFF;
      break;
      case 5:
        A_OFF; B_OFF; C_ON;  D_ON;
      break;
      case 6:
        A_OFF; B_OFF; C_OFF; D_ON;
      break;
      case 7:
        A_ON;  B_OFF; C_OFF; D_ON;
      break;
    }
    i++;                          // 步进加1
    if(i==8) i=0;                 // 重新开始循环步进
    HAL_Delay(STEPMOTOR_SPEED);   // 延时一小段时间,时间长短决定电机转速     1.这个延时可以控制速度
  }
}


 这里公共端是接GDN,所以某相接高低平就接通,并且这里采用单双拍工作方式。每一步切换都有一个延时,这个延时可以控制速度。改变步数的顺序可以控制方向。

2.28BYJ-48步进电机旋转控制 

uln2003.h uln2003.c跟上面一样,只是main.c不同,并且加了按键控制。

main.c

#include "stm32f4xx_hal.h"
#include "StepMotor/bsp_uln2003.h"
#include "key/bsp_key.h"

#define STEPMOTOR_SPEED               1    // 定义步进电机速度,值越小,速度越快
                                          
                                           
#define STEPMOTOR_CIRCLE_NUMBER       10   // 转动圈数

#define STEPMOTOR_DIRECTION           1    // 1:顺时针  0:逆时针


uint8_t speed = STEPMOTOR_SPEED;      // 用一个变量保存速度

// 转动圈数:28BYJ-48步进电机的步距角度为5.625/64,即每64个脉冲转5.625度
// 要转一圈需要360/5.625*64=4096个脉冲。 // 没有减速:一个脉冲 转 5.625 如果转360 要64个脉冲   减速后:因为减速比是1:64  轴需要 64 *64 =4096个脉冲  
    
uint32_t Circle_number= 0;          // 圈数
// 选择方向控制
uint8_t direction = STEPMOTOR_DIRECTION;  // 用一个变量保存方向

void SystemClock_Config(void);

/**
  * 函数功能: 系统时钟配置
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
  __HAL_RCC_PWR_CLK_ENABLE();                                     // 使能PWR时钟

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);  // 设置调压器输出电压级别1

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;      // 外部晶振,8MHz
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;                        // 打开HSE 
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                    // 打开PLL
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;            // PLL时钟源选择HSE
  RCC_OscInitStruct.PLL.PLLM = 8;                                 // 8分频MHz
  RCC_OscInitStruct.PLL.PLLN = 336;                               // 336倍频
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                     // 2分频,得到168MHz主时钟
  RCC_OscInitStruct.PLL.PLLQ = 7;                                 // USB/SDIO/随机数产生器等的主PLL分频系数
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:168MHz
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB时钟: 168MHz
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;               // APB1时钟:42MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;               // APB2时钟:84MHz
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

  HAL_RCC_EnableCSS();                                            // 使能CSS功能,优先使用外部晶振,内部时钟源为备用
  
 	// HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
	// HAL_RCC_GetHCLKFreq()/100000	 10us中断一次
	// HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);                 // 配置并启动系统滴答定时器
  /* 系统滴答定时器时钟源 */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* 系统滴答定时器中断优先级配置 */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/**
  * 函数功能: 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
  * 输入参数: step:指定步进序号,可选值0~7
  *           direction:方向选择
  *               可选值:1:顺时针
  *                       0:逆时针
  * 返 回 值: 无
  * 说    明: 无
  */
static void step_motor_pulse(uint8_t step,uint8_t direction)
{
  uint8_t temp=step;
  
  if(direction==0)    // 如果为逆时针旋转
  {
    temp=7-step;      // 调换节拍信号
  }
  switch(temp)
  {
    // 8个节拍控制:A->AB->B->BC->C->CD->D->DA
    case 0:
      A_ON;  B_OFF; C_OFF; D_OFF;
    break;
    case 1:
      A_ON;  B_ON;  C_OFF; D_OFF;
    break;
    case 2:
      A_OFF; B_ON;  C_OFF; D_OFF;
    break;
    case 3:
      A_OFF; B_ON;  C_ON;  D_OFF;
    break;
    case 4:
      A_OFF; B_OFF; C_ON;  D_OFF;
    break;
    case 5:
      A_OFF; B_OFF; C_ON;  D_ON;
    break;
    case 6:
      A_OFF; B_OFF; C_OFF; D_ON;
    break;
    case 7:
      A_ON;  B_OFF; C_OFF; D_ON;
    break;
  }
}


/**
  * 函数功能: 主函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 无
  */
int main(void)
{    
  /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  HAL_Init();
  /* 配置系统时钟 */
  SystemClock_Config();
  
  KEY_GPIO_Init();
  
  ULN2003_GPIO_Init();
  
  /* 无限循环 */
  while (1)
  {
    if(KEY1_StateRead()==KEY_DOWN)
    {
      direction=1; // 顺时针方向
      Circle_number=STEPMOTOR_CIRCLE_NUMBER;//赋值给目标旋转圈数,重新开始旋转
    }
    if(KEY2_StateRead()==KEY_DOWN)
    {
      direction=0; // 逆时针方向
      Circle_number=STEPMOTOR_CIRCLE_NUMBER;//赋值给目标旋转圈数,重新开始旋转
    }
    if(KEY3_StateRead() == KEY_DOWN) // 加速
    {
      speed --;
      if(speed <= STEPMOTOR_SPEED)
        speed = STEPMOTOR_SPEED;
    }
    if(KEY4_StateRead() == KEY_DOWN) // 减速
    {
      speed ++;
    }
  }
}
/**
  * 函数功能: 滴答定时器回调函数.
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 每隔一定的时间就输出新节拍信号
  */
void HAL_SYSTICK_Callback(void) 
{
  static uint8_t count=0;               // 用于旋转速度控制
  
  static uint8_t step=0;                // 当前步进节拍
  
  static uint16_t pulse_count=0;        // 脉冲计数,4096个脉冲电机旋转一圈
  
  if(Circle_number)                     // 如果等待旋转圈数不为0
  {
    count++;                            // 增加时间计数
    if(count==speed)                    // 时间计数与目标速度相对时执行下一节拍输出 // 旋转一圈要 4096ms *speed
    {
      step_motor_pulse(step,direction); // 输出新节拍信号
      
      pulse_count++;                    // 脉冲输出数增加      
      step++;                           // 节拍数增加
      if(step==8) step=0;               // 循环开始输出节拍
      count=0;                          // 清零时间计数
    }
    
    if(pulse_count==4096)               // 如果已经输出了4096个脉冲信号,已经转动了一圈
    {
      pulse_count=0;                    // 脉冲计数清零
      
      Circle_number--;                  // 等待旋转圈数减1
    }
  }
  else  // 转完设置的圈数停止旋转
  {
    A_OFF;  B_OFF; C_OFF; D_OFF;        // 停机 
  }
}

物联沃分享整理
物联沃-IOTWORD物联网 » 【28BYJ-48步进电机:开启你的创新之旅】

发表评论