当前位置:   article > 正文

机器人制作开源方案 | 智能循迹避障小车_智能小车开源

智能小车开源

作者:刘元青、邹海峰、付志伟、秦怀远、牛文进

单位:哈尔滨信息工程学院

指导老师:姚清元

      智能小车是移动式机器人的重要组成部分,而移动机器人不仅能够在经济、国防、教育、文化和生活中起到越来越大的作用,也是研究复杂智能行为的产生、探索人类思维模式的有效工具与实验平台。

      本文设计的是一款基于Arduino的智能小车,它利用Arduino作为主控系统。它用蓝牙模块进行无线数据传输,实现无线控制。它利用红外线反射等原理,实现自动循迹效果。同时它利用超声波测距模块来进行测距,将测得的距离数据传给Arduino,经过Arduino处理给出反馈,驱动电机转动,实现自动避障的功能。

1. 系统设计与实现

1.1 系统设计

1.1.1 系统架构

      Roboduino智能小车车身由Arduino开发板和舵机等设备组成,其功能实现则由Arduino IDE编写程序以及Helloblock的调试来完成。

1.1.2 功能架构

      基于Arduino的Roboduino智能小车通过烧录WiFi遥控程序,利用超声波测距原理实现自动避障,利用红外线反射原理实现自动循迹,此外还有其他功能模式。

1.1.3 技术架构

      通过在Arduino IDE平台编写C代码来实现功能模块,将WIFI无线连接程序烧录至Arduino开发板,内含相关功能模块代码,利用超声波测距技术和红外线传感器分别实现自动避障和自动循迹功能。

1.2 系统实现

1.2.1 超声波测距

       实验原理:超声波模块是利用超声波特性检测距离的传感器。其带有两个超声波探头,分别用作发射和接收超声波。本次实验我们所使用的模块,其测量的范围是 0-3m。

      超声波时序图:以下时序图表明你只需要提供一个10uS 以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公式: uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为60ms 以上,以防止发射信号对回响信号的影响。

超声波模块引脚:根据硬件接口速查手册可知,超声波模块的超声波功能由Uno板的 Pin12引脚直接驱动。

实验程序

超声波测距(RGBUltrasonic_Ranging.ino)

  1. /*
  2. * @par Copyright (C): 2010-2019, Shenzhen Yahboom Tech
  3. * @file Ultrasonic_Ranging.c
  4. * @author Cindy
  5. * @version V1.0
  6. * @date 2018.10.18
  7. * @brief Ultrasonic_Ranging
  8. * @details
  9. * @par History
  10. *
  11. */
  12. #include <Wire.h>
  13. #include "Adafruit_PWMServoDriver.h"
  14. Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
  15. const int SingPin = 12;
  16. float distance;
  17. /**
  18. * Function setup
  19. * @author liusen
  20. * @date 2017.07.25
  21. * @brief Initial configuration
  22. * @param[in] void
  23. * @retval void
  24. * @par History no
  25. */
  26. void setup()
  27. {
  28. pwm.begin();
  29. pwm.setPWMFreq(60); //Analog servos run at ~60 Hz updates
  30. LOGO_breathing_light(255, 40, 5); //Gradually light the blue light of the Yhaboom_LOGO
  31. Serial.begin(9600);
  32. Serial.println("Ultrasonic sensor:");
  33. }
  34. /**
  35. * Function LOGO_light(brightness,time,increament)
  36. * @author wusicaijuan
  37. * @date 2019.06.26
  38. * @brief LOGO_light
  39. * @param[in1] brightness
  40. * @param[in2] time
  41. * @param[in3] increament
  42. * @param[out] void
  43. * @retval void
  44. * @par History no
  45. */
  46. void LOGO_breathing_light(int brightness, int time, int increament)
  47. {
  48. if (brightness < 0)
  49. {
  50. brightness = 0;
  51. }
  52. if (brightness > 255)
  53. {
  54. brightness = 255;
  55. }
  56. for (int b = 0; b < brightness; b += increament)
  57. {
  58. int newb = map(b, 0, 255, 0, 4095);
  59. pwm.setPWM(7, 0, newb);
  60. delay(time);
  61. }
  62. }
  63. /**
  64. * Function loop
  65. * @author Cindy
  66. * @date 2019.07.30
  67. * @brief main fuction
  68. * @param[in] void
  69. * @retval void
  70. * @par History no
  71. */
  72. void loop()
  73. {
  74. pinMode(SingPin,OUTPUT);
  75. digitalWrite(SingPin, LOW);
  76. delayMicroseconds(2);
  77. digitalWrite(SingPin, HIGH);
  78. delayMicroseconds(10);
  79. digitalWrite(SingPin, LOW);
  80. pinMode(SingPin, INPUT);
  81. delayMicroseconds(50);
  82. distance = pulseIn(SingPin, HIGH) / 58.00;
  83. Serial.print("distance is :");
  84. Serial.print(distance);
  85. Serial.print("cm");
  86. Serial.println();
  87. delay(1000);
  88. }

操作流程

      我们需要通用 Arduino IDE 软件打开RGBUltrasonic_Ranging.ino文件,然后点击菜单栏中的“√”编译程序,并且等待左下角出现“编译成功”的字样。

在 Arduino IDE 的菜单栏中,我们需要选择【工具】---【端口】---选择设备管理器中刚刚显示端口号。

选择完成后,点击菜单栏下的“→”将代码上传到 UNO 板。 当左下角出现“上 传完成”字样时,表示程序已成功上传到 UNO 板。

程序下载完成之后,我们需要打开 Arduino IDE 界面右上角的“串口监视器”。

在串口监视器中选择和程序中相同的波特率。

接下来,我们就可以在串口监视器上面看到超声波模块当前所测量的距离被打印出来了。

1.2.2 巡线测试

      实验原理:红外传感器巡线的基本原理是利用物体的反射性质,我们本次实验是巡黑线行驶,当红外线发射到黑线上时会被黑线吸收掉,发射到其他的颜色的材料上会有反射到红外的接手管上。

      巡线模块引脚:根据硬件接口速查手册可知,三路巡线模块分别用Uno板的A0、A1、A2引脚驱动。

实验程序

① Tracking_PID_v1.ino

  1. /*
  2. * @par Copyright (C): 2010-2019, Shenzhen Yahboom Tech
  3. * @file Tracking_test.c
  4. * @author wusicaijuan
  5. * @version V1.0
  6. * @date 2019.08.05
  7. * @brief Tracking_test
  8. * @details
  9. * @par History
  10. *
  11. */
  12. #include "Adafruit_PWMServoDriver.h"
  13. Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
  14. float max = 3.85;
  15. float s = 100;
  16. float Kp = 37, Ki = 4, Kd = 60;
  17. float error = 0, P = 0, I = 0, D = 0, PID_value = 0;
  18. float previous_error = 0, previous_I = 0;
  19. int sensor[3] = {0, 0, 0};
  20. int initial_motor_speed = 40;
  21. const int key = 7;
  22. void read_sensor_values(void);
  23. void calculate_pid(void);
  24. void motor_control(void);
  25. void keyscan(void);
  26. void Clear_All_PWM(void);
  27. /**
  28. * Function setup
  29. * @author wusicaijuan
  30. * @date 2019.08.05
  31. * @brief Initial configuration
  32. * @param[in] void
  33. * @retval void
  34. * @par History no
  35. */
  36. void setup()
  37. {
  38. // put your setup code here, to run once:
  39. pwm.begin();
  40. pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
  41. Clear_All_PWM();
  42. pinMode(A0, INPUT);
  43. pinMode(A1, INPUT);
  44. pinMode(A2, INPUT);
  45. pinMode(key, INPUT);
  46. keysacn();
  47. }
  48. /**
  49. * Function loop
  50. * @author wusicaijuan
  51. * @date 2019.07.30
  52. * @brief main fuction
  53. * @param[in] void
  54. * @retval void
  55. * @par History no
  56. */
  57. void loop()
  58. {
  59. read_sensor_values();
  60. calculate_pid();
  61. motor_control();
  62. }
  63. /**
  64. * Function read_sensor_values
  65. * @author wusicaijuan
  66. * @date 2019.07.30
  67. * @brief read sensor value to change car movement
  68. * @param[in] void
  69. * @retval void
  70. * @par History no
  71. */
  72. void read_sensor_values()
  73. {
  74. sensor[0] = analogRead(A0);
  75. sensor[1] = analogRead(A1);
  76. sensor[2] = analogRead(A2);
  77. if (sensor[0] > 100)
  78. {
  79. sensor[0] = 1;
  80. }
  81. else
  82. {
  83. sensor[0] = 0;
  84. }
  85. if (sensor[1] > 100)
  86. {
  87. sensor[1] = 1;
  88. }
  89. else
  90. {
  91. sensor[1] = 0;
  92. }
  93. if (sensor[2] > 100)
  94. {
  95. sensor[2] = 1;
  96. }
  97. else
  98. {
  99. sensor[2] = 0;
  100. }
  101. if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1))
  102. {
  103. error = 2;
  104. }
  105. else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1))
  106. {
  107. error = 1;
  108. }
  109. else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0))
  110. {
  111. error = 0;
  112. }
  113. else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 0))
  114. {
  115. error = -1;
  116. }
  117. else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0))
  118. {
  119. error = -2;
  120. }
  121. else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0))
  122. {
  123. if (error > 0)
  124. {
  125. //spin left
  126. error = max;
  127. }
  128. else
  129. {
  130. //spin right
  131. error = -max;
  132. }
  133. }
  134. }
  135. /**
  136. * Function calculate_pid
  137. * @author wusicaijuan
  138. * @date 2019.06.25
  139. * @brief calculate_pid
  140. * @param[out]
  141. * @retval
  142. * @par History no
  143. */
  144. void calculate_pid()
  145. {
  146. P = error;
  147. I = I + previous_I;
  148. D = error - previous_error;
  149. PID_value = (Kp * P) + (Ki * I) + (Kd * D);
  150. // Serial.println(PID_value);
  151. previous_I = I;
  152. previous_error = error;
  153. }
  154. void motor_control()
  155. {
  156. // Calculating the effective motor speed:
  157. int left_motor_speed = initial_motor_speed - PID_value;
  158. int right_motor_speed = initial_motor_speed + PID_value;
  159. // The motor speed should not exceed the max PWM value
  160. // left_motor_speed = constrain(left_motor_speed, -255, 255);
  161. // right_motor_speed = constrain(right_motor_speed, -255, 255);
  162. left_motor_speed = constrain(left_motor_speed, -s, s);
  163. right_motor_speed = constrain(right_motor_speed, -s, s);
  164. run(left_motor_speed, right_motor_speed);
  165. }
  166. /**
  167. * Function run
  168. * @author wusicaijuan
  169. * @date 2019.06.25
  170. * @brief run
  171. * @param[in] Speed
  172. * @param[out] void
  173. * @retval void
  174. * @par History no
  175. */
  176. void run(float Speed1, float Speed2)
  177. {
  178. Speed1 = map(Speed1, -255, 255, -4095, 4095);
  179. Speed2 = map(Speed2, -255, 255, -4095, 4095);
  180. if (Speed2 > 0)
  181. {
  182. pwm.setPWM(10, 0, Speed2); //Right front wheel Forward
  183. pwm.setPWM(11, 0, 0);
  184. pwm.setPWM(8, 0, Speed2); //Right rear wheel Forward
  185. pwm.setPWM(9, 0, 0);
  186. }
  187. else
  188. {
  189. pwm.setPWM(10, 0, 0);
  190. pwm.setPWM(11, 0, abs(Speed2));
  191. pwm.setPWM(8, 0, 0);
  192. pwm.setPWM(9, 0, abs(Speed2));
  193. }
  194. if (Speed1 > 0)
  195. {
  196. pwm.setPWM(13, 0, Speed1); //Left front wheel Forward
  197. pwm.setPWM(12, 0, 0);
  198. pwm.setPWM(15, 0, Speed1); //Left front wheel Forward
  199. pwm.setPWM(14, 0, 0);
  200. }
  201. else
  202. {
  203. pwm.setPWM(13, 0, 0);
  204. pwm.setPWM(12, 0, abs(Speed1));
  205. pwm.setPWM(15, 0, 0);
  206. pwm.setPWM(14, 0, abs(Speed1));
  207. }
  208. }
  209. /**
  210. * Function sleft
  211. * @author wusicaijuan
  212. * @date 2019.06.25
  213. * @brief turn left(Left wheel stopRight wheel advance)
  214. * @param[in] Speed
  215. * @param[out] void
  216. * @retval void
  217. * @par History no
  218. */
  219. void sleft(float Speed)
  220. {
  221. pwm.setPWM(10, 0, Speed); //Right front wheel Forword
  222. pwm.setPWM(11, 0, 0);
  223. pwm.setPWM(8, 0, Speed); //Right rear wheel Forword
  224. pwm.setPWM(9, 0, 0);
  225. pwm.setPWM(13, 0, 0); //Left front wheel Back
  226. pwm.setPWM(12, 0, Speed);
  227. pwm.setPWM(15, 0, 0); //Left rear wheel Back
  228. pwm.setPWM(14, 0, Speed);
  229. }
  230. /**
  231. * Function sright
  232. * @author wusicaijuan
  233. * @date 2019.06.25
  234. * @brief spin_right(Left wheel advance,Right wheel back)
  235. * @param[in] Speed
  236. * @param[out] void
  237. * @retval void
  238. * @par History no
  239. */
  240. void sright(float Speed)
  241. {
  242. pwm.setPWM(10, 0, 0);
  243. pwm.setPWM(11, 0, Speed); //Right front wheel Back
  244. pwm.setPWM(8, 0, 0);
  245. pwm.setPWM(9, 0, Speed); //Right rear wheel Back
  246. pwm.setPWM(13, 0, Speed); //Left front wheel Forword
  247. pwm.setPWM(12, 0, 0);
  248. pwm.setPWM(15, 0, Speed); //Left rear wheel Forword
  249. pwm.setPWM(14, 0, 0);
  250. }
  251. /**
  252. * Function keysacn
  253. * @author wusicaijuan
  254. * @date 2019.06.04
  255. * @brief keysacn
  256. * @param[in1] void
  257. * @retval void
  258. * @par History no
  259. */
  260. void keysacn()
  261. {
  262. int val;
  263. val = digitalRead(key); //Read the level value of digital 7 port assigned to val
  264. while (val == HIGH) //Cycles when the button is not pressed
  265. {
  266. val = digitalRead(key);
  267. }
  268. while (val == LOW) //When button is not pressed
  269. {
  270. delay(1);
  271. val = digitalRead(key); //Read the level value of digital 7 port assigned to val
  272. while (val == HIGH) //Determine if the button is released
  273. {
  274. break;
  275. }
  276. }
  277. }
  278. /*
  279. * Function Clear_All_PWM
  280. * @author wusicaijuan
  281. * @date 2019.07.04
  282. * @brief Turn off PWM
  283. * @param[in] void
  284. * @param[out] void
  285. * @retval void
  286. * @par History no
  287. */
  288. void Clear_All_PWM()
  289. {
  290. for (int i = 0; i < 16; i++)
  291. {
  292. pwm.setPWM(i, 0, 0);
  293. }
  294. }

② Tracking_test.ino

  1. /*
  2. * @par Copyright (C): 2010-2019, Shenzhen Yahboom Tech
  3. * @file Tracking_test.c
  4. * @author wusicaijuan
  5. * @version V1.0
  6. * @date 2019.08.05
  7. * @brief Tracking_test
  8. * @details
  9. * @par History
  10. *
  11. */
  12. #include "Adafruit_PWMServoDriver.h"
  13. Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
  14. int sensor[3];
  15. const int key = 7; //Define key pin
  16. void keyscan(void);
  17. void Clear_All_PWM(void);
  18. #define L_Value analogRead(A2)
  19. #define M_Value analogRead(A1)
  20. #define R_Value analogRead(A0)
  21. /**
  22. * Function setup
  23. * @author liusen
  24. * @date 2017.07.25
  25. * @brief Initial configuration
  26. * @param[in] void
  27. * @retval void
  28. * @par History no
  29. */
  30. void setup()
  31. {
  32. // put your setup code here, to run once:
  33. pwm.begin();
  34. pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates
  35. Clear_All_PWM();
  36. pinMode(A0, INPUT);
  37. pinMode(A1, INPUT);
  38. pinMode(A2, INPUT);
  39. pinMode(key, INPUT);
  40. keysacn();
  41. }
  42. /**
  43. * Function loop
  44. * @author wusicaijuan
  45. * @date 2019.07.30
  46. * @brief main fuction
  47. * @param[in] void
  48. * @retval void
  49. * @par History no
  50. */
  51. void loop()
  52. {
  53. read_sensor_values();
  54. }
  55. /**
  56. * Function read_sensor_values
  57. * @author wusicaijuan
  58. * @date 2019.07.30
  59. * @brief read sensor value to change car movement
  60. * @param[in] void
  61. * @retval void
  62. * @par History no
  63. */
  64. /*450350400分别是中间探头左侧探头右侧探头黑白线之间的临界值,
  65. * 请用户一定要根据实际情况打印观察这三个数据,并进行修改。
  66. */
  67. void read_sensor_values()
  68. {
  69. if(M_Value>340)
  70. {
  71. run(65);
  72. }
  73. else if(L_Value > 350)
  74. {
  75. sleft(75);
  76. while(L_Value>350);
  77. }
  78. else if(R_Value > 400)
  79. {
  80. sright(75);
  81. while(R_Value > 400);
  82. }
  83. }
  84. /**
  85. * Function run
  86. * @author wusicaijuan
  87. * @date 2019.06.25
  88. * @brief run
  89. * @param[in] Speed
  90. * @param[out] void
  91. * @retval void
  92. * @par History no
  93. */
  94. void run(float Speed)
  95. {
  96. Speed = map(Speed, 0, 255, 0, 4095);
  97. pwm.setPWM(10, 0, Speed); //Right front wheel Forward
  98. pwm.setPWM(11, 0, 0);
  99. pwm.setPWM(8, 0, Speed); //Right rear wheel Forward
  100. pwm.setPWM(9, 0, 0);
  101. pwm.setPWM(13, 0, Speed); //Left front wheel Forward
  102. pwm.setPWM(12, 0, 0);
  103. pwm.setPWM(15, 0, Speed); //Left front wheel Forward
  104. pwm.setPWM(14, 0, 0);
  105. }
  106. /**
  107. * Function left
  108. * @author wusicaijuan
  109. * @date 2019.06.26
  110. * @brief turn left(Left wheel stopRight wheel advance)
  111. * @param[in] Speed
  112. * @param[out] void
  113. * @retval void
  114. * @par History no
  115. */
  116. void left(float Speed)
  117. {
  118. Speed = map(Speed, 0, 255, 0, 4095);
  119. pwm.setPWM(10, 0, Speed); //Right front wheel Reverse
  120. pwm.setPWM(11, 0, 0);
  121. pwm.setPWM(8, 0, Speed); //Right rear wheel Reverse
  122. pwm.setPWM(9, 0, 0);
  123. pwm.setPWM(13, 0, 0); //Left front wheel Stop
  124. pwm.setPWM(12, 0, 0);
  125. pwm.setPWM(15, 0, 0);
  126. pwm.setPWM(14, 0, 0);
  127. }
  128. /**
  129. * Function right
  130. * @author wusicaijuan
  131. * @date 2019.06.26
  132. * @brief turn right (Left wheel advance,Right wheel stop)
  133. * @param[in] Speed
  134. * @param[out] void
  135. * @retval void
  136. * @par History no
  137. */
  138. void right(float Speed)
  139. {
  140. Speed = map(Speed, 0, 255, 0, 4095);
  141. pwm.setPWM(10, 0, 0); //Right front wheel Stop
  142. pwm.setPWM(11, 0, 0);
  143. pwm.setPWM(8, 0, 0);
  144. pwm.setPWM(9, 0, 0);
  145. pwm.setPWM(13, 0, Speed); //Left front wheel Reverse
  146. pwm.setPWM(12, 0, 0);
  147. pwm.setPWM(15, 0, Speed); //Left rear wheel Reverse
  148. pwm.setPWM(14, 0, 0);
  149. }
  150. /**
  151. * Function sleft
  152. * @author wusicaijuan
  153. * @date 2019.06.25
  154. * @brief spin_left(Left wheel back,Right wheel advance)
  155. * @param[in] Speed
  156. * @param[out] void
  157. * @retval void
  158. * @par History no
  159. */
  160. void sleft(float Speed)
  161. {
  162. Speed = map(Speed, 0, 255, 0, 4095);
  163. pwm.setPWM(10, 0, Speed); //Right front wheel Forword
  164. pwm.setPWM(11, 0, 0);
  165. pwm.setPWM(8, 0, Speed); //Right rear wheel Forword
  166. pwm.setPWM(9, 0, 0);
  167. pwm.setPWM(13, 0, 0); //Left front wheel Back
  168. pwm.setPWM(12, 0, Speed);
  169. pwm.setPWM(15, 0, 0);
  170. pwm.setPWM(14, 0, Speed); //Left rear wheel Back
  171. }
  172. /**
  173. * Function sright
  174. * @author wusicaijuan
  175. * @date 2019.06.25
  176. * @brief spin_right(Left wheel advance,Right wheel back)
  177. * @param[in] Speed
  178. * @param[out] void
  179. * @retval void
  180. * @par History no
  181. */
  182. void sright(float Speed)
  183. {
  184. Speed = map(Speed, 0, 255, 0, 4095);
  185. pwm.setPWM(10, 0, 0);
  186. pwm.setPWM(11, 0, Speed); //Right front wheel Back
  187. pwm.setPWM(8, 0, 0);
  188. pwm.setPWM(9, 0, Speed); //Right rear wheel Back
  189. pwm.setPWM(13, 0, Speed); //Left front wheel Forword
  190. pwm.setPWM(12, 0, 0);
  191. pwm.setPWM(15, 0, Speed); //Left rear wheel Forword
  192. pwm.setPWM(14, 0, 0);
  193. }
  194. /**
  195. * Function keysacn
  196. * @author wusicaijuan
  197. * @date 2019.06.04
  198. * @brief keysacn
  199. * @param[in1] void
  200. * @retval void
  201. * @par History no
  202. */
  203. void keysacn()
  204. {
  205. int val;
  206. val = digitalRead(key); //Read the level value of digital 7 port assigned to val
  207. while (val == HIGH) //Cycles when the button is not pressed
  208. {
  209. val = digitalRead(key);
  210. }
  211. while (val == LOW) //When button is not pressed
  212. {
  213. delay(10);
  214. val = digitalRead(key); //Read the level value of digital 7 port assigned to val
  215. while (val == HIGH) //Determine if the button is released
  216. {
  217. break;
  218. }
  219. }
  220. }
  221. /*
  222. * Function Clear_All_PWM
  223. * @author wusicaijuan
  224. * @date 2019.07.04
  225. * @brief Turn off PWM
  226. * @param[in] void
  227. * @param[out] void
  228. * @retval void
  229. * @par History no
  230. */
  231. void Clear_All_PWM()
  232. {
  233. for (int i = 0; i < 16; i++)
  234. {
  235. pwm.setPWM(i, 0, 0);
  236. }
  237. }

③ TrackingSensorTest.ino

  1. //30 27 29
  2. void setup()
  3. {
  4. Serial.begin(115200);
  5. pinMode(A0, INPUT);
  6. pinMode(A1, INPUT);
  7. pinMode(A2, INPUT);
  8. }
  9. void loop()
  10. {
  11. delay(50);
  12. Serial.print(analogRead(A0));
  13. Serial.print(",");
  14. Serial.print(analogRead(A1));
  15. Serial.print(",");
  16. Serial.println(analogRead(A2));
  17. }

实验现象

      对于程序Tracking_test.ino,首先打开在TrackingSensorTest文件夹中 TrackingSensorTest.ino。并通过数据线将小车(或者是已经插入扩展板的 Uno板)与电脑连接。然后将三路巡线模块处于白色底部上(必须是你的小车将要行驶的巡线赛道的白色底部),如下图所示将三路巡线模块处于黑色赛道上(必须是你的小车将要行驶的巡线黑色赛道)。

在Arduino IDE界面的右上角打开串口监视器,需要选择与程序中所设置的相同的波特率。

当巡线传感器的三个探头检测到白色时,检测到黑色时,打印出当前输出的模拟值。

如果数据显示一点波动,这是正常的。

打开 Tracking_test 文件夹中的 Tracking_test.ino 文件,并且根据上一步打印出来的数值,取一个最佳的临界值,修改程序中的数据。

      修改完成之后,保存程序并将程序下载小车上。

      对于程序:Tracking_PID.ino首先,打开在TrackingSensorTest 文件夹中 TrackingSensorTest.ino。并通过数据线将小车(或者是已经插入扩展板的 Uno 板)与电脑连接。然后,将三路巡线模块处于白色底部上(必须是你的小车将要行驶的巡线赛道的白色底部)。

在 Arduino IDE 界面的右上角打开串口监视器,需要选择与程序中所设置的相同的波特率。

当巡线传感器的三个探头检测到白色时,打印出当前输出的模拟值。

如果数据显示一点波动,这是正常的,可以取五个数据的平均值。

打开Tracking_PID 文件夹中的 Tracking_PID.ino 文件,并且修改程序中的数据。

1.2.3 WIFI摄像头控制

实验原理:根据硬件接口速查手册可知,WIFI 摄像头模块是通过串口进行通讯的。

实验程序

WIFI模块(WIFI_control_car_15.ino)

  1. /**
  2. * @par Copyright (C): 2010-2019, Shenzhen Yahboom Tech
  3. * @file Wifi control car.c
  4. * @author Cindy
  5. * @version V1.0
  6. * @date 2019.09.11
  7. * @brief
  8. * @details
  9. * @par History
  10. *
  11. */
  12. #include <Arduino.h>
  13. #include "Adafruit_PWMServoDriver.h"
  14. #include "Adafruit_NeoPixel.h"
  15. #include "RGBLed.h"
  16. #include "avr/pgmspace.h"
  17. #define RGB_GREEN 0xFF0000 //定义RGB灯的颜色
  18. #define RGB_RED 0x00FF00
  19. #define RGB_BLUE 0x0000FF
  20. #define RGB_YELLOW 0xFFFF00
  21. #define RGB_PURPLE 0x00FFFF
  22. #define RGB_WHITE 0xFFFFFF
  23. #define RGB_CYAN 0xFF00FF
  24. #define RGB_OFF 0x000000
  25. const int RgbPin = 11; //定义七彩超声波模块上面RGB灯的引脚
  26. RGBLed mRgb(RgbPin,2);
  27. Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
  28. #define SERVOMIN 150
  29. #define SERVOMAX 600
  30. #define PIN 6 //定义RGB的引脚
  31. #define MAX_LED 1 //扩展板上仅有一个同类型的板载RGB灯
  32. Adafruit_NeoPixel strip = Adafruit_NeoPixel(MAX_LED, PIN, NEO_RGB + NEO_KHZ800);
  33. const char enServo[] = {0, 1, 2, 3};
  34. const unsigned char music_max[5] = {42,39,36,70,25}; //音乐歌曲的最大长度
  35. #define run_car '1'
  36. #define back_car '2'
  37. #define left_car '3'
  38. #define right_car '4'
  39. #define spin_left_car '5'
  40. #define spin_right_car '6'
  41. #define stop_car '7'
  42. #define H_servoL 'L'
  43. #define H_servoR 'R'
  44. #define H_servoS 'S'
  45. #define V_servoU 'U'
  46. #define V_servoD 'D'
  47. #define V_servoS 'S'
  48. int Servo_LR = 90;
  49. int Servo_UD = 90;
  50. const int flag_time = 2000; //时间标记点间隔2s
  51. int newtime = 0; //记录系统当前的时间
  52. int lasttime = 0; //记录系统上一次的时间点
  53. int g_num = 0;
  54. int buzzer = 10; //定义蜂鸣器的引脚
  55. int CarSpeedControl = 80; //set speed of car
  56. int SingPin = 12;
  57. int distance = 0;
  58. int red, green, blue;
  59. int initial_motor_speed = 100;
  60. int sensor[3];
  61. int time = 40000;
  62. int count = 10;
  63. /*小车运动状态枚举*/
  64. const typedef enum {
  65. enRUN = 1,
  66. enBACK,
  67. enLEFT,
  68. enRIGHT,
  69. enSPINLEFT,
  70. enSPINRIGHT,
  71. enSTOP
  72. } enCarState;
  73. /*舵机状态枚举*/
  74. const typedef enum {
  75. enHServoL = 1,
  76. enHServoR,
  77. enHServoS
  78. } enHServoState;
  79. int IncomingByte = 0; //接收到的数据字节
  80. String InputString = ""; //用来存储接收到的数据
  81. boolean NewLineReceived = false; //上一次数据结束的标志
  82. boolean StartBit = false; //协议开始标志
  83. String ReturnTemp = ""; //用来存储返回值
  84. static int g_CarState = enSTOP; //1前进 2后退 3左转 4 右转 0停止
  85. static int g_HServoState = enHServoS; //1:左转 2:右转 3:停止
  86. int g_modeSelect = 0; //0:默认的状态
  87. int g_modeMusic = 0; //0:默认的状态
  88. int g_musicSelect = 1;
  89. int g_modeCar = 0;
  90. boolean g_motor = false;
  91. //Music
  92. enum enMusic
  93. {
  94. enStar=1,
  95. Bingo=2,
  96. MerryChristmas=3,
  97. Ode=4,
  98. Birthday=5
  99. };
  100. #define G5 392
  101. #define A6 440
  102. #define B7 494
  103. #define c1 525
  104. #define d2 587
  105. #define e3 659
  106. #define f4 698
  107. #define g5 784
  108. #define a6 880
  109. #define b7 988
  110. #define C1 1047
  111. #define D2 1175
  112. #define E3 1319
  113. #define F4 1397
  114. #define GG5 1568
  115. #define AA6 1769
  116. #define g4 392
  117. #define c5 523
  118. #define a4 440
  119. #define d5 587
  120. #define e5 659
  121. #define b4 494
  122. #define c6 1047
  123. #define d6 1175
  124. #define b5 988
  125. #define a5 880
  126. #define g5 784
  127. #define e6 1319
  128. #define f6 1397
  129. #define a5 880
  130. #define f5 698
  131. const PROGMEM int ODe[70][2] //歌曲--欢乐颂
  132. {
  133. {e3,2},{e3,2},{f4,2},{g5,2},{g5,2},{f4,2},{e3,2},{d2,2},{c1,2},{c1,2},{d2,2},{e3,2},{e3,3},{d2,1},{d2,4},
  134. {e3,2},{e3,2},{f4,2},{g5,2},{g5,2},{f4,2},{e3,2},{d2,2},{c1,2},{c1,2},{d2,2},{e3,2},{d2,3},{c1,1},{c1,4},
  135. {d2,2},{d2,2},{e3,2},{c1,2},{d2,2},{e3,1},{f4,1},{e3,2},{c1,2},
  136. {d2,2},{e3,1},{f4,1},{e3,2},{d2,2},{c1,2},{d2,2},{G5,2},
  137. {e3,2},{e3,2},{f4,2},{g5,2},{g5,2},{f4,2},{e3,2},{d2,2},{c1,2},{c1,2},{d2,2},{e3,2},{d2,3},{c1,1},{c1,4},
  138. };
  139. const PROGMEM int BIrthday[25][2] //歌曲--生日快乐
  140. {
  141. {G5,2},{A6,2},{G5,2},{c1,2},{B7,4},
  142. {G5,2},{A6,2},{G5,2},{d2,2},{c1,4},
  143. {G5,2},{g5,2},{e3,2},{c1,2},{B7,2},{A6,2},
  144. {f4,2},{e3,2},{c1,2},{d2,2},{c1,2}
  145. };
  146. const PROGMEM int STar[42][2] //歌曲--小星星
  147. {
  148. {c1,2},{c1,2},{g5,2},{g5,2},{a6,2},{a6,2},{g5,4},
  149. {f4,2},{f4,2},{e3,2},{e3,2},{d2,2},{d2,2},{c1,4},
  150. {g5,2},{g5,2},{f4,2},{f4,2},{e3,2},{e3,2},{d2,4},
  151. {g5,2},{g5,2},{f4,2},{f4,2},{e3,2},{e3,2},{d2,4},
  152. {c1,2},{c1,2},{g5,2},{g5,2},{a6,2},{a6,2},{g5,4},
  153. {f4,2},{f4,2},{e3,2},{e3,2},{d2,2},{d2,2},{c1,4},
  154. };
  155. const PROGMEM int MErryChristmas[36][2] //歌曲--圣诞快乐
  156. {
  157. {g5,1},{g5,1},{c6,2},{c6,1},{d6,1},{c6,1},{b5,1},{a5,2},{a5,2},{0,2},
  158. {a5,1},{a5,1},{d6,2},{d6,1},{e6,1},{d6,1},{c6,1},{b5,2},{g5,2},{0,2},
  159. {g5,1},{g5,1},{e6,2},{e6,1},{f6,1},{e6,1},{d6,1},{c6,2},{a5,2},{0,2},
  160. {g5,1},{g5,1},{a5,1},{d6,1},{b5,1},{c6,2}
  161. };
  162. const PROGMEM int BIngo[39][2] //歌曲--宾果
  163. {
  164. {g4,1},{c5,1},{c5,1},{c5,1},{g4,1},{a4,1},{a4,1},{g4,1},{g4,1},
  165. {c5,1},{c5,1},{d5,1},{d5,1},{e5,2},{c5,1},{0,1},
  166. {e5,2},{e5,2},{f5,1},{f5,1},{f5,2},{d5,2},{d5,2},{e5,1},{e5,1},{e5,2},
  167. {c5,2},{c5,2},{d5,1},{d5,1},{d5,1},{c5,1},{b4,1},{g4,1},{a4,1},{b4,1},{c5,2},{c5,1},{c5,1}
  168. };
  169. int serial_putc( char c, struct __file * )
  170. {
  171. Serial.write( c );
  172. return c;
  173. }
  174. void printf_begin(void)
  175. {
  176. fdevopen( &serial_putc, 0 );
  177. }
  178. /*
  179. * Function Clear_All_PWM
  180. * @author wusicaijuan
  181. * @date 2019.07.04
  182. * @brief 关闭PCA9685的所有PWM
  183. * @param[in] void
  184. * @param[out] void
  185. * @retval void
  186. * @par History No
  187. */
  188. void Clear_All_PWM()
  189. {
  190. for (int i = 0; i < 16; i++)
  191. {
  192. pwm.setPWM(i, 0, 0);
  193. }
  194. }
  195. /**
  196. * Function setup
  197. * @author Cindy
  198. * @date 2019.09.11
  199. * @brief 初始化设置
  200. * @param[in] void
  201. * @retval void
  202. * @par History no
  203. */
  204. void setup()
  205. {
  206. Serial.begin(9600);
  207. printf_begin();
  208. strip.begin();
  209. strip.show();
  210. pwm.begin();
  211. pwm.setPWMFreq(60);
  212. Clear_All_PWM();
  213. Servo180(1,90); //将三个舵机都初始化至90
  214. Servo180(2,90);
  215. Servo180(3,90);
  216. breathing_light(255, 40, 5);
  217. pinMode(buzzer, OUTPUT);
  218. digitalWrite(buzzer, HIGH);
  219. }
  220. /**
  221. * Function setBuzzer_Tone
  222. * @author Cindy
  223. * @date 2019.09.02
  224. * @brief 设置蜂鸣器的音调
  225. * @param[in] void
  226. * @param[out] void
  227. * @retval void
  228. * @par History no
  229. */
  230. void setBuzzer_Tone(uint16_t frequency, uint32_t duration)
  231. {
  232. int period = 1000000L / frequency;//1000000L
  233. int pulse = period / 2;
  234. for (long i = 0; i < duration * 200000L; i += period)
  235. {
  236. digitalWrite(buzzer, 1);
  237. delayMicroseconds(pulse);
  238. digitalWrite(buzzer, 0);
  239. delayMicroseconds(pulse);
  240. }
  241. if(frequency==0)
  242. delay(230*duration);
  243. delay(20);
  244. }
  245. /**
  246. * Function 5-music
  247. * @author Cindy
  248. * @date 2019.09.02
  249. * @brief 五首歌曲
  250. * @param[in] void
  251. * @param[out] void
  252. * @retval void
  253. * @par History no
  254. */
  255. void birthday(int j) //生日快乐
  256. {
  257. setBuzzer_Tone(pgm_read_word_near(&BIrthday[j][0]), pgm_read_word_near(&BIrthday[j][1]));
  258. }
  259. void ode(int j) //欢乐颂
  260. {
  261. setBuzzer_Tone(pgm_read_word_near(&ODe[j][0]), pgm_read_word_near(&ODe[j][1]));
  262. }
  263. void star(int j) //小星星
  264. {
  265. setBuzzer_Tone(pgm_read_word_near(&STar[j][0]), pgm_read_word_near(&STar[j][1]));
  266. }
  267. void merryChristmas(int j) //圣诞快乐
  268. {
  269. setBuzzer_Tone(pgm_read_word_near(&MErryChristmas[j][0]), pgm_read_word_near(&MErryChristmas[j][1]));
  270. }
  271. void bingo(int j) //宾果
  272. {
  273. setBuzzer_Tone(pgm_read_word_near(&BIngo[j][0]), pgm_read_word_near(&BIngo[j][1]));
  274. }
  275. /**
  276. * Function music_Play
  277. * @author Cindy
  278. * @date 2019.09.11
  279. * @brief 播放音乐
  280. * @param[in] void
  281. * @param[out] void
  282. * @retval void
  283. * @par History no
  284. */
  285. void music_Play(uint8_t v_song, uint8_t index)
  286. {
  287. switch(v_song)
  288. {
  289. case enStar:
  290. {
  291. star(index);
  292. break;
  293. }
  294. case Bingo:
  295. {
  296. bingo(index);
  297. break;
  298. }
  299. case MerryChristmas:
  300. {
  301. merryChristmas(index);
  302. break;
  303. }
  304. case Ode:
  305. {
  306. ode(index);
  307. break;
  308. }
  309. case Birthday:
  310. {
  311. birthday(index);
  312. break;
  313. }
  314. }
  315. }
  316. /*
  317. * Function Servo180(num, degree)
  318. * @author wusicaijuan
  319. * @date 2019.06.25
  320. * @bried 控制180度舵机旋转
  321. * @param[in1] index
  322. 1: s1
  323. 2: s2
  324. 3: s3
  325. 4: s4
  326. * @param[in2] degree (0 <= degree <= 180)
  327. * @retval void
  328. */
  329. void Servo180(int num, int degree)
  330. {
  331. long us = (degree * 1800 / 180 + 600); // 0.6 ~ 2.4
  332. long pwmvalue = us * 4096 / 20000; // 50hz: 20,000 us
  333. pwm.setPWM(enServo[num - 1], 0, pwmvalue);
  334. }
  335. /**
  336. * Function Distance_test
  337. * @author Cindy
  338. * @date 2019.09.11
  339. * @brief 超声波测距
  340. * @param[in] void
  341. * @param[out] void
  342. * @retval void
  343. * @par History no
  344. */
  345. void Distance_test()
  346. {
  347. pinMode(SingPin,OUTPUT);
  348. digitalWrite(SingPin, LOW);
  349. delayMicroseconds(2);
  350. digitalWrite(SingPin, HIGH);
  351. delayMicroseconds(15);
  352. digitalWrite(SingPin, LOW);
  353. pinMode(SingPin, INPUT);
  354. delayMicroseconds(50);
  355. distance = pulseIn(SingPin, HIGH) / 58;
  356. //Serial.print("distance is :");
  357. //Serial.print(distance);
  358. //Serial.print("cm");
  359. //Serial.println();
  360. //delay(1000);
  361. }
  362. /**
  363. * Function PCB_RGB(R,G,B)
  364. * @author wusicaijuan
  365. * @date 2019.06.26
  366. * @brief 控制板载的RGB
  367. * @param[in1] R
  368. * @param[in2] G
  369. * @param[in3] B
  370. * @param[out] void
  371. * @retval void
  372. * @par History
  373. *
  374. */
  375. void PCB_RGB(int R, int G, int B)
  376. {
  377. uint8_t i = 0;
  378. R = map(R, 0, 255, 0, 200);
  379. G = map(G, 0, 255, 0, 200);
  380. B = map(B, 0, 255, 0, 200);
  381. uint32_t color = strip.Color(G, R, B);
  382. strip.setPixelColor(i, color);
  383. strip.show();
  384. }
  385. /**
  386. * Function Ultrasonic_RGB(R,G,B)
  387. * @author wusicaijuan
  388. * @date 2019.06.26
  389. * @brief 控制超声波模块上面的七彩灯
  390. * @param[in1] R
  391. * @param[in2] G
  392. * @param[in3] B
  393. * @param[out] void
  394. * @retval void
  395. * @par History no
  396. */
  397. void Ultrasonic_RGB(int R, int G, int B)
  398. {
  399. mRgb.setColor(0,G,R,B);
  400. mRgb.show();
  401. }
  402. /**
  403. * Function advance
  404. * @author wusicaijuan
  405. * @date 2019.06.25
  406. * @param[in] 小车前进
  407. * @param[out] void
  408. * @retval void
  409. * @par History no
  410. */
  411. void advance(int Speed)
  412. {
  413. Speed = map(Speed, 0, 255, 0, 4095);
  414. pwm.setPWM(10, 0, Speed); //右前方车轮前进
  415. pwm.setPWM(11, 0, 0);
  416. pwm.setPWM(8, 0, Speed); //右后方车轮前进
  417. pwm.setPWM(9, 0, 0);
  418. pwm.setPWM(13, 0, Speed); //左前方车轮前进
  419. pwm.setPWM(12, 0, 0);
  420. pwm.setPWM(15, 0, Speed); //左后方车轮前进
  421. pwm.setPWM(14, 0, 0);
  422. }
  423. /**
  424. * Function brake
  425. * @author wusicaijuan
  426. * @date 2019.06.25
  427. * @brief 小车停止
  428. * @param[in] void
  429. * @param[out] void
  430. * @retval void
  431. * @par History no
  432. */
  433. void brake()
  434. {
  435. pwm.setPWM(8, 0, 0);
  436. pwm.setPWM(9, 0, 0);

  1. pwm.setPWM(11, 0, 0);
  2. pwm.setPWM(10, 0, 0);
  3. pwm.setPWM(12, 0, 0);
  4. pwm.setPWM(13, 0, 0);
  5. pwm.setPWM(14, 0, 0);
  6. pwm.setPWM(15, 0, 0);
  7. }
  8. /**
  9. * Function left
  10. * @author wusicaijuan
  11. * @date 2019.06.26
  12. * @brief 小车左转
  13. * @param[in] Speed
  14. * @param[out] void
  15. * @retval void
  16. * @par History no
  17. */
  18. void left(int Speed)
  19. {
  20. Speed = map(Speed, 0, 255, 0, 4095);
  21. pwm.setPWM(10, 0, Speed); //右前方车轮前进
  22. pwm.setPWM(11, 0, 0);
  23. pwm.setPWM(8, 0, Speed); //右后方车轮前进
  24. pwm.setPWM(9, 0, 0);
  25. pwm.setPWM(13, 0, 0); //左侧车轮停止
  26. pwm.setPWM(12, 0, 0);
  27. pwm.setPWM(15, 0, 0);
  28. pwm.setPWM(14, 0, 0);
  29. }
  30. /**
  31. * Function right
  32. * @author wusicaijuan
  33. * @date 2019.06.26
  34. * @brief 小车右转
  35. * @param[in] Speed
  36. * @param[out] void
  37. * @retval void
  38. * @par History no
  39. */
  40. void right(int Speed)
  41. {
  42. Speed = map(Speed, 0, 255, 0, 4095);
  43. pwm.setPWM(10, 0, 0); //右侧车轮停止
  44. pwm.setPWM(11, 0, 0);
  45. pwm.setPWM(8, 0, 0);
  46. pwm.setPWM(9, 0, 0);
  47. pwm.setPWM(13, 0, Speed); //左前方车轮前进
  48. pwm.setPWM(12, 0, 0);
  49. pwm.setPWM(15, 0, Speed); //左后方车轮前进
  50. pwm.setPWM(14, 0, 0);
  51. }
  52. /**
  53. * Function spin_left
  54. * @author wusicaijuan
  55. * @date 2019.06.25
  56. * @brief 左旋(左轮后退,右轮前进)
  57. * @param[in] Speed
  58. * @param[out] void
  59. * @retval void
  60. * @par History no
  61. */
  62. void spin_left(int Speed)
  63. {
  64. Speed = map(Speed, 0, 255, 0, 4095);
  65. pwm.setPWM(10, 0, Speed); //右前方车轮前进
  66. pwm.setPWM(11, 0, 0);
  67. pwm.setPWM(8, 0, Speed); //右前方车轮前进
  68. pwm.setPWM(9, 0, 0);
  69. pwm.setPWM(13, 0, 0);
  70. pwm.setPWM(12, 0, Speed); //左前方车轮后退
  71. pwm.setPWM(15, 0, 0);
  72. pwm.setPWM(14, 0, Speed); //左后方车轮后退
  73. }
  74. /**
  75. * Function spin_right
  76. * @author wusicaijuan
  77. * @date 2019.06.25
  78. * @brief 右旋(左轮前进,右轮后退)
  79. * @param[in] Speed
  80. * @param[out] void
  81. * @retval void
  82. * @par History no
  83. */
  84. void spin_right(int Speed)
  85. {
  86. Speed = map(Speed, 0, 255, 0, 4095);
  87. pwm.setPWM(10, 0, 0);
  88. pwm.setPWM(11, 0, Speed); //右前方车轮后退
  89. pwm.setPWM(8, 0, 0);
  90. pwm.setPWM(9, 0, Speed); //右后方车轮后退
  91. pwm.setPWM(13, 0, Speed); //左前方车轮前进
  92. pwm.setPWM(12, 0, 0);
  93. pwm.setPWM(15, 0, Speed); //左后方车轮前进
  94. pwm.setPWM(14, 0, 0);
  95. }
  96. /**
  97. * Function back
  98. * @author wusicaijuan
  99. * @date 2019.06.25
  100. * @brief 小车后退
  101. * @param[in] Speed
  102. * @param[out] void
  103. * @retval void
  104. * @par History No
  105. */
  106. void back(int Speed)
  107. {
  108. Speed = map(Speed, 0, 255, 0, 4095);
  109. pwm.setPWM(10, 0, 0);
  110. pwm.setPWM(11, 0, Speed); //右前方车轮后退
  111. pwm.setPWM(8, 0, 0);
  112. pwm.setPWM(9, 0, Speed); //右后方车轮后退
  113. pwm.setPWM(13, 0, 0);
  114. pwm.setPWM(12, 0, Speed); //左前方车轮后退
  115. pwm.setPWM(15, 0, 0);
  116. pwm.setPWM(14, 0, Speed); //左后方车轮后退
  117. }
  118. /**
  119. * Function whistle
  120. * @author Cindy
  121. * @date 2019.09.11
  122. * @brief 鸣笛
  123. * @param[in] void
  124. * @param[out] void
  125. * @retval void
  126. * @par History no
  127. */
  128. void whistle()
  129. {
  130. for (int i = 0; i < 100; i++)
  131. {
  132. digitalWrite(buzzer, HIGH); //发出声音
  133. delay(3);
  134. digitalWrite(buzzer, LOW); //不发出声音
  135. delay(1);
  136. }
  137. }
  138. /**
  139. * Function breathing_light(brightness,time,increament)
  140. * @author wusicaijuan
  141. * @date 2019.06.26
  142. * @brief logo内嵌的蓝色RGB灯
  143. * @param[in1] brightness
  144. * @param[in2] time
  145. * @param[in3] increament
  146. * @param[out] void
  147. * @retval void
  148. * @par History no
  149. */
  150. void breathing_light(int brightness, int time, int increament)
  151. {
  152. if (brightness < 0)
  153. {
  154. brightness = 0;
  155. }
  156. if (brightness > 255)
  157. {
  158. brightness = 255;
  159. }
  160. for (int b = 0; b < brightness; b += increament)
  161. {
  162. int newb = map(b, 0, 255, 0, 4095);
  163. pwm.setPWM(7, 0, newb);
  164. delay(time);
  165. }
  166. }
  167. /********************************************************************************************************/
  168. /*模式3-巡线模式*/
  169. /**
  170. * Function Tracking_Mode
  171. * @author Cindy
  172. * @date 2019.09.11
  173. * @brief 巡线
  174. * @param[in1] void
  175. * @param[out] void
  176. * @retval void
  177. * @par History no
  178. */
  179. //可根据实际情况修改程序中的参数
  180. void Tracking_Mode()
  181. {
  182. sensor[0] = analogRead(A0);
  183. sensor[1] = analogRead(A1);
  184. sensor[2] = analogRead(A2);
  185. if(sensor[0]>100) //三个参数100100100大家可根据实际情况进行调节
  186. {
  187. sensor[0] = 1;
  188. }
  189. else
  190. {
  191. sensor[0] = 0;
  192. }
  193. if(sensor[1]>100)
  194. {
  195. sensor[1] = 1;
  196. }
  197. else{
  198. sensor[1] = 0;
  199. }
  200. if(sensor[2]>100)
  201. {
  202. sensor[2] = 1;
  203. }
  204. else
  205. {
  206. sensor[2] = 0;
  207. }
  208. if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1))
  209. {
  210. spin_left(80);
  211. }
  212. else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1))
  213. {
  214. left(100);
  215. }
  216. else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0))
  217. {
  218. advance(70);
  219. }
  220. else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 0))
  221. {
  222. right(100);
  223. }
  224. else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0))
  225. {
  226. spin_right(80);
  227. }
  228. else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0))
  229. {
  230. //Clear_All_PWM();//全部检测到白色,保持上一个状态
  231. }
  232. else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1))
  233. {
  234. //Clear_All_PWM();//全部检测到黑色,保持上一个状态
  235. }
  236. }
  237. /********************************************************************************************************/
  238. /*模式2: 超声波避障模式*/
  239. /**
  240. * Function bubble
  241. * @author Cindy
  242. * @date 2019.09.11
  243. * @brief 采用冒泡排序法。
  244. * @param[in1] a:超声波数组的首地址
  245. * @param[in2] n:超声波数组的大小
  246. * @param[out] void
  247. * @retval void
  248. * @par History no
  249. */
  250. void bubble(unsigned long *a, int n)
  251. {
  252. int i, j, temp;
  253. for (i = 0; i < n - 1; i++)
  254. {
  255. for (j = i + 1; j < n; j++)
  256. {
  257. if (a[i] > a[j])
  258. {
  259. temp = a[i];
  260. a[i] = a[j];
  261. a[j] = temp;
  262. }
  263. }
  264. }
  265. return;
  266. }
  267. /**
  268. * Function Distance
  269. * @author Cindy
  270. * @date 2019.09.11
  271. * @brief 去掉最大值和最小值,取中间三个数据的平均值
  272. * @param[in] void
  273. * @param[out] void
  274. * @retval void
  275. * @par History No
  276. */
  277. void Distance()
  278. {
  279. unsigned long ultrasonic[5] = {0};
  280. int num = 0;
  281. while (num < 5)
  282. {
  283. Distance_test();
  284. ultrasonic[num] = distance;
  285. //printf("L%d:%d\r\n", num, (int)distance);
  286. num++;
  287. delay(10);
  288. }
  289. num = 0;
  290. bubble(ultrasonic, 5);
  291. distance = (ultrasonic[1] + ultrasonic[2] + ultrasonic[3]) / 3;
  292. return;
  293. }
  294. enum {
  295. LEFT_DIRECTION,
  296. RIGHT_DIRECTION,
  297. FRONT_DIRECTION,
  298. ALL_CHECKED_START_ACTION
  299. };
  300. /**
  301. * Function ult_check_distance_and_action
  302. * @author Cindy
  303. * @date 2019.09.11
  304. * @brief 舵机转动检测距离
  305. * @param[in] void
  306. * @param[out] void
  307. * @retval void
  308. * @par History no
  309. */
  310. int ult_check_distance_and_action(uint8_t p_direction)
  311. {
  312. static int LeftDistance = 0; //LeftDistance
  313. static int RightDistance = 0; //RightDistance
  314. static int FrontDistance = 0; //FrontDistance
  315. static int cnt = 0;
  316. int ret = 0;
  317. if (0 == g_modeSelect)
  318. {
  319. cnt = 0;
  320. brake();
  321. LeftDistance = 0;
  322. RightDistance = 0;
  323. FrontDistance = 0;
  324. ret = -1;
  325. return ret;
  326. }
  327. mRgb.setColor(0,RGB_GREEN);
  328. mRgb.show();
  329. if (LEFT_DIRECTION == p_direction)
  330. {
  331. Servo180(1, 180);
  332. } else if (RIGHT_DIRECTION == p_direction)
  333. {
  334. Servo180(1, 0);
  335. } else if (FRONT_DIRECTION == p_direction)
  336. {
  337. Servo180(1, 90);
  338. }
  339. else if (ALL_CHECKED_START_ACTION == p_direction) //舵机转动左,右,前三个方向完成测距
  340. {
  341. if (0 == cnt)
  342. {
  343. brake();
  344. delay(50);
  345. }
  346. cnt++;
  347. if (LeftDistance < 25 && RightDistance < 25 && FrontDistance < 25) //比较三个方向的距离
  348. {
  349. mRgb.setColor(0,RGB_PURPLE);
  350. mRgb.show();
  351. spin_right(80);
  352. delay(19);
  353. } else if (LeftDistance >= RightDistance)
  354. {
  355. mRgb.setColor(0,RGB_BLUE);
  356. mRgb.show();
  357. spin_left(80);
  358. delay(13);
  359. } else if (LeftDistance < RightDistance)
  360. {
  361. mRgb.setColor(0,RGB_YELLOW);
  362. mRgb.show();
  363. spin_right(80);
  364. delay(13);
  365. }
  366. if (cnt > 50) //此处是控制小车左旋、右旋的时间19*50/13*50
  367. {
  368. brake();
  369. LeftDistance = 0;
  370. RightDistance = 0;
  371. FrontDistance = 0;
  372. cnt = 0;
  373. ret = 1;
  374. return ret;
  375. }
  376. else
  377. {
  378. return ret;
  379. }
  380. }
  381. delay(20);
  382. cnt++;
  383. if (cnt > 20) //这里是用来控制,让舵机每次转动之后延迟20ms
  384. {
  385. cnt = 0;
  386. Distance();
  387. if (LEFT_DIRECTION == p_direction)
  388. {
  389. LeftDistance = distance;
  390. } else if (RIGHT_DIRECTION == p_direction)
  391. {
  392. RightDistance = distance;
  393. } else if (FRONT_DIRECTION == p_direction)
  394. {
  395. FrontDistance = distance;
  396. }
  397. ret = 1;
  398. }
  399. return ret;
  400. }
  401. /**
  402. * Function UltrasonicAvoidServoMode
  403. * @author Cindy
  404. * @date 2019.09.11
  405. * @brief 超声波避障模式
  406. * @param[in] void
  407. * @param[out] void
  408. * @retval void
  409. * @par History no
  410. */
  411. void UltrasonicAvoidServoMode()
  412. {
  413. static int cnt_1 = 0;
  414. static int distance_smaller_25 = 0;
  415. static int bak_distance = 0;
  416. int ret = 0;
  417. if (0 == distance_smaller_25)
  418. {
  419. Distance_test();
  420. bak_distance = distance;
  421. }
  422. if (bak_distance < 25) //如果检测到的距离小于25,小车开始避障
  423. {
  424. if (0 == distance_smaller_25)
  425. {
  426. cnt_1 = 0;
  427. distance_smaller_25 = 1;
  428. brake();
  429. delay(50);
  430. }
  431. ret = ult_check_distance_and_action(cnt_1);
  432. if (-1 == ret)
  433. {
  434. distance_smaller_25 = 0;
  435. bak_distance = 0;
  436. cnt_1 = 0;
  437. return;
  438. }
  439. else if (1 == ret)
  440. {
  441. cnt_1 ++;
  442. }
  443. if (4 == cnt_1)
  444. {
  445. distance_smaller_25 = 0;
  446. bak_distance = 0;
  447. cnt_1 = 0;
  448. }
  449. }
  450. else if(bak_distance >= 25) //如果距离大于25,小车保持前进
  451. {
  452. if (1 == distance_smaller_25)
  453. {
  454. distance_smaller_25 = 0;
  455. }
  456. bak_distance = 0;
  457. advance(95);
  458. }
  459. }
  460. /********************************************************************************************************/
  461. /*模式1---七彩灯模式*/
  462. /**
  463. * Function color_light
  464. * @author Cindy
  465. * @date 2019.09.11
  466. * @brief 通过舵机转动到不同的角度改变RGB的颜色
  467. * @param[in] pos:舵机转动的角度
  468. * @param[out] void
  469. * @retval void
  470. * @par History no
  471. */
  472. void color_light(int pos)
  473. {
  474. //当舵机转动到150-180度之间,点亮白色
  475. if (pos > 150)
  476. {
  477. mRgb.setColor(0,RGB_WHITE);
  478. mRgb.show();
  479. }
  480. //当舵机转动到125-150度之间,点亮红色
  481. else if (pos > 125)
  482. {
  483. mRgb.setColor(0,RGB_RED);
  484. mRgb.show();
  485. }
  486. //当舵机转动到100-125度之间,点亮绿色
  487. else if (pos > 100)
  488. {
  489. mRgb.setColor(0,RGB_GREEN);
  490. mRgb.show();
  491. }
  492. //当舵机转动到75-100度之间,点亮蓝色
  493. else if (pos > 75)

  1. mRgb.setColor(0,RGB_BLUE);
  2. mRgb.show();
  3. }
  4. //当舵机转动到50-75度之间,点亮黄色
  5. else if (pos > 50)
  6. {
  7. mRgb.setColor(0,RGB_YELLOW);
  8. mRgb.show();
  9. }
  10. //当舵机转动到25-50度之间,点亮紫色
  11. else if (pos > 25)
  12. {
  13. mRgb.setColor(0,RGB_PURPLE);
  14. mRgb.show();
  15. }
  16. //当舵机转动到0-25度之间,点亮青色
  17. else if (pos > 0)
  18. {
  19. mRgb.setColor(0,RGB_CYAN);
  20. mRgb.show();
  21. }
  22. else
  23. {
  24. mRgb.setColor(0,RGB_OFF);
  25. mRgb.show();
  26. }
  27. }
  28. /**
  29. * Function ServoColorRGBMode
  30. * @author wusicaijuan
  31. * @date 2019.06.26
  32. * @brief 七彩灯模式
  33. * @param[in1] brightness
  34. * @param[in2] time
  35. * @param[in3] increament
  36. * @param[out] void
  37. * @retval void
  38. * @par History no
  39. */
  40. static int pos = 0;
  41. static int is_max_pos = 0;
  42. void ServoColorRGBMode()
  43. {
  44. if (0 == is_max_pos)
  45. {
  46. pos += 25;
  47. if (pos >= 180)
  48. {
  49. is_max_pos = 1;
  50. }
  51. } else {
  52. pos -= 25;
  53. if (pos <= 0)
  54. {
  55. is_max_pos = 0;
  56. }
  57. }
  58. Servo180(1, pos);
  59. color_light(pos);
  60. delay(200);
  61. }
  62. /**
  63. * Function BeepOnOffMode
  64. * @author Cindy
  65. * @date 2019.09.11
  66. * @brief 切换模式鸣笛
  67. * @param[in] void
  68. * @param[out] void
  69. * @retval void
  70. * @par History no
  71. */
  72. void BeepOnOffMode()
  73. {
  74. for (int i = 0; i < 200; i++)
  75. {
  76. digitalWrite(buzzer, HIGH); //发出声音
  77. delay(3);
  78. digitalWrite(buzzer, LOW); //不发出声音
  79. delay(1);
  80. }
  81. }
  82. /**
  83. * Function serial_data_parse
  84. * @author Cindy
  85. * @date 2019.09.11
  86. * @brief Serial port data parsing and specify the corresponding action
  87. * @param[in] void
  88. * @param[out] void
  89. * @retval void
  90. * @par History no
  91. */
  92. void serial_data_parse()
  93. {
  94. //Serial.println(InputString);
  95. //解析串口发来指令并控制舵机云台的转动
  96. //首先,判断是否进入了模式选择
  97. if (InputString.indexOf("Mode") > 0 && (InputString.length() == 9) )
  98. {
  99. if (InputString[6] == '0'&& InputString[7] == '0') //stop
  100. {
  101. Clear_All_PWM();
  102. g_CarState = enSTOP;
  103. g_modeSelect = 0;
  104. BeepOnOffMode();
  105. Servo180(1,90);
  106. Ultrasonic_RGB(0,0,0);
  107. }
  108. else if(InputString[6] != '0' && InputString[7] == '1')
  109. {
  110. switch (InputString[6])
  111. {
  112. //case '0': g_modeSelect = 0; Clear_All_PWM(); break;
  113. case '1': g_modeSelect = 1; BeepOnOffMode(); break;
  114. case '2': g_modeSelect = 2; BeepOnOffMode(); break;
  115. case '3': g_modeSelect = 3; BeepOnOffMode(); break;
  116. default: g_modeSelect = 0; break;
  117. }
  118. //delay(1000);
  119. //BeepOnOffMode();
  120. }
  121. InputString = "";
  122. NewLineReceived = false;
  123. return;
  124. }
  125. if (g_modeSelect != 0)
  126. {
  127. InputString = "";
  128. NewLineReceived = false;
  129. return;
  130. }
  131. if (InputString.indexOf("Music") > 0 && (InputString.length() == 10))
  132. {
  133. //Serial.println(InputString);
  134. g_modeMusic = 1; //开启音乐模式
  135. g_musicSelect = (InputString[8] - 0x30)*10 + (InputString[7] - 0x30); //将字符串转化成数字
  136. g_num = 0;
  137. InputString = "";
  138. NewLineReceived = false;
  139. return;
  140. }
  141. //解析上位机发来的舵机云台的控制指令并执行舵机旋转
  142. if (InputString.indexOf("Servo") > 0 )
  143. {
  144. //$Servo,UD180# servo rotate 180
  145. if (InputString.indexOf("UD") > 0) //控制垂直方向的舵机(摄像头上下转动)
  146. {
  147. int i = InputString.indexOf("UD"); //寻找以PTZ开头,#结束中间的字符
  148. int ii = InputString.indexOf("#", i);
  149. if (ii > i)
  150. {
  151. String m_skp = InputString.substring(i + 2, ii);
  152. int m_kp = m_skp.toInt(); //将找到的字符串变成整型
  153. Servo180(3, 180 - m_kp); //让舵机转动到指定角度m_kp
  154. }
  155. InputString = ""; //清空串口数据
  156. NewLineReceived = false;
  157. return; //跳出循环
  158. }
  159. //$Servo,LRS# 舵机停止
  160. //$Servo,LRL# 舵机左转
  161. //$Servo,LRR# 舵机右转
  162. if (InputString.indexOf("LR") > 0)
  163. {
  164. switch (InputString[9])
  165. {
  166. case H_servoL:
  167. g_HServoState = enHServoL;
  168. break;
  169. case H_servoR:
  170. g_HServoState = enHServoR;
  171. break;
  172. case H_servoS:
  173. g_HServoState = enHServoS;
  174. break;
  175. }
  176. InputString = ""; //清除串口数据
  177. NewLineReceived = false;
  178. return;
  179. }
  180. }
  181. //解析上位机发来的通用协议指令,并执行相应的动作
  182. //如:$1,0,0,0# 小车前进
  183. //将数据的长度作为判断的依据
  184. if ((InputString.indexOf("Mode") == -1) && (InputString.indexOf("Servo") == -1) && (InputString.length() == 9))
  185. {
  186. //Light up RGB
  187. if (InputString[7] == '1')
  188. {
  189. int r = random (0, 255);
  190. int g = random (0, 255);
  191. int b = random (0, 255);
  192. PCB_RGB(r,g,b);
  193. Ultrasonic_RGB(r,g,b);
  194. InputString = ""; //清除串口数据
  195. NewLineReceived = false;
  196. return;
  197. }
  198. //Make whistle
  199. if (InputString[5] == '1')
  200. {
  201. whistle(); //鸣笛
  202. }
  203. //调节小车的速度
  204. if (InputString[3] == '1') //加速
  205. {
  206. CarSpeedControl += 20;
  207. if (CarSpeedControl > 150)
  208. {
  209. CarSpeedControl = 150;
  210. }
  211. InputString = ""; //清除串口数据
  212. NewLineReceived = false;
  213. return;
  214. }
  215. if (InputString[3] == '2') //减速
  216. {
  217. CarSpeedControl -= 20;
  218. if (CarSpeedControl < 50)
  219. {
  220. CarSpeedControl = 50;
  221. }
  222. InputString = ""; //清除串口数据
  223. NewLineReceived = false;
  224. return;
  225. }
  226. switch (InputString[1])
  227. {
  228. case run_car:
  229. g_CarState = enRUN;
  230. break;
  231. case back_car:
  232. g_CarState = enBACK;
  233. break;
  234. case left_car:
  235. g_CarState = enLEFT;
  236. break;
  237. case right_car:
  238. g_CarState = enRIGHT;
  239. break;
  240. case spin_left_car:
  241. g_CarState = enSPINLEFT;
  242. break;
  243. case spin_right_car:
  244. g_CarState = enSPINRIGHT;
  245. break;
  246. case stop_car:
  247. g_CarState = enSTOP;
  248. break;
  249. default:
  250. g_CarState = enSTOP;
  251. break;
  252. }
  253. InputString = ""; //清除串口数据
  254. NewLineReceived = false;
  255. //控制小车的运动状态
  256. switch (g_CarState)
  257. {
  258. case enSTOP:
  259. brake();
  260. break;
  261. case enRUN:
  262. advance(CarSpeedControl);
  263. break;
  264. case enLEFT:
  265. left(CarSpeedControl);
  266. break;
  267. case enRIGHT:
  268. right(CarSpeedControl);
  269. break;
  270. case enBACK:
  271. back(CarSpeedControl);
  272. break;
  273. case enSPINLEFT:
  274. spin_left(CarSpeedControl);
  275. break;
  276. case enSPINRIGHT:
  277. spin_right(CarSpeedControl);
  278. break;
  279. default:
  280. brake();
  281. break;
  282. }
  283. }
  284. InputString = ""; //清除串口数据
  285. NewLineReceived = false;
  286. return;
  287. }
  288. /**
  289. * Function serial_data_postback
  290. * @author Cindy
  291. * @date 2019.09.11
  292. * @brief 将采集的传感器数据通过串口传输给上位机显示
  293. * @param[in] void
  294. * @retval void
  295. * @par History NO
  296. */
  297. void serial_data_postback()
  298. {
  299. /*将超声波的数据传送到APK并且显示出来 */
  300. //$CSB,000#
  301. //Ultrasonic Data
  302. Distance_test();
  303. ReturnTemp = "$CSB," ;
  304. ReturnTemp.concat(distance);
  305. ReturnTemp += "#";
  306. Serial.print(ReturnTemp);
  307. return;
  308. }
  309. /*
  310. * Function HServo_State
  311. * @author wusicaijuan
  312. * @date 2019.07.04
  313. * @brief Control state of servo
  314. * @param[in] void
  315. * @param[out] void
  316. * @retval void
  317. * @par History no
  318. */
  319. void HServo_State() //控制摄像头水平方向转动(左---右)
  320. {
  321. if (g_HServoState != enHServoS)
  322. {
  323. if (g_HServoState == enHServoL)
  324. {
  325. Servo_LR++;
  326. if (Servo_LR > 180)
  327. {
  328. Servo_LR = 180;
  329. }
  330. Servo180(2, Servo_LR);
  331. delay(5);
  332. }
  333. if (g_HServoState == enHServoR)
  334. {
  335. Servo_LR--;
  336. if (Servo_LR < 0)
  337. {
  338. Servo_LR = 0;
  339. }
  340. Servo180(2, Servo_LR);
  341. delay(5);
  342. }
  343. return;
  344. }
  345. }
  346. /**
  347. * Function serialEvent
  348. * @author Cindy
  349. * @date 2019.09.11
  350. * @brief
  351. * @param[in] void
  352. * @param[out] void
  353. * @retval void
  354. * @par History
  355. */
  356. void serialEvent() //该函数在Arduino内部被自动调用
  357. {
  358. while (Serial.available())
  359. {
  360. //一个字节一个字节地读,下一句是读到的放入字符串数组中组成一个完成的数据包
  361. IncomingByte = Serial.read();
  362. if (IncomingByte == '$')
  363. {
  364. StartBit = true;
  365. }
  366. if (StartBit == true)
  367. {
  368. InputString += (char) IncomingByte;
  369. }
  370. if (StartBit == true && IncomingByte == '#')
  371. {
  372. NewLineReceived = true;
  373. StartBit = false;
  374. }
  375. }
  376. }
  377. /**
  378. * Function loop
  379. * @author Cindy
  380. * @date 2019.09.11
  381. * @brief 主函数
  382. * @param[in] void
  383. * @retval void
  384. * @par History
  385. */
  386. void loop()
  387. {
  388. if (NewLineReceived)
  389. {
  390. serial_data_parse();
  391. }
  392. newtime = millis();
  393. if (newtime - lasttime > flag_time)
  394. {
  395. lasttime = newtime;
  396. InputString = ""; //清除串口数据
  397. }
  398. switch (g_modeSelect)
  399. {
  400. case 1:
  401. ServoColorRGBMode(); //七彩灯模式
  402. break;
  403. case 2:
  404. UltrasonicAvoidServoMode();//超声波避障模式
  405. break;
  406. case 3:
  407. Tracking_Mode(); //巡线模式
  408. break;
  409. case 0:
  410. default:
  411. break;
  412. }
  413. if( g_modeMusic == 1 )
  414. {
  415. switch (g_musicSelect)
  416. {
  417. case 11:
  418. music_Play(1, g_num);
  419. break;
  420. case 12:
  421. music_Play(2, g_num);
  422. break;
  423. case 13:
  424. music_Play(3, g_num);
  425. break;
  426. case 14:
  427. music_Play(4, g_num);
  428. break;
  429. case 15:
  430. music_Play(5, g_num);
  431. break;
  432. case 0:
  433. default:
  434. g_modeMusic = 0;
  435. break;
  436. }
  437. g_num++;
  438. if(g_musicSelect != 0 && g_num >= music_max[g_musicSelect % 10 - 1])
  439. {
  440. g_num = 0;
  441. g_modeMusic = 2; //stop music
  442. }
  443. }
  444. // if (g_modeSelect == 0 && g_modeMusic == 0 && g_motor == false) //上报超声波距离
  445. // {
  446. // time--;
  447. // if (time == 0)
  448. // {
  449. // count--;
  450. // time = 40000;
  451. // if (count == 0)
  452. // {
  453. // serial_data_postback();
  454. // time = 40000;
  455. // count = 10;
  456. // }
  457. // }
  458. // }
  459. HServo_State();
  460. }

实验现象

      程序下载完成之后,使用APK控制小车。 手机连接上WIFI摄像头模块的WIFI热点:Yahboom_WIFI,无需密码,可以直接连接。 具体步骤如下:程序下载完成之后,将WIFI 摄像头模块的接线插入扩展板上相应位置。打开小车的电源开关,可以看到WIFI摄像头模块上面红色的指示灯处于闪烁状态。下载APK:安卓用户请用浏览器扫描二维码,下载并安装APK;苹果用户请用相机扫码二维码或者进入APP Store搜索“YahboomRobot”,下载并安装该APK。

      模式选择当模式切换成功之后,我们可以听到蜂鸣器鸣笛。如果你点击了一下选项,没有听到蜂鸣器鸣笛的话,就证明没有进入模式,请APK界面的按钮,或者再次长按APK 界面的按钮再松手,即可成功进入相应的模式。

2. 结论

      相较于其他系统,Arduino表现出编程简易、成本低、平台跨越等一系列优势,将其应用于智能小车设计具有十分重要的现实意义.文章通过阐述整体系统设计方案,对Arduino单片机智能小车硬件设计、软件设计及示例功能的实现展开探讨,旨在为促进智能小车设计的健康稳定发展提供必要借鉴。

      小车以Arduino为控制核心,用单片机产生PWM波,控制小车速度。利用灰度传感器对路面黑色轨迹进行检测,并将路面检测信号反馈给单片机。单片机对采集到的信号予以分析判断,及时控制驱动电机以调整小车转向,从而使小车能够沿着黑色轨迹自动行驶,实现小车自动循迹的目的。

以Arduino单片机为控制核心,基于超声波测距的原理,利用超声波传感器,检测小车前方障碍物的距离,然后把数据传送给单片机。当超声波检测到距离小车前方15CM有障碍物时单片机就发出指令让小车左转一定角度,然后停止行进继续探测。如果前方15CM没有障碍物则直行,否则继续左转一定角度。如此通过超声波不断的循环检测周边环境的情况进行自动避障。

      总体来说,基于Arduino的Roboduino智能小车还是有市场前景的,这是人工智能必要的产物,紧跟时代潮流。

更多详情请见:【S054】智能循迹避障小车

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/438558
推荐阅读
相关标签
  

闽ICP备14008679号