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

发布于:2025-05-16 ⋅ 阅读:(20) ⋅ 点赞:(0)

飞书文档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就是改变步数。

示例工程

参考飞书文档


网站公告

今日签到

点亮在社区的每一天
去签到