# 巡线机器人5--自适应颜色
之前的章节我们都假设是白色的纸张,黑色的胶带,这节我们通过数学运算,来让机器人自己适应纸张和胶带的颜色。
# 情景分析
- 回顾上一节,第一个假设的地方是在计算是否碰到胶带,假设胶带的感应值大于纸张的感应值。使用一个大的感应值减去一个小的感应值,如果超过范围就判定为碰到。我们知道,,它们只有符号的区别,如果去掉符号,就都是数字3 。类似于从家里到学校是多远,从学校到家里就是多远。我们可以通过
if(v<0)v=-v
来去掉负号,也可以通过绝对值函数abs(v)
来处理,结果是等效的。使用abs(A0-A1)<300
来描述A0和A1的差距,就可以不假设A0,A1谁大、谁小。 - 第二个是假设T为最大值,P是最小值,来为map函数提供范围。同上,对于范围而言,从10到7和从7到10 ,范围是不变的。只需要让大的更大,小的更小就行了。
- map函数对应公式,作用是从一个范围对应到另一个范围。并不要求范围一定是从小到大。P,T不管谁大谁小,靠近纸张就减速,靠近胶带就加速。现有的逻辑依然成立。所以不用修改。
# 流程解析
程序开始需要定义变量P,T,VL,VR。
开机后机器人右转,因为我们不知道胶带和纸张的值谁大一些,所以使用
abs(analogRead(A1) - analogRead(A0))
来计算它们的差距,经过abs取绝对值以后,差距就一定是正数,如果数值大于300。就判定碰到胶带了。右转时右边碰到的是胶带,将右边传感器感应值保存到变量T。左边保存到变量P。程序进入loop,分别读取两个传感器
VR = analogRead(A0)
,VL = analogRead(A1)
。程序运行到这已经知道P,T的具体数值了(也可以推断胶带和纸张的颜色了),这时如果VL,VR不在P,T之间,需要更新P,T。比较P,T的大小,有两种情况:
- T > P,就让T更大
T = max(T, max(VL, VR))
,P更小P = min(P, min(VL, VR))
。 - P > T,就让P更大
P = max(P, max(VL, VR))
,T更小T = min(T, min(VL, VR))
。
- T > P,就让T更大
根据传感器计算速度,也可以用if来区分:
- P>T :map(Vx , T , P , 120 ,0 )
- T>P :map(Vx , P , T , 0 ,120)
发现两种表达式是同一个功能。想法就是传感器值靠近P速度慢,值靠近T速度快。所以去掉if,两种表达式随便选一种都可以。我们保持原来的形式L.forward(map(VR, P, T, 0, 120))
,R.forward(map(VL, P, T, 0, 120))
# 参考程序
- oseppBlock IDE程序
- Arduino IDE程序
#include <oseppRobot.h>
OseppTBMotor L(12, 11);
OseppTBMotor R(8, 3, LOW);
int P = 0;
int T = 0;
int VL = 0;
int VR = 0;
void setup() {
L.forward(60);
R.backward(60);
while (abs(analogRead(A1) - analogRead(A0)) < 300) {
}
T = analogRead(A0);
P = analogRead(A1);
}
void loop() {
VR = analogRead(A0);
VL = analogRead(A1);
if (T > P) {
T = max(T, max(VL, VR));
P = min(P, min(VL, VR));
} else {
T = min(T, min(VL, VR));
P = max(P, max(VL, VR));
}
L.forward(map(VR, P, T, 0, 120));
R.forward(map(VL, P, T, 0, 120));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 运行结果
同之前一样放置机器人。打开电源,机器人找到胶带后尝试跟着走。只要机器人能分清胶带和纸,任何颜色组合都可以。
# 课程解读
- 我们通过abs函数计算绝对值,让巡线机器人不要求特定的胶带颜色。
- 机器人现在还假设开机时向右边转弯,我们下一节去掉这个条件,只假设开机时,是对着纸张。不限定转弯的方向。
- map函数的实现代码:
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
1
2
3
2
3