极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14392|回复: 1

Arduino小车制作

[复制链接]
发表于 2016-1-12 16:32:23 | 显示全部楼层 |阅读模式
本帖最后由 lzy 于 2016-1-12 17:00 编辑


      

——课题四:多功能小车的控制与应用   
组员   卢振耀   王哲   董昌智
任务分配
董昌智(组长):负责总体车的构架与程序编写
王    哲(组员):负责各模块的精细调节与配件组装
卢振耀(组员):负责各传感器的分布安装与测试程序
团队优势
合作分工明确、组员责任意识强、凝聚力较高,能共同钻研攻克难关。
实验过程的不足与缺陷
整个制作过程进度较慢,各模块稳定性不高,有时由于麻痹大意会出现低级失误(烧坏了不少传感器和小灯泡)。小车在运行过程中也会出现无法解释的现象,通过各部分纠错以及程序及场地的适应,最终完善了程序以及找到稳定工作电压,使其正常实现预期功能。
关键字:智能小车   红外避障   wifi遥控   循迹模式           摄像头实时显示
1.各部件展示图与原理图
1.1摄像头模块
1.2红外避障模块与循迹模块
1.3WIFI模块的连接




1.4
红外避障模块的连接

1.5感应器的工作原理图
1.6整体效果展示图
2.制作过程与经过
2.1第一阶段
课题四的任务分配下来,我们有许多新想法,但由于时间与材料的欠缺,最终选择了制作多功能小车,并期望将多种运行模式合为一体,可以实现多种实用功能。在教员提供的材料支持下,我们又在此基础上购置了额外功能的配件(wifi控制模块、摄像头、循迹模块),想把车构建的更强大。然后经过多次试验测试各部件功能的好坏,去掉灵敏度低的元件。经过两天左右的材料准备与思想碰撞,我们具体将车的概念模型构思完毕,万事俱备,等待开工。
2.2第二阶段
第二阶段的主要任务当然是实现实体车的安装过程,其任务量也不容小觑。我们在选车的底座时抉择了很久,既要选协调性高的底座,又要与我们预期传感器的安装位置相兼容,考虑诸多因素,最终选择了这块底板:面积较大,有许多合适孔位便于我们扩展不同的硬件。其次是传感器固定,先将红外传感器用铜柱连接,固定于车身最前部位(具体位置再由车运行时调整),左中右各一个,便于前进时的红外探测。然后是循迹传感器的分布:我们将三个循迹传感器固定在一块PCB板上,距离调整适当(根据循迹的线宽调整),并与所写程序相匹配,将其安装在万向轮的前方,并在传感器四周装了8各小灯泡,作为光线补偿,减小场地误差因素。
接着是主板的固定,既要稳定牢固,又要便于接线,还要方便USB接口的连接。因此我们将其置于小车尾部。然后我们用铜柱搭建了第二层的固定区。主要安放稳压模块、wifi控制模块以及摄像头。这些部件体积较大,因此在板上经过多次协调后,按该方式固定,经过试验,稳定性较高。待基础元件安置完毕后,我们接着进行了工作量较为复杂的接线环节。这个步骤考虑的因素那就更多了,如何配线合理、整齐,是否接线准确无误、是否能分清所接线对应何部位,都是要考虑的因素。线的数量少还好说,一旦有一捆线在你面前,谁都会凌乱的。
经过三位组员的共同努力下,利用面包板,将所有线连接完毕,经过反复检查与确认无误后,接电池开机,LUCKY,各部件等均亮(心情大好),功能有待进一步检验。
然后将各模块的接线用扎带固定,便于区分与调节。
2.3第三阶段
最挑战人极限的一个阶段。就是程序的编写与调试。之前测试各部件的灵敏度均完好,想着程序编写任务就简单多了。果真,将每个模块分布的任务单独写好并测试,也都OK,想着将程序组合后,就大功告成了。
最为关键的就在于程序的组合问题。这也是我们最耗时。最耗精力的一个过程。将所有部件程序调配在一个主程序中,编译,改错后,拷进arduino uno主板中,将车运行,结果机器小车丝毫不动。然后将程序又重新拷了数遍,发现依旧不动。这个才是开始...搞不清楚到底哪里出了问题,然后又把各模块的程序重新依次拷入分别调试检验,结果发现有些部位的响应并不准确。然后以为找出错误了的我们兴致勃勃的在实验场地上将其纠正,重新拷入程序等待完工。结果发现小车动是动了,却并不按照我们的程序来执行相应动作,我们还发现了一个难以解决的问题,就是只在电机转动程序下的小车竟然会根据传感器的反应来改变动作。比如我们拷入了小车直行的程序,其运动会根据传感器读不同的值作出不同响应。那么我们写的电机前进、后退、左转、右转都失去了意义。但我们发现了当拔掉传感器时,电机正常转动;接入传感器时,电机失常。于是我们推断出传感器所接的模拟端口对电机产生了影响。于是我们经过多次试验发现是模拟值端口有四个被电机占用,虽然没有接线,但确实产生了影响。于是我们将传感器接入数字端口,只通过判断01来更改程序,发现问题解决———这是第一个难点
第二个难点:程序思路的欠考虑与不完善。在小车运行过程中,经常会出现卡死在某个位置或在某处动作凌乱。针对于这种情况,就是在编写程序时考虑的情况不周到或是某些情况出现冲突。经过三个人的反复纠错与对程序运行时可能出现的情况作综合考虑,并通过不断拷入调试,最终才将程序相应任务实现。
然后是wifi端与手机电脑的连接,并实时传输到屏幕上,根据软件的控制与相应代码的编写,我们也实现了远程控制小车的运动状态,并可以在手机或电脑端控制它的运行模式(例如红外避障模式、循迹模式的切换),我们也在屏幕上看见了车前方的画面,可以用来监控。
程序稳定后,我们又发现电压的影响也较大,在通过不断测量电压值,我们也确定了一个最佳电压值供小车在较为理想的状态下运行。最终,小车的程序部分完成,最艰难的环节告一段落。
三个阶段的实现,也就标志着多功能小车的完成。最后经过一些善后处理,使小车更加稳定,运行时性能更好。
演示汇报时,我们也将小车的所有功能与用途均展现出来,没有出什么差错,我们都很开心,至少这一周的努力没有白费,所有付出的辛劳与汗水都是值得的。
3.制作感想与反思
3.1制作感想
(一)、整体设计很重要。在动手制作前合理有序的规划线路以及各模块的位置,这对于整个制作过程的顺利进行以及后期的调试、差纠错有重要影响。
(二)、程序编写要清晰。在编写程序时要注意区分代码的层次性。尤其是底层代码要确保无误,然后逐层累加,一步步的实现各项功能。这样也便于后期的程序调试。此次编程过程中先实现前进、后退、左转、右转四项基本功能,然后再进一步编写避障、循迹、控制等模块的代码。
(三)、调试过程需耐心。当整体框架制作完成后的调试过程中,难免会出现各种各样的状况,在这种情况下必须保持清醒,切忌烦躁。尤其是像传感器的调试、轮速的调控、代码的修改等较为精细的工作,要有充足的耐心。
3.2反思与展望
在制作过程中和制作完成后,我们小组的成员学到了很多,也有很多的感受体会。
有一些预期的功能没有时间实现,比如循迹、液晶显示、超声波定距。也产生了许多其他的想法,比如模块化设计搭建,以让整个外观更加协调大方;底层搭建精细化,以让控制更加准确;还可以尝试增加语音控制模块,实现创意控制。
附件:
//源代码:
#include <Servo.h>    //舵机控制库
int distance;
int EN2 = 14;    //电机驱动控制
int EN3 = 15;    //电机驱动控制
int EN4 = 16;    //电机驱动控制
int EN5 = 17;    //电机驱动控制
int EA= 3;
int EB= 5;
int x1=2;   //左侧循迹模块
int x2=4;   //中间循迹模块
int x3=7;   //右侧循迹模块
int h1=8;   //左侧红外模块
int h2=12;   //中间红外模块
int h3=13;  //右侧红外模块
int lx=90;
int a,b,c;
//2路舵机
Servo servoX; //云台X轴舵机 左右
Servo servoY; //云台Y轴舵机 上下
int mkk,kkl,lkf;
/////////////      /////////
///////////////////////////////////////
void bizhang(int x,int y,int z)//a b c
{
if(x==1&&y==0&&z==0)
{
you();
delay(200);
}
else if(x==0&&y==0&&z==1)
{
  zuo();
  delay(200);
}
else if(x==0&&y==0&&z==0)
{
   hou();
   delay(800);
   zuo();
   delay(200);
   
}
else
{
  qian();
delay(200);
}
}
/////////////    //////////
///////////////////////////////////////
void ting(void)
        {
          analogWrite(EA,0);
          analogWrite(EB,0);
          digitalWrite(EN2,LOW);   
          digitalWrite(EN3,LOW);
          digitalWrite(EN4,LOW);   
          digitalWrite(EN5,LOW);      
        }
/////////////    //////////
///////////////////////////////////////
        
void qian(void)
        {
          analogWrite(EA,130);//调节参数可调速度(0-255
          analogWrite(EB,160);//调节参数可调速度(0-255   
          digitalWrite(EN2,LOW);
          digitalWrite(EN3,HIGH);
          digitalWrite(EN4,LOW);
          digitalWrite(EN5,HIGH);
        }
/////////////   退   ////////
///////////////////////////////////////
void hou(void)
        {  
          analogWrite(EA,255);//调节参数可调速度(0-255
          analogWrite(EB,220); //调节参数可调速度(0-255     
          digitalWrite(EN2,HIGH);
          digitalWrite(EN3,LOW);
          digitalWrite(EN4,HIGH);
          digitalWrite(EN5,LOW);            
        }
/////////////     /////////
///////////////////////////////////////
void zuo(void)
        {  
          analogWrite(EA,180);//调节参数可调速度(0-255
          analogWrite(EB,180); //调节参数可调速度(0-255     
          digitalWrite(EN2,LOW);
          digitalWrite(EN3,HIGH);
          digitalWrite(EN4,HIGH);
          digitalWrite(EN5,LOW);     
        }  
/////////////   //////////
///////////////////////////////////////      
void you(void)
        {  
          analogWrite(EA,180);//调节参数可调速度(0-255
          analogWrite(EB,180); //调节参数可调速度(0-255     
          digitalWrite(EN2,HIGH);
          digitalWrite(EN3,LOW);
          digitalWrite(EN4,LOW);
          digitalWrite(EN5,HIGH);
         
        }
///////////////      ///////
///////////////////////////////////////
void servo_left()
{
  int servotemp=servoX.read();//获取舵机目前的角度值
  servotemp-=2;//舵机运动1
  if(servotemp<170&&servotemp>10) //我定义的舵机旋转角度为10度到170
  servoX.write(servotemp);
  else if (servotemp<=10)  servoX.write(10);
  else servoX.write(170);
}
/////////////// ////////////
///////////////////////////////////////
void servo_right()
{
  int servotemp=servoX.read();//获取舵机目前的角度值
  servotemp+=2;//舵机运动1
  if(servotemp<170&&servotemp>10)//我定义的舵机旋转角度为10度到170
  servoX.write(servotemp);
  else if (servotemp<=10)  servoX.write(10);
  else servoX.write(170);
}
/////////////// ////////////
///////////////////////////////////////
void servo_up()
{
  int servotemp1=servoY.read();//获取舵机目前的角度值
  servotemp1+=2;//舵机运动1
  if(servotemp1<170&&servotemp1>10)//我定义的舵机旋转角度为10度到170
  servoY.write(servotemp1);
  else if (servotemp1<=10)  servoY.write(10);
  else servoY.write(170);
}
///////////////   ////////////
///////////////////////////////////////
void servo_down()
{
  int servotemp1=servoY.read();//获取舵机目前的角度值
  servotemp1-=2;//舵机运动1
  if(servotemp1<170&&servotemp1>10)//我定义的舵机旋转角度为10度到170
  servoY.write(servotemp1);
  else if (servotemp1<=10)  servoY.write(10);
  else servoY.write(170);
}
///////////////////////////////////////
///////////////////////////////////////
void setup()
{
  a = digitalRead(x1);
  b = digitalRead(x2);
  c = digitalRead(x3);
  servoX.attach(10);//水平舵机接10
  servoY.attach(11);//上下舵机接11
  servoX.write(90);//输出舵机初始位置为90
  servoY.write(90);//输出舵机初始位置为90
  pinMode(x1, INPUT); //定义左感測器
  pinMode(x2, INPUT); //定义左感測器
  pinMode(x3, INPUT); //定义左感測器
  pinMode(h1, INPUT); //定义左感測器
  pinMode(h2, INPUT); //定义左感測器
  pinMode(h3, INPUT); //定义左感測器
  pinMode(EN2,OUTPUT);
  pinMode(EN3,OUTPUT);
  pinMode(EN4,OUTPUT);
  pinMode(EN5,OUTPUT);
  pinMode(EA,OUTPUT);
  pinMode(EB,OUTPUT);
   for(kkl=0;kkl<20;kkl++)
  {
    delay(500);//延时500M秒,避免WF171路由器启动时产生干扰字符从串口发出
  }
  lkf=0;
   Serial.begin(9600);//设置波特率为9600bps
}
///////////////////////////////////////
///////////////////////////////////////
void loop()
{
   
/* if(distance<=5 & distance>1)
  {
    hou();
    delay(100);
    ting();
    distance=0;
  } */
  Serial.available();
  lkf = Serial.read();
  switch(lkf)
  {
  case 'a':
     qian();
     lkf=0;
     break;   
   case 'b':
     hou();
     lkf=0;
     break;     
   case 'c':
     zuo();
     lkf=0;
     break;
   case 'd':
    you();
    lkf=0;
     break;
   case '7':
  
   {
     while(1)
     {
   a = digitalRead(h1);
   b = digitalRead(h2);
   c = digitalRead(h3);
   bizhang(a,b,c);
   lkf = Serial.read();
   if(lkf=='e')break;
     }
   }
   
    lkf=0;
     break;  
   case 'e':
    ting();
     lkf=0;
     break;
   case '3':
      servo_left();
     delay(10);
      servo_down();
     lkf=0;
     break;
   case '2':
    servoX.write(150);
    servoY.write(150);
    lkf=0;
    break;
   case '1':
     servo_right();
     delay(10);
     servo_up();
     lkf=0;
     break;
  case '9':
     servo_down();
     lkf=0;
     break;
  case '8':
    servo_up();
    lkf=0;
    break;
  }
   
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-1-12 17:05:32 | 显示全部楼层
+10086  +10086
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-10-17 08:22 , Processed in 0.090486 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表