前言
( J3 O! ~, ~; z8 u$ H: ^本篇文章将带大家学习STM32智能小车的循迹功能。0 F5 c y; F/ k1 T. ^+ B" @' g F
1 K0 f" e F( f8 T( U, F
一、红外循迹模块工作原理及接线图4 _9 g, }% A7 U$ _9 Y4 _+ C& r
红外循迹模块工作原理, n9 n1 d" m3 G3 U0 ]; u; E
电路工作描述
& f( N$ ]* K' V- B- U; |以其中一路为例
; K& \# L, t7 ]% ?2 M* C3 Z0 X" \1 D6 ^- E9 p
) h6 x' A3 f5 A& P5 T7 n" l+ u8 ]2 j8 W) C0 k# `# b( y3 D
TCRT5000传感器的红外发射二极管不断发射红外线,当发射的红外线没有被反射回来或者反射回的强度不够大时,红外接收管一直处于关闭状态,此时比较器LM393的2脚的电压低于3脚的电压,输出OUT1为低电平,LED1为点亮状态;当红外反射强度足够且被接收到时,比较器LM3932脚的电压大于3脚的电压,输出OUT1为低电平,LED1为熄灭状态。简单的可以理解为遇到黑线灯亮,遇到白线灯灭。7 ]& p% c: C5 o0 _- a7 g/ L: [: S
) v# W1 W M) ]3 d* d% j0 D红外循迹模块和STM32的接线图+ `3 Y7 B9 V* P. H9 q: k
此红外循迹模块使用到了4个IO口分别接到了STM32的PA4~PA7。
1 x9 N3 f# V; Q6 x' F
$ N9 q+ U$ Q; h& }3 w6 r% L1 i5 Y
+ i6 z! r" t6 \9 u
' O k% g c: [) k二、cubeMX配置1 Y: ^' _& _, y! d8 E+ S
将红外循迹的4个IO口都设置为上拉输入模式即可。3 F. z0 @$ j' I
2 U' ]: w- U, X
0 }' v D/ q- z1 f1 H, F, I; k
( k- M z# C: {* Q' N5 v$ ^( b三、代码解析
6 u8 [3 X5 l0 p/ _3 Y% V' N5 V5 S* Qfind.c
% p; D& N1 L7 J& z5 G% v
1 d0 u# g% d8 n; b- #include "find.h"
! ]6 B4 V7 ]8 u0 |& E3 x9 ?7 f# E/ [ - #include "Moto.h"! P6 e* m+ o5 [3 d/ C" y
. `2 Y3 p$ c- k2 s9 s N7 N1 U- extern TIM_HandleTypeDef htim3;
& I# R5 O) R7 X( g - ' x& a; B. z9 y3 d# j7 e$ R
- /*9 V, I% u8 _8 A3 T
- 函数功能:调节小车左右电机PWM
; H: q$ r- r8 } - Left:左电机PWM
- R- B$ Z- y5 s - Right:右电机PWM6 @4 C' P0 ?* [) C! B
- */
* w& z* p% z2 |5 d - void Moto_speed_set(int Left,int Right)
) r+ }: A- R' \- A J - {
4 C- ?2 I2 T$ R8 g$ t - __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, Right);3 O" ], G7 k% J8 Y6 S
- __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, Left);
9 v9 d5 X! Y; k0 _! f9 I - }3 g7 Q4 J! D" n9 p6 ]
( G& c7 o1 J8 K% S, V+ l" t- /*& R5 h: s* M- o
- 函数功能:循迹1 B, o9 C ^& H" @
- */
. V* X* x0 z$ o8 ~ - void Find(void)- ?1 `$ |( i K% M" d5 e; U, }
- {9 U3 t+ k9 w3 z2 y* X& g2 t
- //全是白线前进' [- Z5 {" z1 D! w
- if((IO1_read()==0)&&(IO2_read()==0)&&(IO3_read()==0)&&(IO4_read()==0))* l# y, O% P' X: B1 g
- {2 w6 F! K1 a5 d) M; {# B
- Moto_speed_set(800,800);
0 ?" }7 @$ g; D: x - car_move(0);
! o6 L* Y3 N2 T% z7 e" ~+ o - }- ~2 O2 m c" Q6 K; f
- //右边有黑线小车向左即左轮加速右轮减速
: U0 `3 F+ ?* A) |. P4 u7 r - else if((IO1_read()==0)&&(IO2_read()==1)&&(IO3_read()==0)&&(IO4_read()==0))
7 I0 W7 n( V @% x: P8 ? - {# |+ y5 s! |0 w
- Moto_speed_set(800,0);
6 a% k. p& o- c! f( b5 }7 F( S6 M: M - car_move(0);
: O* D# t! \4 }# C - }+ }) {+ o( M" C; W+ [8 E# _* d
- //右边有黑线小车向左即左轮加速右轮减速# u2 n' a5 j* g0 {" W# L
- else if((IO1_read()==1)&&(IO2_read()==1)&&(IO3_read()==0)&&(IO4_read()==0))5 w! Z% Z( D, s4 B& S5 @, |; f
- {$ F/ ~+ b1 @4 a
- Moto_speed_set(800,0);
4 n/ h6 S' l6 L5 t. U' F1 Y1 w - car_move(0); . f2 }0 J: `. Z X
- }9 T$ {6 ~+ p7 u9 O- l+ u0 r
- //右边有黑线小车向左即左轮加速右轮减速
" c; B5 \8 b) r" F* `7 a - else if((IO1_read()==1)&&(IO2_read()==0)&&(IO3_read()==0)&&(IO4_read()==0))
0 g% w3 ~- P) T2 o% { - {
8 [0 B2 C" Y2 H# \+ l. j" r+ g$ U - Moto_speed_set(800,0);
Z$ e; h4 ]+ |2 } - car_move(0); . V5 s. m* I0 e& a
- }
; ^, d5 _' D0 X; i1 L* i0 b( s - 2 C* h+ e& F- K; f8 J9 z
- : Y/ T: r' ^/ R: D+ M/ q7 W
- //左边有黑线小车向右即右轮加速左轮减速1 d' L2 V( _; Q; [! h# W
- else if((IO1_read()==0)&&(IO2_read()==0)&&(IO3_read()==1)&&(IO4_read()==0))
! v7 u( L* A+ Y! }' @+ w - {6 O8 o" i3 I9 m2 h" r9 f- {
- Moto_speed_set(0,800);
# x. D* u3 s( k. J# D - car_move(0);
) d1 M! h% m' a, X8 c( e - }
' M7 M+ {+ `' `$ p9 Z9 A - //左边有黑线小车向右即右轮加速左轮减速
+ ~, R9 z2 E& y/ B8 |% O0 g2 J0 m - else if((IO1_read()==0)&&(IO2_read()==0)&&(IO3_read()==1)&&(IO4_read()==1))
: K+ l: [3 j' ]2 t& ` - {# X/ M$ H4 N9 z5 V8 q6 i
- Moto_speed_set(0,800);" O! F- P, }8 {
- car_move(0);
- j% A5 u) v* z - }
( e' h% L4 q3 {$ q - //左边有黑线小车向右即右轮加速左轮减速) L. K( a" Q) z3 M) [/ K/ N' ?7 W
- else if((IO1_read()==0)&&(IO2_read()==0)&&(IO3_read()==0)&&(IO4_read()==1))" F7 n8 A0 S' Y/ }
- {
: |2 d1 Z3 b0 M( {4 x3 R - Moto_speed_set(0,800);
5 I0 ]* L4 l4 x: y) {& `0 E! p! \ - car_move(0);
9 e0 S. R* ?, F( f6 I) F - }6 P0 a9 k% |$ i1 G
1 R) O; g1 Q- U* q4 p$ ] g6 H- //全是黑线停车) Y: k0 u& j/ ~
- if((IO1_read()==1)&&(IO2_read()==1)&&(IO3_read()==1)&&(IO4_read()==1))- x$ J/ X1 u( d5 L; T9 w& \6 R
- {
1 `+ f( u( v: ` - Moto_speed_set(0,0);
1 _0 u- z) J% O% { - car_move(2);' S4 `& g( t& W& a+ l( e O( ?+ R
- }! _( u+ n; S' W& o! y
- }
复制代码
$ J$ `6 b3 ?2 t# o# w; g# tfind.h
1 a- A4 O/ [/ J$ U2 G7 R+ ?! d1 p- R7 _% `+ d; m: R, i% H5 `
- #ifndef _FIND_H_0 E* P: Y }# a
- #define _FIND_H_. o+ c4 q+ v$ [# g) x) v
- 1 h* Z: N+ B, {+ E$ Q- h
- #include "main.h"
6 C8 X8 L) K! m8 I) W: f1 M - * S9 }! t' Z' v2 D
- #define u8 unsigned char
3 o; D: Z2 k9 v1 q0 l/ c9 A - #define u16 unsigned short+ n" a! V- |+ p; r% e; f! l1 X
- #define u32 unsigned int4 {$ d$ H+ r8 V% J
, m2 v: i0 Y! \) M" l* q! L- //红外循迹IO口定义
! K; y) p/ q- E# j - //传感器从右到左 IO1 IO2 IO3 IO4
1 G1 |% `+ y% x! i# b% P; R8 U- \ - #define IO1_read() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4)
- x% T& u4 M4 A8 P" ^) O - #define IO2_read() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5)
% F# {! U% u2 n& T4 D K - #define IO3_read() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)
; w/ p8 j( ~2 q4 \; s+ G5 } - #define IO4_read() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)
- F! |5 ?: F0 J9 ?9 W. {5 N - 9 N% o+ b/ g w5 K, _
- ' A- g, _! A9 x9 W( V" J) `8 q
- void Find(void);3 B8 G0 ]8 y- S$ b/ o: J6 l I4 ?, S
- void Moto_speed_set(int Left,int Right);
3 t6 Z% [- a" X8 y
v0 q8 t1 R. n
' o% C3 E* z4 s" \- #endif
复制代码
3 n- Q, j+ U+ ]; T) C x* n总结4 m- O' }( G# L& C) F3 q1 K
循迹代码已经贴出希望大家可以好好理解一下循迹算法的编写。
4 M: N. ?4 Y/ l6 G$ I0 C, J: }5 p; l5 O% R) c
B$ A0 c! P) u+ |2 T: d$ o; n
|