目录

 

一、小车简介

二、材料清单

三、Arduino UNO R3简介及使用说明 

四、各模块安装接线及测试

1.驱动模块接线及测试

(1)减速直流电机

(2)L298N电机驱动模块 

(3)具体接线

(4)代码及测试  

2.巡线模块接线及测试

(1)TCRT5000红外反射传感器

(2)具体接线

(3)代码及测试

(4)PWM调速

3.蓝牙模块接线及测试

(1)HC-05蓝牙模块

(2)具体接线

(3)代码及测试

4.超声波避障模块接线及测试

(1)HC-SR04超声波测距模块

(2) SG90舵机

(3)具体接线

(4)代码及测试


一、小车简介

       本小车选用Arduino UNO R3主控板,在小车上搭建了电机驱动模块、蓝牙模块、红外线传感器模块、超声波模块实现小车的基本运动、蓝牙通信、巡线、避障功能。

二、材料清单

小车所使用的材料如下表:

名称 注释 数量
小车底盘套件

底盘*2、轮子*4、减速直流电机*4、紧固件*8、M3*30螺丝*8、M3螺母*14、M3*6螺丝*6、L30+6铜柱*6

1套
Arduino开发板 Arduino UNO R3 1个
电机驱动模块 L298N电机驱动模块 1个
电池 18650锂电池 2节
电池盒 18650电池盒(2节) 1个
红外线传感器模块 TCRT5000红外反射传感器 4个
蓝牙模块 HC-05主从一体无线蓝牙模块 1个
超声波模块 HC-SR04超声波测距模块 1个
舵机 SG90舵机 1个
杜邦线

若干

三、Arduino UNO R3简介及使用说明 

        Arduino Uno是基于ATmega328P,它有14个数字输入/输出引脚(其中6个可用作PWM输出)、6个模拟输入、一个16 MHz陶瓷谐振器(CSTCE16M0V53-R0)、一个USB连接、一个电源插孔、一个ICSP接头和一个复位按钮。

该开发板的详细资料链接:Arduino UNO 

四、各模块安装接线及测试

1.驱动模块接线及测试

(1)减速直流电机

 该小车使用的减速直流电机参数如下:

工作电压 DC 3V DC 5V DC 6V
工作电流 100mA 100mA 120mA
减速比 48:1
空载转速 100 r/min 190 r/min 240 r/min

(2)L298N电机驱动模块 

       利用L298N模块可以实现电机的正转、反转,从而驱动小车实现前进、后退及转向功能。其具体引脚功能和使用方法如下:

12V输入:12V是由L298N芯片所能接受的最大电压,一般外接5~12V直流电源的正极。

GND :接地端一般接直流电源的负极,在与Arduino开发板连接时两者要共地。

5V输入:由于L298N模块自带板载5V输出使能,5V接口可稳定输出5V电压给Arduino板供电。

A、B通道使能(ENA、ENB):此处有跳线帽,未拔掉时,马达A、B端稳定输出5V电压,拔掉后,可实现PWM调速,改变A、B两端电压,从而改变马达转速。

I/O控制输入:有4个输入接口:IN1、IN2、IN3、IN4,与这四个输入对应的输出为:马达A输出的OUT1、OUT2和马达B输出的OUT3、OUT4。

L298N模块控制电机的原理如下:(下表中高、低为电平状态)

电机 运动状态 IN1 IN2 IN3 IN4
电机A 正转 / /
反转 / /
停止 / /
电机B 正转 / /
反转 / /
停止 / /

(3)具体接线

       此部分为两节串联的18650锂电池(总电压7.4V)作为电源,L298N马达驱动模块,四个减速直流电机和UNO开发板的接线:

18650锂电池 正极+ —— 12V输入 L298N模块
负极- —— GND
UNO开发板 A0 —— IN1
A1 —— IN2
A2 —— IN3
A3 —— IN4
GND —— GND
5V —— 5V输入
L1、L2电机 a端 —— OUT1
b端 —— OUT2
R1、R2电机 a端 —— OUT3
b端 —— OUT4

下面是仿真接线图:(所用仿真软件linkboy点此下载

       注意:此处未使用L298N电机驱动模块 的A、B使能通道,因此A、B使能端的跳线帽不能拔掉,所以不具有PWM调速功能,电机输入电压为板载的5V。

(4)代码及测试  

        Arduino程序的编写一边用到官方软件ArduinoIDE(windows点此下载),打开后写入代码,在工具中选择端口和开发板信息即可进行编译及上传。驱动测试部分输入以下代码:

//定义小车五种运动状态
#define STOP 0      //停止
#define FORWARD 1   //向前
#define BACKWARD 2  //后退
#define TURNLEFT 3  //左转
#define TURNRIGHT 4 //右转

int leftmotor1=A0;  //定义所用到的引脚
int leftmotor2=A1;  //用A0、A1、A2、A3脚(模拟信号引脚可作为数字引脚使用)
int rightmotor1=A2;
int rightmotor2=A3;

void setup()  //定义用到的引脚为输出端
{
  pinMode(leftmotor1,OUTPUT);
  pinMode(leftmotor2,OUTPUT);
  pinMode(rightmotor1,OUTPUT);
  pinMode(rightmotor2,OUTPUT);
}

void motorRun(int m) //定义小车的运动函数
 {
  switch(m)
  {
    case FORWARD://小车前进,左、右两个电机均正转
    digitalWrite(leftmotor1,LOW);  
    digitalWrite(leftmotor2,HIGH); 
    digitalWrite(rightmotor1,LOW); 
    digitalWrite(rightmotor2,HIGH);
    break;

    case BACKWARD://小车后退,左、右两个电机均反转
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    case TURNLEFT://小车左转,左边两个电机反转、右边两个电机正转
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case TURNRIGHT://小车右转,左边两个电机正转、右边两个电机反转
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    default://四个电机都停止转动
    digitalWrite(leftmotor1,LOW);//四个引脚同为高电平或者低电平
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,LOW);
    }
  }


void loop()
{
int m;
for(m=0;m<5;m++)//小车依次执行停止、前进、后退、左转、右转各两秒
  {
    motorRun(m);
    delay(2000);
  }
}

按照下图摆放好电机,并在上面标注电机位置,观察电机转动现象:

        正常现象:所有电机停止2秒,正转2秒,反转2秒, L1、L2反转R1、R2正转2秒,L1、L2正转R1、R2反转2秒,依次循环。(若出现左边或两个电机转向不一致的情况,则将转向错误的电机两头接线调换即可),调试后电机转动现象若正常,即可安装底盘和车轮:

 然后连接好UNO开发板、L298N模块、电源,即可放在地面进行测试。

2.巡线模块接线及测试

(1)TCRT5000红外反射传感器

       TCRT5000红外反射传感器,一种集发射与接收于一体的光电传感器,它由一个红外发光二极管和一个NPN红外光电三极管组成。检测反射距离1mm-25mm适用,可以应用于机器人避障、机器人进行白线或者黑线的跟踪,可以检测白底中的黑线,也可以检测黑底中的白线,是巡线机器人的必备传感器。

 引脚介绍:

VCC:该模块工作电压为3.3V~5V,一般将Arduino开发板的5V接口引出与之相连。

GND:接电源负极,连接时注意与各个模块共地。

A0:模拟信号输出口,当传感器在接收到反射的不同距离的时,该引脚输出的电压会不同。

D0:数字信号输出口,用于判断是否检测到黑线,该小车用该模块巡线因此仅使用D0引脚。

工作原理:该传感器的红外发射二极管不断的向外发射红外光线,由于黑色有较强的吸光能力,当该模块发射的红外线照射到黑线时,红外线被黑线吸收,导致循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,反射回来的红外线使循迹模块上光敏三极管饱和,此时模块上两个LED常量。

(2)具体接线

        此部分仅需要在驱动部分接线的基础上将两个红外线传感器模块与Arduino开发板连接。在红外模块介绍中提到,我们仅用到D0引脚检测是否有黑线,而没有必要使用A0引脚来判断距离。另外,由于后续模块要接大量的5V和GND端,可以用排针(如下图)来扩展开发板的5V和GND端使用。

红外线传感器1(安装于小车头部左端) VCC —— 5V扩展端 UNO开发板
GND —— GND扩展端
D0 —— 数字接口10
红外线传感器2(安装于小车头部右端) VCC —— 5V扩展端
GND —— GND扩展端
D0 —— 数字接口11

下面是仿真接线图:(在驱动接线的基础上增加)

(3)代码及测试

       在此部分小车会通过车头的两个红外线传感器检测到地面是否有黑线,若左边的传感器模块检测到有黑线,说明小车位置偏右,需要左转。同理,当右边检测到黑线时,小车左转。同时检测到黑线时,小车停止。输入以下代码,接好线即可进行验证。

#define STOP 0  //停止
#define FORWARD 1  //向前
#define BACKWARD 2  //后退
#define TURNLEFT 3  //左转
#define TURNRIGHT 4  //右转

int leftmotor1=A0;
int leftmotor2=A1;
int rightmotor1=A2;
int rightmotor2=A3;
int trac1=10;       //定义两个红外线传感器所连接的引脚  
int trac2=11;

void setup()
{
  pinMode(leftmotor1,OUTPUT);
  pinMode(leftmotor2,OUTPUT);
  pinMode(rightmotor1,OUTPUT);
  pinMode(rightmotor2,OUTPUT);
  pinMode(trac1,INPUT);//将10、11引脚设置为输入口
  pinMode(trac2,INPUT);
}

void tracing()//循迹程序
{
  int data[2];//定义一个数组来保存传感器输入的数据
  data[0]=digitalRead(10);
  data[1]=digitalRead(11);
  if(!data[0]&&!data[1])//左右都未检测到黑线
  {
    motorRun(FORWARD);//向前
    }
  if(data[0])//左边检测到黑线
  {
    motorRun(TURNLEFT);//左转
    }

  if(data[2])//右边检测到黑线
  {
    motorRun(TURNRIGHT);//右转
    }

  if(data[0]&&data[1])//左右都检测到黑线
  {
    motorRun(STOP);//停止
 while(1);
    } 
  }


void motorRun(int m)
 {
  switch(m)
  {
    case FORWARD://左、右两个电机均正转
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case BACKWARD://左、右两个电机均反转
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    case TURNLEFT://左边两个电机反转、右边两个电机正转
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case TURNRIGHT://左边两个电机正转、右边两个电机反转
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    default://四个电机都停止转动
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,LOW);
    }
  }


void loop()
{
   tracing();
}

正常现象:小车会沿着黑线运动,当运动到“T”字时停止。

       由于该小车仅使用了两个红外线传感器模块,并且该模块的安装高度也会影响它的检测结果,当安装位置过高时,反射光线不足,也会默认检测到黑线。另外由于小车速度较快,在弯道半径较小时不按黑线行驶。可以再增加两个传感器并调整到合理的安装高度,还可以通过L298N模块的A、B使能通道对电机进行PWM调速,在弯道时设置较小的速度来优化巡线效果。

(4)PWM调速

Arduino开发板的数字引脚中,有“~”的I/O(3、5、6、9、10、11)口表示有PWM调速功能(PWM调速原理),因此我们可选择6、9分别连接L298N的ENA、ENB使能端进行PWM调速。由于数字 I/O口输出范围为0~255,若输出x,则电机的输入电压为(x/255*5)V,经测试,这里将6、9接口的输出设置为110,这样的巡线效果较好。具体代码更改如下:


#define STOP 0  //停止
#define FORWARD 1  //向前
#define BACKWARD 2  //后退
#define TURNLEFT 3  //左转
#define TURNRIGHT 4  //右转

int leftmotor1=A0;
int leftmotor2=A1;
int rightmotor1=A2;
int rightmotor2=A3;
int trac1=10;
int trac2=11;
int leftPWM=6;//定义pwm调速引脚
int rightPWM=9;

void setup()
{
  pinMode(leftmotor1,OUTPUT);
  pinMode(leftmotor2,OUTPUT);
  pinMode(rightmotor1,OUTPUT);
  pinMode(rightmotor2,OUTPUT);
  pinMode(trac1,INPUT);
  pinMode(trac2,INPUT);
  pinMode(leftPWM,OUTPUT);//定义PWM调速为输出口
  pinMode(rightPWM,OUTPUT);
}

void tracing()//循迹程序
{
  int data[2];
  data[0]=digitalRead(10);
  data[1]=digitalRead(11);
  if(!data[0]&&!data[1])//左右都未检测到黑线
  {
    motorRun(FORWARD,110);//向前
    }
  if(data[0])//左边检测到黑线
  {
    motorRun(TURNLEFT,110);//左转
    }

  if(data[1])//右边检测到黑线
  {
    motorRun(TURNRIGHT,110);//右转
    }

  if(data[0]&&data[1])//左右都检测到黑线
  {
    motorRun(STOP,0);//停止
    while(1);
  }
    } 


void motorRun(int m,int v)
 { 
  analogWrite(leftPWM,v);//写一个值(PWM)到引脚,V的范围为0~255
  analogWrite(rightPWM,v);
  switch(m)
  {
    case FORWARD://左、右两个电机均正转
    Serial.println("FORWARD");
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case BACKWARD://左、右两个电机均反转
    Serial.println("BACKWARD");
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    case TURNLEFT://左边两个电机反转、右边两个电机正转
    Serial.println("TURNLEFT");
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case TURNRIGHT://左边两个电机正转、右边两个电机反转
    Serial.println("TURNRIGHT");
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    default://四个电机都停止转动
    Serial.println("STOP");
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,LOW);
    }
  }


void loop()
{
  tracing();
}

事实上,只改写了驱动程序

void motorRun(int m,int v)

 增加了变量v,通过改变v来改变输入给电机的电压大小,从而实现调速。

3.蓝牙模块接线及测试

(1)HC-05蓝牙模块

       HC-05是主从一体的蓝牙模块,出产默认为从机,可连接各种单片机或直接连接单片机串口,空旷场地下有效距离为10米。与手机或电脑的蓝牙配对成功后,可以作为全双工串口通信使用,无需了解任何蓝牙协议。默认波特率为9600。

引脚介绍:

STATE:蓝牙状态引出脚,未连接时输出低电平,连接时输出高电平。

EN:AT指令设置脚,连接后可通过更改AT指令设置蓝牙模块为主机。

VCC:该模块工作电压为3.6V~6V,一般将Arduino开发板的5V接口引出与之相连。

GND:接电源负极,连接时注意与各个模块共地。

TX:发送端,一般与开发板的串口接收端连接。

RX:接收端,一般与开发板的串口发送端连接。

       由于该模块可实现全双工串口通信,因此不需要特地设置主机或从机。在该小车中,蓝牙模块仅使用TX、RX、VCC、GND四个引脚。

(2)具体接线

HC-05蓝牙模块与Arduino开发板的具体接线:

HC-05蓝牙模块 TX —— 数字接口0(RX) UNO开发板
RX —— 数字接口1(TX)
VCC —— 5V扩展端
GND —— GND扩展端

下面是仿真接线图:(在驱动部分的基础上)

 (在此基础上,还需要将L298N的ENA、ENB分别与开发板的6、9端连接)

(3)代码及测试

这一部分使用到串口通信,先介绍一下Arduino编程与串口有关的函数:

Serial.begin()//打开串口
Serial.available()//获取串口上可读取的数据的字节数
Serial.read()//读串口数据
Serial.print()//向串口发数据无换行
Serial.write()//写二进制数据到串口

蓝牙部分的详细代码:

#define STOP 0  //停止
#define FORWARD 1  //向前
#define BACKWARD 2  //后退
#define TURNLEFT 3  //左转
#define TURNRIGHT 4  //右转

int leftmotor1=A0;
int leftmotor2=A1;
int rightmotor1=A2;
int rightmotor2=A3;
int leftPWM=6;
int rightPWM=9;

void setup()
{
  Serial.begin(9600);//串口初始化波特率9600
  pinMode(leftmotor1,OUTPUT);
  pinMode(leftmotor2,OUTPUT);
  pinMode(rightmotor1,OUTPUT);
  pinMode(rightmotor2,OUTPUT);
  pinMode(leftPWM,OUTPUT);
  pinMode(rightPWM,OUTPUT);
}

void motorRun(int m,int v)
 { 
  analogWrite(leftPWM,v);
  analogWrite(rightPWM,v);
  switch(m)
  {
    case FORWARD://左、右两个电机均正转
    Serial.println("FORWARD");//向串口发数据并换行
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case BACKWARD://左、右两个电机均反转
    Serial.println("BACKWARD");
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    case TURNLEFT://左边两个电机反转、右边两个电机正转
    Serial.println("TURNLEFT");
    digitalWrite(leftmotor1,HIGH);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,HIGH);
    break;

    case TURNRIGHT://左边两个电机正转、右边两个电机反转
    Serial.println("TURNRIGHT");
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,HIGH);
    digitalWrite(rightmotor1,HIGH);
    digitalWrite(rightmotor2,LOW);
    break;

    default://四个电机都停止转动
    Serial.println("STOP");
    digitalWrite(leftmotor1,LOW);
    digitalWrite(leftmotor2,LOW);
    digitalWrite(rightmotor1,LOW);
    digitalWrite(rightmotor2,LOW);
    }
  }


void loop()
{             
 if(Serial.available()>0) // 判断串口是否有数据写入
 {
 char m=Serial.read();//读取蓝牙模式
 Serial.print(m);//向开发板串口发数据
 if(m<5)
 { 
 motorRun(m,200);
}
}
}

手机可下载蓝牙串口助手,通过手机蓝牙向HC-05蓝牙模块发送数据来控制小车运动。

4.超声波避障模块接线及测试

(1)HC-SR04超声波测距模块

        HC-SR04超声波模块常用于机器人避障、物体测距等场所,该模块主要是由两个通用的压电陶瓷超声传感器,并加外围信号处理电路构成的。

引脚介绍:

VCC:该模块工作电压为3.6V~6V,一般将Arduino开发板的5V接口引出与之相连。

GND:接电源负极,连接时注意与各个模块共地。

Trig:控制端,控制发出的超声波信号。

Echo:接收端,接收反射回来的超声波信号。

工作原理:

  • 使用单片机的一个引脚发送一个至少10us高电平的TTL脉冲信号到模块的Trig引脚,用于触发模块工作;
  • 模块检测到触发信号之后,会自动发送8个40khz的方波,然后自动切换至监测模式,监测是否有信号返回(超声波信号遇障碍物会返回);
  • 如果有信号返回,通过模块的Echo引脚会输出一个高电平, 高电平持续的时间就是超声波从发射到返回的时间;
  • 因为声音在空气中的速度为340米/秒,即可计算出所测的距离。
  • (2) SG90舵机

           舵机模块可以通过指令控制舵机转动的角度,此车使用的是180°舵机。舵机初始化时指向0°角,转动的有效范围为:-90° ~ +90° 。小车在遇到障碍物时,通过舵机带动超声波模块转动,从而判断左右距离的远近,以此控制小车左转或右转。

    工作原理:舵机的控制信号为周期是20ms 的脉宽调制(PWM)信号,其中脉冲宽度从0.5ms-2.5ms,相对应舵盘的位置为0—180度,呈线性变化。也就是说,给它提供一定的脉宽,它的输出轴就会保持在一个相对应的角度上,无论外界转矩怎样改变,直到给它提供一个另外宽度的脉冲信号,它才会改变输出角度到新的对应的位置上。舵机内部有一个基准电路,产生周期20ms,宽度1.5ms的基准信号,有一个比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机的转动信号。

    详细资料链接:SG90舵机工作原理

    (3)具体接线

            经过测试,由于SG90的舵机信号控制引脚只能接9、10,在这里接9,将原来的右侧电机pwm调速端改接5引脚。

    HC-SR04超声波测距模块 VCC —— 5V扩展端 开发板
    GND —— GND扩展端
    Trig —— 数字引脚8
    Echo —— 数字引脚7
    SG90舵机 红色线 —— 5V扩展端
    棕色线 —— GND扩展端
    橙色线 —— 数字引脚9

    仿真接线图:

           接好线后,将超声波模块与舵机连接固定好,确保舵机转动能带动超声波模块转动,连接好如下图所示:

    (4)代码及测试

    在这一部分使用到了舵机库文件,并且在使用时对舵机初始化。

    #include<Servo.h>//加入含有舵机控制库的头文件
    
    
    #define STOP 0  //停止
    #define FORWARD 1  //向前
    #define BACKWARD 2  //后退
    #define TURNLEFT 3  //左转
    #define TURNRIGHT 4  //右转
    
    
    int leftmotor1=A0;
    int leftmotor2=A1;
    int rightmotor1=A2;
    int rightmotor2=A3;
    int leftPWM=6;
    int rightPWM=5;
    
    Servo myServo;//舵机
    int inputPin=7;//定义超声波信号接收接口
    int outputPin=8;//定义超声波信号发出接口
    
    void setup()
    {
      Serial.begin(9600);
      myServo.attach(9);//舵机引脚初始化
      pinMode(leftmotor1,OUTPUT);
      pinMode(leftmotor2,OUTPUT);
      pinMode(rightmotor1,OUTPUT);
      pinMode(rightmotor2,OUTPUT);
      pinMode(leftPWM,OUTPUT);
      pinMode(rightPWM,OUTPUT);
      pinMode(inputPin,INPUT);//超声波控制引脚初始化
      pinMode(outputPin,OUTPUT);
    }
    
    
    void motorRun(int m,int v)
     {
      analogWrite(leftPWM,v);
      analogWrite(rightPWM,v);
      switch(m)
      {
        case FORWARD://左、右两个电机均正转
        Serial.println("FORWARD");
        digitalWrite(leftmotor1,LOW);
        digitalWrite(leftmotor2,HIGH);
        digitalWrite(rightmotor1,LOW);
        digitalWrite(rightmotor2,HIGH);
        break;
    
        case BACKWARD://左、右两个电机均反转
        Serial.println("BACKWARD");
    
        digitalWrite(leftmotor1,HIGH);
        digitalWrite(leftmotor2,LOW);
        digitalWrite(rightmotor1,HIGH);
        digitalWrite(rightmotor2,LOW);
        break;
    
        case TURNLEFT://左边两个电机反转、右边两个电机正转
        Serial.println("TURNLEFT");
        digitalWrite(leftmotor1,HIGH);
        digitalWrite(leftmotor2,LOW);
        digitalWrite(rightmotor1,LOW);
        digitalWrite(rightmotor2,HIGH);
        break;
    
        case TURNRIGHT://左边两个电机正转、右边两个电机反转
        Serial.println("TURNRIGHT");
        digitalWrite(leftmotor1,LOW);
        digitalWrite(leftmotor2,HIGH);
        digitalWrite(rightmotor1,HIGH);
        digitalWrite(rightmotor2,LOW);
        break;
    
        default://四个电机都停止转动
        Serial.println("STOP");
        digitalWrite(leftmotor1,LOW);
        digitalWrite(leftmotor2,LOW);
        digitalWrite(rightmotor1,LOW);
        digitalWrite(rightmotor2,LOW);
    
        }
      }
    
    int getDistance()//定义一个测距函数
    {
      digitalWrite(outputPin,LOW);
      delayMicroseconds(2);//使发出超声波信号接口低电平2us
      digitalWrite(outputPin,HIGH);
      delayMicroseconds(10);//使发出超声波信号接口高电平10us
      digitalWrite(outputPin,LOW);//发出超声波信号接口保持低电平
      int distance=pulseIn(inputPin,HIGH);//读取脉冲时间
      distance=distance/58;//将脉冲时间转化为距离
      Serial.println(distance);//输出距离值
      if(distance>=50)//如果距离大于50cm
      {
        return 50;//返回50
        }
        else //如果小于50cm,返回距离值
        return distance;
      }
      
    void avoidance()
    {
      int p;
      int dis[3];
      motorRun(FORWARD,200);
      myServo.write(90);//舵机在正中间
      dis[1]=getDistance();//得到正中间距离
      if(dis[1]<30)//如果小于30cm
      {
        motorRun(STOP,0);//小车停止
        for(p=90;p<=150;p++)//舵机转动检测两边距离
        {
          myServo.write(p);
          delay(15);//延时供其运动
          }
       dis[2]=getDistance();//检测到左边距离
       for(p=150;p>=30;p--)
        {
          myServo.write(p);
          delay(15);
          if(p==90)
          dis[1]=getDistance();
          }
         dis[0]=getDistance();//检测到右边距离
         for(p=30;p<=90;p++) 
         {
          myServo.write(p);
          delay(15);
          }
          if(dis[0]<dis[2])//左边距离小于右边
          {
            motorRun(TURNLEFT,255);//小车左转
            delay(500);
            }
           else//右边距离小于左边
           {
            motorRun(TURNRIGHT,255);//小车右转
            delay(500); 
            }
        }
      }
      
    void loop()
    {
      avoidance();
        }
        

          代码:

    distance=distance/58;//将脉冲时间转化为距离

             解释一下为什么是除以58,脉冲时间读取函数pulseIn()单位为ms,声音在空气中的传播速度为340m/s=0.034cm/us,根据这个可以算出1/0.034=29.15us/cm,发出超声波到碰到障碍物再到返回超声波为一个来回,所以应该为2*29.15=58.3us/cm,也就是说1cm的距离需要58us,那么距离distance(㎝)=pulseIn()/58。

           至此就可以输入代码测试了,另外,由于该模块始终检测正前方距离,遇到障碍才会停,因此在运动时车身两侧存在死角,可能会发生碰擦,但对正前方的障碍物能准确躲避。

    物联沃分享整理
    物联沃-IOTWORD物联网 » Arduino小车知识汇总

    发表评论