03/31
17:05
IT 嵌入式

Arduino平台制作机器人小车——巡线小车篇

去年我跟大家提出要做飞机的想法,晓伟说有难度,后来泓江说可以做四轴,看过《三个白痴》的都知道,四轴酷酷的外形一点都不亚于固定翼飞机或单旋翼飞机(直升机)。

四轴

那几天我疯狂地搜索网络上的资料,初步理解四轴的工作原理以后,开始紧锣密鼓地收集各个部件的信息,包括支架,电机,浆片,飞控板,电调,电源,传感器(陀螺仪,3轴传感器等等)。结果让我头疼的是,想要配齐这些部件,要花费1500至2000的费用。但是市面上卖的成品也就1500左右。所以因为费用的原因,这个计划一拖再拖。

看到这里可能会觉得飞机和小车?一点也不搭调啊。其实这两者确实没什么必然联系,只是后来,晓伟说做小车成本会便宜些,所以我就先计划做小车去了。

寒假里花了500多块大洋买了一些基本工具,包括一个工具箱(里面基本包括了所有电工需要的工具例如钳子,剪刀,焊具,磨具,钻具,电表等等),一套小车底盘包括减速电机,轮子(主动轮,万向轮),一套Arduino开发板,包括主开发板,电机(直流电机,步进电机,舵机)扩展板,senser扩展板,蓝牙模块,18650锂电池电源两枚以及充电器,后来又外增了红外传感器。

这学期无意间看到海报墙上有机器人小车的比赛就果断报名了,举办方要求可以有两种形式参赛,一种是手焊的模拟电路,另一种是单片机的数字电路。由于我已经基本都有材料了,所以就选择了使用单片机。

Arduino:Arduino 是一款便捷灵活、方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE)。它适用于艺术家、设计师、爱好者和对于“互动”有兴趣的朋友们。由于网络上有许多关于Arduino的资料,我在这里就不再赘述。不过值得一提的就是,这货是开源的!相信如果是搞技术的一听到开源这个词就会感觉到十分的亲切吧!我也不例外,除了对那些无私的开发者表示崇高的敬意,剩下的就只剩膜拜了。

Arduino

我是上Arduino中文社区学的基础知识,如果有点C语言的编程基础,一个晚上搞定跟珜羽一起学基本没什么问题,这样,就相当于简单地认识并且入门了arduino。Arduino给我的感觉就是不像学其他单片机那样,记什么什么好多模块啊,架构啊,寄存器啊之类的,很适合非专业人士上手。

小车:网络上对于这类小车有许多种玩法,比较经典的就是通过蓝牙或者wifi或者无线模块实现远程控制。传统的是使用遥控器,近年由于Android系统的开发,不少人也用手机进行遥控,还增加了拍摄功能。然后就是用小车非控制式地完成一些任务,巡线就是其中一种了。

IMG_2013033116055501_副本

寒假里已经实现了用手机对小车的遥控(还得多亏了许多开放源代码的大牛让我们大大减少了复杂的编码量,特别是跨平台的对接问题),只是寒假里偷懒,一直都没有实现一个用户体验好点的遥控器,这个会在今后继续完善。

那这次比赛的要求是让小车在1.7cm宽的黑色工胶带上巡线行进,其余背景都为白色。

传感器:传感器分为两种,一种是搭配发光二极管和光敏电阻,另一种是红外传感也是一发一收。我选用的是已经封装好了的红外传感器,输入5V电源正负极,输出0或1高低电平。遇到黑色是低电平,白色为高电平。

红外传感器

电源:我选用的是18650充电锂电池,两节,所以续航能力较强。

186503

电机扩展板:我选用了Arduino配套的L293D,其实也可以选择L298N,价格上也不会差太多,不过配套的话,外形会更和谐一点,两块板直接堆砌在一起。而且L293D官网有提供相关的函数库代码,可以直接下载导入Arduino的library里面去,然后直接调用。

扩展板

这样一来,基本硬件配件问题都解决了。接下来就是组装和专心敲代码了。

组装:其实组装工作也并不复杂,将扩展板堆砌在Arduino主板上,再将板子固定在底盘即可。

IMG_2013033116274900_副本

然后就是电机的连接,电源的输入,以及传感器的连接(注:这里由于数字输入口被电机扩展板占用,无法再向上堆砌senser扩展板,所以我选择模拟信号的入口)。

完成这些工作已经大概完成了八成的任务了,但是精彩才刚刚开始,因为代码才是最精华的部分。考虑到我要用四个传感器来识别路面情况,所以对于传感器个数多或者少的情况,此代码可能就不可用了,不过核心的思想应该还是一样的。

直接上代码吧,不解释了,代码很简单,应该能够看懂

#include "AFMotor.h"

AF_DCMotor motor1(2, MOTOR12_8KHZ); // create motor #2, 8KHz pwm
AF_DCMotor motor2(1, MOTOR12_8KHZ);
int speed1 = 254;  // the largest speed when in the straight forward way
int speed2 = 254;
int bigset = 120;  // outer layer senser
int smallset = 135; // inner layer senser
int tmp = smallset; // in order to avoid trembling
int s1=0;
int s2=0;
int count = 0;  // in order to avoid noisy of the outer layer senser detecting (it is really dengerous to regard noisy as black width in this algorithm)

void forward()
{
  motor1.setSpeed(speed1);
  motor2.setSpeed(speed2);
}
void setup()
{
  Serial.begin(9600);           // set up Serial library at 9600 bps

  motor1.setSpeed(speed1);     // set the speed to 200/255      right
  motor2.setSpeed(speed2);     // set the speed to 200/255      left
}

void turnleft(int delta)
{
   motor2.run(BACKWARD);
   motor1.setSpeed(delta);
   motor2.setSpeed(delta);
}
void turnright(int delta)
{
   motor1.run(BACKWARD);
   motor1.setSpeed(delta);
   motor2.setSpeed(delta);
}

void loop()
{
  // four sensers
  int sensorValue1 = analogRead(A1); // left1
  int sensorValue2 = analogRead(A2); // left2
  int sensorValue3 = analogRead(A3); // right2
  int sensorValue4 = analogRead(A4); // right1

  motor1.run(FORWARD);      // turn it on going forward
  motor2.run(FORWARD);      // turn it on going forward

  if((sensorValue2>500)&&(sensorValue3>500)&&(sensorValue1>500)&&(sensorValue4>500))  // just go forward
  {
    forward();
    delay(3);
  }
  else if(sensorValue2<500)   // inner layer senser, turn right
  {
    turnright(tmp);
    delay(2);
    tmp = tmp/4*3;
    if(tmp<(smallset/5)) tmp = smallset;
  }
  else if(sensorValue3<500)  // inner layer sener, turn left
  {
    turnleft(tmp);
    delay(2);
    tmp = tmp/4*3;
    if(tmp<(smallset/5)) tmp = smallset;
  }
  else if(sensorValue1<500) // outer layer senser, turn left until the inner sener detecte
  {
    if(count<10)  // in order to filter the noisy and the count is a tradeoff
    {
      turnleft(bigset);
      delay(1);
      count++;
    }
    else
    {
      count = 0;
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      delay(200);  // cushion
      motor1.run(FORWARD);
      motor2.run(FORWARD);
      while(1)     // outer layer senser, turn left until the inner sener detecte
      {
        if(analogRead(A3)>500)
       {
         turnleft(bigset);
         delay(1);
       }
       else
       {
         motor1.run(RELEASE);
         motor2.run(RELEASE);
         delay(100);
         break;
       }
      }
    }
  }
  else if(sensorValue4<500)  // outer layer senser, turn right until the inner sener detecte
  {
    if(count<10)  // in order to filter the noisy and the count is a tradeoff
    {
      turnright(bigset);
      delay(1);
      count++;
    }
    else
    {
      count=0;
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      delay(200);  // cushion
      motor1.run(FORWARD);
      motor2.run(FORWARD);
      while(1)    // outer layer senser, turn right until the inner sener detecte
      {
        if(analogRead(A2)>500)
       {
         turnright(bigset);
         delay(1);
       }
        else
        {
         motor1.run(RELEASE);
         motor2.run(RELEASE);
         delay(100);
         break;
        }
      }
    }
  }
}

好了,代码贴完也就代表着此教程到此为止了,最后上视频吧:

视频: arduino巡迹小车
视频: 巡线小车

另外再附上几个相关的教程:
Arduino小车诞生记
盒仔——基于Arduino的遥控机器人

发表评论