制作基于Arduino的避障小车




项目简介:

在这个项目中我们使用一个Arduino主控板通过红外接近传感器控制直流电机的速度及方向,来达到让小车自动避让障碍物的效果。

成品图:

器材:

Arduino主控板x1(推荐UNO,MEGA或Due);

2WD机器人底盘x1;

双H桥直流电机驱动板x1;

红外接近传感器(或超声波传感器)x2-3;

直流电机x2;

电池组x1-2;

面包板x1(可选);

杜邦跳线若干;

实施步骤:

我们将这个项目分成几部分来进行:

1.使用Arduino通过直流电机驱动板控制电机转动;

2.使用Arduino从红外接近传感器中读取数据;

3.零件的组装与电路的连接;

4.编写并调试程序;

ok,我们从第一部分开始。

我们需要先了解一下如何使用直流电机驱动板。(以L298为例)。

图片来源:robotbase.taobao.com

在这块驱动板上我们主要使用到的引脚有如下几个:

其中,上方红,绿色的引脚分别连接两个电机,下方蓝色VMS和GND引脚风别接电池组的正、负极。下方EA,EB分别为两个电机的使能引脚,输入高电平或模拟值使电机运转。I2,I1及I4,I3分别控制电机A、B的转动方向。(比如I1接低电平I2接高电平使电机顺时针转;I1接高电平I2接低电平使电机逆时针转)。

下面我们按照下图连接电路,

将以下代码输入Arduino IDE:

int pinI1 = 2; //定义I1
int pinI2 = 4; //定义I2
int speedpin = 3; //定义EA
void setup() {

    //将以上引脚设为输出
    pinMode(pinI1, OUTPUT);
    pinMode(pinI2, OUTPUT);
    pinMode(speedpin, OUTPUT);
}
void loop() { //使电机以全速的39%顺时针运转2秒
    digitalWrite(pinI1, LOW);
    digitalWrite(pinI2, HIGH);
    analogWrite(speedpin, 100); //这个值用于PWM调速,介于1-255之间
    delay(2000); //延时2000毫秒

    //逆时针运转2秒

    digitalWrite(pinI1, HIGH);

    digitalWrite(pinI2, LOW);

    analogWrite(speedpin, 100);

    delay(2000);

}

如果没有发生错误,电机将会顺时针转动两秒,然后逆时针转动两秒,然后循环。

我们已经知道了如何通过电机驱动板来控制电机旋转,然后我们需要使用红外接近传感器来判断障碍物。

我使用的是如图的传感器,

引脚定义为:

红色–5v电源;

绿色–接地;

黄色–输出,无障碍物时输出高电平,有障碍物时输出低电平;

下面我们来进行测试

保留上面的电路,然后将红色线接入5v(vin或5v)输出,绿色线接GND引脚,黄色线接11引脚。

输入以下代码:

int inpin = 11;
int pinI1 = 2;
int pinI2 = 4;
int speedpin = 3;

void setup() {
    pinMode(pinI1, OUTPUT);
    pinMode(pinI2, OUTPUT);
    pinMode(speedpin, OUTPUT);
    pinMode(inpin, INPUT);
}
void loop() {
    int in = digitalRead(inpin);
    if ( in == LOW) {

        digitalWrite(pinI1, LOW);
        digitalWrite(pinI2, HIGH);
        analogWrite(speedpin, 100);
    }

}

将红外探头挡住,此时电机会顺时针方向运转。

了解了元件的使用方法之后,我们现在开始组装小车。

这是我使用的小车底盘:

图片来源:swbee.taobao.com/

小车的组装并不复杂,按照说明书即可。

然后按照下图连接Arduino及各元件。

将下面的代码输入IDE:

//motorpin
int pinI1 = 2;
int pinI2 = 4;
int speedpinr = 3;
int pinI3 = 7;
int pinI4 = 8;
int speedpinl = 5;
//senorpin
int inl = 11;
int inr = 12;
//int inm=9;

long ti = 0;
long s = 0;

void setup() {
    //motorpin
    pinMode(pinI1, OUTPUT);
    pinMode(pinI2, OUTPUT);
    pinMode(pinI3, OUTPUT);
    pinMode(pinI4, OUTPUT);
    pinMode(speedpinl, OUTPUT);
    pinMode(speedpinr, OUTPUT);
    //senorpin
    pinMode(inl, INPUT);
    //pinMode(inm,INPUT);
    pinMode(inr, INPUT);
    //sensor5vin
    pinMode(6, OUTPUT);

    digitalWrite(6, HIGH);
    pinMode(A5, OUTPUT);
    digitalWrite(A5, HIGH);
    Serial.begin(9600);
    Serial.flush();

}
void loop() {
    s = s + 1;
    if (s >= 120) {
        s = 0;
    }
    Serial.print(“ = ”);
    Serial.print(s);
    Serial.print(“[“); Serial.print(ti); Serial.print(“]”);
    //sensorM
    int l = digitalRead(inl);
    int r = digitalRead(inr);

    // Serial.print(l);
    // Serial.print(r);
    if (l == HIGH && r == HIGH) {

        forward();
        delay(100);

    }

    l = digitalRead(inl);
    r = digitalRead(inr);

    // Serial.print(l);
    // Serial.print(r);
    if (l == LOW && r == LOW) {
        if (s < 120 && ti >= 3) {
            leftx();
        } else {
            reverse();
        }
        delay(100);

    }

    l = digitalRead(inl);
    r = digitalRead(inr);

    if (l == LOW && r == HIGH) {

        right();
        delay(100);
    }

    l = digitalRead(inl);
    r = digitalRead(inr);

    if (l == HIGH && r == LOW) {

        left();
        delay(100);
    }

}

void forward() {
    digitalWrite(pinI1, LOW);
    digitalWrite(pinI2, HIGH);
    digitalWrite(pinI3, LOW);
    digitalWrite(pinI4, HIGH);
    analogWrite(speedpinl, 130);
    analogWrite(speedpinr, 100);

    //delay(1000);
}

void right() {
    digitalWrite(pinI1, LOW);
    digitalWrite(pinI2, HIGH);
    digitalWrite(pinI3, LOW);
    digitalWrite(pinI4, HIGH);
    analogWrite(speedpinl, 140);
    analogWrite(speedpinr, 55);
}

void left() {
    digitalWrite(pinI1, LOW);
    digitalWrite(pinI2, HIGH);
    digitalWrite(pinI3, LOW);
    digitalWrite(pinI4, HIGH);
    analogWrite(speedpinl, 55);
    analogWrite(speedpinr, 135);
}

void reverse() {
    digitalWrite(pinI1, HIGH);
    digitalWrite(pinI2, LOW);
    digitalWrite(pinI3, HIGH);
    digitalWrite(pinI4, LOW);
    analogWrite(speedpinl, 95);
    analogWrite(speedpinr, 75);
    ti = ti + 1;
    delay(1500);
}

void leftx() {
    digitalWrite(pinI1, LOW);
    digitalWrite(pinI2, HIGH);
    digitalWrite(pinI3, HIGH);
    digitalWrite(pinI4, LOW);
    analogWrite(speedpinl, 85);
    analogWrite(speedpinr, 85);
    ti = 0;
    s = 0;
    delay(2000);
}

然后小车即可运行,并且自动避开障碍物。

后记:

1.虽然这个代码可以正常运行,但是效率并不高;

2.由于条件所限我只使用了2个传感器,只能够满足基本的要求,如果要实现更好的效果,请使用至少3个传感器;

3.红外传感器只能探测前方有无障碍存在,并且探测距离不定,如果有条件可以使用可以精确测距的超声波传感器;

4.小车出现2个轮子不一样快是正常的,请调节EA/EB引脚的模拟值来调节速度;

5.在上面的代码中我使用了串口通信对程序进行调试(Serial打头的语句),在对arduino编程的时候用好串口调试会有很大帮助;

6.在上面的代码中我加入了一种异常处理,可以实现在一段时间(大约10秒)内连续3次触发reverse()函数,小车将会180度掉头并向前行驶,机器人在运行过程中会遇到各种异常情况,所以在代码中一定要考虑到异常情况的处理;




Posted

in

by

Comments

6 responses to “制作基于Arduino的避障小车”

  1. […] 使用L298N扩展板驱动直流电机:这个之前已经研究过了,详见:https://nyan.im/posts/301.html […]

    1. Frank Avatar

      诶哟卧槽我刚发现图全挂了

      1. 随风漂流的星光 Avatar

        我这里部分可见。第一次看的时候还好

        1. Frank Avatar

          那是之前托管在sae的图片,迁移的时候链接没有改过来

          1. 随风漂流的星光 Avatar

            嗯,我看关于的时候了解了

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.