Arduino手自两用蓝牙避障小车

Arduino手自两用蓝牙避障小车

:该说明文档制作于大二时期,不足之处,敬请谅解。

1.设计目的
本人做这个小车的出发点的目的做给家里的侄子玩,顺便是完成大一时没完成的事情,搞定这个后打算学习STM32,毕竟Arduino作为新手玩玩还行,基础板uno能实现的功能不多,高级板还不如学习STM。

现在,我为大家阐述一下做这个小车的过程,希望能让大家少走一些弯路(因为自己吃过它的大亏)

2.准备材料
Arduino基础板一块,sg舵机一个,超声波一个,蓝牙HC-05一个,下载:蓝牙串口助手”APP,L298N驱动模块一个,电源8—12V一个(实际7V以上也行,主要用于L298Nd的供电,实测有效),普通电机四个(带底盘轮子,网购,总共20几块),面包板一块,杜邦线一扎。

备注:自备小螺丝刀,胶带,剪刀等工具

3.模块学习
各模块的代码我就不写了,不知道的上网一搜教程全部都有,我主要想提醒一下注意的地方。

(1)舵机模块(三根线,分别为VCC,GND,信号线)
注意事项:
1)不要接错线,VCC接5V(一般最好用5V单独供电,低于4.5V后无法驱动)
2)舵机的信号线接在引脚9、10,如果接在其他引脚,如(3引脚)后面测试避障程序时会影响到电机的信号。

(2)超声波模块(四根线,VCC,GND,Tri,Eco)
注意事项:
1)测试时最好先接GND,再接VCC

(3)L298N驱动模块(一般情况是用于驱动两路电机,L298D用于驱动四路电机。但主用它来驱动四个电机也行,实测有效)
注意事项:
1)5V接口可以用板载5V,但12V接口的电压要高于7V为好,低于7V难驱动电机
2)做驱动模块时主要要测两边电机的转向是否一致,不一致要调整信号 线的接线位置
3)L298N驱动四路电机,楼主的方法是,将每一侧的电机并联,然后再借L298N的一个输出端,如此即可。

(4)HC-05蓝牙模块(重点)
注意事项:
1)接线,一定不要接错VCC,GND,RX(接板子TX),TX(接板子RX)
2)烧录程序的时候一定要拔掉RX,TX(不然直接烧毁蓝牙,楼主曾有惨痛经历,用十几块钱买了一个教训)
3)设置蓝牙模式,首先,拔掉蓝牙RX,TX。接着,拔掉USB(连接电脑的烧录线)。然后,紧按蓝牙的黑色按钮(不要松开),接上USB,直到蓝牙的指示灯由急闪烁变为两秒一次闪烁,即进入蓝牙设置模式。
(备注:蓝牙分为开机模式:不停闪烁;设置模式:两秒一次闪烁,工作模式:两秒闪烁两次)
4)进入设置模式后,可以设置蓝牙的名字,连接密码,主从机模式等就行。楼主现在简述一下我的设置经过。

首先,我先把设置蓝牙名字,密码,主从机的程序烧进板子(记得拔掉蓝牙RX和TX)。
接着,我拔掉USB线,,紧按蓝牙的黑色按钮(蓝牙此时连上VCC和GND的),再插上USB,等待蓝牙进入设置模式,松开手。
然后,插上RX和TX。最后,拔掉USB再插上,蓝牙进入开机模式,此时使用下载好的蓝牙串口助手APP,登录搜索蓝牙,看是否找到你设置的蓝牙(不行的话重复几次)

5)蓝牙连接好后,进入APP设置一些参数(这个可以参考网上的教程,有很多详细的说明,在此没有实物就不说明了,摸索下就会,不难)
6)这里为楼主使用的蓝牙设置程序和APP,都上给大家。
蓝牙app:串口调试助手(没有可以留言)
调试代码

#define AT 2
#define LED 13
void setup()
{
       pinMode(LED,OUTPUT);
       pinMode(AT,OUTPUT);
       digitalWrite(AT,HIGH);
       Serial.begin(38400);//这里应该和你的模块通信波特率一致
       delay(100);
       Serial.println("AT");
       delay(100);
       Serial.println("AT+NAME=Jack-Bluetooth");//命名模块名
       delay(100);
       Serial.println("AT+ROLE=0");//设置主从模式:0从机,1主机
       delay(100);
       Serial.println("AT+PSWD=1234");//设置配对密码,如1234
       delay(100);
       Serial.println("AT+UART=9600,0,0");//设置波特率9600,停止位1,校验位无
       delay(100);
       Serial.println("AT+RMAAD");//清空配对列表
}
void loop()
{
       digitalWrite(LED, HIGH);
       delay(500);
       digitalWrite(LED, LOW);
       delay(500);
}

4.模块组合调试

(1)舵机和超声波模块(上代码)
这个模块组合不难,主要是测试两个模块的组合效果。楼主直接上代码,大家不明白的可以留言。

 #include <Servo.h>//宏定义舵机函数
Servo s;//命名舵机
int Trig=4;
int Echo=2;
float cm;
void setup() {
  s.attach(9);//定义舵机引脚
  s.write(50); //初始化舵机角度
  Serial.begin(9600);
  pinMode(Trig,OUTPUT);
  pinMode(Echo,INPUT);
}

void loop() {
  s.write(50);
  digitalWrite(Trig,LOW);//给一个低电平的方波进行
 delayMicroseconds(2);
 digitalWrite(Trig,HIGH);
 delayMicroseconds(10);
 digitalWrite(Trig,LOW);
 cm=pulseIn(Echo,HIGH)/58.0;//pulsenIn用来检测低电平变高电平的时间
 cm=(int(cm*100.0))/100.0;
 Serial.print(cm);
 Serial.print("cm");
 Serial.println();
 delay(1000);
 if (cm<10)
 s.write(10);
 else
 s.write(100);
 delay(2000);
 s.write(50); //测距完成,舵机回到中位
  delay(2000);

}

(2)舵机—超声波—L298N模块(上代码)
这个组合就是避障小车的效果,楼主不太会说,直接上代码,不明白的地方留言。

#include <Servo.h>
//#define MODE      '1'//选择模式
//#define STOP      '2' //手机蓝牙设置
//#define FORWARD   '3'
//#define BACKWARD  '4'
//#define TURNLEFT  '5'
//#define TURNRIGHT '6'
int motorL1=6; //右边轮子
int motorL2=5;
int motorR1=3; //左边轮子
int motorR2=11;
int ledL=16; //左转弯灯
int ledR=17;//转弯灯
int ledB=10  ; //倒车灯
int ledG=13; //大灯
Servo s; //超声波转向舵机
int trig=4; //发射信号
int echo=2; //接收信号
unsigned int S; //距离存储
int MODE=1;

void setup() {
Serial.begin(9600); //设置波特率
pinMode(trig,OUTPUT); //设置引脚模式
pinMode(echo,INPUT);
pinMode(motorL1,OUTPUT);
pinMode(motorL2,OUTPUT);
pinMode(motorR1,OUTPUT);
pinMode(motorR2,OUTPUT);
pinMode(ledL,OUTPUT);
pinMode(ledR,OUTPUT);
pinMode(ledB,OUTPUT);
pinMode(ledG,OUTPUT);
pinMode(12,OUTPUT);  
s.attach(9); //定义舵机所用引脚
s.write(50); //初始化舵机角度
tone(12,800,500);//代表蜂鸣器,800代表频率,500代表发声时间
delay(2000); //开机延时
}

void loop() //主函数
{ 
    while(Serial.available())
    {
      char cmd = Serial.read();//读取蓝牙模块发送到串口的数据
       Serial.print(cmd);
       if(cmd=='1')//模式
          {
             bizhan();
           }
       else if(cmd=='3' )//前进
          {
            Serial.println("FORWARD "); //输出状态
           ledoff(); //关闭所有LED
           ledg(); //运行大灯函数
           digitalWrite(motorL1,HIGH) ;//启动所有电机向前
           digitalWrite(motorL2,LOW);
           analogWrite(motorL1,130);
           analogWrite(motorL2,0);
           digitalWrite(motorR1,HIGH); 
           digitalWrite(motorR2,LOW);
           analogWrite(motorR1,130);
           analogWrite(motorR2,0);
          }
       else if(cmd=='4')//后退
          {
          Serial.println("BACKWARD"); //输出状态
          ledoff();
          ledb();
          digitalWrite(motorL1,LOW);
          analogWrite(motorL2,HIGH);
          analogWrite(motorL1,0);
          analogWrite(motorL2,130);
          digitalWrite(motorR1,LOW);
          analogWrite(motorR2,HIGH);
         analogWrite(motorR1,0);
         analogWrite(motorR2,130);
          }
        else if(cmd=='5')//左转
         {
          Serial.println("TURNLEFT");//输出状态
          ledoff();
         digitalWrite(motorL1,HIGH);
         analogWrite(motorL2,LOW);
         analogWrite(motorL1,130);
         analogWrite(motorL2,0);
         analogWrite(motorR1,LOW);
         digitalWrite(motorR2,HIGH);
         analogWrite(motorR1,0);
         analogWrite(motorR2,130);
         for (int x=0;x<5;x++)//右边LED函数
         { //执行5次
          ledl(); 
         }
         }  
      else if(cmd=='6')//右转
        {
          Serial.println("TURNRIGHT");//输出状态 
          ledoff();
          analogWrite(motorL1,LOW);
          digitalWrite(motorL2,HIGH);
          analogWrite(motorL1,0);
          analogWrite(motorL2,130);
         digitalWrite(motorR1,HIGH);
         analogWrite(motorR2,LOW);
         analogWrite(motorR1,130);
         analogWrite(motorR2,0);
         for (int x=0;x<5;x++)
          {
           ledr();
           }
        }
     else if(cmd=='2')//停止
       {  
      Serial.println("STOP"); //输出状态
      digitalWrite(motorL1,LOW);
      digitalWrite(motorL2,LOW);
      digitalWrite(motorR1,LOW);
      digitalWrite(motorR2,LOW);
      }
}
}
//子函数
void bizhan()
{
    s.write(50); //让舵机位于正中间
     range(); //执行测距函数
     if(S<5)//5cm
     { //判断障碍物距离,距离太近
      back(); //后退
      delay(2000); //后退时间
      }
     else if(S<=30&&S>=5)
     { //距离中等
      turn();
      }//运行转向判断函数
      else
     { //距离充足
     line(); //运行直行函数
    }
}

void turn()
{ //判断转向函数
lull(); //停止所用电机
s.write(10); //舵机转到20度既右边(角度与安装方式有关)
delay(1000); //留时间给舵机转向
range(); //运行测距函数
s.write(50); //测距完成,舵机回到中位(角度与安装方式有关)
delay(1000); //留时间给舵机转向
if (S>30) {L();} //判断左边障碍物距离,如果距离充足,运行左转 
else 
{
s.write(100); //否则,舵机转动到100度,测左边距离
delay(1000);
range(); //测距
s.write(50); //中位
delay(1000);
if(S>30)
{ R();} //右转
else{ 
back();
delay(2000);
}//判断右边距离,距离充足右转否则后退1秒
int x=random(1); //产生一个0到1的随机数
if (x=0){L();}//X=0,左转 
else{R();} //X=1,右转
} 

}

void range(){ //测距函数
digitalWrite(trig,LOW); //测距
delayMicroseconds(2); //延时2微秒
digitalWrite(trig,HIGH);
delayMicroseconds(20);
digitalWrite(trig,LOW);
int distance = pulseIn(echo,HIGH); //读取高电平时间
distance = distance/58; //按照公式计算
S = distance; //把值赋给S
Serial.println(S); //向串口发送S的值,可以在显示器上显示距离
if (S<5){
tone(12,800,50);
delay(50); //延时 
}
}

void line(){ //f前进函数
ledoff(); //关闭所有LED
ledg(); //运行大灯函数
digitalWrite(motorL1,HIGH) ;//启动所有电机向前
digitalWrite(motorL2,LOW);
analogWrite(motorL1,130);
analogWrite(motorL2,0);
digitalWrite(motorR1,HIGH); 
digitalWrite(motorR2,LOW);
analogWrite(motorR1,130);
analogWrite(motorR2,0);
}

void back(){ //后退函数
ledoff();
ledb();
digitalWrite(motorL1,LOW);
analogWrite(motorL2,HIGH);
analogWrite(motorL1,0);
analogWrite(motorL2,130);
digitalWrite(motorR1,LOW);
analogWrite(motorR2,HIGH);
analogWrite(motorR1,0);
analogWrite(motorR2,130);
}

void L(){
ledoff;
digitalWrite(motorL1,HIGH);
analogWrite(motorL2,LOW);
analogWrite(motorL1,130);
analogWrite(motorL2,0);
analogWrite(motorR1,LOW);
digitalWrite(motorR2,HIGH);
analogWrite(motorR1,0);
analogWrite(motorR2,130);
for (int x=0;x<5;x++){ //执行5次
ledl(); //右边LED函数
}
lull(); //暂停所有电机
}

void R(){
ledoff();
analogWrite(motorL1,LOW);
digitalWrite(motorL2,HIGH);
analogWrite(motorL1,0);
analogWrite(motorL2,130);
digitalWrite(motorR1,HIGH);
analogWrite(motorR2,LOW);
analogWrite(motorR1,130);
analogWrite(motorR2,0);
for (int x=0;x<5;x++){
ledr();
}
lull();
}

void lull(){
digitalWrite(motorL1,LOW);
digitalWrite(motorL2,LOW);
digitalWrite(motorR1,LOW);
digitalWrite(motorR2,LOW);
}

void ledl(){
digitalWrite(ledL,HIGH);
delay(50);
digitalWrite(ledL,LOW);
delay(50);
}

void ledr(){
digitalWrite(ledR,HIGH);
delay(50);
digitalWrite(ledR,LOW);
delay(50);
}

void ledb(){
digitalWrite(ledB,HIGH);
}

void ledg(){
digitalWrite(ledG,HIGH);
}

void ledoff(){
digitalWrite(ledL,LOW);
digitalWrite(ledL,LOW);
digitalWrite(ledL,LOW);
digitalWrite(ledL,LOW);
}

(3)蓝牙—L298N模块(代码在(2)里)
这是简单的蓝牙遥控的空能,在网上有很多教程,楼主就不细说了,上代码。
备注:谨记蓝牙的使用方法,蓝牙很容易损坏。

5.完成所有模块组合(蓝牙—超声波避障小车)
这个组合是避障功能和蓝牙遥控功能的组合,之所以将它单独拿出来讲,是因为自己在网上没有找到相关的一个例子,吃了不少苦头(在程序整合的时候,逻辑很恼人)。

注意事项:
(1)不要用switch case语句,因为楼主用该语句时出现的最大问题是,程序跳不出。
智能小车调试视频

6.结语
不足之处,请留言,欢迎交流学习。

  • 4
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值