|
步进电机特点: 步进电机主要用于一些有定位要求、进行精确控制的场合。特别适合要求运行平稳、低噪音、响应快、使用寿命长、高输出扭矩的应用场合。比如3D打印机、工业机器人等场景。 1 D) \ |, i" \1 S- g
, j) x' q- g+ ^步进电机在工业机器人中的应用
% c8 h: I1 {: e9 x8 A步进电机相关概念:拍数
* K% z% B, F9 ?4 J; |$ m完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例,有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即A-AB-B-BC-C-CD-D-DA-A。 步距角
6 d$ O2 z- }# T+ o3 x. X控制系统每发一个步进脉冲信号,电机所转动的角度。现在市场上常规的二、四相混合式步进电机基本步距角都是1.8°。
% a9 Y* F3 X" W# ^
1 M% k+ u- U) R/ u1 _7 O p+ ~相关问题:问题:有一步进电机参数,如下:
. A8 o) n/ ?, h5 x9 Q6 ], G6 O6 e! v [电压 12VDC 1 ^/ |; s% I, j( k! [% z- _2 a/ |
相数 4
2 ^, R5 C4 h% m5 \ 减速比 1/64
' j" V; B: T/ n ` 步距角 1.8° /64
( v2 Q t7 Z- J* M6 ~ 驱动方式 四相八拍 ] 5 w4 R. J+ M d, y
请问: 步距角1.8°/64 ,后面的 “/64”表示什么意思?此步进电机转一圈,要多少步? . a4 i# Y d$ ~, K5 O, F. h
答案:12VDC的步进电机,L298N的VS接12V直流电源。步进电机本身到电机轴之间是有一级齿轮减速的,64指减速比,即:电机本身的转子转64圈,输出的电机轴才转1圈。步距角1.8° /64表示,每走动64拍,转过角度为1.8度,转一圈共需要(360/1.8)*64=12800拍(步)
1 w! u& c/ T4 `; f9 U
若是新手,不知道怎么设计电机驱动电路,可以直接购买电机驱动模块,市面上这种功能模块非常多,比如L298N电机驱动模块,只需要单片机6个IO外加一个电机供电电源即可驱动步进电机。 6 A* y2 |9 Y7 R, k* {' d2 y0 ~
6 \3 |$ g2 o! r4 z( r
L298N主要参数说明控制信号供电:直流5V; 电机供电:直流3V~46V(建议使用36V以下) 最大工作电流:2.5A 额定功率:25W 控制信号输入电压范围:
. S) P6 q" T+ T4 f l0 `低电平:-0.3V <= Vin <= 1.5V 高电平:2.3V <= Vin <= Vss
7 T' R J5 `5 U+ E" p9 {
使能信号输入电压范围: 7 u1 Z5 [* F1 f. } V
L298N芯片的输入电压有两个: 如果步进电机为5VDC供电,那么VSS和VS可以短接到一起;( _( i' _; B4 l
VSS和VS两个电源要共地;
0 }6 b( x6 L8 B; c6 YL298N使用的过程中,发热较大,最好添加散热片。
# C4 u t: l, w
# h! o' H" S! ^* M
如果想自己设计电路实现电机的驱动,可以参考如下电路。
* i6 ?1 l, E* u9 x L298N原理图
0 T# r/ P. N4 f3 j5 S应用实例
4 S, ^1 J! }/ n5 F 驱动步进电机驱动四线两相电机,四个状态为1、AB正电压;2、A-B正电压;3、A-B-正电压;4、AB-正电压。
% i# Y. o/ G/ q/ X$ G- ^程序中使能ENA和ENB之后,令StepMotor_OUT1~StepMotor_OUT4按四个状态变化,时序控制如下图所示,即可控制步进电机的方向:
( X8 q, K3 Q6 d( r) ^4 [, Y5 }
5 e* I; X! Z) m5 \& ~5 f$ v
实现代码1. 驱动步进电机的引脚初始化- 8 X/ H; x/ E; S9 } A$ Y6 o' Y
- void StepMotor_Init(void)# Z( `6 `9 J2 e0 |% O
- {
0 g7 }# K. z0 f4 o - GPIO_InitTypeDef GPIO_InitStructure;7 \" ~+ J( N. s( c% e2 u* F
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PC端口时钟
. b- I* {- V8 X- N& T -
$ `4 Q. C: T( n s' G$ x7 m - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;5 X% @1 e" g, d; A3 x$ w) j
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;" i4 [# V0 S* ^! z+ Y* G4 o
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
8 [9 v7 t _1 G* T! Z* _ - GPIO_Init(GPIOC, &GPIO_InitStructure);1 X- E8 [9 V, }. {) S l
- GPIO_SetBits(GPIOC,GPIO_Pin_6);
; A9 _: f1 k* i2 D' E - GPIO_SetBits(GPIOC,GPIO_Pin_7);5 ~2 Z. E; w: ~9 I; v
-
) n4 |7 u3 s+ Q - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;; C$ |2 X2 V$ f: s# ^, B G
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
2 y" G. D4 @+ q* @ - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
4 p( d9 V9 Z" y# Q- a - GPIO_Init(GPIOB, &GPIO_InitStructure);$ a, k; P+ n. V& r" `- V; [# U0 D
- % O' d' f* \) q$ R- T4 v) Q
- L298D_1AA = 0;0 u( W2 J% j8 D+ k$ D; g( ?" k
- L298D_2AA = 0;
7 `- b1 _9 @9 C9 | - L298D_3AA = 0;
/ w/ Y" @. J; z$ L! f/ v - L298D_4AA = 0;5 ^0 A2 ~2 U; W8 v& ^; D4 u
- L298D_12ENA = 0;7 F3 q6 x$ V2 I: G: u
- L298D_34ENA = 0;
! T8 n* A$ T' _; m! j1 b0 n! ~ - }
复制代码
8 o, s! o, Q- ~' \( Q# g9 `% [
& M0 b- l+ c8 n- U$ ]" I/ A5 m2. 两相电机驱动代码,包括正转和反转
0 m: b) n* i% Y7 K, h* V- 2 g% m* V8 P% I) ^! K( p7 m9 b
- void TwoPhaseMotor(unsigned char nInputData ,unsigned char nDirection)
! ?6 O; o) p4 P' }" j, i - {
" G- {% ~' h& Q- [( |# }8 D - if(1 == nDirection) //逆时针
' U! k; _% b) s, i0 B; G - {
6 t4 h/ A: `- n0 j; _% C9 F9 k - switch(nInputData)8 n# F" ]: O, ` H- R# a& Y
- {4 K7 t$ Z: s8 Z2 g9 s* {9 O5 Z6 t# V
- case 1:
2 I+ X+ {& O2 n4 k% d1 f - {6 s q9 e% y; F) [3 T$ l
- L298D_1AA = 0;
% j3 S$ L' \& R' k5 | - L298D_2AA = 1;
* D N3 E+ q) [: a8 z' F9 U4 L/ { - L298D_3AA = 0;6 O" [- d4 t- V, w( K( h% ~0 Q3 e
- L298D_4AA = 1;
7 g; u, \8 e( n: |- J7 I - }& R4 {0 V2 k) r/ i+ o
- break;+ U3 w" z+ [) w
- case 2:4 N* r+ [4 c9 ] j3 ^2 _
- {% J1 y1 e/ d) Y
- L298D_1AA = 0;3 |+ B1 d( ^' X) J& O
- L298D_2AA = 1;4 z& ?; M! k" h( K k
- L298D_3AA = 1;
. ~7 P& [! c2 K4 S' G - L298D_4AA = 0;
6 l6 X& X; }5 `3 f3 ^9 l - }+ q! J3 G/ \/ {0 [# V& ]# D
- break;
% P s8 f4 n. s - case 3:
# [# r7 I1 h! P- \ - {$ Y) a9 f- m; F' B+ R; S6 B( d
- L298D_1AA = 1;7 f% h: Q n: l+ k" R& c/ ^! t& t% A
- L298D_2AA = 0;! r0 h; g: h3 v6 o# a. W
- L298D_3AA = 1;
' G! C4 Q$ R3 m, L - L298D_4AA = 0;
* l3 q/ T, O# D" V% F7 V - }
1 v# x+ W( P0 r - break;
. l2 d4 l/ t' @4 _$ ^4 q4 Y - case 4:1 r3 h8 v+ Z% F: b9 {
- {
) ~! B8 n9 f! @7 \, X - L298D_1AA = 1;
# l9 l# `1 n6 Q9 K - L298D_2AA = 0;
" K. C5 b; Y s3 B. s; q7 r/ ? - L298D_3AA = 0;* \+ w& b( n U% J: i( i: ?1 P
- L298D_4AA = 1;, A! ^# }! B& n
- }. p% O, X+ T" U$ `
- break;
4 c& {& M) J- n) h. a+ i - }: w( p) Y0 f" A7 m. O, f: c2 q5 d
- }
! M& {* |$ `- P' V2 K4 J - else if(0 == nDirection) //顺时针
, E! m; I$ z$ J3 d* Z" w - {
5 }( x. q: i7 Y9 l3 J3 x8 U1 q6 n2 j - switch(nInputData)
- z8 F5 M3 }8 |2 J' s) } - {
+ J# |! m9 D, V0 X) _7 X4 F+ z& P - case 1:
0 w, _" Q. ]7 V3 b/ A7 m. o - {) @, H l- v' h) K
- L298D_1AA = 1;, v) W. W' R, X" j
- L298D_2AA = 0;9 I+ R+ V3 b9 Q7 C
- L298D_3AA = 0;
7 x6 o$ b$ Q% a( [0 O' B5 i5 I/ r - L298D_4AA = 1;
6 W( `& c0 g* F - }
, B0 H5 y1 d# q1 j* w - break;/ V( n6 y7 N2 y5 j% ]9 Y
- case 2:
1 d$ n9 z$ c" i5 S - {: g$ i0 m% P5 ]2 M* T1 J3 ?
- L298D_1AA = 1;
$ l4 c% P1 S3 d$ _, ] - L298D_2AA = 0;
# i6 W* @6 a2 @( c/ P - L298D_3AA = 1;' m2 O- d0 i7 s! o- d+ q1 m
- L298D_4AA = 0; D9 }8 U0 n% D% ~, I9 z8 K r
- }
4 [4 p% C% ~6 I4 }8 C - break;
" C6 R1 y8 [9 [( p/ t: b - case 3:. {2 m; a C1 M; B% \- A
- {
$ t; N) S& G* L' J" @- y3 |2 m5 H- k - L298D_1AA = 0;
~5 L7 v. P# |- ?. { - L298D_2AA = 1;
- ~8 L. f" K$ R( x3 V% ^3 ~: y; r - L298D_3AA = 1;7 ~: E2 Y# [- G, J( F: ?$ L
- L298D_4AA = 0;
/ o9 |4 h- `9 q8 N+ g - }5 p" T- n. h. l$ O( z
- break;
6 v$ S/ e) h4 r+ y# s - case 4:
; S6 X, g6 Y# }7 l - {
X) [5 R- G, t3 n+ j - L298D_1AA = 0;
6 r8 W. C& V! r% A2 w& p0 G - L298D_2AA = 1;
3 B+ |+ o O7 ]/ ?) C' P$ {+ r+ `. l - L298D_3AA = 0;
& l8 {' e" _- W - L298D_4AA = 1;
: x! ]1 @) a9 g3 x- I - }- V/ P: i( ]' Z# U9 m9 ^
- break;& s3 S& s d; S+ m
- }
( X6 ]1 J8 u: E4 i8 v - }
- a% r' s1 `# p- p: M - }
复制代码 6 m; X8 w' @8 B- i/ B
1 v- {* r! I0 l& B g. u" j
上面函数调用一次,步进电机走一步,对上面函数进行封装,既得到走任意步,可控制方向的函数: - - W# Y& X( u: J! @
- void TwoPhaseMotorNCircle(int n,unsigned char direction)$ ?/ S* J2 B/ V+ r+ B! K6 A: G+ @
- {
5 [ G, `' i$ X) }& K - int i,j;; g" m6 E. d& @0 o$ x' M
-
* c' Q. N' u- {" p - L298D_12ENA = 1; //只有转的时候使能,否则持续供电,芯片和电机过热。
! q! A+ ^) ?7 |" ~0 P+ u - L298D_34ENA = 1;
4 A$ w. _- Z: ]- C* i. { -
% B+ h; F4 T- i' P3 o - for(i=0;i<n;i++)
% S9 n( `# T. {* w8 f+ Y Z - {
" h) m! U" p" p- d. X0 v - for(j=1;j<=4;j++) `5 d- P8 e2 e: I* D1 R m& g
- {7 ?2 ~! g8 h4 R1 C E. o: V B. Q
- TwoPhaseMotor(j,direction);; {2 c& F4 `/ L X: _' N
- delay_ms(2);$ J) X( A7 Y2 l q8 l3 P
- }
' M+ B. `9 a% `) J - }4 }/ R+ K! E6 }5 n3 \
-
8 Q& D) c/ l _% Z - L298D_12ENA = 0;
, C/ z/ d" p0 w5 s$ D0 m) X - L298D_34ENA = 0;
# ]' A+ _: G; B - }
复制代码
& Q1 @, K7 l+ } C3. 主函数中调用说明:' E1 @ Z$ _# k$ M( X
主函数代码如下:: T! C0 b( {/ S. s* C0 ~
" v& g j2 i4 n( A7 k- int main(void)( d, L A: ]# a8 w5 k
- {7 b5 s' L/ G4 a. k, G
- //解析payload数据包使用6 ]; n% A' s7 ]1 B& s
- cJSON *receive_json, *item_obj;
0 ^; B( h, X! C' U4 l -
0 n {# C6 i9 }2 r+ I- _ ^ - u16 i;5 x; T* b$ x5 O" \* C
- u16 uart2Len=0;# X$ Q1 _6 U" ?8 n( ^; f2 D' u
- 6 _! f; k @+ k& @" J
- u8 dtbuf[50]; //打印缓存器
! h; ~; t2 ~6 @% i. c - # q9 C" b1 q a: I7 p! _
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
, }7 C$ B0 [) E% K4 e# j- [) ~2 q
( g: ^: D; j$ e1 s* l8 c- USART2_RX_STA=0;$ t& |* o6 |" j
- memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF)); R2 F" p, ?$ n& F- B
-
1 f. E- n- j5 \' R1 h3 P - memset(dtbuf,'\0',50);. g- W7 I8 A6 Q7 f; f; n
- ; K W& d7 S6 B
- //初始化
7 |) b2 L( x; C" B - //延时函数初始化
, s+ A" K3 d2 [ - delay_init();+ c+ J) f1 j2 h% o$ o
- * I7 b6 |5 S0 E4 y% ]" `
- uart_init(115200); //串口1:Debug,初始化为115200- S' A" D f4 [3 j( E: D
- uart2_init(115200);# D, ]7 [8 A8 L; o! Q# y7 }" P
- . q1 z1 `% }: D ?4 H! g: c4 G
- //定时器3,--步进电机使用" C0 R! {6 _8 k6 X
- TIM3_Int_Init(99,7199); //1ms中断
3 n% p. b4 W* C6 M6 K7 J, M) S% x1 E( h - TIM3_Set(0);
) s- m5 F- b- n2 _& r0 l - 8 K7 l5 M0 n& X% N8 N' g6 N, p
- StepMotor_Init();8 I$ g0 l, @( U# t& n0 |
- 3 ]" @$ j3 ]$ w. T( p7 x
- printf("System Init OK \r\n");2 R' R' O. S2 o* G7 E' n
- " n% l; ]! b* X
- //主循环; S1 @$ G- ?0 L! ^6 t0 G5 n4 ]0 N
- while(1)
: d% s/ s* V8 t3 V - {; R2 B. C, R `3 s: z
- //ESP8266
! a- J/ L" ]- a+ I - if(USART2_RX_STA&0x8000)
: V1 @. \$ Y% K - {4 R3 G; z( ^: j4 u2 o
- uart2Len=USART2_RX_STA&0x3f;
' F0 w4 H* e* @. d -
) h; v1 B/ N5 m5 ~% w, T* O - receive_json = cJSON_Parse(USART2_RX_BUF); //创建JSON解析对象,返回JSON格式是否正确
8 P9 ]" ]+ g# O" S. m* H - if (!receive_json) C; o" K2 E" @6 Z: o* t
- {
0 J0 k" d5 ]" f P n - printf("JSON格式错误:%s\r\n", cJSON_GetErrorPtr()); //输出json格式错误信息0 I+ _: ^/ g# ~5 O, U" \
- }2 f/ ^% f6 r$ F& t: Z" f, J
- else' f: t+ _) P: I' p5 Y
- {
) b9 {! ~' v% P1 _# [! }. } - printf("JSON格式正确:\n%s\r\n",cJSON_Print(receive_json) );
. a! o3 q0 Y) J w. y5 r - item_obj = receive_json->child; //获取name键对应的值的信息
( j8 ?* w0 ?4 g) m- o: n -
5 s' k/ ]; o. s9 a - while(item_obj)6 D$ u$ c: b, n9 Y3 _
- {
2 C# `0 d% _" E' E) d - char * string = item_obj->string;4 C' f; T, [5 B6 C; L2 I
-
1 Y! g" Z6 r5 s/ u1 }3 E) {0 [" i - if(!strcmp(string,"PowerSwitch"))
0 p, ]9 i% I. r/ u - {
& U7 M- `4 l- T+ t! n - if(item_obj->valueint==1)/ L3 ]# b* Z, S! i3 o$ j) o
- {. S& a( P2 E5 T
- L298D_12ENA = 1; //只有转的时候使能,否则持续供电,芯片和电机过热。
0 A# Q. e; }4 D; s1 y - L298D_34ENA = 1;
) d3 M, U5 j% R, n% F' J6 s& k - ) n" A2 ]) z8 E0 ~( X
- TIM3_Set(1);
2 h ^6 {/ E' z -
- O- Y/ F# S3 o( k8 @- D* j - nRotationCounting = 0;9 X$ e/ h! B( Y) {# M
-
- q! J! q# c) }7 ~) ~2 |; g - stuAliOSIoT.PowerSwitch = 1;
' z8 b# `, t" N# h+ d; |( v - + g8 N3 Z: C: F4 j; c* o
- printf("PowerSwitch:1\r\n");3 [5 G3 W3 ]4 n* s. r# F3 l! d
- }
. c* E- R( A; }* v# k - else if(item_obj->valueint==0)( ]3 I/ M: F7 d1 V% m- c8 d" c
- {/ V" ^! h/ \: L* x8 D. t
- //步进电机运动停止; o9 T2 d' F0 u+ r/ J
- L298D_12ENA = 0;
4 K. F& _# C, v- F* u - L298D_34ENA = 0;. g6 ]7 B& |' K+ u$ l+ b G3 i
-
. F% S1 v+ E+ P: p - TIM3_Set(0);# O# Q4 k8 v* c! F+ w8 M
-
# c. k1 c5 }9 m - stuAliOSIoT.PowerSwitch = 0;( k. x2 Y$ e6 Q) _8 Y- l# z8 z+ V
- , S, N# }+ X1 A0 `3 C4 E* o3 d1 v2 L
- printf("PowerSwitch:0\r\n");0 _% N4 \& a5 D( [: t6 i4 m
- }' d/ ^$ t8 X) v* y0 h
- }
6 }# g. P" g5 v# f' b% G - 6 b. B4 m. B3 G5 ^* g" @
- item_obj = item_obj->next;* _ X% a. ~2 m8 E" t
- }
; ~0 _" B# M0 K9 x' L, @ -
1 R% u* s0 m+ W$ w - cJSON_Delete(receive_json);$ z; z9 B3 Y" e
- % U* a5 o5 l3 y" z0 q8 ~
- }
+ }' d' s. i9 [ -
. N% C' H: e& _# [9 [ - USART2_RX_STA=0;4 e' H4 g, \) y8 |; S6 L4 t5 P
- memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF)); //清空数组* K( {5 p# m, m
- }5 h- B0 Y- }- j* f1 o( X9 q4 C
-
) D; A+ S5 l$ Y3 d8 t! w" Q! ? - delay_ms(10);
0 k. R( h5 k& p% Y+ b2 K4 V - }
& l6 Y9 C' ` X. g. n - ' w8 Y5 U4 `) t3 f& n! ?* X, c* ]
- }
复制代码* y2 \/ z/ T$ b+ Y- `, K8 F0 i) U. s
定时器中代码如下: - 6 i- R6 g3 t! q2 P
- //定时器3中断服务程序
' ]2 y8 m" R4 R - void TIM3_IRQHandler(void)
+ u% V1 c8 y* D O - {! z3 r; j: r( c. Y( T
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
7 W! h W% p4 l, r/ M6 p - {
3 B: m$ Q3 @$ ~% M( D, X - TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIM3更新中断标志' |, k% s+ v) B! t) I Z+ y
-
; a' H- A6 A! x0 X% ? - nRotationCounting++;; e$ S I( m. U( H' N- V, A
- if(nRotationCounting > nSingleCycleDataPoints)
7 q5 c! a/ t0 k& ` - {( h6 J1 j/ ~/ L2 x: S
- if(nRotationDirection==0)7 f- Y1 J4 i4 Q+ p* d$ j) [
- {
5 `( y O1 e6 ? g. U& B @ - nRotationDirection=1;
0 }9 V5 G: E+ ?" J# v2 j - }
4 a! p; @% C& X - else if(nRotationDirection==1)6 {' ^1 `5 j: }1 u5 |
- {9 ?$ O( u ^% L( w
- nRotationDirection=0;
4 N w& n3 U% N# C# c+ {7 Y! p/ [ - }
3 `0 V3 B& Q3 ?- o/ p R -
5 L+ J- ?( P1 U6 {; o$ Q! G - nRotationCounting=0;6 t0 y& e. @6 y; Z& N! T
- }7 T* ]7 S. x. |# g; D+ {' |/ T
-
, `' |. \6 l) S9 a; \ - if(stuAliOSIoT.PowerSwitch)3 r( G/ B! }$ |+ J4 N) Q) w
- {
- F5 m1 w& n% C: |$ Z$ L& E - if(nRotationDirection==0) //正转
. {, S% T& E) n4 P v6 N - {
" ], ~, |! {$ R, [: j" D: d - TwoPhaseMotor(nRotationCounting%4+1,0); //顺时针
3 ?6 C1 g- V) c - }/ K4 d6 [; @- u7 K9 P
- else if(nRotationDirection==1) //反转! q6 t; F- _7 F" s! K
- {
' c' I. H2 i6 V+ ^$ A6 [ - TwoPhaseMotor(nRotationCounting%4+1,1);+ @7 T' k3 Q& C' {( y8 [
- }
9 d/ e$ U/ W# @2 i" L4 I: {8 H - }' z7 l9 `$ N: E% `( u( }
-
- \ H( U5 i# ]$ m: K2 {. b - //TIM_Cmd(TIM3, DISABLE); //关闭TIM3
+ [4 P& G% |2 G& W: ~ - }- s& _% x4 @2 M6 ^4 m& u. Q# I
- }
复制代码 * @% E# \3 l* X5 _+ R+ T4 o
) y( o* h2 l8 L$ u, \3 r实物图电源座用于提供外部VS供电;
8 T' d" H9 \1 p* p) T( j6 ^; n7 ]; X2 o) x; S, O
|