单片机-STM32部分:15、直流电机与步进电机 PWM/IO

飞书文档https://x509p6c8to.feishu.cn/wiki/InUfwEeJNimqctkyW1mcImianLh

一、步进电机与直流电机:

1-1**、什么是直流电机?**

直流电机是最常见的电机类型。直流电动机通常只有两个引线,一个正极和一个负极。直流电机的转速控制主要依靠改变输入电压的大小来实现,电压越高,电机转速越快。

1-2**、什么是步进电机?**

步进电机是一种将电脉冲信号转换成相应角位移的电机,每个脉冲使电机转动一个固定的角度(步进角),它可以实现更精准的位置控制。

1-3**、直流电机与步进电机的对比:**

直流电机:

优点:价格低、控制方便

缺点:精确的位置控制相对困难,除非采用额外的编码器反馈。

步进电机:

优点:低速扭矩大,控制更精准;

缺点:成本相对高,转速相对较低。

二、思考?为什么****STM32 芯片引脚不能直接接步进电机或直流电机?但可以直接接舵机?

这要从舵机的构造说起,控制芯片+电机组成,stm32实际接的是控制芯片引脚,而不是电机本身。

而步进电机和直流电机内部是没有控制芯片的,如果使用stm32直接接电机,因为stm32芯片引脚驱动能力弱而驱动不起甚至损坏芯片,stm32每个IO的最大电流为40mA,一般步进电机跑起来可能需要几百mA到几A。

驱动能力可以理解为引脚的可以输出的力气,如果力气过小,当然推不动电机运行。

三、如何提升驱动能力呢?

下图就是应用三极管的开关功能,使芯片IO的驱动能力提高。

上图可以简单理解为三极管开关电路,通过控制输入口的电平高低,就可以控制后端电路的开启关闭。

四、直流电机的控制?

4-1**、控制转** /

4-2**、控制转速**

直流电机的速度可以通过改变其输入电压来控制,使用单片机控制转速可以通过PWM控制。

PWM是一种通过发送一系列ON-OFF脉冲来调整输入电压平均值的技术。该平均电压与脉冲的宽度成正比,称为占空比。

占空比越高,施加到直流电机的平均电压就越高,从而导致电机速度增加。占空比越短,施加到直流电机的平均电压越低,导致电机速度降低。

下图显示了具有各种占空比和平均电压的PWM技术。

4-3**、控制方向**

前面我们都只是控制电机往一个方向转动,如果需要更换方向,就需要重新接线,那如果需要自动控制电机的正反转呢?这就需要升级下电路。

下面电路被称为H桥,是因为它使用四个晶体管连接,使示意图看起来像一个"H"。

为了控制直流电机的旋转方向,无需互换引线,可以使用称为H 的电路。H桥是可以双向驱动电机的电子电路。H桥用于许多不同的应用中。最常见的应用之一是控制机器人中的电机。

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

如果需要使用多个三极管,一个一个连接太麻烦了,有没有更好的方式呢?当然有,L293D、L298、和课程用的TC118S都是集成H桥的芯片。

直流驱动芯片****TC118S

https://item.szlcsc.com/89487.html

应用电路图

原理图:

新建工程,设置PB14 PB15为GPIO输出

修改IO名称为DC_AN1、DC_AN2,这里PB14命名应该是DC_AN1,PB15应该是DC_AN2,不过这个命名错不影响控制效果,只影响电机旋转方向,大家留意下即可。

方向控制:

复制代码
main.c
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    //正转
    HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);
    HAL_Delay(5000);
    //停止
    HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);
    HAL_Delay(5000);
    //反转
    HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_SET);
    HAL_Delay(5000);
    //停止
    HAL_GPIO_WritePin(GPIOB,DC_AN1_Pin,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET);
    HAL_Delay(5000);
  }
  /* USER CODE END 3 */

速度控制:

如果需要对直流电机进行速度控制,我们可以使用PWM,我们可以在STM32CUBEMX中看到PB15是支持绑定TIM1_CH3N这个通道的

TIM1_CH3N与TIM1_CH3为互补输出,例如黄色是TIM1_CH3,TIM1_CH3N则为蓝色部分

|----------------------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| | 设置完成后,IO变为黄色 |

我们在左侧设置TIM1的CH3N为PWM模式即可

|--------------------------------------------------------------------------------------------------------------------------------------|
| 需要注意的是: 普通PWM开启的函数为 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3); CH3N由于是高级定时器才有的通道,开启函数为: HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3); |

最终代码

复制代码
main.c
  /* USER CODE BEGIN 2 */
  uint16_t pwm_value = 0;   //占空比 
  HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3); //开启PWM输出
  HAL_GPIO_WritePin(GPIOB,DC_AN2_Pin,GPIO_PIN_RESET); //设置DC_AN2为低,只保持一个方向转动
  /* USER CODE END 2 */
 
  while (1)
  {
    /* USER CODE BEGIN 3 */
    while (pwm_value < 150){
       pwm_value++;
       //修改比较值,修改占空比,占空比为pwm_value/500
       __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, pwm_value);   
       HAL_Delay(10);
    }
    HAL_Delay(1000);
    while (pwm_value){
       pwm_value--;
       __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_3, pwm_value);  
       HAL_Delay(10);
    }
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */

参考工程:参考飞书文档

五、步进电机的控制?

右手法则

步进电机工作原理

步进电机的基本工作原理为:给一个或多个定子相位通电,线圈中通过的电流会产生磁场,而转子会与该磁场对齐;依次给不同的相位施加电压,转子将旋转特定的角度并最终到达需要的位置。

步进电机中间的转子是一个磁铁,周围线圈在通电时会形成磁场,然后把转子吸过来,如果周围线圈按照一定的顺序逐个通电断电时,转子就会被带动转起来。

电机类型

步进电机又分为单极性的步进电机和双极性的步进电机

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

其中左侧为单极性步进电机,右侧为双极性的步进电机。

|-----------------------------------------------------------------|
| 单双极性是指一个步进电机里面有几种电流的流向 单极性是指电机线圈只有一个方向的电流流向。 双极性是指电机线圈有两个电流的回路。 |

单级性电机驱动

下图是单极性步进电机整步旋转的过程,其中,在图示中分为5根线,分别为A、B、C、D和公共端(+),公共端需要一直通电, 剩下ABCD相中只要有一个相通电,即可形成回路产生磁场,图中的通电顺序为A->B->C->D,即可完成上图中的顺时针旋转, 如果想要逆时针旋转只需要将其倒序即可。

双极性的步进电机

下图是一个双极性的步进电机整步,步进顺序。 在第一步中:将A相通电,根据电磁铁原理,产生磁性,并且因异性相吸,所以磁场将转子固定在第一步的位置; 第二步:当A相关闭,B相通电时,转子会旋转90°; 第三步:B相关闭、A相通电,但极性与第1步相反,这促使转子再次旋转90°。 在第四步中:A相关闭、B相通电,极性与第2步相反。重复该顺序促使转子按90°的步距角顺时针旋转。

满步驱动:

单拍满步驱动 双拍满步驱动

半步驱动:

半步驱动的好处是提高分辨率,但是缺点是扭矩只有满步驱动的70%,当然,也可以通过优化线圈中电流大小,来提高半步驱动扭矩。

总结:

步距角:改变一次通电状态(或者说一个脉冲信号)电机转子对应转过的角度。θ=360°/(z*n),θ是步距角,z是转子齿数,n是工作拍数。

在非超载情况下,电机的转速和停止位置只取决于控制脉冲信号的频率和脉冲数;

脉冲数越多,转动角度越大;频率越高,转动速度越快(不能超过电机规定的最高频率)。

42****步进电机

这里的42一般指电机的安装尺寸42mm*42mm,同理,还有28、35、57、60,一般来说尺寸和扭矩成正比

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | | |

  • 两相:2组线圈
  • 步距角:每走一步的角度为1.8度

步进驱动芯片****BDR6622T

https://item.szlcsc.com/769389.html

芯片框图

内部一个桥的框图:

控制:

半步模式:1-4步

满步模式:1-8步

有了上面的理论基础后

我们可以编写代码用全步或半步控制步进电机了,

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |

接线说明

|---------------------|
| 绿色A- 黑色A+ 蓝色B- 红色B+ |

参考代码如下

复制代码
 main.c
 /* USER CODE BEGIN 0 */
    void motor_run(uint8_t direction,uint8_t step){
        if(direction == 0){
        //正转
            switch(step){
                case 0:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);
                break;
                case 1:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);
                break;
                case 2:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);
                break;
                case 3:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);
                break;
            }
        }else{
        //反转
            switch(step){
                case 0:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);
                break;
                case 1:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_SET);
                break;
                case 2:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);
                break;
                case 3:
                HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_SET);
                HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);
                HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);
                break;
            }
        }
    }

    void runstep(){
        uint8_t direction = 0;
        int step = 500;
        for(int i = 0;i < step ;i++){
            motor_run(direction,i%4);
            HAL_Delay(1);
        }
        HAL_GPIO_WritePin(AN1_GPIO_Port,AN1_Pin,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BN1_GPIO_Port,BN1_Pin,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(AN2_GPIO_Port,AN2_Pin,GPIO_PIN_RESET);
        HAL_GPIO_WritePin(BN2_GPIO_Port,BN2_Pin,GPIO_PIN_RESET);
    }
/* USER CODE END 0 */

   
  /* USER CODE BEGIN 2 */
        runstep();
  /* USER CODE END 2 */
 
  //改变runstep()中的direction就是改变方向,改变step就是改变步数。

示例工程

参考飞书文档

相关推荐
霖0021 分钟前
PCIe数据采集系统
数据结构·经验分享·单片机·嵌入式硬件·fpga开发·信号处理
Camellia03111 小时前
嵌入式学习--江科大51单片机day7
单片机·嵌入式硬件·学习·51单片机
Shaun_青璇2 小时前
智能门禁项目
单片机·嵌入式硬件
漠落2 小时前
STM32 SD卡拔插后FatFs挂载失败可能原因
stm32·单片机·嵌入式硬件
电鱼智能的电小鱼2 小时前
产线视觉检测设备技术方案:基于EFISH-SCB-RK3588/SAIL-RK3588的国产化替代赛扬N100/N150全场景技术解析
linux·人工智能·嵌入式硬件·计算机视觉·视觉检测·实时音视频
Python小老六3 小时前
STC51系列单片机引脚分类与功能速查表(以STC89C52为例)
单片机·嵌入式硬件
MaoXian_n3 小时前
[IMX] 03.时钟树 - Clock Tree
arm开发·驱动开发·单片机·嵌入式硬件
茯苓gao4 小时前
电机控制储备知识学习(二) 电机的分类
嵌入式硬件·bldc电机学习
长流小哥5 小时前
STM32 DMA技术深度解析:从原理到实战应用讲解
stm32·单片机·keil5·寄存器编程