跟踪鞋子的小车-Arduino中文社区 - Powered by Discuz! Archiver

lsr123 发表于 2016-10-7 07:19

跟踪鞋子的小车

学习arduino几个月,代码和硬件搭建可能有一些不合理的地方,希望各位多多指正。
暑假突然想到可以用小型的光源来引导小车跟踪鞋子,于是就着手准备材料了。初步的想法是将光源固定在鞋子上,走路时小车就会一直跟在身后。
这里使用了arduino uno作为主控板,DFRobot的小车底盘以及L298驱动扩展版,夏普距离传感器和一个小型充电宝。
小车两侧安置红外传感器用以判断方向,由于使用的发射器的范围不大,为防止发射器和传感器不在一个水平线上,每一侧我都安装了两个。另外在小车第二层的底部固定了一个红外测距,用以在方向调整完后判断并调整与发射器的距离。大致的调整过程如下:
首先调整方向,当左侧传感器返回数值远大于右侧时,说明小车左侧更靠近发射器,因此控制小车左转使其正对发射器,当右侧传感器返回数值远大于右侧时,则控制小车右转。
方向调整完毕以后读取红外测距的数值,当距离小于等于10厘米时小车后退,距离在10厘米和17厘米之间静止不动,距离超过17厘米则前进。

2种特殊情况:
1.小车距离鞋子太近,即使转动很小,两侧的传感器数值变化仍然很大,容易陷入左转-右转-左转-右转的死循环中,因此当距离小于5厘米时调整距离优先,后退之后再判断方向。
2.当发射器于小车的距离过大时,左右红外传感器的返回数值皆为0,小车将停止之前的动作并静止不动,等待发射器再次接近。


由于小车判定方向时只需要接受红外光源一小段时间,因此红外发射器不需要持续发射,因此买了一个兼容arduino的小型红外发射模块,以前做项目时用的小型号主控板,每0.1s给一个20ms的高电平,这样电流不会超过限定值。由于设定小车每个动作持续0.2s,判断+执行一个动作的总时间不会超过0.3s,一秒内可以完成三次调整。


目前由于小车太重,速度跟不上,行走时很容易跟丢。这里先发一个拿鞋子引路的视频,各位谅解哈


http://v.youku.com/v_show/id_XMTc1MDY5NDQ2MA==.html


以下是代码(编程水平有限,判断条件的子函数写的有点乱):

/*
接线:
距离传感器A0
左下红外传感器A2
左上红外传感器A3
右下红外传感器A4
右上红外传感器A5
每个传感器都接扩展板上的vcc和gnd
*/
char E1 = 10;
char M1 = 12;
char E2 = 11;
char M2 = 13;

char disPin = A0;
char IRLL = A2;
char IRLU = A3;
char IRRL = A4;
char IRRU = A5;

int valLL;
int valRL;
int valLU;
int valRU;
int t = 200;
int current;
double dis;

void setup() {
   
//Serial.begin(9600);
pinMode(disPin, INPUT);
pinMode(IRLL, INPUT);
pinMode(IRRL, INPUT);
pinMode(IRLU, INPUT);
pinMode(IRRU, INPUT);
   
}

void loop() {
   
valLL = analogRead(IRLL);
valRL = analogRead(IRRL);
valLU = analogRead(IRLU);
valRU = analogRead(IRRU);

current = checkStatus(valLL, valLU, valRL, valRU);
   
switch (current) {

    case 1:
   turnL(130);
   /*Serial.print("Turn Left -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.println(valRU);*/
   delay(t);
   break;
      
    case 2:
   turnR(130);
   /*Serial.print("Turn Right -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.println(valRU);*/
   delay(t);
   break;
      
    case 3:
    back(180,180);
   /*Serial.print("Right in the middle -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.print(valRU);
   Serial.print(" distance: ");
   Serial.print(dis);
   Serial.print("cm ");
   Serial.println("back");*/
   delay(t);
   break;
      
    case 4:
    brake();
   /*Serial.print("Right in the middle -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.print(valRU);
   Serial.print(" distance: ");
   Serial.print(dis);
   Serial.print("cm ");
   Serial.println("stop");*/
   delay(t);
   break;
      
    case 5:
    advance(180,180);
    /* Serial.print("Right in the middle -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.print(valRU);
   Serial.print(" distance: ");
   Serial.print(dis);
   Serial.print("cm ");
   Serial.println("advance");*/
   delay(t);
   break;
      
    case 6:
    brake();
    /* Serial.print("Out of range -- leftLower : ");
   Serial.print(valLL);
   Serial.print("rightLower : ");
   Serial.print(valRL);
   Serial.print("leftUpper : ");
   Serial.print(valLU);
   Serial.print("rightUpper : ");
   Serial.print(valRU);*/
   delay(t);
   break;
      
    default:
    break;
   
}

}



int checkStatus(int leftLowerValue, int leftUpperValue, int rightLowerValue, int rightUpperValue){
   
static unsigned long last;//记录上一次收到红外线的时间
int carStatus = 0;
uint16_t value = analogRead (disPin);
dis =2076.0 / (value - 11.0);
//任一传感器返回大于100的数值则说明收到了发射源的红外线
if ( leftLowerValue >= 100 || leftUpperValue >= 100 || rightLowerValue >= 100 || rightUpperValue >= 100 )
{

      if( leftLowerValue - rightLowerValue > 180 || leftUpperValue - rightUpperValue > 180 )
      {
             carStatus = 1;
      }
       else if ( rightLowerValue - leftLowerValue > 180 || rightUpperValue - leftUpperValue > 180 )
      {
             carStatus = 2;

      }
//若方向调整完毕,测量距离
      else
      {
          if (dis < 100 ){
          if( dis <= 10 ) carStatus = 3;
          else if( dis > 10 && dis < 17 ) carStatus = 4;
          else carStatus = 5;//测量距离并作出相应的动作
         }
      }
   
last = millis();
if( dis <= 10 ) carStatus = 3; //方向不正但是距离过近时调整距离优先

}

else if(millis() - last > 500)
{
    carStatus = 6;   //当连续500ms没有探测到红外线时说明光源过远,停止小车当前动作
}

return carStatus;

}


void advance(int alspeed, int arspeed){
   
digitalWrite(M1,LOW);
analogWrite(E1,alspeed);
digitalWrite(M2,HIGH);
analogWrite(E2,arspeed);
   
}


void back(int blspeed, int brspeed){
   
digitalWrite(M1,HIGH);
analogWrite(E1,blspeed);
digitalWrite(M2,LOW);
analogWrite(E2,brspeed);
   
}


void turnR(int trspeed){
   
digitalWrite(M1,LOW);
analogWrite(E1,trspeed);
digitalWrite(M2,LOW);
analogWrite(E2,trspeed);
   
}


void turnL(int tlspeed){
   
digitalWrite(M1,HIGH);
analogWrite(E1,tlspeed);
digitalWrite(M2,HIGH);
analogWrite(E2,tlspeed);
   
}


void brake(){
   
digitalWrite(M1,LOW);
digitalWrite(E1,LOW);
digitalWrite(M2,LOW);
digitalWrite(E2,LOW);
   
}

最后附上实物图一张

Kevise 发表于 2016-12-11 23:12

不错,就是感应器距离太近:)
页: [1]
查看完整版本: 跟踪鞋子的小车