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

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

[复制链接]
STMCU小助手 发布时间:2022-6-1 21:01
项目需求) l0 s: c+ ]7 ~8 Q- B1 \* `
    在制作一个使用全向轮的机器人底盘,对于全向轮,电机的精度是影响效果的重要因素。所以使用了步进电机,使用步进电机的优点是可以不使用编码器,开环控制即可达到高精度的效果。

4 B7 T5 ]$ ]( ?- e6 R8 |
调整占空比或者调整周期
    众所周知,PWM有两个重要参数,周期与占空比。
6 _5 x7 }6 b' F/ h    步进电机的运动方式是,每收到一个脉冲,就旋转指定的角度。因此影响电机速度的唯一参数就是PWM的频率。以下附图两张来说明调整占空比与调整周期的区别。
( v* p1 z5 A5 b0 _8 E. [2 \
周期固定,调整占空比
640.png

/ L6 Z# e9 u1 o& i, n+ \    上图中有4个PWM,它们的周期是一样的,不同之处是拥有从80%至20%的占空比。可以看出,无论占空比为多少,在1s内,它们产生的高电平的数量是一样的,即无论占空比为多少,PWM的频率都一致。因此也就无法调整步进电机的速度。因为步进电机的速度仅与PWM的频率有关。
' O7 e7 \+ ^; p/ K
占空比固定,调整周期
640 (1).png

& D9 I- u, Z1 B# @; z+ n( ^7 g+ N( e) [    上图中有4个PWM,它们的占空比都固定为50%,却拥有不同的周期。可以看出,即使占空比固定,只要动态调整周期,PWM就能在相同时间内产生数量不同的脉冲。因此,固定占空比,动态调整PWM周期,即可达到控制步进电机速度的效果。
7 Z, M, \# o$ L: J
基于STM32的实现
    在STM32F1中,定时器具有PWM模式,可以用来产生PWM。但是,STM32的PWM模式,只要确定了时基单元(即确定了PWM周期),改变输出比较寄存器,仅可改变PWM的占空比。0 y9 o% o5 N  z
    若需要改变PWM周期,需不停地改变定时器的时基单元。但时基单元与硬件相关,不适合频繁变更。因此,步进电机的调速,不适合使用STM32下定时器的PWM模式来控制。
/ U: s4 f& Y, i  K! }6 b    在多方查找资料后,确定了一种利用输出比较精确控制PWM周期的方式。
, F) }# |) p/ }  H: z6 A9 m; d
利用输出比较产生频率可变的PWM
    利用输出比较产生频率可变的PWM,原理简单介绍如下:
0 V: V9 D. b" Z3 {    首先配置定时器时基单元,确定脉冲最小长度单位CK。" i1 O  j7 @' v7 y' f
    然后开启定时器的输出比较,设置模式为翻转模式,并开启输出比较中断。. \+ ^; b/ ~: L2 N3 m8 I% l
    将定时器内计数器CNT当前值,加上脉冲长度X(单位为CK),写入输出比较寄存器。8 M, d+ o$ _+ _' z, B- E- s
    在X个CK后,将会触发输出比较中断。同时电平翻转。
0 u, z( J$ J. i" L    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。, d$ Y7 J. q8 w1 H+ p5 ]+ Z
    在X个CK后,将会触发输出比较中断。同时电平翻转。/ s0 u* ?& i. G  Q
    在中断中再次将当前计数器CNT的值,加上脉冲长度X,写入输出比较寄存器。
7 `4 \  Y; {' J! i    如此往复……1 ~1 T+ K1 D3 h2 P* C/ }! v
    以此即可得到一个占空比为50%,周期为2X个CK的PWM。

  {9 l" r0 @7 ?5 \
确定最小单位CK,配置时基单元
    首先确定一个最小的间隔CK,规定PWM的高电平长度和低电平长度的单位都是CK。
2 Z! {7 [+ z  c0 h1 f/ c0 R& S/ i; v7 S    即高电平的长度一定是CK的整数倍。低电平亦然。
% }7 t, B. U0 O) z    然后配置定时器的时基单元,通过CK的长度确定预分频系数。' O0 r8 R3 g+ E
    已知STM32F103的主频为72MHZ,则时基单元中预分频系数为
  1. PSC = 72M / (1/CK)
复制代码
- D5 S% l4 d+ C4 Y/ l/ _; P4 Y' u
    例如,rtz所确定的CK长度为10us(0.00001s),即可得出方程。4 Q& K( P) ^/ W4 v9 q
CT%}9N_KML5GYYJXKS`V31I.png
   预分频系数确定为720后,由高速晶振产生的72MHZ的时钟信号被720分频,得到100000HZ的时钟信号。即时钟信号每秒变动100000次。每次10us。同时可将重装载值设定为0XFFFF(16位定时器的最大值)。因为本次使用的输出比较模式不使用更新中断,该值可随意设置。
  1. TIM_TimeBaseStructure.TIM_Period = 0XFFFF;* f1 \8 @/ O: J6 D5 ~! g
  2. TIM_TimeBaseStructure.TIM_Prescaler =720;
    : O8 z3 D' t5 z0 g
  3. TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    ' S5 Z9 r4 G( k0 Q: o
  4. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    4 p: k+ e& N5 l* W9 P/ Z
  5. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
复制代码
6 C# _& m% g! a7 U$ P6 q9 m
% `+ h6 Y# ?# X# h. U
开启输出比较通道,设置输出比较模式为翻转模式,并配置NVIC,开启输出比较中断,配置输出比较通道:6 {# K+ |. D' g" ^. ?
  1. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    2 o$ n. K9 F4 G7 {0 h, p
  2. TIM_OCInitStructure.TIM_Pulse = 500;5 T. \& [; T; Z1 q
  3. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;5 [. @% ^$ B/ J7 Z' I% A. R
  4. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;* j5 V( a- p( w$ @8 D8 \
  5. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;  L* \2 c6 F9 }$ o0 {/ d& R
  6. TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;1 i, e# H6 z  O; j+ Z. ]
  7. TIM_OC1Init(TIM2, &TIM_OCInitStructure);
复制代码
$ G$ f2 V( i& e, ?0 P5 `% T
    开启输出比较中断,配置NVIC优先级:
  I/ d" H  A7 F/ H" m9 t
  1. TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
    - ?# ^- K1 g$ B2 d" _- F% U& R
  2. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;- t9 t: S4 k; x2 d. N# w; J
  3. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;2 c: J/ q* x8 M8 I# ?; Q1 ~( Y
  4. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;% H: v) m) |! p) L) N0 _
  5. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    , f7 |7 u6 d9 B- a4 `( y. l7 ^
  6. NVIC_Init(&NVIC_InitStructure);
复制代码
+ Q' z; N; `, H5 g
编写中断服务函数5 N  l+ q& O3 U$ x5 s
    在输出比较中断中,唯一要做的事情就是把当前CNT的值取出,加上脉冲长度X,写入输出比较寄存器。& U' ]2 T# R3 t- l
    当计数器达到0XFFFF(之前设定的重装载值)后,再加一会自动变为0.
( u0 y) r( t" v  C    例如,当前CNT值为0XFFFF,脉冲长度为5,很明显,输出比较寄存器应设置为0X0004才可触发下一次中断,而不是0X10004,这样会造成溢出。6 B4 B/ K/ v3 e0 H( \
    因此将CNT的值与脉冲长度相加后,需要取0XFFFF的余数后,再写入输出比较寄存器。
  1. int t_m=5;//低电平和高电平的长度. G8 ?8 {7 T6 _( Z0 C! g1 j4 ?
  2. void TIM2_IRQHandler(void)+ U- [9 s4 N2 b
  3. {% m9 X- m: T' U, K( f( X' m
  4. if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {+ ]3 a( G  a8 E; f  I2 a) G
  5.     TIM_SetCompare1(TIM2,(TIM2->CNT+t_m)%0XFFFF);
    % E, l! \9 k  d2 v+ p  H
  6.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    9 ?8 W; v) C2 f# J! p) w9 I8 C
  7.   }- u( _8 b% U/ z* V" u
  8. }
复制代码
5 g" z# L% h+ A3 Y, z9 E
    动态调整中断服务函数中的变量t_m,即可达到修改PWM频率的效果。
$ Z% c+ K9 Q) K
5 j3 z* P% w# ^$ R$ ]
收藏 评论0 发布时间:2022-6-1 21:01

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版