步进电机28BYJ-48

步进电机

1. 步进电机原理

步进电机:是数字控制电机,它将脉冲信号转变成角位移,即给一个脉冲信号,步进电机就转动一个角度。

步进电机可分为反应式步进电机(简称VR)、永磁式步进电机(简称PM)和混合式步进电机(简称HB),后两种常用。

步进电机控制特点:

  1. 它是通过输入脉冲信号来进行控制的
  2. 电机的总转动角度由输入脉冲数决定
  3. 电机的转速由脉冲信号频率决定

2. 步进电机28BYJ-48

2.1 介绍

28BYJ-48 步进电机

28:步进电机的有效最大外径是28毫米
B:表示是步进电机
Y:表示是永磁式
J:表示是减速型(减速比1:64)
48:可以四拍、八拍运行

在这里插入图片描述

28BYJ-48 的内部结构示意图如下所示。转子上面有6个齿,分别标注为0~5,转子的每个齿上都带有一块永磁体。

定子跟电机的外壳固定在一起的,它上面有8个齿,而每个齿上都缠上了一个线圈绕组,正对的2个齿上的绕组串联在一起的,这2个绕组总是会同时导通或关断的,如此就形成了4相,在图中分别标注为 A-B-C-D,这就是4相的概念。

28BY-J48步进电机结构

工作原理: 假定电机的起始状态就如示意所示,逆时针方向转动,起始时B相绕组的开关闭合,B 相绕组导通,那么导通电流就会在正上和正下两个定子齿上产生磁性,这两个定子齿上的磁性就会对转子上的0和3号齿产生最强的吸引力,就会如图所示的那样,转子的0号齿在正上、3号齿在正下而处于平衡状态;此时我们会发现,转子的1号齿与右上的定子齿也就是 C 相的一个绕组呈现一个很小的夹角,2号齿与右边的定子齿也就是 D 相绕组呈现一个稍微大一点的夹角,很明显这个夹角是1号齿和 C 绕组夹角的2倍,同理,左侧的情况也是一样的。

接下来,我们把 B 相绕组断开,而使 C 相绕组导通,那么很明显,右上的定子齿将对转子1号齿产生最大的吸引力,而左下的定子齿将对转子4号齿,产生最大的吸引力,在这个吸引力的作用下,转子1、4号齿将对齐到右上和左下的定子齿上而保持平衡,如此,转子就转过了起始状态时1号齿和 C 相绕组那个夹角的角度。

再接下来,断开 C 相绕组,导通 D 相绕组,过程与上述的情况完全相同,最终将使转子2、5号齿与定子 D 相绕组对齐,转子又转过了上述同样的角度。

那么很明显,当 A 相绕组再次导通,即完成一个 B-C-D-A 的四节拍操作后,转子的0、3号齿将由原来的对齐到上下2个定子齿,而变为了对齐到左上和右下的两个定子齿上,即转子转过了一个定子齿的角度。依此类推,再来一个四节拍,转子就将再转过一个齿的角度,8个四节拍以后转子将转过完整的一圈,而其中单个节拍使转子转过的角度就很容易计算出来了,即360度/(8*4)=11.25度,这个值就叫做步进角度。而上述这种工作模式就是步进电机的单四拍模式——单相绕组通电四节拍。

我们再来讲解一种具有更优性能的工作模式,那就是在单四拍的每两个节拍之间再插入一个双绕组导通的中间节拍,组成八拍模式。比如,在从 B 相导通到 C 项导通的过程中,假如一个 B 相和 C 相同时导通的节拍,这个时候,由于 B、C 两个绕组的定子齿对它们附近的转子齿同时产生相同的吸引力,这将导致这两个转子齿的中心线对比到 B、C 两个绕组的中心线上,也就是新插入的这个节拍使转子转过了上述单四拍模式中步进角度的一半,即5.625度。这样一来,就使转动精度增加了一倍,而转子转动一圈则需要8*8=64拍了。另外,新增加的这个中间节拍,还会在原来单四拍的两个节拍引力之间又加了一把引力,从而可以大大增加电机的整体扭力输出,使电机更“有劲”了。

除了上述的单四拍和八拍的工作模式外,还有一个双四拍的工作模式——双绕组通电四节拍。其实就是把八拍模式中的两个绕组同时通电的那四拍单独拿出来,而舍弃掉单绕组通电的那四拍而已。其步进角度同单四拍是一样的,但由于它是两个绕组同时导通,所以扭矩会比单四拍模式大。

八拍模式是这类4相步进电机的最佳工作模式,能最大限度的发挥电机的各项性能,也是绝大多数实际工程中所选择的模式。

接下来,我们来了解“永磁式减速步进电机”中这个“减速”的概念了。下图是这个 28BYJ-48 步进电机的拆解图,从图中可以看到,位于最中心的那个白色小齿轮才是步进电机的转子输出,64个节拍只是让这个小齿轮转了一圈,然后它带动那个浅蓝色的大齿轮,这就是一级减速。大家看一下右上方的白色齿轮的结构,除电机转子和最终输出轴外的3个传动齿轮都是这样的结构,由一层多齿和一层少齿构成,而每一个齿轮都用自己的少齿层去驱动下一个齿轮的多齿层,这样每2个齿轮都构成一级减速,一共就有了4级减速,那么总的减速比是多少呢?即转子要转多少圈最终输出轴才转一圈呢?

回头看一下电机参数表中的减速比这个参数吧——1:64,转子转64圈,最终输出轴才会转一圈,也就是需要64×64=4096个节拍输出轴才转过一圈。4096个节拍转动一圈,那么一个节拍转动的角度——步进角度就是360/4096,看一下表中的步进角度参数5.625/64,算一下就知道这两个值是相等的,一切都已吻合了。

关于基本的控制原理本该到这里就全部结束了,但是不管是哪个厂家生产的电机,只要型号是 28BYJ-48,其标称的减速比就都是1:64。但实际上呢?经过拆解计算发现:真实准确的减速比并不是这个值1:64,而是1:63.684!得出这个数据的方法也很简单,实际数一下每个齿轮的齿数,然后将各级减速比相乘,就可以得出结果了,实测的减速比为(32/9)(22/11)(26/9)(31/10)≈63.684,从而得出实际误差为0.0049,即约为百分之0.5,转100圈就会差出半圈。

那么按照1:63.684 的实际减速比,可以得出转过一圈所需要节拍数是6463.684≈4076。但实际上误差还是存在的,因为上面的计算结果都是约等得出的,实际误差大约是0.000056,即万分之0.56,转一万圈才会差出半圈,已经可以忽略不计了。

八拍:(A-AB-B-BC-C-CD-D-DA-A)
在这里插入图片描述

#include "../BSP/bsp_28bjy48/bsp_28bjy48.h"


typedef struct BSPPIN_STRUCT
{
  GPIO_TypeDef *GPIO_Port; //  端口
  uint16_t GPIO_Pin;  //  管脚
}PIN_STRUCT;

#define MOTOR_PIN_COUNT 4

PIN_STRUCT g_sPinIndex[MOTOR_PIN_COUNT] = 
{
  {GPIOA, GPIO_PIN_0},
  {GPIOA, GPIO_PIN_1},
  {GPIOA, GPIO_PIN_2},
  {GPIOA, GPIO_PIN_3},
};


void bsp_MotorGpioInit(void)
{
}


static void bsp_MotorStop(void)
{
  for(uint8_t i = 0; i < MOTOR_PIN_COUNT; i++)
  {
    HAL_GPIO_WritePin(g_sPinIndex[i].GPIO_Port, g_sPinIndex[i].GPIO_Pin, GPIO_PIN_RESET);
  }
}

static void bsp_OpenSingle(uint8_t Pin)
{
  for(uint8_t i = 0; i < MOTOR_PIN_COUNT; i++)
  {
    if(i == Pin)
    {
       HAL_GPIO_WritePin(g_sPinIndex[i].GPIO_Port, g_sPinIndex[i].GPIO_Pin, GPIO_PIN_SET);
    }
    else
    {
      HAL_GPIO_WritePin(g_sPinIndex[i].GPIO_Port, g_sPinIndex[i].GPIO_Pin, GPIO_PIN_RESET);
    }
  }
}

/**
  * 4拍单相驱动
  */
void bsp_MotorSingleStep(uint8_t PinName, uint16_t ms)
{
  bsp_OpenSingle(PinName);
	HAL_Delay(ms);	        // 延时,控制电机速度
	bsp_MotorStop();				// 断电,防止电机过热
}

/**
  * 四拍
  */
void bsp_MotorSingleFour(uint8_t direction, uint32_t step, uint16_t ms)
{
  for(uint32_t j = 0; j < step; j++)
  {
    if(direction == 1)
    {
      for(uint8_t i = 0; i < MOTOR_PIN_COUNT; i++)
      {
        bsp_MotorSingleStep(i, ms);
      }
    }
    else
    {
      for(uint8_t i = MOTOR_PIN_COUNT; i > 0; i--)
      {
        bsp_MotorSingleStep((i-1), ms);
      }
    }
  }
}

/**
  * 八拍单节拍
  * step 节拍序号
  */
void bsp_MotorSingleEightStep(uint8_t step)
{
  switch(step)
    {
      case 0:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_RESET);
        break;
      
      case 1:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_RESET);
        break;
      
      case 2:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_RESET);
        break;
      
      case 3:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_RESET);
        break;
      
      case 4:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_RESET);
        break;
      
      case 5:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_SET);
        break;
      
      case 6:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_SET);
        break;
      
      case 7:
      HAL_GPIO_WritePin(g_sPinIndex[0].GPIO_Port, g_sPinIndex[0].GPIO_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(g_sPinIndex[1].GPIO_Port, g_sPinIndex[1].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[2].GPIO_Port, g_sPinIndex[2].GPIO_Pin, GPIO_PIN_RESET);
      HAL_GPIO_WritePin(g_sPinIndex[3].GPIO_Port, g_sPinIndex[3].GPIO_Pin, GPIO_PIN_SET);
        break;
      default:
        bsp_MotorStop();
        break;
    }
}
/**
  * 八拍
  * direction 方向
  * step 节拍数
  * ms  频率
  */
void bsp_MotorSingleEight(uint8_t direction, uint32_t step, uint16_t ms)
{
  for(uint32_t j = 0; j < step; j++)
  {
    if(direction == 0)
    {
      for(uint8_t i = 0; i < 8; i++)
      {
        bsp_MotorSingleEightStep(i);
        HAL_Delay(ms);
      }
    }
    else
    {
      for(uint8_t i = 8; i > 0; i--)
      {
        bsp_MotorSingleEightStep(i-1);
        HAL_Delay(ms);
      }
    }
  }
}



  • 3
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值