基于Arduino Uno的智能小车(可遥控,避障,调速)模块:L298N HC-05 HC-SR04及sg90(180度)舵机


一、先让小车动起来

1.用到的函数
定义引脚的输入/输出函数

 pinMode(pin, OUT/INPUT);

通过使用pinMode()函数,可以将Arduino的引脚配置为以下三种模式:
输出(OUTPUT)模式
输入(INPUT)模式
输入上拉(INPUT_PULLUP)模式 (这个本片文章不涉及,先不讨论)
pin是要定义输入输出的引脚
例:

int leftMotor1 = 16; //定义16引脚为leftMotor1使之成为输出端
pinMode(leftMotor1, OUTPUT);

将引脚写高(HIGH)低(LOW)电平

digitalWrite(Pin, LOW/HIGH);

例:

digitalWrite(leftMotor1, LOW);//将leftMotor1端置为低电平
digitalWrite(leftMotor1, HIGH);//将leftMotor1端置为高电平

控制电机的转速即控制PWM

analogWrite(pin, value);

例:

analogWrite(10, 200);//设置10端口的PWM值为200

特别说明:
首先,Arduino Uno的5,6,9,10,3,11端口可以使用analogWrite(pin, value)来实现一个指定占空比的PWM。其中pin值的选择(5,6,9,10,3,11),value的值在0~255之间,0为占空比0%,255为占空比100%。
引入的SoftwareSerial函数库

#include <SoftwareSerial.h>//软串口函数库
SoftwareSerial softSerial(2,3);//建立SofwareSerial对象softSerial 且定义 
                               //rx引脚为2 tx引脚为3
read()//该函数可用于从设备接收到数据中读取一个字节的数据。
begin(value);//设置波特率 一般设置为9600
available()//该函数可用于检查设备是否接收到数据。该函数将会返回等待读取的数据字节数。

使用以上函数基本就可以实现用HC05蓝牙控制小车的移动
思路:通过手机端给蓝牙发送指令–>蓝牙接收指令来控制单片机来完成基本动作
使用模块
电机驱动L298N和HC-05蓝牙模块
接线规则和基本原理参考上篇文章

基于51单片机的遥控小车
注意:如果l298n模块的ENA和ENB的引脚键帽没有去掉是短路状态,小车是全速行驶此时不需要使用analogWrite(pin, value)函数即不能实现调速功能

代码如下(示例):

#include <SoftwareSerial.h>
//定义小车各个电机的引脚
int leftMotor1 = 16;
int leftMotor2 = 17;
int rightMotor1 = 18;
int rightMotor2 = 19;
//定义L298n的ENA ENB引脚
int leftPWM = 5;
int rightPWM = 6;
//rx引脚为2 tx引脚为3
SoftwareSerial softSerial(2,3);
char cmdChar='5';//小车停止状态 可见motorRun()中的switch函数
int flag=1;//定义变量flag来控制小车的初始速度

void setup() {
  // put your setup code here, to run once:
  //串口初始化
  Serial.begin(9600); //硬串口波特率为9600
                     //便于通过串口监视器查看小车的状态及后续调试
  softSerial.begin(9600);//软串口波特率9600
  //各个引脚的初始化均为输出状态
  pinMode(leftMotor1, OUTPUT);
  pinMode(leftMotor2, OUTPUT);
  pinMode(rightMotor1, OUTPUT);
  pinMode(rightMotor2, OUTPUT);
  pinMode(leftPWM, OUTPUT);
  pinMode(rightPWM, OUTPUT);
}
void loop() {
  // put your main code here, to run repeatedly:

 if(softSerial.available()){            // 如果软件串口收到信息
    cmdChar = softSerial.read();        // 将信息传递给cmdChar变量
    Serial.print("cmdChar = ");        // 硬件串口输出cmdChar变量信息,
    Serial.println(cmdChar);           // 通过串口监视器输出read函数读取的信息
  }    
    motorRun();
    if(flag==1)//原速
    {
      analogWrite(leftPWM, 200);  
      analogWrite(rightPWM, 200);
    }
    else if(flag==2)//加速
    {
      analogWrite(leftPWM, 255);  
      analogWrite(rightPWM, 255);
    }
    else if(flag==3)//降速
    {
      analogWrite(leftPWM, 80);  
      analogWrite(rightPWM, 80);
    }
}
void motorRun()
{
  switch(cmdChar){  //通过cmdChar来确定小车的状态同时串口监视器会输出对应的状态
    case '1':
      Serial.println("FORWARD");
      FORWARD();
      break;
     case '2':
      Serial.println("BACKWARD"); 
      BACKWARD();
      break;
     case '3':
      Serial.println("TURNLEFT"); 
      TURNLEFT();
      break;
     case '4':
      Serial.println("TURNRIGHT"); 
      TURNRIGHT();
      break;
     case '5':
      Serial.println("STOP"); 
       STOP();
      break;  
     case'7':
     Serial.println("up speed");
      flag=2;
      break;
     case'8':
     Serial.println("low speed");
      flag=3;
      break;
     case'9':
     Serial.println("re speed");
      flag=1;
      break;
  }
}
void FORWARD()
{

      digitalWrite(leftMotor1, HIGH);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, HIGH);
      digitalWrite(rightMotor2, LOW);

}
void BACKWARD()
{     
 
      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, HIGH);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, HIGH); 
  
}
void TURNLEFT()
{     
;
      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, HIGH);
      digitalWrite(rightMotor1, HIGH);
      digitalWrite(rightMotor2, LOW);

}
void TURNRIGHT()
{

      digitalWrite(leftMotor1,HIGH);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, HIGH);

}
void STOP()
{     

      digitalWrite(leftMotor1, LOW);
      digitalWrite(leftMotor2, LOW);
      digitalWrite(rightMotor1, LOW);
      digitalWrite(rightMotor2, LOW);
}


二、加入对应模块实现对应功能

1.HC-SR04及SG90舵机

接线规则及相应原理参考上篇
基于51单片机的超声波避障小车(HC-SR04,SG90舵机)
舵机库及函数的使用

#include <Servo.h>//引用舵机库
Servo myServo;  //定义舵机对象myServo
myServo.write(value);// value值为舵机转动的角度 0-180度

HC-SR04需要使用的函数

 delayMicroseconds(value);//延迟us级函数
pulseIn(Pin, HIGH/LOW);

读引脚的脉冲信号, 被读取的脉冲信号可以是 HIGH 或 LOW. 例如要检测HIGH脉冲信号, Arduino将在引脚变为高电平时开始计时, 当引脚变为低电平时停止记时,并返回脉冲持续时长(时间单位:微秒)。如果在超时时间内没有读到脉冲信号的话, 将返回0

代码如下(示例):

void avoidance()//该函数用于检测前方及左右方向距离 根据距离做出应答
{
  int pos;//定义一个变量用于舵机旋转相应的角度
  int dis[3];//将距离储存到数组中方便比较 
  myServo.write(90);//舵机初始为90度
  FORWARD();
  dis[1]=getDistance(); //测量前方距离
  if(dis[1]<30)  //比较距离是否超过30cm
  {
    STOP();
    for (pos = 90; pos <= 150; pos += 1) 舵机旋转至150{
      myServo.write(pos);             
      delay(15);                       
    }
    dis[2]=getDistance(); //测量左边
    for (pos = 150; pos >= 30; pos -= 1) //舵机旋转至30度
    {
      myServo.write(pos);              
      delay(15);                       
      if(pos==90)
      dis[1]=getDistance(); //在旋转途中再次测量中间距离
    }
    dis[0]=getDistance();  //当旋转至30度时测量右边距离
    for (pos = 30; pos <= 90; pos += 1) 
    {
      myServo.write(pos);             
      delay(15);                       
    }
    if(dis[0]<dis[2]) //右边距离障碍的距离比左边近
    {
      //左转
    TURNLEFT();
    delay(200);
    }
    else  //右边距离障碍的距离比左边远
    {
      //右转
      TURNRIGHT();
      delay(200);
    } 
  }
}
int getDistance()//该函数用于HC-SR04测量距离
{
  digitalWrite(TrigPin, LOW); // 使发出发出超声波信号接口低电平2μs
  delayMicroseconds(2);
  digitalWrite(TrigPin, HIGH); // 使发出发出超声波信号接口高电平10μs 至少10μs
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW); // 保持发出超声波信号接口低电平
  int distance = pulseIn(EchoPin, HIGH); // 读出脉冲时间
  distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
  Serial.println(distance); //输出距离值
  return distance;
}

2.完整程序编写

只需要将测距相关函数添加即可,在motorRun()的switch(cmdChar)中添加case‘6’:

      case '6':
      Serial.println("AVOID");
      avoidance();

void avoidance()和int getDistance()函数添加至motorRun()后方即可


总结

相对于51单片机来说,arduino单片机更加简便自带有许多库可供调用,但是要明白其中的原理还是需要基于51来学习然后可通过arduino来实现。程序及原理方面如有错误或者需要修改请各位车友提出建议

  • 8
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

很瞌睡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值