问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Arduino智能小车的制作记录与综合应用

创作时间:
作者:
@小白创作中心

Arduino智能小车的制作记录与综合应用

引用
CSDN
1.
https://blog.csdn.net/2301_80164525/article/details/136592407

基于Arduino开发板,我们可以制作一个具有蓝牙控制、调速和超声波避障功能的智能小车。本文将详细介绍制作过程,包括所需材料、各模块的接线原理以及完整的代码实现。

一.材料的准备

  1. Arduino UNO R3开发板一个
  2. L298N电机驱动模块一个
  3. HC-05蓝牙模块一个
  4. HC-SR04超声波避障模块
  5. SG90舵机
  6. 面包板一个
  7. 12v锂电池组和转换插头
  8. 杜邦线若干
  9. 小车车身(包含车轮,两个电机等)

二.各模块介绍与接线原理

1.Arduino UNO R3开发板


以上是常见的两种Arduino Uno R3开发板,我用的是第一个,它们的结构和功能基本相同,差别在于上面的板子的微控制器占地面积小,下面的一整个长方形都是,但这长方形里面其实放的就是上面板子里的小正方形,相当于上面的板子的微控制器没有带包装,更简洁。它们作用是相同的,在板子中都类似于在CPU电脑中的地位。

接口中的GND是接地,输出低电压;VIN口提供电压,范围5~9V。

其中的USB接口需准备一节连接线,与电脑相连,将电脑上自己编写好的代码传入开发板。写代码的软件是Arduino IDE,B站上有安装教程。

我Arduino Uno开发板在下文中就用开发板代替。

2.L298N电机驱动模块

该模块用于接收Arduino上的指令,并传给减速直流电机,驱动电机的运动。

具体接线:

其中IN1等的接线根据写的代码来接,我这里用模拟引脚A0等代替数字引脚行使其功能,用其他数字引脚也可以。

注意:L298N上两个通道使能上的跳线帽不要拔掉,如果用我后文中的PWM调速,则要把跳线帽拔掉,来插导线。

3.HC-05蓝牙控制

蓝牙模块与开发板的连接,可以实现在手机端遥控操作小车。这需要在网上下载一个蓝牙调试器。

其中,VCC连接开发板的5V口,GND就连开发板的GND,TXD连开发板的RX,RXD连开发板的TX

在手机上可以根据自己代码上设计的指令,对蓝牙调试器的按钮进行编辑。如图所示

但是,一定要注意,在电脑给开发板上传代码的时候,蓝牙模块一定不要接线,否则代码不会上传成功。

4.舵机和超声波

舵机在这里面起的作用就是转动它的小机械臂,带动超声波转动,从而实现多方位感测距离。舵机有360°的,有180°的,我用的是180°转角的。

舵机上的三根线,棕色的接开发板的GND,中间红色的接开发板的5V,黄色的接由自己定义的数字引脚,我定义的是6号引脚。

超声波下面的接头中,我TRIG接开发板的9号引脚,ECHO接开发板的10号引脚,这两个引脚是自定义的。VCC接开发板的5VGND就接开发板的GND

我当时忘了买连接舵机和超声波的装置,所以就自己做了一个简易的哈哈~

5.PWM调速

我就不多余解释那些具体的调速原理了,直接写操作的吧

拔掉L298N上的使能通道的跳线帽,就会发现有两个接口端,其中靠里面的不动,靠外面的接到开发板上,开发板上的数字引脚中,带有~符号的是可以调速的引脚,那么就只有3,5,6,9,10,11.我是把ENA接到11,把ENB接到5上。

6.面包板

我们发现很多模块都要用到开发板上的5V和GND,但是开发板上的这两个接口是有限的,在B站上看教程的话,会发现很多人用的扩展板来提供引脚,但这样就会有点麻烦,用面包板也能解决这个问题。

面包板的左右两边是分开的,不连通,以1,2,3,4等为行来说的话,每一行是串联的关系,那我们就可以把开发板上的GND 连到任意行比如第一行第a个,那其他模块需要和GND相连的就连在第1行的第b,c,d,e上的任意一个就可以了。

三.代码及测试

#include <Servo.h> //含有舵机控制库的头文件
// 定义超声波引脚
const int trigPin = 9;
const int echoPin = 10;
char serial_val;//存储串口的数据
int left = A0;//设定引脚号左前轮对应A0,A1号引脚
int left2 = A1 ;
int right = 4;//设定引脚号右前轮对应A2,A3号引脚
int right2 =3 ;
int leftPWM=11;//定义pwm调速引脚       在arduino上的引脚中,其中3,5,6,9,10,11能够接pwm调转速
int rightPWM=5;
// 定义舵机引脚
const int servoPin = 6;
// 定义超声波距离变量
long duration;
int distance;
// 创建Servo对象
Servo myservo;
void setup()
{
    //设定引脚为输出模式
    pinMode(right,OUTPUT);
    pinMode(left,OUTPUT);
    pinMode(right2,OUTPUT);
    pinMode(left2,OUTPUT);
    Serial.begin(9600);//配置蓝牙串口波特率,初始化串口通信
    // 设置超声波引脚为输入/输出模式
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);//为输入模式,应接在开发板的输入口上,但我接输出口上也能正常运行
    pinMode(leftPWM,OUTPUT);//定义PWM调速为输出口
    pinMode(rightPWM,OUTPUT);
  
    // 连接舵机
    myservo.attach(servoPin);
}
void loop()
{
    analogWrite(leftPWM,80);//写一个值(PWM)到引脚,V的范围为0~255
    analogWrite(rightPWM,80);
      
    if (Serial.available()>0)//检查串口有无数据
    {   
        serial_val=Serial.read( );
        if (serial_val == 'w')//发送w时前进,在蓝牙中自行编辑一个按钮为w
        {
            advance( );
            Serial.println("The car is ardvancing ");
        }
        else if (serial_val == 'a')//发送a时左转
        {
            turn_left( );
            Serial.println("The car is turning left");
        }
        else if (serial_val == 'd')//发送d时右转
        {
            turn_right( );
            Serial.println("The car is turning right");     
        }
        else  if (serial_val == 'r') //发送r时后退
        {
            retreat( );
            Serial.println("The car is retreating");
        }
        else  if (serial_val == 's')//发送s时停止
        {
            stop( );
            Serial.println("The car is stopping");
        }
        else  if (serial_val == 'b')//发送s时停止
        {
            avoidance();
            Serial.println("The car is bizhang");
        }
    }
}
void advance( )//前进函数
{
    digitalWrite( left, LOW);
    digitalWrite( left2, HIGH);
    digitalWrite( right, LOW);
    digitalWrite( right2, HIGH);
}
void turn_left( )//左转函数
{
    digitalWrite(left,LOW);
    digitalWrite(left2,LOW);
    digitalWrite(right,LOW);
    digitalWrite(right2,HIGH);
}
void turn_right( )//右转函数
{
    digitalWrite(left,LOW);
    digitalWrite(left2,HIGH);
    digitalWrite(right,LOW);
    digitalWrite(right2,LOW);
}
void retreat( )//后退函数
{
    digitalWrite(left,HIGH);
    digitalWrite(left2,LOW);
    digitalWrite(right,HIGH);
    digitalWrite(right2,LOW);
}
void stop( )//停止函数
{
    digitalWrite(left,LOW);
    digitalWrite(left2,LOW);
    digitalWrite(right,LOW);
    digitalWrite(right2,LOW);
}
int getDistance()//定义一个测距函数
{
    digitalWrite(trigPin,LOW);
    delayMicroseconds(2);//使发出超声波信号接口低电平2us
    digitalWrite(trigPin,HIGH);
    delayMicroseconds(10);//使发出超声波信号接口高电平10us
    digitalWrite(trigPin,LOW);//发出超声波信号接口保持低电平
    int distance=pulseIn(echoPin,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];
    advance();
    myservo.write(90);//舵机在正中间
    dis[1]=getDistance();//得到正中间距离
    if(dis[1]<30)//如果小于30cm
    {
        stop();//小车停止
        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])//左边距离小于右边
        {
            turn_left();//小车左转
            delay(500);
        }
        else//右边距离小于左边
        {
            turn_right();//小车右转
            delay(500); 
        }
    }
}

OK了~

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号