├── README.md └── servoUltraSonic ├── common.ino ├── servoUltraSonic.ino └── setting.h /README.md: -------------------------------------------------------------------------------- 1 | # Arduino 摇头舵机超声波迷宫小车 2 | 3 | ## 2020.11.25 更新 4 | 5 | 最近发现这几个小 Demo 还有人在下载,因此重新看了之前传的代码,发现各种注释和格式的不规范,不禁汗颜…… 6 | 想到下载这个项目的应该都是些初学者,为了不引人『误入歧途』,决定抽空把代码都规范一下。 7 | 需要注意的是,这几个项目的教学目标受众是只有微弱 C 基础的人。实际项目中,**注释不应是代码的翻译**。 8 | 希望大家学得开心! 9 | 10 | ## 概要 11 | 12 | 通过调用Arduino舵机以及SR04库,控制舵机带动超声波转向,测量不同方向的距离,从而规划走迷宫路径,进行壁障。 13 | 14 | > 需要注意:与之前的单文件工程不同,此工程采用了多个文件的方式开发,这样增强了代码的可读性。 15 | > 该项目的文件结构如下: 16 | > 17 | > - ..\servoUltraSonic.ino 18 | > - ..\common.ino 19 | > - ..\setting.h 20 | > 21 | > 下载后,打开`..\servoUltraSonic.ino`文件即可打开工程。 22 | 23 | ## 接线表 24 | 25 | |电机左A|电机左B|电机右A|电机右B| ECHO | TRIG |舵机信号| 26 | |:----:|:----:|:----:|:----:|:----:|:----:|:----:| 27 | | D6 | D11| D5 | D3 | D7 | D4 | D9 | 28 | 29 | ## 程序讲解 30 | 31 | > 将问题简化,是编程中应有的思维方式。 32 | 33 | 首先应默认小车在赛道中的行驶方式为**直线行驶,直角转弯**。这样,在宽度一定的赛道上,只测量车体右侧(或左侧)的距离就可以得到车体的位置信息。 34 | 因此我们只需获得车体前方距离,以及右侧(或左侧)的距离,就可以对车的运行状态做出规划,实现走迷宫的功能。 35 | 针对这两个距离,我们可以设置一个阈值,列出表格。 36 | 经过思考,我们可以针对几种简单的情况做出如下决策: 37 | 38 | |前方小于25cm|右方小于25cm|决策| 39 | |:-:|:-:|:-:| 40 | |否|否|直走| 41 | |否|是|直走| 42 | |是|否|右转| 43 | |是|是|左转| 44 | 45 | 总结情况,并转换为Arduino程序语言,可以写为: 46 | 47 | ```cpp 48 | void loop() 49 | { 50 | // 声明两个长整形变量,用于存储前方、右方的测距结果。 51 | long forwardDistance = 0; 52 | long rightDistance = 0; 53 | // 调用函数测量前方距离 54 | forwardDistance = controlServoAndGetDistance(FORWARD); 55 | if (forwardDistance >= 25) 56 | { 57 | // 如果前方距离大于25cm,继续向前走。 58 | forward(); 59 | } 60 | else 61 | { 62 | // 如果前方距离小于25cm,停车,测量右方距离。 63 | brake(); 64 | rightDistance = controlServoAndGetDistance(RIGHT); 65 | if (rightDistance >= 25) 66 | { 67 | // 如果右方距离大于25cm,向右转。 68 | turn(RIGHT); 69 | } 70 | else 71 | { 72 | // 如果右方距离小于25cm,向左转。 73 | turn(LEFT); 74 | } 75 | } 76 | } 77 | ``` 78 | 79 | 经过验证,该控制逻辑符合要求,能适应一般的赛道。 80 | > *迷宫小车程序的主要精华在于控制逻辑,这个简单的实例,仅作为抛砖引玉。希望可以激发你的想象,思考出更加完善的控制逻辑。* 81 | 82 | ## 其他 83 | 84 | 工程已经上传到项目中,可以打包下载,其中有更详细的注释。 85 | -------------------------------------------------------------------------------- /servoUltraSonic/common.ino: -------------------------------------------------------------------------------- 1 | // 该文件包含一些常用控制函数 2 | 3 | /* 4 | * @函数名:void speedControl(int side, int dir); 5 | * @参数:side 可选参数:LEFT / RIGHT 6 | * dir 可选参数:FORWARD / BACK / STOP 7 | * @备注:"MISTAKE"参数用来微调两个电机的速度, 8 | * 例子中右轮较慢,因此在给右轮赋值时多加了5, 9 | * 该数值应根据实际进行适当调节。 10 | */ 11 | #define MISTAKE 5 12 | void speedControl(int side, int dir) 13 | { 14 | int A, B; 15 | int s; 16 | if (LEFT == side) 17 | { 18 | A = carLeftA; 19 | B = carLeftB; 20 | s = SPEED; 21 | } 22 | else if (RIGHT == side) 23 | { 24 | A = carRightA; 25 | B = carRightB; 26 | s = SPEED + MISTAKE; 27 | } 28 | if (FORWARD == dir) 29 | { 30 | analogWrite(A, s); 31 | analogWrite(B, 0); 32 | } 33 | else if (BACK == dir) 34 | { 35 | analogWrite(A, 0); 36 | analogWrite(B, s); 37 | } 38 | else if (STOP == dir) 39 | { 40 | analogWrite(A, 0); 41 | analogWrite(B, 0); 42 | } 43 | } 44 | /* 45 | * @函数名:void turn(int dir); 46 | * @参数:dir 可选参数:LEFT / RIGHT 47 | * @备注:"TURN_TIME"参数用来调节单次转向的延时时间, 48 | * 已用于精确控制专项角度为90度, 49 | * 例子中使用450ms,需要根据实际进行微调。 50 | */ 51 | #define TURN_TIME 450 52 | void turn(int dir) 53 | { 54 | if (LEFT == dir) 55 | { 56 | speedControl(RIGHT, FORWARD); 57 | speedControl(LEFT, BACK); 58 | delay(TURN_TIME); 59 | brake(); 60 | } 61 | else if (RIGHT == dir) 62 | { 63 | speedControl(LEFT, FORWARD); 64 | speedControl(RIGHT, BACK); 65 | delay(TURN_TIME); 66 | brake(); 67 | } 68 | else 69 | { 70 | // do nothing 71 | } 72 | } 73 | /* 74 | * @函数名:brake(); 75 | * @参数:无 76 | * @备注:封装停车函数,便于调用。 77 | */ 78 | void brake() 79 | { 80 | speedControl(LEFT, STOP); 81 | speedControl(RIGHT, STOP); 82 | } 83 | /* 84 | * @函数名:forward(); 85 | * @参数:无 86 | * @备注:封装前进函数,便于调用。 87 | */ 88 | void forward() 89 | { 90 | speedControl(RIGHT, FORWARD); 91 | speedControl(LEFT, FORWARD); 92 | } 93 | /* 94 | * @函数名:backward(); 95 | * @参数:无 96 | * @备注:封装后退函数,便于调用,此项目中未用到。 97 | */ 98 | void backward() 99 | { 100 | speedControl(RIGHT, BACK); 101 | speedControl(LEFT, BACK); 102 | } 103 | /* 104 | * @函数名:long controlServoAndGetDistance(int dir); 105 | * @参数:dir 可选参数:FORWARD / LEFT / RIGHT 106 | * @返回值:长整形 测距均值 107 | * @备注:"dir"参数给定后,会将舵机转至指定角度, 108 | * 例子中,舵机对中值为97, 109 | * 向左为180,向右为19, 110 | * 应根据实际情况进行微调。 111 | * 例子中,LEFT方向没有用到。 112 | */ 113 | long controlServoAndGetDistance(int dir) 114 | { 115 | long disAvg = 999; 116 | if (FORWARD == dir) 117 | { 118 | servoUltraSonic.write(97); 119 | } 120 | else if (LEFT == dir) 121 | { 122 | servoUltraSonic.write(180); 123 | } 124 | else if (RIGHT == dir) 125 | { 126 | servoUltraSonic.write(19); 127 | } 128 | else 129 | { 130 | // do nothing 131 | } 132 | // 该延时的作用为,等待舵机转向完成。 133 | delay(500); 134 | // 调用SR04库的平均值采样方法。该方法每间隔25ms采样5次,去最大最小值,取平均值。 135 | disAvg = sr04.DistanceAvg(25, 5); 136 | return disAvg; 137 | } 138 | -------------------------------------------------------------------------------- /servoUltraSonic/servoUltraSonic.ino: -------------------------------------------------------------------------------- 1 | // 调用库以及其他头文件 2 | #include "Servo.h" 3 | #include "SR04.h" 4 | #include "setting.h" 5 | 6 | // 绑定电机引脚 7 | int carLeftA = 6; 8 | int carLeftB = 11; 9 | int carRightA = 5; 10 | int carRightB = 3; 11 | 12 | // 初始化超声波和舵机 13 | SR04 sr04 = SR04(ECHO_PIN, TRIG_PIN); 14 | Servo servoUltraSonic; 15 | 16 | void setup() 17 | { 18 | // 绑定舵机引脚 19 | servoUltraSonic.attach(9); 20 | // 延时,方便操作。 21 | delay(1000); 22 | /* 23 | * 根据官方文档,使用analogWrite()函数的引脚, 24 | * 可以不使用pinMode()进行初始化,所以略去。 25 | */ 26 | } 27 | void loop() 28 | { 29 | // 声明两个长整形变量,用于存储前方、右方的测距结果。 30 | long forwardDistance = 0; 31 | long rightDistance = 0; 32 | // 调用函数测量前方距离 33 | forwardDistance = controlServoAndGetDistance(FORWARD); 34 | if (forwardDistance >= 25) 35 | { 36 | // 如果前方距离大于25cm,继续向前走。 37 | forward(); 38 | } 39 | else 40 | { 41 | // 如果前方距离小于25cm,停车,测量右方距离。 42 | brake(); 43 | rightDistance = controlServoAndGetDistance(RIGHT); 44 | if (rightDistance >= 25) 45 | { 46 | // 如果右方距离大于25cm,向右转。 47 | turn(RIGHT); 48 | } 49 | else 50 | { 51 | // 如果右方距离小于25cm,向左转。 52 | turn(LEFT); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /servoUltraSonic/setting.h: -------------------------------------------------------------------------------- 1 | // 一些特殊定义 2 | #define LEFT 0 3 | #define RIGHT 1 4 | #define FORWARD 2 5 | #define BACK 3 6 | #define STOP 4 7 | 8 | // 定义超声波模块绑定引脚 9 | #define TRIG_PIN 4 10 | #define ECHO_PIN 7 11 | 12 | // 定义行驶速度,不推荐修改, 13 | // 修改会引起其他一系列修改。 14 | #define SPEED 70 15 | 16 | --------------------------------------------------------------------------------