stm32控制电机使用

设计目的:控制电机转速、转动距离

所涉及内容:步进电机、驱动芯片、定时器编码器功能、PWM输出功能

1.电机

1.1分类

  • 直流电机:

  • 通过电流产生一个旋转磁场,使电机轴旋转。电流方向的变化会改变电动机的转动方向。方向转换需要由H桥电路控制,一般选择使用匹配的驱动芯片。
  • 电机的转速与供电电压成正比,电流的大小与负载成正比。可以通过控制pwm占空比来调速。
  • 步进电机

  • 步进电机是一种特殊类型的电动机,它通过将电流分配到绕组(线圈)来实现精确的定位和速度控制。与传统的直流电机不同,步进电机可以通过精确控制输入信号,实现逐步的旋转,适合需要高精度定位的应用,如3D 打印机、激光切割机和机器人等。
  • 通过分步驱动的方式工作,将电机转动分为若干小步。每个步进对应一个固定的角度(如1.8°的步进电机每转一圈有200个步进)。
  • 步进电机的转动是离散的,精确控制每一步的位置。
  • 电机可根据需求选择直流电机或步进电机等其他类型;微型直流电机如不需要精确位置与方向切换可以直接输出PWM控制不使用驱动芯片。

    1.2步进电机的特点

    1. 精确控制:每个步进都会转动一个固定的角度,一般从1.8度(200步/转)到0.9度(400步/转)不等。例如,雷赛电机42CME02, 步距角1.8°、保持转矩0.2~0.8 N.M、内置1000线增量式光电编码器、大转矩、低发热、高平稳性、高一致性。

    2. 定点控制:适合需要精确移位的应用。

    3. 高扭矩:在低速时具有较高的扭矩。

    4. 构造简单:相对简单的机械结构和控制。

    5. 常见类型:

    6. 永久磁铁步进电机:具有较高的扭矩,适合低速应用。

    7. 恒流步进电机:适合高扭矩应用,具备良好的响应特性。

    8. 混合式步进电机:结合了前两者的优点,兼具高扭矩和精度。

    9. 控制方式:

      步进电机的控制通常通过微步控制器实现,微步技术可以提高电机的平滑性和精度。

    2.驱动芯片

    常见电机驱动芯片

    1. 步进电机驱动芯片:
    2. A4988:常用于控制两相步进电机,能够实现微步控制。
    3. DRV8825:具有更高的电压和电流容许范围,可以驱动更大功率的步进电机。
    4. bd63521:能够实现微步控制。
    5. 直流电机驱动芯片:
    6. L298N:一个双向直流电机驱动芯片,常用于机器人和电动轮车。
    7. TB6612FNG:比L298N更小巧、效率更高,适合低功耗项目。
    8. 伺服电机驱动芯片:
    9. MC33932:专为控制大型直流电机和伺服电机设计,提供高效能和保护功能。

    3.timer配置

    3.1 定时器PWM输出功能

    /**********************************************************
    ** 函数名:PWM_Init_TIM1
    ** 功能描述: 定时器初始化函数
    ** 入口参数:预分频值,自动重装载值
    ** 输入参数: Psc(预分频值),Arr(自动重装载值)
    ** 输出参数: 无
    ***********************************************************/
    void PWM_Init_TIM1(u16 Psc,u16 Arr) 
    {
    	GPIO_InitTypeDef GPIO_InitStruct;                    //GPIO初始化
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;      //定时器初始化
    	TIM_OCInitTypeDef TIM_OCInitStruct;				    //定时器通道初始化
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_TIM2 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟
    	
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;      // 初始化GPIO--PB10为复用推挽输出 TIM2_CH3
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);                          //GPIO初始化
    	
    	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);            //用其默认值填充每个TIM_TimeBaseInitStruct成员
    	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;      //分频因子
    	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;  //向上计数模式
    	TIM_TimeBaseInitStruct.TIM_Period=Arr;                      //自动重装载值
    	TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;				    //预分频值
    	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);             //完成定时器初始化
    	
    	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;     			 // 初始化输出比较
    	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
    	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
    	TIM_OCInitStruct.TIM_Pulse=0;
    	TIM_OC1Init(TIM2,&TIM_OCInitStruct);//定时器通道1初始化
    	
    	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC1预装载寄存器使能//CH1 TIM1
    	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    	
    	TIM_ARRPreloadConfig(TIM2,ENABLE); //允许或禁止在定时器工作时向ARR(自动重装载值)的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值,此处为允许
    	//TIM_CtrlPWMOutputs(TIM1,ENABLE); 
    	//TIM_Cmd(TIM1,ENABLE);           //定时器使能 可以先不使能输出,等需要动作时在开启
    }
    

    3.2定时器编码器功能

    void TIM3_Int_Init()
    {
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
        TIM_ICInitTypeDef TIM_ICInitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
    
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    //定时器设置-------------------------------------------------------------   
      	TIM_TimeBaseInitStructure.TIM_Period = 1000-1;  //重装载值   
        TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;  //预分频
        TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
        TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割
    
        TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
    
    //编码器模式设置--------------------------------------------------------------                 
    
        TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//计数模式3
    
        TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入
        TIM_ICInitStructure.TIM_ICFilter = 0;//滤波器值
        TIM_ICInit(TIM3, &TIM_ICInitStructure);  //将TIM_ICInitStructure中的指定参数初始化TIM3
    //溢出中断设置--------------------------------------------------------------  
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许TIM3溢出中断
    
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    
    
      TIM_SetCounter(TIM3,0); //TIM3->CNT=0
      TIM_Cmd(TIM3, ENABLE);
    }
    //重装载值:    (编码器线数-1 ) *4                因为我们是两相计数,一个脉冲信号4次计数,所以乘4,保证转完1整圈才触发中断
    
  • 转速计算方法:用捕获值(一秒内输出的脉冲数)/编码器线数(转速一圈输出脉冲数)/电机减数比(内部电机转动圈数与电机输出轴转动圈数比,即减速齿轮比 没有则不用除)
  • 运动距离计算:输出的总脉冲数 / 编码器线数*编码器齿轮周长
  • 所转角度计算: 输出的总脉冲数 / 编码器线数 360 或 溢出中断次数360+当前计数值
  • 转动方向: 方向在定时器CR1的DIR位里 dir=(TIMX->CR1 & 0x0010)>>4; //取方向标志位
    if(dir > 0) //向下计数 else //向上计数
  • 4.应用代码

    4.1步进电机修改转速:

    void motor_start(unsigned short speed)
    {
        TIM1->ARR = speed;//重新设置重装载值
        TIM1->CCR1 = speed/2;//重新设置占空比
        TIM_CtrlPWMOutputs(TIM1,ENABLE); 
    	TIM_Cmd(TIM1,ENABLE); 
        
    }
    

    例如:设置速度1000,计算出周期是(1000-1)*(72-1)/72000000 = 1ms 频率为1k,表示1ms输出一个脉冲

    4.2PWM输出中断

    void TIM2_IRQHandler(void)
    {
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
        { 
            //可以记录输出脉冲数
        }
    }
    

    4.3编码器计数中断

    int circle_count=0;//圈数
    void TIM3_IRQHandler(void)
    {
        if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
        {      
            if((TIM3->CR1>>4 & 0x01)==0) //DIR==0
                circle_count++;
            else if((TIM3->CR1>>4 & 0x01)==1)//DIR==1
                circle_count--;
        }
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    }
    

    作者:tuui.

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32电机控制

    发表回复