步进电机特点: 步进电机主要用于一些有定位要求、进行精确控制的场合。特别适合要求运行平稳、低噪音、响应快、使用寿命长、高输出扭矩的应用场合。比如3D打印机、工业机器人等场景。 & q% ?; W U: S# l! U7 C! j/ N9 e
$ d5 l9 b+ J. k e: y1 N步进电机在工业机器人中的应用 5 }% f. |- V9 z. p# m2 X# E
步进电机相关概念:拍数
- X- t6 f! l4 Z; h+ L) H& d# ^4 e4 x, ~7 Y完成一个磁场周期性变化所需脉冲数或导电状态用n表示,或指电机转过一个齿距角所需脉冲数,以四相电机为例,有四相四拍运行方式即AB-BC-CD-DA-AB,四相八拍运行方式即A-AB-B-BC-C-CD-D-DA-A。 步距角+ Y- q+ R# C! N
控制系统每发一个步进脉冲信号,电机所转动的角度。现在市场上常规的二、四相混合式步进电机基本步距角都是1.8°。
2 M& f$ v/ W6 ?. ]; G0 Q/ k( i* t
1 s( m8 a0 R/ Y) J相关问题:问题:有一步进电机参数,如下:0 w, f& k2 Q& B
[电压 12VDC / m# c8 O' r2 N" {
相数 4 / ^& h2 j0 C- Q/ u7 W" _
减速比 1/64 ' j& ^& j7 c D4 v& E7 U
步距角 1.8° /64 h! T# c& h9 q) Z2 l2 z* _
驱动方式 四相八拍 ]
6 E" c$ s+ O: w2 m3 t% e4 U# ?0 h 请问: 步距角1.8°/64 ,后面的 “/64”表示什么意思?此步进电机转一圈,要多少步?
% S& J% I2 C$ ]# z" k D/ o1 |
答案:12VDC的步进电机,L298N的VS接12V直流电源。步进电机本身到电机轴之间是有一级齿轮减速的,64指减速比,即:电机本身的转子转64圈,输出的电机轴才转1圈。步距角1.8° /64表示,每走动64拍,转过角度为1.8度,转一圈共需要(360/1.8)*64=12800拍(步)
: S" k9 Z- s" H- r* g. _
若是新手,不知道怎么设计电机驱动电路,可以直接购买电机驱动模块,市面上这种功能模块非常多,比如L298N电机驱动模块,只需要单片机6个IO外加一个电机供电电源即可驱动步进电机。
9 Y7 S% I: p7 W7 ` 9 l/ a' j$ V R2 w
L298N主要参数说明控制信号供电:直流5V; 电机供电:直流3V~46V(建议使用36V以下) 最大工作电流:2.5A 额定功率:25W 控制信号输入电压范围: & B) y4 D5 A$ ^+ C" k$ d1 ^
低电平:-0.3V <= Vin <= 1.5V 高电平:2.3V <= Vin <= Vss & ^0 h! I% H( y
使能信号输入电压范围:
) R3 j' g; t; X6 yL298N芯片的输入电压有两个: 如果步进电机为5VDC供电,那么VSS和VS可以短接到一起;, @; o. s2 a0 U9 \9 _8 T$ m. w
VSS和VS两个电源要共地;- x7 j; n" s" I2 w+ G8 P5 e
L298N使用的过程中,发热较大,最好添加散热片。
. d. A# c% S8 X* q: S! }
& h6 e" _5 _7 ^, S3 S
如果想自己设计电路实现电机的驱动,可以参考如下电路。
; v/ a" t6 f) T# N4 ? L298N原理图
5 o* O1 B; s2 N5 }& a. ]应用实例! Q3 ~( _3 J" Z7 ~6 J- S
驱动步进电机驱动四线两相电机,四个状态为1、AB正电压;2、A-B正电压;3、A-B-正电压;4、AB-正电压。 1 S' ]' E- j. d- O& s1 [" G
程序中使能ENA和ENB之后,令StepMotor_OUT1~StepMotor_OUT4按四个状态变化,时序控制如下图所示,即可控制步进电机的方向:
- M) j. K* Z6 m5 ~: l/ e$ T 6 z$ F7 B" p7 ~6 H% k
实现代码1. 驱动步进电机的引脚初始化
1 @: @* I, K# s" e5 }3 g! K- void StepMotor_Init(void)
( X; G* H6 X* j9 o s9 S' m9 c+ | - {
/ m! `( v( ~$ ^6 @$ s - GPIO_InitTypeDef GPIO_InitStructure;' O5 {+ l5 G+ Q6 L$ V) p
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PC端口时钟
; j2 \ I- R+ f0 U$ |9 w9 W -
0 ^: C: B' z5 [( \ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;! T; P9 @: q+ M' a
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
3 d9 C, S/ p' j8 M8 t* x - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
' b' V4 c) t" B' r8 q - GPIO_Init(GPIOC, &GPIO_InitStructure);& ^( g4 C- s3 F1 h* y
- GPIO_SetBits(GPIOC,GPIO_Pin_6);
+ y2 Y% a/ P- W4 |3 Z - GPIO_SetBits(GPIOC,GPIO_Pin_7);
% P C. m$ y* e+ ` - ! E+ e4 O( i- \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;1 g, B7 G2 F% M5 `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
; i: j( i4 I, T, x - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;( i4 @- i- ~1 L+ Q% }0 T, A
- GPIO_Init(GPIOB, &GPIO_InitStructure);0 R! a1 o2 _/ r2 B {/ v1 \) A
- ! s U) Z" v+ e! E7 o, e
- L298D_1AA = 0;0 l# ~6 R3 q& @
- L298D_2AA = 0;: [3 W+ W3 T, @* Y: |5 f- S) o4 ]) H9 |
- L298D_3AA = 0;/ Q9 R% S6 U* t/ c J
- L298D_4AA = 0;
3 B8 d" H9 c" R, G2 [ - L298D_12ENA = 0;
2 U$ a- V, b# |# ] - L298D_34ENA = 0;
% J, W% L% d% i - }
复制代码 0 C3 C% [2 J1 v9 }' l
9 v: [( W. q& W6 o9 }! Z2. 两相电机驱动代码,包括正转和反转5 o4 X$ N. R1 V1 C1 ?6 {8 D7 P7 k
- ' L' g/ h6 q# V# V( U( d' {
- void TwoPhaseMotor(unsigned char nInputData ,unsigned char nDirection)
8 \5 N3 v# z' m8 d" A - {
7 `/ \2 Z) H K6 G$ y - if(1 == nDirection) //逆时针# J9 T$ o. I! c3 f' \
- {
+ C# N7 Y) v" F3 P" `9 q4 ] - switch(nInputData)' r% |* B9 s- |. d
- {( J. B( k5 ?. I) m3 Q' M
- case 1:
+ I1 Z2 ~! x0 v8 } - {# x. k6 k- ^9 o5 j" k& p
- L298D_1AA = 0;/ ^4 H5 M$ h' J+ \( p" I
- L298D_2AA = 1;; p( V. Q8 [, L
- L298D_3AA = 0;# ]. |5 Z7 b0 H Z
- L298D_4AA = 1;
4 X% }! z4 d- X k - }
/ |% G4 D, O9 O - break;
3 p/ v) J& K, w- p - case 2:
) Z# m, U @# ?. {5 c9 i - {2 D/ j4 J I* N* d4 l+ ]8 g1 @
- L298D_1AA = 0;
; h, M! }) S; x6 ~- p; x - L298D_2AA = 1;3 c2 w i" ?7 Z r& R/ c
- L298D_3AA = 1;
, F2 O) w1 p$ h' f* ~+ Q - L298D_4AA = 0;9 t6 b- q# c) G5 s% [" ]) O7 h6 I
- }
% K# F& `1 N$ ? - break;
& B3 G) Y- Q* k, k. |, u - case 3: T$ o* @) Y! ]+ l7 ~3 }
- {
% y' Q0 `& r4 H% D# t+ _ - L298D_1AA = 1;
& ^7 g, S9 @: V9 Q' [ - L298D_2AA = 0;. X* b1 H/ T* Z5 X9 X+ ]
- L298D_3AA = 1;
# I6 o. D8 Z3 x- A - L298D_4AA = 0;
. b( V- S* y s4 q6 u - }* W# V4 s. P* j+ h/ B! l2 |
- break;5 H7 s1 T/ F/ p5 c+ \3 K2 Y0 \
- case 4:8 Y; G1 _" F2 k1 F3 z' s( M: z
- {. i/ \. H9 z+ v% `9 d
- L298D_1AA = 1;
2 @4 n7 b! n3 p - L298D_2AA = 0;
, I$ c0 O C& m+ D+ e# m - L298D_3AA = 0;
k/ \( l$ K) m& ^ - L298D_4AA = 1;
0 ], ^6 ?8 `* i8 l0 l5 F - }1 w: G# S: B! P( C3 G* @
- break;, U* w% Z# M3 M7 |$ ~6 G+ B4 T
- }( g) E$ L% a. m6 v
- }
$ [, k% Y, I$ |" Q6 g - else if(0 == nDirection) //顺时针* u9 n. c9 S5 g2 C8 V& M
- {4 Y3 p* K( w% h+ g1 _- k
- switch(nInputData)
9 ]$ y2 d! Y% R( [ - {
, S1 m0 x }4 C$ x. b5 A - case 1:
+ |% `: s9 J# { t. |: H* I/ h - {$ N1 S( s. G8 I0 D6 W4 ]' w( [3 V
- L298D_1AA = 1;9 L5 r+ S) O8 o, F. Z: L. A/ x
- L298D_2AA = 0;% C* ?8 m8 B/ \% s
- L298D_3AA = 0;$ g8 ~5 b6 L0 t" F; b1 y
- L298D_4AA = 1;* G4 e! }, y: B7 |
- }% i( W3 K6 u0 E6 h) h1 N
- break;
! E6 D9 ^) j4 b0 Y! w( G - case 2:
1 K# [: U5 U9 i" a: R6 _ - {! h4 n# K9 |+ _
- L298D_1AA = 1;
9 }: T0 u; J6 @* b - L298D_2AA = 0;
9 x$ q/ W+ L/ M/ M3 _! s; R - L298D_3AA = 1;: N6 A# A7 Q( @$ [4 n
- L298D_4AA = 0;
, { ^9 Y3 |0 j7 F - }1 v7 \7 }# ~ v% `! `
- break;
& g7 e; N5 h/ k; J5 ~! C* Y- b) J - case 3:
1 F! q5 s& n" f* d3 A4 ^% ]4 H - {4 S1 p1 r* t0 D6 K0 o" t" n! U
- L298D_1AA = 0;) w& W2 T; O- z. R4 ~
- L298D_2AA = 1;
5 S0 l$ I+ {$ G4 V, }; n+ E0 V& } - L298D_3AA = 1;
* x4 O: Q( R: Y( P - L298D_4AA = 0;. c% d; ? `; p- i
- }
5 x E' W: m( h% e+ A% @ - break;: g! _$ E8 K# d- C8 z# ]
- case 4: B3 m; d8 L# D% O
- {
% q8 b6 h. i2 C - L298D_1AA = 0;/ t9 ]4 F7 T3 _) J( P% l: L
- L298D_2AA = 1;! ?( b7 Y | y! x4 @: v7 S; T
- L298D_3AA = 0;1 S+ ?0 r; E+ g: Q3 {
- L298D_4AA = 1;
+ ]4 m- D5 J, C- T - }
, G1 S6 p* V5 J; P3 l# ^0 t+ \! O - break;
1 M& L$ e! L" N+ b) [; R, e - }
; C: j; J8 }) d! y - }
" W/ H s f8 X - }
复制代码 ' E; W+ a, u/ @4 b, @9 ~
9 K i8 H1 Q( u5 q( s% m7 ?# }6 A
上面函数调用一次,步进电机走一步,对上面函数进行封装,既得到走任意步,可控制方向的函数:
& P/ I# U8 v3 t! f2 B( q- void TwoPhaseMotorNCircle(int n,unsigned char direction)3 @" T& k8 V7 n! M
- {
3 u3 `0 Z7 v" r4 Z, b w+ x - int i,j;
2 C& Z. B2 C" J8 T& W) K7 ~2 [ - 3 \; Y& Q3 q6 F+ O* m
- L298D_12ENA = 1; //只有转的时候使能,否则持续供电,芯片和电机过热。& X* p+ u1 n. w: ? `; h9 V7 J6 E6 `
- L298D_34ENA = 1;! l) a. k+ V$ `
- 0 }4 m8 ? t$ G* s/ p" W) a
- for(i=0;i<n;i++)
( b9 r, q3 H1 t, B1 a% f+ o9 r' g - {
) [# ]! ^5 \2 k! Q - for(j=1;j<=4;j++)5 ]! E1 ?. u0 p) R ^
- {
' d1 x% D, ^& c. M. o: ?$ X8 n d - TwoPhaseMotor(j,direction);
* j' v0 q' A+ c( K4 v/ b( o6 g1 c - delay_ms(2);
* S: _' P' j9 e0 w6 z% j0 _/ ?1 I: a$ \* y - }
% Y" f& t {! k2 R( A) m - }! F# O3 J% t% _" X
-
# \: A; R. A* L0 F, l/ K, Q - L298D_12ENA = 0;* I- a# u X# P6 q( }; u+ k
- L298D_34ENA = 0;$ C* V7 t0 H& E2 S$ ^
- }
复制代码 6 _& h& N: x e+ v/ y) t. |; W
3. 主函数中调用说明:$ y9 l( B( o( H" K+ C# a$ b
主函数代码如下:
( s& }* o4 R6 V% ]. ]" O6 Q- ; G4 D5 p0 b- e. o
- int main(void)
/ E+ D' j. _* C) ? n2 y: L - {9 W$ v% X8 D/ c6 O. _" }
- //解析payload数据包使用# @: D8 T& G0 B+ ]
- cJSON *receive_json, *item_obj;* c9 q# H5 o \" J J
- + H+ f& c% z* l2 w) a
- u16 i; J5 u* R! E. R r2 g; l
- u16 uart2Len=0;
3 Q ]' ]4 ?8 t _2 l -
. J% K9 H, u7 o. x - u8 dtbuf[50]; //打印缓存器
8 w' G) L- e/ N1 i - / j S2 z B) [2 D7 |% ^( |/ i: K
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);" T- l# }; O; F$ u* ~3 V
- ; ]8 T8 p8 C s" c
- USART2_RX_STA=0;
) y& v7 P! E. ?$ z4 {1 Q - memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF));* L) l8 W: X4 ?; q0 w; `8 s
-
! U( N1 t, H$ B' M$ p - memset(dtbuf,'\0',50);. A* b" Q# O4 d
- - d w: Z4 z b; I
- //初始化
/ t( j( _# |( u - //延时函数初始化9 [. I- r. P6 D
- delay_init();
: ~4 s/ ]# s5 U4 R s9 v -
2 w" Q9 W" w8 \ - uart_init(115200); //串口1:Debug,初始化为115200
! g y* [/ v0 M: m, ]6 {: _- h - uart2_init(115200);
) e d0 a& c/ X# s2 Z8 ?/ R -
( H/ ?( x# _* z% Y& O - //定时器3,--步进电机使用
8 Q: q6 S- k& z1 s+ b - TIM3_Int_Init(99,7199); //1ms中断
& ^! Y' z9 X7 o. {9 ~ - TIM3_Set(0);1 r. x, [9 ~. C: N' }6 U, |- C8 [) p7 W
) ]$ x) \+ {8 P* l! T- StepMotor_Init();
$ H$ @: v0 M& U8 Y8 Y - 4 A% Y3 N% j7 P0 g
- printf("System Init OK \r\n");
! n% [5 i8 D" o. S% U - ( s, @ a! c1 Q2 A
- //主循环/ Z( }3 ]0 G6 Q4 n; }4 N; ~: z5 U
- while(1)
4 j% p' H8 s5 B/ f: J - {
. Z1 o5 j; o, C$ j/ j3 r; U - //ESP8266$ T, q; d+ Y) w
- if(USART2_RX_STA&0x8000)" @9 @5 y3 J# l- t: G
- {
5 m; x) W, h7 M3 ^+ \ - uart2Len=USART2_RX_STA&0x3f;
, Q' F6 [* P. N9 e - & c9 l" k/ B I8 {
- receive_json = cJSON_Parse(USART2_RX_BUF); //创建JSON解析对象,返回JSON格式是否正确4 F- \. N; ?+ ]/ y
- if (!receive_json)& r7 R* W; x ~$ b6 \4 c6 g0 W
- {9 y; L! H' b% H4 |6 k' \
- printf("JSON格式错误:%s\r\n", cJSON_GetErrorPtr()); //输出json格式错误信息
# p0 v! P3 K: } - }
1 N2 h! o: M9 ]1 E+ z2 H3 ~ - else
! |+ e# R1 m0 m - {+ v; k$ ^- o9 X, X. F+ Q: }
- printf("JSON格式正确:\n%s\r\n",cJSON_Print(receive_json) );( g* S' M' F' C- D0 O# `
- item_obj = receive_json->child; //获取name键对应的值的信息4 J$ Q3 x; Z ?4 f9 s# [, E
- r' a k& G' m6 W
- while(item_obj)$ ]+ ?( Y( I( f4 G0 X1 q
- {
F) v% a1 N" r, z! u% B5 T - char * string = item_obj->string;
3 {) G7 o* ~5 n -
: z' h1 Z/ ` y7 }& B - if(!strcmp(string,"PowerSwitch"))
* v8 H2 S" w: Z% O& I - {( j- ]. ^6 H" e0 I, e2 P9 A
- if(item_obj->valueint==1)
' {) S3 q& T, G& B' T) O; E - {
% Q& @3 N6 ?* ` f - L298D_12ENA = 1; //只有转的时候使能,否则持续供电,芯片和电机过热。5 c( Z. z: Q/ Q7 u( V' D
- L298D_34ENA = 1;
- \% x1 r* e4 P# K# y -
( o2 ?+ u7 `8 H! P' K - TIM3_Set(1);
8 h5 H* U' G; \. S - - U* L/ y! G0 i0 K2 b9 i
- nRotationCounting = 0;
& j! ~- m) ~8 S; a( b - * c" g, X( h" z3 j5 J. @. k& V
- stuAliOSIoT.PowerSwitch = 1;
- O' {/ P" p" I' X9 \$ s - # k( r5 d7 E$ c/ m* ~5 p
- printf("PowerSwitch:1\r\n");
" p8 q" m# p1 H - }. r1 B9 l* f, I
- else if(item_obj->valueint==0)
. D% H* s; Q1 }! D - {3 ]( w$ X0 X2 d7 I% E
- //步进电机运动停止8 _3 B) h, u, ^: C" E! {4 v
- L298D_12ENA = 0;. ~3 P4 Q6 M0 N" s" y% v5 R% u7 l
- L298D_34ENA = 0;& [8 B8 k: Z. i) h7 Y+ r2 Z
-
; d) j* h7 E* V - TIM3_Set(0);
+ H* W6 \/ }$ v& u9 n -
% N; t" E* v( z. }' Y3 ~/ q/ M - stuAliOSIoT.PowerSwitch = 0;
0 f4 Q r% k, V! N1 r - 7 w8 ^$ g x# i6 E6 D7 l
- printf("PowerSwitch:0\r\n");
+ {$ k [6 D( s( t- B: ^ - }2 a, l& p- n3 X8 v& L1 u" G
- }
$ [4 E+ u( p+ L" Z* w - % x5 C k+ F3 @
- item_obj = item_obj->next;, c; W, s k; I) H& [% W
- }. r/ ^/ L }( ]5 i3 j9 [: E& R
-
* |, A. W+ O; f - cJSON_Delete(receive_json);
$ m& i/ i, T5 W3 H. [, T -
9 e, n3 f! |9 t$ B8 m/ O7 c* u - }/ H) D8 w, u& k3 C3 }& l0 c
-
5 v" ]/ d! c) i - USART2_RX_STA=0;) H6 i3 l& N0 t) F0 X
- memset(USART2_RX_BUF, 0, sizeof(USART2_RX_BUF)); //清空数组- ^; a; Y0 g, { }! n5 E
- }3 D/ O! i M. }- I# m1 y
- 0 h' W9 ^6 t0 \
- delay_ms(10);
* P3 H7 g1 T! T O - }
. X2 U: A8 W$ ~5 d2 h7 @ -
8 h6 s2 @: S* e. v! H" B$ F! j3 ]; G - }
复制代码
1 D: n J8 u3 `2 Q
定时器中代码如下: - 9 g" `+ f2 Y! r" n5 ?
- //定时器3中断服务程序
& e; G0 s0 l( ^9 D8 J5 P1 u- b8 Q - void TIM3_IRQHandler(void)! q( o' b' O$ L9 Q7 X
- {" X7 e* z8 E* v# \+ j# Q) U1 @
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断: x6 H, O6 B# O7 @
- {6 B4 P- T3 X$ J
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIM3更新中断标志
7 ~ v% x: F0 ~ -
! c$ {8 J9 ?9 W$ T - nRotationCounting++;; v3 C, M7 O6 }0 \- h+ m" Q
- if(nRotationCounting > nSingleCycleDataPoints)
; b$ A% e( Q( j7 Y - {7 X. {* g. Q) C, Q; c. n6 ?' ^9 Z
- if(nRotationDirection==0)
/ u9 h5 A$ N! n) U" k - {1 n% t r1 m _+ h: A) |
- nRotationDirection=1;9 H3 k+ A: e- {- Z* e
- }7 Q ~+ T7 L% y" p" b; M g4 @
- else if(nRotationDirection==1)* H. t1 V1 r- v
- {
2 P' ~) s+ I h3 z, Z) T' n, y' ^ - nRotationDirection=0;7 ?+ j3 b# M* W G
- }0 @' v0 \) o2 j4 H
- 6 m, w. K- G1 v" |. Z
- nRotationCounting=0;
1 b& q/ G5 a( ]% P( ? - }6 Y) k! M$ n# V7 t3 ^+ \" c, ?
- ; s- [: k& F% v c
- if(stuAliOSIoT.PowerSwitch)
: D- W+ {4 v: D" S+ p3 T" O - {, r1 T% j0 B1 _7 s, @
- if(nRotationDirection==0) //正转
9 q5 E8 Z2 j% G# K8 n' u - {( s& B( P6 s+ Q5 ]
- TwoPhaseMotor(nRotationCounting%4+1,0); //顺时针1 b P r2 a; a9 k6 `! k6 ]- Q7 h0 F
- }6 N1 Y8 Q6 V/ Y( [3 O$ ?4 V
- else if(nRotationDirection==1) //反转
5 O& Z# X* y$ D; R9 k$ q - {5 Y; b* W) s0 g1 b
- TwoPhaseMotor(nRotationCounting%4+1,1);2 @3 v' Y/ N- |. u
- }
8 g0 P- i/ Q# P3 T; R - }/ t" l7 u" @7 c
-
3 ~3 E3 C3 C n/ s4 F1 U - //TIM_Cmd(TIM3, DISABLE); //关闭TIM3! M) K# v; `1 x$ Q; j" [$ A
- }0 d( I. m7 Q# [8 Z, @8 M
- }
复制代码
: j" }, `6 t& F! a* q
+ q8 |6 ?# U7 c8 G% X/ L实物图电源座用于提供外部VS供电;
4 Q/ }3 l3 I7 g/ X6 t; K0 f% u2 `
6 v6 e$ d8 y) y |