# 相扑机器人--前言
这一章我们来编程一个相扑机器人,机器人放置在胶带围起来的环形区域内。通过超声波传感器来检测“敌人”,并将它推到区域外。
在正式教程前,我们重新认识一下函数,之前我们已经使用过map
,abs
,min
,max
这些函数,函数就是将常用的代码包装起来。我们第一个要包装的是读取传感器的代码:
OseppRangeFinder U(2);
int P = 0; //开机时记录的纸张感应值作为参考
boolean SR; //右边传感器是否在胶带上
boolean SL; //左边传感器是否在胶带上
boolean SU; //是否发现目标
void readSensor() {
//对于胶带的判断比较随意
//只要和纸的参考值差距300以上,就判定为在胶带上。宁可信其有。
//如果机器人太敏感,把300加大。保持纸张干净。
SR = abs(analogRead(A0) - P) > 300;
SL = abs(analogRead(A1) - P) > 300;
SU = U.ping() < 600; // 600毫米内有东西就判定为发现目标
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
代码定义了一个函数readSensor
,函数名字可以随便起,自己看到函数名知道含义就可以了(最好是别人看到也能猜到),名字的要求跟变量名一样。它不像map
,abs
这些函数有返回值,所以函数的类型时void
,表示没有返回值(我们在函数内修改了变量作为结果),像Arduino的setup
,loop
都是void
类型函数。有返回值的函数把void改为返回值类型,在函数内用return返回,例如
int myAbs(int value){
if(value < 0){
return -value;//立刻返回,不会再执行函数内的其他代码
}
return value;//如果函数有返回值,要保证任何分支内都有return语句。
}
1
2
3
4
5
6
2
3
4
5
6
函数可以带有参数,例子中的int value
就是参数。参数只能再函数内使用。也可以在函数内定义变量,称为局部变量,局部变量有作用域,只在“{...}”范围内起作用。例如:
int mid(int pin1, int pin2) {
int t; // t只在函数的{}内起作用
{ //随时都可以用{}来定义一个区域,外部看不到里面的变量
int v1;
int v2;
v1 = analogRead(pin1);
v2 = analogRead(pin2);
t = (v1 + v2); //内部可以使用外部的变量t
}
//在这里不能使用v1,v2
return t / 2;// return的值用表达式也可以
}
int M = 0; //这里定义全局变量M,但是只有下面的代码能用它。上面的代码不能使用
void setup() {
int M; //局部变量可以跟外部的名字相同,但有更高的优先级
M = 100; //所以这里设置的是局部变量M,全局变量M没有改变
Serial.begin(115200);
}
void loop() {
//在这里不能使用pin1,pin2,v1,v2,t
Serial.println(M); //输出0
M = mid(A1, A0); //计算A1,A0两个传感器的中间值
Serial.println(M); //输出中间值
while (1); //用死循环模拟停机
}
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
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
局部变量在每次进入函数时,如果没有设置,值是不确定的,如果想要像全局变量一样,要加上static
关键字,称为静态变量,除了只能在定义它的{}范围内使用,其他性质跟全局变量一样。例如:
int seq(){
//只在程序启动的时候设置初始值,进入函数时不会重复设置初始值。
static int n=0;
n++; //自增,表示n=n+1,同n+=1 相同功能
return n;
}
int notsure(){
int n=0; //如果局部变量不初始化,值是不确定的
n++;
return n;
}
void setup(){
Serial.begin(115200);
Serial.println(seq());//打印1
Serial.println(seq());//打印2
Serial.println(notsure());//打印1
Serial.println(notsure());//打印1
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
函数参数可以有默认值,例如:
int number(int what=0){
return what;
}
void loop(){
int one=number(1); //参数为1,返回1
int zero=number(); //默认参数为0,返回0
}
1
2
3
4
5
6
7
2
3
4
5
6
7
一个程序内可以有多个同名字的函数,但是函数的参数必须不同,叫做函数重载,例如
int myMax(int a, int b) {
if (a > b)
return a;
else
return b;
}
int myMax(int a, int b, int c) {
//只给两个参数将调用前面定义的myMax
int t = myMax(a, b);
return myMax(t, c);
}
void loop() {
myMax(2, 3); //调用第一个myMax
myMax(2, 3, 4); //调用第二个myMax
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15