EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 jacky401 于 2019-7-16 18:15 编辑
7 a. {! R5 B# T8 K5 P8 _4 `
, O3 ~5 I4 I ]: n5 B1.试验设备及接线
- d: b# i5 t' Q0 M# _1.1实验设备 · MiniQ 桌面机器人底盘 5 n' d5 S) j2 g0 J$ a
0 j0 X( l6 }& |
- 底盘直径:122mm
" [; K8 H J. q( a- 轮子直径:42mm 5 ^: }2 t1 {1 B! G5 F
- 底盘高度:15mm ; O$ e; O2 N; `; Z. R
- 兼容 Arduino 标准板及 Romeo 控制器固定孔
- `; c* w) X* n/ k2 l$ |4 X2 Y" V7 C- 电机参数: · N20 电机电压:3-9V · 无负载转速:13000rpm · 50:1 减速箱 · 260rpm@6V · 40mA@6V · 360mA 堵转@6V · 10 盎司英寸扭矩@6V · Romeo 三合一 Arduino 兼容控制器
% U C8 O0 u- v5 D7 A0 m# M- 采用 Atmel Atmega328 单片机 + R, X* X6 X; ~& y: K
- Arduino UNO bootloader ' r2 J5 Y3 `9 a2 f
- 完全兼容 Aruduino UNO 的端口布局
/ n0 C# @# i+ w+ |- 集成 APC220 无线数传和 DF-BluetoothV3(SKU:TEL0026)蓝牙模块接口 1 I! z x# T5 N2 G$ g0 [
- 支持 5 组 I2C 总线接口
6 y6 u2 X/ ]" y( ^$ E- 支持两路电机驱动,峰值电流 2A,4 个控制口使用跳线切换
" _4 L: g( I3 l2 k3 Z/ W3 Q- 外部输入电压范围:6V~20V
8 e- L$ v$ N! a9 J" K- 更详细的参数介绍详见附录的网页地址。+ A1 u5 S- ]; S- f
1 y9 z9 W# P# q& r$ I; x$ S0 M
· MiniQ 小车上层安装板
& d# _2 P6 P+ J u
3 z2 B9 T- f$ C: y/ n8 r
· Benewake TFmini 标版
; N& N1 M: V8 h g
TFmini 详细参数见 TFmini 使用说明。! R/ M& Y+ X% }! T
7 @/ u; U7 Y" U- ]( R/ O% L& h8 ?
· 9g 舵机
5 \/ D' R8 c+ f6 p5 _' w
1.2接线1 [- T# @2 E' F
4 N- g" p' v; l2.小车避障原理- i! K4 Q0 H% t% ^ ]
小车启动后,小车开始向前运动。当雷达探测到前方阈值内有障碍物时,小车停止运动,开始左右扫描寻路。舵机搭载 TFmini 从 90°开始向 180°扫描,然后从 180°向 0°扫描。+ r' k7 t$ R* _2 G( D4 P+ @2 [
4 m0 z; b- T! c6 T当扫描方向无障碍物时,小车向此方向转向,舵机回正到 90°。若从左至右扫描一圈都没有可以行进的路线,则小车后退,舵机回正。 9 O8 ~) R8 d2 k" v
逻辑流程图如下所示:
6 F; B& L6 y9 L( H* ?% V
; y6 T4 t7 \* ]6 J w7 X7 z# i- f3.注意事项 · 当前避障原理模型只用来抛砖引玉,探索用 TFmini 避障的可行性,并不能大范围的适用于大规模的商业场景,如有需要,应以专业软件开发人员的代码为准。 · 搭载的外部电源过重时,会影响小车车轮的摩擦力,可能两个车轮的转速不一致,导致小车并不能按照轨迹行驶。 · 小车车轮在光滑地面有可能造成空转的现象,导致小车不能走直线。 · 如果单独对 TFmini 外部供电,则需将外部电源和控制板共地处理。 · 如果搭载更高复杂度的程序,要考虑芯片的能力,当前开发板在跑程序时已经发现会有卡顿的现象。 4.附录
, _) T1 w$ Z! S/ ?, R* j4.1代码$ H! I$ c1 ~) }1 t% O/ ?0 K5 o
#include <Servo.h>0 N' @% E9 ]# P! n% V
Servo myservo;
+ a/ t4 y4 V$ x9 L) V! `5 g& ~int pos=90; //定义舵机角度, v2 I; z% k. C2 F! Q- r3 ~
bool flag=true;//定义舵机转向
" h6 g+ E& ^: Y1 n. j0 ^float dist_f;//定义foward 方向距离9 `( X9 r' Q" C5 Z8 f" G0 ]+ T
float dist_s;//定义sideway 方向距离% w" o: z+ _: Y n# c1 o* m
int E1=5; //定义 M1 使能
# c, h" o& p7 X7 Aint E2=6; //定义 M2 使能- d( I$ F* W$ e
int M1=4; //定义 M1 控制+ ^+ G- O! r: M
int M2=7; //定义 M2 控制" Z& n. {) {* F) s
int temp_distance =0;/ R: u# W4 t7 x: d8 z
/**) v8 r/ V3 y$ d. v+ g3 X
* 双轮停止
5 i5 ^& h* W* K& ~; j( g*/. X9 X, |; k6 ^5 y1 u8 i
void brake(void){6 P& ?& g) X k6 Q9 y
digitalWrite(E1,LOW); //给 E1 低电平
: }5 p+ a. V, [/ o: BdigitalWrite(E2,LOW); //给 E2 低电平
3 C T+ u( Y% n' `' ~' o' Z}0 N2 ~, }/ c! b* c f5 }6 M& N
/**2 J8 w8 e& d6 H# w
* 双轮前进$ Z- n, J d/ j7 x' I7 ]
*/5 R7 j% U7 d; B+ W( J- W6 |3 R
void advance(char a, char b){
; d: t0 I$ p3 K' canalogWrite(E1,a);
5 T' |4 i" \/ }4 QdigitalWrite(M1,LOW);2 k g2 I6 w+ q: e4 Q
analogWrite(E2,b);
/ F' s9 q. g$ P, [6 Q0 k9 \+ }0 y! AdigitalWrite(M2,LOW);
8 g6 a7 ]; p% B}; y1 N, F" b. @
/**
" F8 n. K1 t- i# a3 `9 K* C* 双轮后退
( o1 d; b. j- X! s! q$ q5 d*/
' f4 V7 K1 Z/ w; pvoid back(char a, char b){
! Y( e6 x* g2 @7 c( oanalogWrite(E1,a);
+ a! H0 i- J- K& x( VdigitalWrite(M1,HIGH);
+ G* T6 y) R9 f, z% ?' RanalogWrite(E2,b);
/ t+ x, u, F+ v5 W0 j, r y6 @digitalWrite(M2,HIGH);
, |1 H/ F( n" y% n}
j/ y2 T' a' j6 \( r" H/**
2 p% m1 l) n. | L4 M* 左转; S0 y! ?0 s5 Y E* i ?4 c1 i
*/
; `- D3 O! D4 jvoid turn_L(char a, char b){# q$ y$ l, M1 ]9 n1 I8 _
analogWrite(E1,a);. @. L) \) x$ l+ r" L
digitalWrite(M1,LOW);' S! v3 v5 `$ Z0 J1 `' U3 X
analogWrite(E2,b);
: ^/ f$ j7 K, I- F! {digitalWrite(M2,HIGH);
+ F/ A. x$ A0 \+ m4 v! V" ]% h7 T}+ j: r+ N% P6 I7 `
/**+ v) E" U8 {4 ~# `/ `3 V2 X
* 右转
/ u+ j6 z: o& n- O' D" w: \7 \*/
! g/ J3 C' y9 r+ w- W( mvoid turn_R(char a, char b){# e Y3 t+ S. N* Q3 B
analogWrite(E1,a);
2 u3 m( L- f$ j/ i$ YdigitalWrite(M1,HIGH);* w2 m- t+ x4 o) a
analogWrite(E2,b);
% [6 m1 I+ f3 M% Q% ^& U' |digitalWrite(M2,LOW);
+ ]$ o! O7 Q- ^}* q% v. U. l: |
/**
$ P! B- s1 K' N) U* 读取 TFmini 测量结果$ m5 R7 ]$ U o# X ]' q. n
*/; P3 @9 h1 M) I, f0 n8 d- M' K
void getTFminiData(int* distance, int* strength){' Z ?6 Q. y2 C+ e* A, j
static char i = 0;
( m+ e4 O: T7 u+ Nchar j = 0;
0 X' b- P4 }) l: L9 h) l( `3 eint checksum = 0;
9 O* U+ }8 ] T$ }2 S f& Ostatic int rx[9];
) D( t4 I: I5 Yif(Serial.available()) {
4 [+ U! e* V# w q9 \& Zrx = Serial.read(); w! z0 U# D' b: B+ J3 k
if(rx[0] != 0x59) {
2 ~) Y% L# _9 W& W* m* ji = 0;
$ F9 U. a9 Q) j% d) q8 V. }; k5 t' o. n} else if(i == 1 && rx[1] != 0x59) {5 s% H3 v, a2 q7 I" p) J
i = 0;/ l9 l {2 T: x1 O9 h
} else if(i == 8) {! ^8 Q0 [7 M5 c
for(j = 0; j < 8; j++) {
; R0 m3 z' m* _. N( Q6 g$ |0 Q% Wchecksum += rx[j];0 S4 M5 b- n# m9 p' S8 `& b
}
) d$ }" G6 a0 E6 w& z/*2 B; h; u( \/ v4 t1 \
if(rx[8] == (checksum % 256)) {
! P7 o. _7 m/ w d, _*distance = rx[2] + rx[3] * 256;
7 i2 f8 g+ o' P( l*strength = rx[4] + rx[5] * 256;
( ~$ t4 j, W3 \" I6 K0 `1 A}*/! E% k s8 K# E/ v: [" a3 s W1 b: N
*distance = rx[2] + rx[3] * 256;
5 |2 D$ v y% R, o6 ^* F*strength = rx[4] + rx[5] * 256;+ S y9 |2 m* C: I |. T
i = 0;
8 M2 [% X6 O' U* l: @' a1 I* x} else {2 f+ H9 _' i0 D3 P
i++;" G( P! I G9 ~6 c
} j/ A _5 j$ ^0 X
}
7 m P1 u3 \% o1 q0 T7 l% X}
; ~) w2 X {; k J) ]2 I" Lvoid setup() {
+ W5 d( j1 Q* `) }" [7 J8 c1 X. b9 S3 P// put your setup code here, to run once:. c* V- L/ v" l. F" q* [2 D0 a
Serial.begin(115200);8 ?/ t5 w, S# ?& q
//舵机的插口在 4
2 o0 O" C; I0 umyservo.attach(4);
$ ^' {# z) j$ X+ x7 E- m! |; c/ Xbrake();
' g) {0 A, \) x( W0 }+ l: ]4 f5 _/*2 ~: h s% |6 T7 P- ]
* 将雷达指向前方
/ r; t3 w1 k* b# ^*/! \* t4 ^6 P, h) P+ F& i1 o
myservo.write(pos);1 T7 }* W$ V C" N9 J. v
/*
% b) ]& ?* e# [+ m* 设置轮胎电机输出口
, N- g4 j: l6 r0 P% ~, J/ h' b' [7 n*/
: [, B% g* J* ApinMode(4,OUTPUT);" w6 r* y+ ?, S: L& I
pinMode(5,OUTPUT);
: s5 J+ m3 J4 C8 _. P- BpinMode(6,OUTPUT);( o, J1 X/ k, \4 K! n3 [/ M
pinMode(7,OUTPUT);3 R0 T. b$ [8 M/ T- \" W" ?
delay(10);& i0 n8 {- W4 H/ W; G- |
}
2 r0 G$ h2 P. Uvoid loop() {
7 Q% _& ~" e6 x+ a3 U( {9 ~/*
# `' b6 e; [) ^* g8 |3 d* 读数一次' R" N/ A' d7 H6 J8 E& I) U
*/8 M4 m1 P, U1 Y. M6 L
int distance = 0;
3 J& P1 h$ J4 K6 J5 b) ]int strength = 0;9 ^: v2 Y# ?; u, g6 x
getTFminiData(&distance, &strength);& H# ]$ E; L. y; ~$ x% u. c- O
while(!distance) {
3 S7 C4 n/ f- @2 \4 l( vgetTFminiData(&distance, &strength);6 `+ R) O8 \( e9 n b
Serial.print("Distance: ");
$ S, I4 {8 S0 j+ `Serial.print(distance);/ b5 R0 Y5 y6 f, Y( z5 C/ |3 f- G
Serial.print("cm ");4 Q8 m. q; e+ A# p# `* S, @2 _
Serial.print("strength: ");
. _# w: ~' k, n0 l$ A, D* XSerial.println(strength);
, E. a7 z/ q) Q( ~; i( b}
, M0 p9 c& ?6 _ {2 Q/*
( w. [: A; K& p, r: l* 设置 30CM 阈值
6 W4 g5 s+ A4 r*/; X0 ?+ A6 E; r( ]( w% a0 _5 d5 [
if(distance <= 30 && distance > 0){& G3 x7 x# Q# ?/ n. c
temp_distance = distance;6 p+ k( f/ F& j2 k4 ]2 f f t" k N
}7 m# O5 U& Y' X. o- L$ H
delay(10);9 z8 G/ P5 ]& L: Z) G X! o x
/*. f" Z) C' q$ h" N; w1 r9 u; @, r6 ?
* 判断读数距离0 F/ Z; c' y+ ]
* 如果度数距离小于阈值,则停车,开始向左向右扫描,直到扫描出有空隙可以走,然后车轮转弯,然后扫描器回正/ w/ l, r& c% z1 p# F
* 如果读数距离大于阈值,则开车- |' `1 K0 t+ d+ G" Y5 R; {) [+ s
*/
' O3 y* O; _" Q( m X& Bif(temp_distance <= 30 && temp_distance >= 0){
4 O4 P- g% l2 |* \1 ?- X* Hbrake();: R2 x. e' s- P: ]# V4 B" d
/*
6 J2 @- K( R* `2 `* 判断当前舵机应该向左还是向右转
( V" S0 G z: g7 q*/8 @2 l3 u) Z( Y) b; y
if(flag){2 P) h' B4 t" ]$ v0 y' [ Q# F# W
if(pos<170){- Q1 b j) l3 E1 R% v
pos=pos+45;$ N5 T% s* s& {! i3 x
}else{
+ T7 E' j& q9 q( f( Z/ V3 rflag = false;6 B: v! ~" I+ S
}/ n3 ^ {4 O, m; S; h/ u
/* Y- Y4 [( ]; o G* Z1 F8 u
* 如果探测距离大于阈值,则舵机回正,小车转向3 k4 b. ~5 X7 L7 N7 c
*/
1 X+ h9 K9 t3 f4 ^2 k1 ~! Lif(distance > 32){
+ B& ]- `9 y0 Y+ H5 V, f' Vpos = 90;
a+ k* f, W7 M# L+ r1 ?5 }1 Cmyservo.write(pos);
, c" t& r# Y& odelay(1200);
. a! w% F) u" n) W1 B$ p1 d: T% I//判断小车回正方向
5 B3 ?& G C. o& c; J i- h: O. R6 Rif(pos >= 90){9 w7 t ?3 |5 z+ _# E s5 Y: p5 x
turn_L(35,35);
& s3 i" B: g% a! S5 n}else{
7 T+ F# m; j; I8 I4 w) D5 d6 Eturn_R(35,35);5 x6 k" K, X$ o( }) L0 y+ ^- P
}
9 H3 I4 ?: W3 Tdelay(250);$ K: k+ ?& U$ |
temp_distance = distance;9 G( B( i( @" ?6 s) B& n# u
}* F1 s# W6 f4 @3 o' D8 n
/*) C) D/ ^6 J+ U( O
* 如果探测距离小于阈值,则继续扫描
, _4 s% n& R( @" K- }*/7 a% n3 t2 p1 W: k3 |8 O' j
else{! q) P- N% W u4 d j2 `
myservo.write(pos);
8 W0 |' K8 v: E& E9 D6 ^- t" |delay(1200);1 ~. `" I. e( d, X8 v
}9 P" y; y9 u" F0 W% v3 k% _6 h8 ]. H: [
}else{& S& V' t8 w: o( m
if(pos>10){$ T# ~ x/ Q3 h, T& M
pos=pos-45;
. ?9 i! m5 U ]2 \$ P$ Q}else{' F+ C0 ?* M, K. }( Q" ?6 b _
flag=true;
7 V0 ^+ ~! f6 H" c+ g0 L3 c: j9 o}" `* f8 r" t: J
/*
: p% u4 s6 r# b* 如果探测距离大于阈值,则舵机回正,小车转向6 ], m! T3 K/ |. a _# R' b
*/
) Y8 e' D+ I$ P* @if(distance > 32){
! e, W* |, Y% o1 B3 y3 `pos = 90;, T: v1 r3 g% }' t% q# h9 J, R
myservo.write(pos);. m' \1 B" y* H- n5 Y+ G7 F( Q
delay(1200);" Y: q; ?8 ~, s1 _4 G+ i: ~' J
//判断小车回正方向
" T1 q4 [) W6 B' ~9 Jif(pos >= 90){
8 n- K: ^- n0 G6 r1 Dturn_L(35,35);
8 y' R/ r3 f. `" @. b z: B}else{9 E2 L. R( N" \4 P9 O
turn_R(35,35);
/ P; I; u* M$ y, N}& f( A# b* q9 ]; N
delay(250);
1 O# X- E, n0 Itemp_distance = distance;3 N0 I R0 _2 f& ~1 y" M
}7 G( J. h: G8 e3 i/ t2 K1 j) N4 m( I
/*& v5 C! _1 }9 g8 `
* 如果探测距离小于阈值,则继续扫描
5 f: M9 J3 F' `& O% a: X o* N*/
7 B# W+ x' ]% n: ]else{# C5 p3 L+ Q7 C- r
myservo.write(pos);" l3 A' }' ]2 M# S
delay(1200);
. ? {4 h2 s3 j7 j# H}! L1 s+ W7 Q1 \, `; k' Y6 {
}$ f% ]% b! x/ r
}% H# Y: `& P) \- P; m! d$ W
/*# r( h g6 S/ b8 e- d
* 如果前方没有障碍物,直行
0 |5 |' v0 o( s a% r7 S+ S/ H* X*/
" [. m: M9 o% s+ R( t9 celse if(distance > 32 && distance < 1200){
1 c. `1 H. I; Z3 Y; badvance(35,35);
* j9 r; ^/ Z t( v: ]& a}) S) I* l9 s6 V+ X* R, e! X
/*( s& u- o" x" G" Z! F
* 如果雷达挂了,小车停止
' T* s3 e" \0 r*/' x1 w! v; {* f' u f4 q
else if(distance == -3){. Y# E2 w3 f+ O: ?5 }6 ~ L
brake();, p; u, R3 K3 `' W$ o
}
) L: Y, U& y5 @8 W+ `}
S% N* P$ K3 F5 W7 \( w0 e& b9 g% ^# \* H: |3 k1 L, M
|