# 巡线机器人5--自适应颜色

之前的章节我们都假设是白色的纸张,黑色的胶带,这节我们通过数学运算,来让机器人自己适应纸张和胶带的颜色。

# 情景分析

  1. 回顾上一节,第一个假设的地方是在计算是否碰到胶带,假设胶带的感应值大于纸张的感应值。使用一个大的感应值减去一个小的感应值,如果超过范围就判定为碰到。我们知道107=310-7=3710=37-10=-3,它们只有符号的区别,如果去掉符号,就都是数字3 。类似于从家里到学校是多远,从学校到家里就是多远。我们可以通过if(v<0)v=-v来去掉负号,也可以通过绝对值函数abs(v)来处理,结果是等效的。使用abs(A0-A1)<300来描述A0和A1的差距,就可以不假设A0,A1谁大、谁小。
  2. 第二个是假设T为最大值,P是最小值,来为map函数提供范围。同上,对于范围而言,从10到7和从7到10 ,范围是不变的。只需要让大的更大,小的更小就行了。
  3. map函数对应公式(valuefromLow)×toHighttoLowfromHighfromLow+toLow(value-fromLow)\times\frac{toHight-toLow}{fromHigh-fromLow}+toLow,作用是从一个范围对应到另一个范围。并不要求范围一定是从小到大。P,T不管谁大谁小,靠近纸张就减速,靠近胶带就加速。现有的逻辑依然成立。所以不用修改。

# 流程解析

  1. 程序开始需要定义变量P,T,VL,VR。

  2. 开机后机器人右转,因为我们不知道胶带和纸张的值谁大一些,所以使用abs(analogRead(A1) - analogRead(A0))来计算它们的差距,经过abs取绝对值以后,差距就一定是正数,如果数值大于300。就判定碰到胶带了。右转时右边碰到的是胶带,将右边传感器感应值保存到变量T。左边保存到变量P。

  3. 程序进入loop,分别读取两个传感器VR = analogRead(A0)VL = analogRead(A1)

  4. 程序运行到这已经知道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))
  5. 根据传感器计算速度,也可以用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))
uml diagram

# 参考程序

  • 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

# 运行结果

同之前一样放置机器人。打开电源,机器人找到胶带后尝试跟着走。只要机器人能分清胶带和纸,任何颜色组合都可以。

# 课程解读

  1. 我们通过abs函数计算绝对值,让巡线机器人不要求特定的胶带颜色。
  2. 机器人现在还假设开机时向右边转弯,我们下一节去掉这个条件,只假设开机时,是对着纸张。不限定转弯的方向。
  3. 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

# oseppBlock操作视频

# ArduinoIDE操作视频