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

【电机培训】玩个ST牌电调?

[复制链接]
RuiJey 发布时间:2017-8-30 20:56
本帖最后由 RuiJack 于 2017-8-30 21:22 编辑
5 B' ?+ o3 D" Z$ }' D' i
) _) D$ d: L; C" ^  R3 V/ K      此次培训的视频和工具大家都差不多能介绍的都介绍了诶,我们还可以怎么玩玩?
2 ^: s$ Y  r: g3 O2 W      好像之前一直想把四轴用的电调也做来玩玩,但又不会电机控制咧。这次好像可以捡个便宜,用ST的库来仿照做一个?& V! |) V! l+ m0 N

  G6 b- A- X) h1 i9 s$ G      那么,初步想法是这样的 -> 原来的工程 + PWM捕获 = 简易电调。
% `" f& T7 m4 v4 h0 c      连工程都用原来的,可是懒到家了。
, U: X, ]* W: y. F6 c8 j      好了,首先来看看可用的资源。nucleo-F302的板子,电机驱动库SPN7的示例功工程中已经使用了TIM1,TIM2,TIM6,TIM16,额。为了保证尽可能少的改动,来看看还有哪个定时器可以用吧。
) n/ J$ c$ g& Y5 [! }  s/ Y
QQ截图20170830194600.png

3 E, ]5 V* k/ y, Y/ a      好吧,至少还有两个定时器可供选择,TIM15,TIM17,但是板子上已经有很多已经都有用了,有些也被电机驱动库作为其他功能用了,对照数据手册和nucleo-F302板子的AD PCB功能,来寻找可用的GPIO,这里就省略耗时的过程。来看下其中一个可用的IO: L1 j1 u  p" _2 u9 M6 z
QQ截图20170830195025.png
+ h" |/ K2 s5 @3 U2 Q8 H
      是的,你没有看错,这还是UART2的RX引脚,已经被用了,好在可以暂时不用串口2来接收上位机数据,只用于向电脑发送调试数据。对应板子上的插针是& x3 G/ E% a/ l- r
QQ截图20170830195414.png

( s% ~; T" M4 {4 Y7 m! X) }      刚好还有个插针,后面再介绍下这还有个方便测试的好处。
  r# v6 z, U  \1 f
5 H7 q: f$ p1 D# D/ N6 F! s      好了,继续正题。接下来开始初始化TIM15 CH2.之前还没有接触过HAL库,很多地方就参考库中的例程来了。
! h! r6 j( v/ R! s' q      首先是GPIO初始化。之所以连这个也提出来,是因为一直在纳闷儿引脚要配置为复用上下拉模式,可能有段时间没用32的定时器捕获模式了,有点忘了。
% [: u9 R. t. |1 q+ c0 {& T4 ?1 r: _! }) [# ?# N3 ]
  1.   GPIO_InitStruct.Pin = GPIO_PIN_3;
    . V4 Q" m; c4 u# H- L! Z
  2.   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    3 J2 @- o3 N' q1 r. s: }9 O
  3.   GPIO_InitStruct.Pull = GPIO_PULLDOWN;0 h1 t5 T/ x5 j8 I0 E  Y
  4.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    3 N; A/ a" S5 N7 }; Q' s
  5.   GPIO_InitStruct.Alternate = GPIO_AF9_TIM15;5 {; [' V" E6 m% S( F
  6.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);3 k+ ^7 @% z1 x/ s5 g: |
复制代码
     然后是定时器基本参数的初始化。
  1.   htim15.Instance = TIM15;+ _" R! q9 G) a0 a3 `
  2.   htim15.Init.Prescaler = 72 - 1;
    3 u% B3 m5 t' ^* }  |
  3.   htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
    % e4 J) O8 ?' n! `/ c2 V( q! ?
  4.   htim15.Init.Period = 0xFFFF;1 j$ u. j( F! j. o0 A  S) q
  5.   htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    " ^2 b* o! \* i; d' p9 ^& N4 ?& G; A
  6.   htim15.Init.RepetitionCounter = 0;
    8 O% U0 V8 X5 K
  7.   htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    + J4 u2 O2 |- e* p
  8.   if(HAL_TIM_IC_Init(&htim15) != HAL_OK)
    8 s1 h" H9 \- D7 U* e6 h6 v
  9.   {: V9 Q; Z; K& O/ b! ?' L
  10.         BSP_LED_On(LED2);        
    1 y- S% X0 |6 a1 M( X: e  |0 C3 x" v
  11.   }2 `# @6 R5 k7 g9 p2 ~
复制代码
     接着是两个定时器通道的配置。这里直接使用了32定时器的PWM输入模式,以前在F1上就用得方便,这里也将两个内部输入通道连接到同一个输入引脚,CH2,通道1用作高电平脉宽采集,通道2用作PWM周期采集。两个通道的配置差异主要是采样边沿,和通道映射。* i- z/ J  ?( ]& ~6 a0 j
  1.   sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
    3 j- ~8 A3 ^$ C4 b
  2.   sConfigIC.ICFilter = 0;1 c, I$ d0 J! W' a2 u9 ]

  3.   h- M# c4 I) Z! d- f
  4.   sConfigIC.ICPolarity = TIM_ICPOLARITY_FALLING;0 r+ ^* f, ]5 i6 H5 E* n/ B% h
  5.   sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
    - _! A& C3 \3 X/ e7 U* b) Z
  6.   if(HAL_TIM_IC_ConfigChannel(&htim15, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
    3 L4 N2 B  `9 ^, r. ~
  7.   {                1 Z1 p% }* [4 T/ L& s2 z
  8.         BSP_LED_On(LED2);" E( h, O) @4 K* Q( i
  9.   }
    % R/ j: n+ k$ q) p( b

  10. ( }5 b5 W3 L3 J/ e7 R& Y
  11.   sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING;
    1 w( B6 k: c% B- b7 L
  12.   sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;. L/ P$ Z3 F4 v- N7 `5 K- N
  13.   if(HAL_TIM_IC_ConfigChannel(&htim15, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)4 |  ?3 P7 x$ [
  14.   {. _5 E% z1 \! X3 O7 ]7 |
  15.         BSP_LED_On(LED2);
    . w* [9 ^& U% J
  16.   }- L0 c/ L( p: M0 c! E0 |
复制代码
    这里有一段是输入捕获的配置,跟以前STD库有些区别,还没细看,直接从HAL库例程中拿过来先用着4 V* u& E& ^4 F0 t' P7 f
  1.   sSlaveConfig.SlaveMode        = TIM_SLAVEMODE_RESET;& w8 k) U( R. V, o2 m  z& \
  2.   sSlaveConfig.InputTrigger     = TIM_TS_TI2FP2;
    + t+ l. n( o; `% p  u
  3.   sSlaveConfig.TriggerPolarity  = TIM_TRIGGERPOLARITY_NONINVERTED;
    , @8 H- h+ S6 w' n5 }$ B1 I
  4.   sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;# U- z- U  r$ |( }7 o3 t! E
  5.   sSlaveConfig.TriggerFilter    = 0;$ S1 K9 V6 `# q. L
  6.   if(HAL_TIM_SlaveConfigSynchronization(&htim15, &sSlaveConfig) != HAL_OK)4 L, f% v# U  @1 `5 y
  7.   {
    ) t0 P+ n! ~1 w, W9 R
  8.       BSP_LED_On(LED2);- @2 ?$ p8 a1 Z' M/ |+ v' ?5 O- U2 d
  9.   }
      G4 B2 m. Z7 e
复制代码
     还有两个通道输入捕获中断的使能' _+ Z; N5 v/ N: \  m
  1.   if (HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_2) != HAL_OK)+ M0 o+ F# L+ Z- R" y+ Y
  2.   {
    # o" q! S: Z& R5 i" ]1 p
  3.       BSP_LED_On(LED2);
    / F% T" |0 {) j4 B2 b5 L
  4.       Error_Handler();
    * s! s! |0 b& H# u
  5.   }- k5 v# H& @! ~* o8 Z

  6. . ?4 e) J% J  F! v+ C; d2 L! h
  7.   if (HAL_TIM_IC_Start_IT(&htim15, TIM_CHANNEL_1) != HAL_OK)
    ; ~+ S7 K( B: b+ T3 b
  8.   {
    ; ]9 ?2 k. ]7 |1 a( X
  9.       BSP_LED_On(LED2);
    " ]& V) M1 _: x7 g% D
  10.       Error_Handler();
    ; `2 F; p8 Z% H* y( Q1 L
  11.   }4 A2 m( N1 u  C; O# D* H
复制代码
     我们在按顺序看中断部分,首先是中断向量的使能。这里需要注意的是TIM15的中断和TIM1 BREAK中断是用的同一个中断向量。- x  O2 A! n& Z9 Z4 J) V/ X
  1. #define TIM15_IRQn       TIM1_BRK_TIM15_IRQn& k. X  W( B3 R
复制代码
     所以最终我们还是得对原有工程进行修改,还是按顺序先来看中断服务函数) n5 @+ H9 f& n# e
  1. void TIM1_BRK_TIM15_IRQHandler(void)1 m* g3 M- _0 k% U
  2. {
    - N3 i9 y2 B) z' [

  3. + e# W- V! o$ i* t% B
  4.       if(__HAL_TIM_GET_FLAG(&htim1, TIM_FLAG_BREAK) != RESET)
    2 t6 w6 X& ^: D" e5 m) `2 i# h7 d
  5.       {7 U( k! H( L) A$ a0 U, |8 g5 v
  6.             MC_StopMotor(); # p- X  k. G- q+ ]& e" g8 J' \
  7.             SIXSTEP_parameters.STATUS = OVERCURRENT;        
    ' q- E  {5 y# X9 X
  8.       }: y+ G) c! r4 S8 m; l5 d7 P

  9. ( X$ X9 W- H6 C* [/ i8 t
  10.       HAL_TIM_IRQHandler(&htim1);
    1 z, H1 U. O0 f1 t
  11.       HAL_TIM_IRQHandler(&htim15);2 n1 b7 n2 |  K2 `5 t7 y& {. s
  12. }
    " B& J- l- g& `  a
复制代码
     最后一行就是添加的TIM15中断服务函数入口。, r$ J+ w* G8 s$ v
      接下来继续刚才提到需要修改的两个地方,由于HAL库中将中断分类处理进行了封装,这里就不贴这个部分,直接来看需要修改的部分。
2 x1 V: _( p6 v4 ~, }) G( H* l: l      首先是TIM6的计数器溢出中断,这里改好的,对入口参数进行检查,确认是TIM6的溢出中断,才执行原来的函数。同时为TIM15添加溢出中断的回调函数。3 z/ R0 _" b0 \2 ^% d0 V1 O7 H
  1.   void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    ( T" N+ Z2 y: }, w' C3 ]: H  C
  2.   {7 s  k8 s- B; K. ^
  3.     if(htim->Instance == TIM6)
    1 a* S* O9 _) b3 B  K* E$ U- z
  4.     {" m7 C1 x, I; x6 W
  5.         MC_TIMx_SixStep_timebase();
    & S4 Q  c, g. V3 D: J; p+ {
  6.     }, R8 K1 R: z& o2 \' u* F
  7.     else if(htim->Instance == TIM15)
    ) f6 M; Q" @% u/ G
  8.     {
    * z. ^1 d/ s$ \4 U8 {7 ?; {
  9.         TIM15_PeriodElapsedCallback();
    , f3 ^, k/ k! \
  10.     }
    . U) Y7 o0 L" R/ U$ u
  11.                 7 u$ H3 Q& N0 Z! B6 B5 z# p2 W( f, m. L
  12.   }
复制代码
     话说写到这我突然忘了还有哪个地方的中断服务函数要改,敢信?唉,像我这样思路不清晰的,写代码真是个定时炸弹呀,指不定哪里留了个BUG还记不起来了。 大家待会儿直接对照看工程代码吧。& s7 U/ L4 B# }0 t- r
      TIM15用到了两个中断,一个是溢出中断,记录溢出次数,另一个是读取捕获到的高电平脉宽值和PWM周期值。前面将定时器时钟设置为1/72主频,这样捕获到的值的单位刚好就是us
1 [8 d% r& X# m0 n
  1. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim). L( |( F6 {: F4 L
  2. {               
    $ z+ @3 L% g1 p0 A+ N, [
  3.     if (htim->Instance == TIM15)
    : Y" s& }; U. z* p
  4.     {7 _/ |5 j: e/ n0 x! s8 N  I+ i) u/ D
  5.         if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
    - p' ~% S2 R- u) ~
  6.         {2 n) f  J- l' v$ f
  7.             capCnt++;
    ! ?% ?  g+ e9 E! w
  8. 7 c( j/ H. N4 _. E: ~5 [+ [' B" w
  9.             pulsePeriod = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2) + periodCnt * 0xFFFF;- S9 y5 @2 Q: u1 E% R
  10.             pulsePeriod        += 1;
    6 q" x  k% Q, Q8 L/ m% |# Q
  11.             periodCnt = 0;
    5 p, `9 _0 W" X3 a* n( y
  12.             pulseWidth = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);" b1 g; P5 _3 U2 d( t: H
  13.             pulseWidth += 1;5 ?6 ~5 L1 c* B) a& F- ?
  14. / o/ g; ?' z/ @
  15.             if (pulsePeriod != 0)
    8 f( e- N1 S# Q2 [2 C7 G
  16.             {
    ) C9 E& c# _& }% O3 K
  17.                 uwDutyCycle = (pulseWidth * 100) / pulsePeriod;; O! k5 b' r$ n) W
  18.                 uwFrequency = ulTmrClk  / pulsePeriod;
    0 o: f$ x% A6 T0 [5 i4 g
  19.             }  \+ ]  I: m  [/ q' L
  20.             else$ @/ R% |. K+ Z& x! X  Y$ o6 r
  21.             {/ b& p) j: W7 D& a- L* [
  22.                 uwDutyCycle = 0;
    9 ^' o4 T& q6 t; g( q
  23.                 uwFrequency = 0;% A$ U0 ]7 U& J! e
  24.                 pulsePeriod = 0;  _$ c8 p- m4 V' _2 }
  25.                 pulseWidth = 0;
      z- V% T6 A7 c! j# i" c. c! j
  26.             }% k8 {# P. u/ r! H! Z
  27.         }" @9 I3 h5 k1 e4 Q6 Y" s! _
  28.     }
    6 G' Z4 Y4 _5 S; d
  29. }        0 }, d3 ~+ r) _: g" _
复制代码
     好了,主要的两个部分就这些,剩下的就是启动停止电机和设置速度。这部分就不贴吧,直接上传功臣压缩包。6 N: N# C- l4 b' b5 x; p
; ?& }$ V8 G- i0 u, C  I
      话说我还去移植6步换相的库,浪费的时间都可以熟悉HAL库,然后开始学习FOC库了
: w9 W' r) Z$ M5 H4 g, u% _: M' \) Z, g5 V" @: M* [0 ?
      今天先上传,改天有时间再来完善,大家看了一起讨论讨论。4 i2 x- d5 {6 v1 T' X
/-------------------------------------------------------------------------------------------------------------------/
  D: L6 n* o/ t, ]      顺便把测试图片和视频上传了
QQ截图20170830210638.png
: @* I6 U# \7 D0 g

1 G" u5 ~6 S/ c$ l, ~: R! q# E7 N      测试视频,使用函数发生器给电调信号,周期20ms,油门对应的脉冲宽度1-2ms。- `, Y# w# U4 I% T

, C- [. v5 T9 N7 @0 B+ i2 R; a# `
# J" |, S' }* U8 S; E$ I
7 M& P/ e# n/ L- v  s

Rui_STM32CubeExpansion_SPN7_V1.1.0.part01.rar

下载

9.5 MB, 下载次数: 82

原来工程上改的,只能打包上传了

Rui_STM32CubeExpansion_SPN7_V1.1.0.part02.rar

下载

9.24 MB, 下载次数: 74

有点大,分个卷

赞 收藏 2 评论5 发布时间:2017-8-30 20:56

举报

5个回答
Grant 回答时间:2017-9-2 19:13:21
出了很久了,一直没发布,最近才公开。
2 N7 x: W. {0 ?3 E1 ghttp://www.st.com/content/st_com ... t5571_gl_bn_aug2017
% S4 r- d; Y8 m) ~) j: w6 |" k+ K0 Z; `
en.steval-esc001v1_image.jpg
. U; P7 v1 H  t/ ]6 M- fworkbench界面有改动,电机硬件参数增加了诸如摩擦系数等,看起来速度环下以后PID不用用户改了。* R* [. e8 j3 a2 ]) x: @1 M3 u

$ R: B. e% F" F: k$ `2 QST其实是有几个版本的ESC的,还有一个是深圳ST做的基于STSPIN32F0的版本,另外说还有一个完整的无人机方案,包括姿态控制和ESC,说是开源的,可能还需要一些时间才能公开。
RuiJey 回答时间:2017-8-30 21:01:37
TIM15 CH2对应的PA3这个引脚,刚好是串口2的接收引脚,所以你会发现这个引脚连接在板载ST-LINK的串口TX引脚上,所以这里还有个方便的调试方法,直接用ST-LINK的串口向板子发送数据,任意数据,这样在这个引脚上就会有方波产生,嘿,还不用接信号源,也不会用手给输出脉冲信号了,直接用串口发送任意数据。简单粗暴还很方便。
zero99 回答时间:2017-8-31 09:06:46
不错,支持一下
五哥 回答时间:2017-8-31 09:28:15
ST新出了电调板,用的是STM32F303做的,比较高端。性能还没有测试。
RuiJey 回答时间:2017-8-31 11:37:53
五哥 发表于 2017-8-31 09:281 m1 P2 H: p( s3 W; r6 l5 v, N& U, G
ST新出了电调板,用的是STM32F303做的,比较高端。性能还没有测试。

+ g  T# P1 P+ g6 f7 }3 e" `分享个链接学习下?% l: C! X7 n! V
PCB工程应该是开源的吧
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版