STM32实现:步进电机的速度控制

发布时间:2024-04-02  

项目需求

在制作一个使用全向轮的机器人底盘,对于全向轮,电机的精度是影响效果的重要因素。所以使用了步进电机,使用步进电机的优点是可以不使用编码器,开环控制即可达到高精度的效果。


调整占空比或者调整周期

众所周知,PWM有两个重要参数,周期与占空比。     步进电机的运动方式是,每收到一个脉冲,就旋转指定的角度。因此影响电机速度的唯一参数就是PWM的频率。以下附图两张来说明调整占空比与调整周期的区别。

周期固定,调整占空比

fe693d5c-8273-11ed-8abf-dac502259ad0.png

    上图中有4个PWM,它们的周期是一样的,不同之处是拥有从80%至20%的占空比。可以看出,无论占空比为多少,在1s内,它们产生的高电平的数量是一样的,即无论占空比为多少,PWM的频率都一致。因此也就无法调整步进电机的速度。因为步进电机的速度仅与PWM的频率有关。

占空比固定,调整周期

fe7c1b84-8273-11ed-8abf-dac502259ad0.png

    上图中有4个PWM,它们的占空比都固定为50%,却拥有不同的周期。可以看出,即使占空比固定,只要动态调整周期,PWM就能在相同时间内产生数量不同的脉冲。因此,固定占空比,动态调整PWM周期,即可达到控制步进电机速度的效果。

基于STM32的实现

在STM32F1中,定时器具有PWM模式,可以用来产生PWM。相关文章:STM32中PWM的配置与应用详解。但是,STM32的PWM模式,只要确定了时基单元(即确定了PWM周期),改变输出比较寄存器,仅可改变PWM的占空比。     若需要改变PWM周期,需不停地改变定时器的时基单元。但时基单元与硬件相关,不适合频繁变更。因此,步进电机的调速,不适合使用STM32下定时器的PWM模式来控制。     在多方查找资料后,确定了一种利用输出比较精确控制PWM周期的方式。

利用输出比较产生频率可变的PWM

利用输出比较产生频率可变的PWM,原理简单介绍如下:     首先配置定时器时基单元,确定脉冲最小长度单位CK。
    然后开启定时器的输出比较,设置模式为翻转模式,并开启输出比较中断。
    将定时器内计数器CNT当前值,加上脉冲长度X(单位为CK),写入输出比较寄存器。
    在X个CK后,将会触发输出比较中断。同时电平翻转。
    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。
    在X个CK后,将会触发输出比较中断。同时电平翻转。
    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。
    如此往复……     以此即可得到一个占空比为50%,周期为2X个CK的PWM。


确定最小单位CK,配置时基单元


首先确定一个最小的间隔CK,规定PWM的高电平长度和低电平长度的单位都是CK。     即高电平的长度一定是CK的整数倍。低电平亦然。     然后配置定时器的时基单元,通过CK的长度确定预分频系数。     已知STM32F103的主频为72MHZ,则时基单元中预分频系数为:


PSC = 72M / (1/CK)

    例如,rtz所确定的CK长度为10us(0.00001s),即可得出方程。

fe904abe-8273-11ed-8abf-dac502259ad0.png


   预分频系数确定为720后,由高速晶振产生的72MHZ的时钟信号被720分频,得到100000HZ的时钟信号。即时钟信号每秒变动100000次。每次10us。同时可将重装载值设定为0XFFFF(16位定时器的最大值)。因为本次使用的输出比较模式不使用更新中断,该值可随意设置。

TIM_TimeBaseStructure.TIM_Period = 0XFFFF;

TIM_TimeBaseStructure.TIM_Prescaler =720;

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

开启输出比较通道,设置输出比较模式为翻转模式,并配置NVIC,开启输出比较中断,配置输出比较通道:


TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_Pulse = 500;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

TIM_OC1Init(TIM2, &TIM_OCInitStructure);

    开启输出比较中断,配置NVIC优先级:

TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

编写中断服务函数


在输出比较中断中,唯一要做的事情就是把当前CNT的值取出,加上脉冲长度X,写入输出比较寄存器。     当计数器达到0XFFFF(之前设定的重装载值)后,再加一会自动变为0。     例如,当前CNT值为0XFFFF,脉冲长度为5,很明显,输出比较寄存器应设置为0X0004才可触发下一次中断,而不是0X10004,这样会造成溢出。     因此将CNT的值与脉冲长度相加后,需要取0XFFFF的余数后,再写入输出比较寄存器。


int t_m=5;//低电平和高电平的长度

void TIM2_IRQHandler(void)

{

if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {

    TIM_SetCompare1(TIM2,(TIM2->CNT+t_m)%0XFFFF);

    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

  }

}

动态调整中断服务函数中的变量t_m,即可达到修改PWM频率的效果。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>