你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32实例-步进电机的速度控制

[复制链接]
STMCU小助手 发布时间:2022-6-1 21:01
项目需求
& l* C; d' e' |! R; V+ J
    在制作一个使用全向轮的机器人底盘,对于全向轮,电机的精度是影响效果的重要因素。所以使用了步进电机,使用步进电机的优点是可以不使用编码器,开环控制即可达到高精度的效果。
0 S, E: e' t  v: A4 ]3 D7 ?
调整占空比或者调整周期
    众所周知,PWM有两个重要参数,周期与占空比。3 g& ~6 F' `2 x5 Q2 i: {1 t0 M0 Z- L3 m+ ~
    步进电机的运动方式是,每收到一个脉冲,就旋转指定的角度。因此影响电机速度的唯一参数就是PWM的频率。以下附图两张来说明调整占空比与调整周期的区别。

( q" G  D5 P/ K/ K
周期固定,调整占空比
640.png

, h0 f) V. B7 H+ R. q    上图中有4个PWM,它们的周期是一样的,不同之处是拥有从80%至20%的占空比。可以看出,无论占空比为多少,在1s内,它们产生的高电平的数量是一样的,即无论占空比为多少,PWM的频率都一致。因此也就无法调整步进电机的速度。因为步进电机的速度仅与PWM的频率有关。
6 t2 w& t5 S7 ?" N/ @
占空比固定,调整周期
640 (1).png

" V; N0 M0 m4 }& T! J1 O4 N! e8 E/ {2 q    上图中有4个PWM,它们的占空比都固定为50%,却拥有不同的周期。可以看出,即使占空比固定,只要动态调整周期,PWM就能在相同时间内产生数量不同的脉冲。因此,固定占空比,动态调整PWM周期,即可达到控制步进电机速度的效果。
- h7 a) z) i7 n
基于STM32的实现
    在STM32F1中,定时器具有PWM模式,可以用来产生PWM。但是,STM32的PWM模式,只要确定了时基单元(即确定了PWM周期),改变输出比较寄存器,仅可改变PWM的占空比。1 U  F, \/ P: ^
    若需要改变PWM周期,需不停地改变定时器的时基单元。但时基单元与硬件相关,不适合频繁变更。因此,步进电机的调速,不适合使用STM32下定时器的PWM模式来控制。3 n- c% Y. P9 }$ M" A9 b
    在多方查找资料后,确定了一种利用输出比较精确控制PWM周期的方式。

" f" k# Q# q  w; I
利用输出比较产生频率可变的PWM
    利用输出比较产生频率可变的PWM,原理简单介绍如下:& G1 ], H& ^7 e2 X  E4 |- I
    首先配置定时器时基单元,确定脉冲最小长度单位CK。
; |" ~" T+ |: i7 \" g: L& r  U    然后开启定时器的输出比较,设置模式为翻转模式,并开启输出比较中断。
6 U2 d3 v9 |' c" U' [/ K    将定时器内计数器CNT当前值,加上脉冲长度X(单位为CK),写入输出比较寄存器。6 K( f5 w7 B% x; d) i  u
    在X个CK后,将会触发输出比较中断。同时电平翻转。9 O9 H- ?+ |% `9 S* \
    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。
) S+ u# l& A6 n/ d    在X个CK后,将会触发输出比较中断。同时电平翻转。
0 X8 H/ V, m5 q6 ]6 H( f$ L    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。
: n4 r2 d3 F$ S0 l8 [) V: p    如此往复……
/ |: Y+ J; a  J: D7 G1 d5 F    以此即可得到一个占空比为50%,周期为2X个CK的PWM。
- b6 g# M: J7 Z  k/ g" [! l- u
确定最小单位CK,配置时基单元
    首先确定一个最小的间隔CK,规定PWM的高电平长度和低电平长度的单位都是CK。; P6 E/ k8 v+ n& v- ]6 k
    即高电平的长度一定是CK的整数倍。低电平亦然。
# V) ~! V7 S8 v' P5 Z- w    然后配置定时器的时基单元,通过CK的长度确定预分频系数。$ F4 k2 x; T& L% m
    已知STM32F103的主频为72MHZ,则时基单元中预分频系数为
  1. PSC = 72M / (1/CK)
复制代码
8 |- Q% Y) z0 T
    例如,rtz所确定的CK长度为10us(0.00001s),即可得出方程。
! v5 v; A% V( O! c0 p6 F
CT%}9N_KML5GYYJXKS`V31I.png
   预分频系数确定为720后,由高速晶振产生的72MHZ的时钟信号被720分频,得到100000HZ的时钟信号。即时钟信号每秒变动100000次。每次10us。同时可将重装载值设定为0XFFFF(16位定时器的最大值)。因为本次使用的输出比较模式不使用更新中断,该值可随意设置。
  1. TIM_TimeBaseStructure.TIM_Period = 0XFFFF;
    5 V6 y2 f8 C- I0 J. d  E$ w0 J
  2. TIM_TimeBaseStructure.TIM_Prescaler =720;5 b5 ~! Y$ x: Q4 a6 g9 Z& t
  3. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    - b/ e9 V& C3 V0 ^) o. {
  4. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;' N8 E, h2 {8 S6 b; X
  5. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
复制代码
% ?( U3 U: [) M& S. C2 O
+ E  f2 o* ]' _/ u* R6 B8 i. n4 Y
开启输出比较通道,设置输出比较模式为翻转模式,并配置NVIC,开启输出比较中断,配置输出比较通道:
' j" B% A" @$ E+ p3 q. @$ N5 y
  1. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    $ H1 O- p: k% X3 D
  2. TIM_OCInitStructure.TIM_Pulse = 500;2 G# h; j8 S. R: R0 A/ U. F. q1 e
  3. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    ) T. v1 F/ {7 x$ b5 Y6 j
  4. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;: K; O# V! _: I" j0 s- |( i
  5. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    0 F, C( e1 a, r( N# k
  6. TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    0 Q' t0 P( Q4 `5 d6 T
  7. TIM_OC1Init(TIM2, &TIM_OCInitStructure);
复制代码

% C8 a' U% y/ f" {
    开启输出比较中断,配置NVIC优先级:
' T9 a9 @  O; @0 J7 O, s
  1. TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);, O! E1 c/ d+ i" T
  2. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    & o3 v$ Z$ T  V* d
  3. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;6 ?& R. E- Q0 S$ c
  4. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    * F! y$ e- q* ~# f; x) y
  5. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;3 L9 b5 j  v4 d2 @" n; t9 \, P
  6. NVIC_Init(&NVIC_InitStructure);
复制代码

- L8 L' A4 {" x编写中断服务函数
5 }0 \$ A$ v/ n1 g
    在输出比较中断中,唯一要做的事情就是把当前CNT的值取出,加上脉冲长度X,写入输出比较寄存器。
' L) M5 B* N' ~# n9 i    当计数器达到0XFFFF(之前设定的重装载值)后,再加一会自动变为0.# f  |; n/ x9 g7 ?: Z
    例如,当前CNT值为0XFFFF,脉冲长度为5,很明显,输出比较寄存器应设置为0X0004才可触发下一次中断,而不是0X10004,这样会造成溢出。1 C8 R* d2 q- K' ?& I4 H
    因此将CNT的值与脉冲长度相加后,需要取0XFFFF的余数后,再写入输出比较寄存器。
  1. int t_m=5;//低电平和高电平的长度
    6 D( o  f: m3 G9 `6 }
  2. void TIM2_IRQHandler(void)
    & B% J( S- R$ G  i1 K- r8 M
  3. {
    # V# O7 l/ R5 O3 V# F: ?
  4. if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
    6 d1 g; }* f! |2 H. ~% a
  5.     TIM_SetCompare1(TIM2,(TIM2->CNT+t_m)%0XFFFF);9 e  m6 Q# e" X. {" ~
  6.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    " ]1 _  H! i) S$ H1 T) |
  7.   }+ y# G" O0 k3 d% x8 B% G
  8. }
复制代码
' x5 o* O, A! D7 w: a0 s9 z
    动态调整中断服务函数中的变量t_m,即可达到修改PWM频率的效果。

6 E; u1 h6 }# p# t! v+ x
+ q  P. r: ]4 j0 y1 |$ r( _! N5 {
赞 收藏 评论0 发布时间:2022-6-1 21:01

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版