HAL库配置STM32F1系列PWM驱动步进电机(二)

接着上一篇,我要先补完利用PWM对步进电机进行调速的实验

PWM主要有两大要素:频率&占空比

频率

简单来说就是信号在1s内由高电平跳转到低电平再跳转回高电平的次数,一高一低再一高,这便是一个脉冲,一个脉冲对应一个步距角,一般步进电机的步距角分为1.8°和0.9°,因此我们需要转动多少°只需要调节脉冲数即可,而步进电机的转速则是受到脉冲发送频率的影响

占空比

占空比就是在一个PWM周期中高电平占整个周期的比值,一个PWM周期即为1/PWM频率,对于直流电机来说,其是由正负极控制运动,因此占空比越大电机转速越快,对于步进电机来说占空比影响的是电机的转矩,如果占空比过小可能会出现电机无法转动的情况

电机驱动

现在再重新细说一下电机驱动的原理,这里由L298N为例

步进电机工作原理

这是一个二相四线电机,其分为转子和定子,在二者上带有均分的小齿,不妨假设转子齿数为60,定子齿数为40(每个磁极的极弧上有10个小齿),这样定子上的齿距为θ = 360°/60 = 6°

不难得出这样的设计会发生齿错位现象,即当定子A的某一齿对准转子齿时,B相的齿就会与转子偏移[(60-40)/40]*θ = 3°,因此每个通电脉冲驱动电机转动3°,按照一定的节拍规律就可以实现电机的正转反转以及角度。而驱动四线两相电机,四个状态为1、AB正电压;2、A-B正电压;3、A-B-正电压;4、AB-正电压。也就是说我们只需要控制4个IO的电平信号就可以实现对电机的控制

L298N电机驱动

考虑到我之前用的智控驱动集成度过高,不适合初学的我学习,我找了一个很常见的电机驱动模块

L298N是意法半导体集团旗下量产的一种电机驱动芯片,拥有工作电压高、输出电流大、驱动能力强、发热量低、抗干扰能力强等特点,通常用来驱动继电器、螺线管、电磁阀、直流电机以及步进电机。

具体信息可以翻阅芯片手册

回到我们的红板模块上

其由一个L298N电机驱动芯片以及78M05稳压芯片组成,前者用于驱动电机,后者提供电流过热保护,对应引脚如下,详情可以跳转这个链接查看L298N 电机驱动板 - 详细介绍 - 知乎 (zhihu.com)

 

 这款芯片模块可以带两个直流电机或者一个二相四线步进电机,这里标出的接口指的是步进电机的接线

如果是正常驱动电机,则ENA和ENB的两个跳线帽都不用拔掉,若要通过PWM波进行驱动,则需要将PWM通道接到ENA靠近丝印一侧的引脚上

 工程以及代码

建立工程

这样就可以生成工程了 

代码部分

​
#define L298NA1(state) HAL_GPIO_WritePin(GPIOF,GPIO_PIN_7,state)
#define L298NA2(state) HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,state)
#define L298NB1(state) HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,state)
#define L298NB2(state) HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,state)
//定义信号线对应到电机的每个节拍号

​
void Pulse(unsigned char nInputData ,unsigned char nDirection)    //电机走一个步距角(四个节拍)
{
  if(nDirection == 1)
  {
    switch (nInputData) {
      case 1:
      {
        L298NA1(0);
        L298NA2(1);
        L298NB1(0);
        L298NB2(1);
      }
        break;
      case 2:
      {
        L298NA1(0);
        L298NA2(1);
        L298NB1(1);
        L298NB2(0);
      }
        break;
      case 3:
      {
        L298NA1(1);
        L298NA2(0);
        L298NB1(1);
        L298NB2(0);
      }
        break;
      case 4:
      {
        L298NA1(1);
        L298NA2(0);
        L298NB1(0);
        L298NB2(1);
      }
        break;
    }
  }
  else if(nDirection == 0)
  {
    switch (nInputData) {
      case 1:
      {
        L298NA1(1);
        L298NA2(0);
        L298NB1(0);
        L298NB2(1);
      }
        break;
      case 2:
      {
        L298NA1(1);
        L298NA2(0);
        L298NB1(1);
        L298NB2(0);
      }
        break;
      case 3:
      {
        L298NA1(0);
        L298NA2(1);
        L298NB1(1);
        L298NB2(0);
      }
        break;
      case 4:
      {
        L298NA1(0);
        L298NA2(1);
        L298NB1(0);
        L298NB2(1);
      }
        break;
    }
  }
}
uint8_t Key_on()    //按键检测
{
  uint8_t KeyNum=0;
  if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==RESET)
  {
    HAL_Delay(20);
    KeyNum = 1;
  }
  if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==RESET)
  {
    HAL_Delay(20);
    KeyNum = 2;
  }
  return KeyNum;
}
void Motor_Start(unsigned char n,unsigned char nDirection)    //电机启动函数,n代表要走多少个步距角,dir代表方向
{
  uint16_t i;
  uint8_t j;
  for(i=0;i<=n;i++)
  {
    for(j=0;j<=4;j++)
    {
      Pulse(j,nDirection);
      HAL_Delay(2);
    }
  }
}
void Motor_Start_PWM(unsigned char nDirection)    //PWM模式。调用前要先打开PWM通道
{
  uint8_t j;
    for(j=0;j<=4;j++)
    {
      Pulse(j,nDirection);
      HAL_Delay(2);
    }
}
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint16_t arr;   //初始化存储装载值变量
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);    //打开PWM通道
  arr = __HAL_TIM_GET_AUTORELOAD(&htim3);   //获取当前装载值
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    Key = Key_on();   //检测按键
    switch (Key)    //对应模式
    {
      case 1:dir = !dir;Key = 0;break;    //翻转方向
      case 2:
        arr += 50;
        __HAL_TIM_SET_AUTORELOAD(&htim3,arr);   //设置新的装载值
        __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&htim3)/2);    //确保占空比始终不变
        Key = 0;break;    //电机减速
    }
    Motor_Start_PWM(dir);   //启动电机
  }
  /* USER CODE END 3 */
}

实验现象

不出以外电机就开始转动了,经测试方向控制以及调速部分均无问题

 

  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值