一、舵机的“自白”
0 n- I" s* `3 {7 M% T我(舵机)是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。1 ~. Z2 b: X, e
9 }; e, r" t8 a& V+ L' a那么问题来了?我们用舵机来干嘛呢,当然是控制方向了,如今,基本上飞机或者智能车又或是机器人等等都会用到舵机这个东西,所以说,认识舵机,并且运用舵机就成为我们必不可少的知识学习了,下面附图:
. S( N! h- z6 m' v4 L3 l
1 o8 M! g) @/ o
1 ]$ J6 E* r$ y
1 s5 G5 y" u7 k/ }这里我用的是S3003舵机,其他类型的舵机应该也是大同小异。
& S% Y; @3 i2 z+ j/ l! _) Q) ]6 |5 C1 \4 O% q
其中,有三条线,一条接电源(5V即可),一条接地,最后一条接控制(即单片机输出的PWM控制),下面会给上具体实现代码,总的来说跟上一讲区别不大,主要就是PWM周期输出控制,利用 TIM_SetComparex() 函数来设置占空比实现,但是多出的是计算问题,因为舵机有对应角度的时间计算,下面具体讲解:' @% \. |7 F. S
6 {' K* [8 Y$ [' s% }: Q( ?
舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度为例,的其控制关系是这样的:) j! R% }$ ~8 c" y( y. {7 j' @
0 t* i- z" N2 h6 m
0.5ms--------------0度;4 b6 u% Z% D1 ] _. S
9 Q/ t2 n! T! A4 c; |3 s$ o. m
1.0ms------------45度;8 @) J1 u" Q6 _0 v3 W* w0 w4 y
6 `* u; T) J, _* c+ ^6 B% T8 P
1.5ms------------90度;* x* w5 N5 R" ~6 y
9 T) z% b/ b7 a% s
2.0ms-----------135度;' z+ r$ Z8 x- v
$ A6 H% H& _+ ]: A
2.5ms-----------180度;& J, ~# }1 ?: B7 B' [. ^3 \, H
- t% Z1 m/ V% Q2 D/ E& N基本上,我们学生党所需要的舵机的控制角度对应就是上述关系了,至于360度舵机这里简单提一下,主要是我这个舵机做不到(哈哈哈,这舵机180°的), e% s! n: d; p* u3 @
! {# i% T2 E( n) ^
这里讲一下360°舵机的
0 i* ^( r( q+ t) v6 r% C( E7 {( A9 y8 w S% I+ s
0.5ms--------------0度;正向持续转(最大速度)6 y5 O1 L; b6 A, P0 {+ b- T
3 A: f0 T. f7 |5 ~8 y 1.5ms------------90度;停止转动,速度无
/ b8 _7 m; Q& @7 Z' `% ?7 R. A6 a/ x$ J- A
2.5ms-----------180度;逆向持续转(最大速度)/ _4 \4 d8 P5 Q
; x- X0 Z6 ? w9 ^
调整PWM周期即可改变转动速度和方向。
7 ^4 F4 Z ?% X
% E4 H( X/ q* ` C& p6 F言归正传,到了这里基本上对控制舵机角度其实有了一定概念了,下面就直接附上代码部分了" q% A, i8 H$ R# R0 V4 `
' Y% m! f' e' |8 y `
二、代码部分; w4 t1 a! ?( [( j0 l4 z
- #include "sys.h"& ?- k6 _4 R. N4 j) d$ m
- #include "duoji.h"
2 Z* v, B9 ?. z0 ?" O7 _
) ^7 ]. G3 p/ s% ]) M( B$ q- void duoji_Pwm_Init()2 ?' k9 {0 c3 e2 u) y" ~
- {' Y+ `& |9 p' D, E, Q$ C9 X. h
- GPIO_InitTypeDef GPIO_InitTypeStruce;
& K2 K& V+ n6 r8 c - TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruce;
0 k0 r R9 j2 p% _) V6 ?( m m - TIM_OCInitTypeDef TIM_OCInitTypeStruce;" X6 K1 f- [1 k
-
& y2 [7 I) e G3 x* W. n - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);- t, l( c& m" H$ w: z8 f
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
m ?. J! @0 G1 D1 p# [ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);5 O& t# o; z. V- z$ {1 D1 ]
- ; A( B8 a9 |* N8 b1 y3 }
- GPIO_InitTypeStruce.GPIO_Mode=GPIO_Mode_AF_PP;
/ [) N0 w$ O+ c9 y2 ? - GPIO_InitTypeStruce.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;//这里是我之前的代码,主要是控制到4个舵机,这里大家只用一个输出口即可/ _4 j a6 b+ T, I4 e
- GPIO_InitTypeStruce.GPIO_Speed=GPIO_Speed_50MHz;! N6 q1 a8 K7 I1 F) K w) ]. [. D
- X4 w9 b3 |# w7 v8 ]+ W
- TIM_TimeBaseInitTypeStruce.TIM_Period=1999;//这里是自动重装值设置
$ Y5 ^: t( Z; k9 y - TIM_TimeBaseInitTypeStruce.TIM_Prescaler=719;//这里是预分频系数
. [7 [- b5 Q6 K L: f) p - TIM_TimeBaseInitTypeStruce.TIM_ClockDivision=0;2 F* {2 H9 }( l9 ~
- TIM_TimeBaseInitTypeStruce.TIM_CounterMode=TIM_CounterMode_Up;
4 k6 C9 n) {& I3 d' N, h$ P" v$ A( {/ a -
$ r* y$ k$ @% u - TIM_OCInitTypeStruce.TIM_OCMode=TIM_OCMode_PWM1;
" q! D' j" N) q, ] - TIM_OCInitTypeStruce.TIM_OutputState=TIM_OutputState_Enable;
% t' D- a( \# w: b; L* `; r: @2 ` - TIM_OCInitTypeStruce.TIM_OCPolarity=TIM_OCPolarity_High;
1 F3 I6 _( f, C: m - " n7 a9 `. \9 f, y1 r0 S8 K. b/ {7 f) a$ |
- GPIO_Init(GPIOB,&GPIO_InitTypeStruce);# O1 G& E" R. {4 c
- TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitTypeStruce);
4 H8 A n2 }' r - TIM_OC1Init(TIM4,&TIM_OCInitTypeStruce);
3 {/ H& W& ]" b2 \ - //TIM_OC2Init(TIM4,&TIM_OCInitTypeStruce);//这些是TIM4其他通道初始化
+ u; d3 N% k3 B, c! j1 c4 U - //TIM_OC3Init(TIM4,&TIM_OCInitTypeStruce);0 M# M! X$ t* ^
- //TIM_OC4Init(TIM4,&TIM_OCInitTypeStruce);- R& d# e* ?0 e7 [
- 2 e; O4 I% S) v5 l6 `$ ?# S
- TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Enable);! [4 D$ h+ B8 h5 Q3 Y1 X$ t
- //TIM_OC2PreloadConfig(TIM4,TIM_OCPreload_Enable);7 g+ E, ^; K8 B
- //TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
1 ~8 d9 C4 i! }5 y Z - //TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable);
|# e% k2 U( P" ^& n. P3 w6 \ -
+ X( v! @! f5 R# A9 G - TIM_Cmd(TIM4,ENABLE);
$ e: ]* Q1 e* q3 d- f - - Z2 y2 N# g! d% b: i p% A% }
- }
复制代码 & q5 L5 {8 e# _9 V# Q7 W$ A4 m
主函数部分1 {- ^7 @- O% M1 A! a k
. R2 h3 S3 |" [5 b
- #include "led.h"
$ ]2 k" e; T. U" v6 [ - #include "delay.h"; o( x' I0 h7 g/ E9 \+ v
- #include "key.h"
; H% }. Y1 U9 ^: B9 k. Y6 G - #include "sys.h"" A2 T9 |# A5 a( p8 f
- #include "usart.h"
( b( t, B& j& y9 P! q3 L: ^# N/ ^ - #include "duoji.h"
; y, I7 C6 ^9 I4 [# R3 D - , P& V* O/ X6 ]7 I+ F3 f7 X
7 ?! J! `, [! m8 ?( Y6 G; B- int main()
9 H: N1 z* T2 T. U - {
. F: b! ~! z0 ^* @* t; j - ; G7 Q; S% W9 b" R$ ~( Z. o9 ?/ h
- delay_init(); 7 Y S! B% L( ]4 X% f- |$ P
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
7 W! d3 m: n6 ^- Q: H% [ - uart_init(115200); //6 a+ n5 g0 v! Q; ?7 v& X
- LED_Init(); //" c g f$ N) m+ V! F
- KEY_Init(); //; f$ }! Y4 O) Y2 u$ a2 p% n. @
- duoji_Pwm_Init();
6 g% M+ \* }2 f9 r4 D - while(1)
8 C# Z3 @ A. p+ m, T - {/ N( s( c" @ K, x! h! r5 V
- LED0 = !LED0; 3 u) i# q; D6 k+ S _1 J4 o
- $ Z1 `! w6 a V9 R+ }
- TIM_SetCompare1(TIM4,50);//这里设置占空比改变角度,用TIM4定时器,可以自己更换% S2 M$ x0 D L* X
- TIM_SetCompare2(TIM4,50);
% `, R1 x) T F - delay_ms(5000);( }9 ?1 ?$ q2 W
- delay_ms(5000);6 T" B' m: H8 c, N6 o! k& ?* q
- TIM_SetCompare1(TIM4,250);- H4 U$ N7 b* l9 R2 ]
- TIM_SetCompare2(TIM4,250);
- q% F) z; U* v' J. I% q - delay_ms(5000);9 d! b" f4 P1 x3 [$ P" s5 j
- delay_ms(5000);; E0 I6 f8 I! x7 V$ @; T
-
+ W" g3 S2 ^0 w5 S2 i - }% z) O) i' x3 y) W- {7 w
- , ?/ F4 P, h) ]: L! Y8 q7 q
- }
复制代码
. B& f! h: K# k1 k( }( b6 m这里的代码是其他地方用的,拿来简单修改一下而已,基本上就是这样了。
- M2 j& @; J$ X# b r' R. b+ q- D3 l2 ~' {9 A
三、如何计算得到该要控制的角度, N& n5 Q( x1 o, `. o0 D, s. X( }
这里直接上纸描述,字丑谅解哈哈哈5 B j7 o) d8 s- ?
9 T: K8 B2 U4 V4 q' W; h4 ]% E
# D% `4 s: V5 a2 h; b
9 _( |7 f2 Q! Q$ J0 V& y& \* T 其中的arr和psc可以自己设置,再计算出相应角度的占空比值即可。大家可以自己调试一番,定会有所收获。
! Q- C3 w' |# n; ?% t
$ Z- T) `! i0 ~. I) O6 r5 A5 `8 b* W/ @1 Q, q% l
|