当前位置:   article > 正文

51单片机智能小车之跟随小车、避障小车原理和代码_五一单片机小车避障

五一单片机小车避障

目录

1. 红外壁障模块分析​编辑

2. 跟随小车的原理

3. 跟随小车开发和调试代码

4. 超声波模块介绍

5. 摇头测距小车开发和调试代码


1. 红外壁障模块分析

原理和循迹是一样的,循迹红外观朝下,跟随朝前

  • TCRT5000传感器的红外发射二极管不断发射红外线
  • 当发射出的红外线没有被反射回来或被反射回来但强度不够大时
  • 红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态
  • 被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和
  • 此时模块的输出端为低电平,指示二极管被点亮
  • 总结就是一句话,没反射回来,D0输出高电平,灭灯

2. 跟随小车的原理

  • 左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
  • 右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转

3. 跟随小车开发和调试代码

  1. //main.c
  2. #include "motor.h"
  3. #include "delay.h"
  4. #include "reg52.h"
  5. //sbit leftSensor = P2^7;
  6. //sbit rightSensor = P2^6;
  7. sbit leftSensor = P2^5;
  8. sbit rightSensor = P2^4;
  9. void main()
  10. {
  11. while(1){
  12. if(leftSensor == 0 && rightSensor == 0){
  13. goForward();
  14. }
  15. if(leftSensor == 1 && rightSensor == 0){
  16. goRight();
  17. }
  18. if(leftSensor == 0 && rightSensor == 1){
  19. goLeft();
  20. }
  21. if(leftSensor == 1 && rightSensor == 1){
  22. //停
  23. stop();
  24. }
  25. }
  26. }
  27. //motor.c
  28. #include "reg52.h"
  29. sbit RightCon1A = P3^2;
  30. sbit RightCon1B = P3^3;
  31. sbit LeftCon1A = P3^4;
  32. sbit LeftCon1B = P3^5;
  33. void goForward()
  34. {
  35. LeftCon1A = 0;
  36. LeftCon1B = 1;
  37. RightCon1A = 0;
  38. RightCon1B = 1;
  39. }
  40. void goRight()
  41. {
  42. LeftCon1A = 0;
  43. LeftCon1B = 1;
  44. RightCon1A = 0;
  45. RightCon1B = 0;
  46. }
  47. void goLeft()
  48. {
  49. LeftCon1A = 0;
  50. LeftCon1B = 0;
  51. RightCon1A = 0;
  52. RightCon1B = 1;
  53. }
  54. void goBack()
  55. {
  56. LeftCon1A = 1;
  57. LeftCon1B = 0;
  58. RightCon1A = 1;
  59. RightCon1B = 0;
  60. }
  61. void stop()
  62. {
  63. LeftCon1A = 0;
  64. LeftCon1B = 0;
  65. RightCon1A = 0;
  66. RightCon1B = 0;
  67. }
  68. //delay.c
  69. #include "intrins.h"
  70. void Delay1000ms() //@11.0592MHz
  71. {
  72. unsigned char i, j, k;
  73. _nop_();
  74. i = 8;
  75. j = 1;
  76. k = 243;
  77. do
  78. {
  79. do
  80. {
  81. while (--k);
  82. } while (--j);
  83. } while (--i);
  84. }

4. 超声波模块介绍

使用超声波模块,型号:HC-SR04

  • 怎么让它发送波 Trig ,给Trig端口至少10us的高电平
  • 怎么知道它开始发了 Echo信号,由低电平跳转到高电平,表示开始发送波
  • 怎么知道接收了返回波 Echo,由高电平跳转回低电平,表示波回来了
  • 怎么算时间 Echo引脚维持高电平的时间! 波发出去的那一下,开始启动定时器 波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
  • 怎么算距离 距离 = 速度 (340m/s)* 时间/2

时序图:

5. 摇头测距小车开发和调试代码

  1. //main.c
  2. #include "reg52.h"
  3. #include "hc04.h"
  4. #include "delay.h"
  5. #include "sg90.h"
  6. #include "motor.h"
  7. #define MIDDLE 0
  8. #define LEFT 1
  9. #define RIGHT 2
  10. void main()
  11. {
  12. char dir;
  13. double disMiddle;
  14. double disLeft;
  15. double disRight;
  16. Time0Init();
  17. Time1Init();
  18. //舵机的初始位置
  19. sgMiddle();
  20. Delay300ms();
  21. Delay300ms();
  22. dir = MIDDLE;
  23. while(1){
  24. if(dir != MIDDLE){
  25. sgMiddle();
  26. dir = MIDDLE;
  27. Delay300ms();
  28. }
  29. disMiddle = get_distance();
  30. if(disMiddle > 35){
  31. //前进
  32. goForward();
  33. }else if(disMiddle < 10){
  34. goBack();
  35. }else
  36. {
  37. //停止
  38. stop();
  39. //测左边距离
  40. sgLeft();
  41. Delay300ms();
  42. disLeft = get_distance();
  43. sgMiddle();
  44. Delay300ms();
  45. sgRight();
  46. dir = RIGHT;
  47. Delay300ms();
  48. disRight = get_distance();
  49. if(disLeft < disRight){
  50. goRight();
  51. Delay150ms();
  52. stop();
  53. }
  54. if(disRight < disLeft){
  55. goLeft();
  56. Delay150ms();
  57. stop();
  58. }
  59. }
  60. }
  61. }
  62. //hc04.c
  63. #include "reg52.h"
  64. #include "delay.h"
  65. sbit Trig = P2^3;
  66. sbit Echo = P2^2;
  67. void Time1Init()
  68. {
  69. TMOD &= 0x0F; //设置定时器模式
  70. TMOD |= 0x10;
  71. TH1 = 0;
  72. TL1 = 0;
  73. //设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
  74. }
  75. void startHC()
  76. {
  77. Trig = 0;
  78. Trig = 1;
  79. Delay10us();
  80. Trig = 0;
  81. }
  82. double get_distance()
  83. {
  84. double time;
  85. //定时器数据清零,以便下一次测距
  86. TH1 = 0;
  87. TL1 = 0;
  88. //1. Trig ,给Trig端口至少10us的高电平
  89. startHC();
  90. //2. echo由低电平跳转到高电平,表示开始发送波
  91. while(Echo == 0);
  92. //波发出去的那一下,开始启动定时器
  93. TR1 = 1;
  94. //3. 由高电平跳转回低电平,表示波回来了
  95. while(Echo == 1);
  96. //波回来的那一下,我们开始停止定时器
  97. TR1 = 0;
  98. //4. 计算出中间经过多少时间
  99. time = (TH1 * 256 + TL1)*1.085;//us为单位
  100. //5. 距离 = 速度 (340m/s)* 时间/2
  101. return (time * 0.017);
  102. }
  103. //delay.c
  104. #include "intrins.h"
  105. void Delay2000ms() //@11.0592MHz
  106. {
  107. unsigned char i, j, k;
  108. i = 15;
  109. j = 2;
  110. k = 235;
  111. do
  112. {
  113. do
  114. {
  115. while (--k);
  116. } while (--j);
  117. } while (--i);
  118. }
  119. void Delay10us() //@11.0592MHz
  120. {
  121. unsigned char i;
  122. i = 2;
  123. while (--i);
  124. }
  125. void Delay300ms() //@11.0592MHz
  126. {
  127. unsigned char i, j, k;
  128. _nop_();
  129. i = 3;
  130. j = 26;
  131. k = 223;
  132. do
  133. {
  134. do
  135. {
  136. while (--k);
  137. } while (--j);
  138. } while (--i);
  139. }
  140. void Delay150ms() //@11.0592MHz
  141. {
  142. unsigned char i, j, k;
  143. i = 2;
  144. j = 13;
  145. k = 237;
  146. do
  147. {
  148. do
  149. {
  150. while (--k);
  151. } while (--j);
  152. } while (--i);
  153. }
  154. void Delay450ms() //@11.0592MHz
  155. {
  156. unsigned char i, j, k;
  157. _nop_();
  158. i = 4;
  159. j = 39;
  160. k = 209;
  161. do
  162. {
  163. do
  164. {
  165. while (--k);
  166. } while (--j);
  167. } while (--i);
  168. }
  169. //sg90.c
  170. #include "reg52.h"
  171. #include "delay.h"
  172. sbit sg90_con = P1^1;
  173. int jd;
  174. int cnt = 0;
  175. void Time0Init()
  176. {
  177. //1. 配置定时器0工作模式位16位计时
  178. TMOD &= 0xF0; //设置定时器模式
  179. TMOD |= 0x01;
  180. //2. 给初值,定一个0.5出来
  181. TL0=0x33;
  182. TH0=0xFE;
  183. //3. 开始计时
  184. TR0 = 1;
  185. TF0 = 0;
  186. //4. 打开定时器0中断
  187. ET0 = 1;
  188. //5. 打开总中断EA
  189. EA = 1;
  190. }
  191. void sgMiddle()
  192. {
  193. //中间位置
  194. jd = 3; //90度 1.5ms高电平
  195. cnt = 0;
  196. }
  197. void sgLeft()
  198. {
  199. //左边位置
  200. jd = 5; //135度 1.5ms高电平
  201. cnt = 0;
  202. }
  203. void sgRight()
  204. {
  205. //右边位置
  206. jd = 1; //0度
  207. cnt = 0;
  208. }
  209. void Time0Handler() interrupt 1
  210. {
  211. cnt++; //统计爆表的次数. cnt=1的时候,报表了1
  212. //重新给初值
  213. TL0=0x33;
  214. TH0=0xFE;
  215. //控制PWM波
  216. if(cnt < jd){
  217. sg90_con = 1;
  218. }else{
  219. sg90_con = 0;
  220. }
  221. if(cnt == 40){//爆表40次,经过了20ms
  222. cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
  223. sg90_con = 1;
  224. }
  225. }
  226. //motor.c
  227. #include "reg52.h"
  228. sbit RightCon1A = P3^2;
  229. sbit RightCon1B = P3^3;
  230. sbit LeftCon1A = P3^4;
  231. sbit LeftCon1B = P3^5;
  232. void goForward()
  233. {
  234. LeftCon1A = 0;
  235. LeftCon1B = 1;
  236. RightCon1A = 0;
  237. RightCon1B = 1;
  238. }
  239. void goRight()
  240. {
  241. LeftCon1A = 0;
  242. LeftCon1B = 1;
  243. RightCon1A = 0;
  244. RightCon1B = 0;
  245. }
  246. void goLeft()
  247. {
  248. LeftCon1A = 0;
  249. LeftCon1B = 0;
  250. RightCon1A = 0;
  251. RightCon1B = 1;
  252. }
  253. void goBack()
  254. {
  255. LeftCon1A = 1;
  256. LeftCon1B = 0;
  257. RightCon1A = 1;
  258. RightCon1B = 0;
  259. }
  260. void stop()
  261. {
  262. LeftCon1A = 0;
  263. LeftCon1B = 0;
  264. RightCon1A = 0;
  265. RightCon1B = 0;
  266. }

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

闽ICP备14008679号