arduino小车制作心得

在制作arduino小车之前,需要了解一些基础知识,虽然大部分的东西都在调库,以及调试,首先要明白arduino的代码基本上是由两部分组成的loop(循环部分)和set up(启动阶段),在我的学习的阶段我了解了digital系列的函数还有analog系列的函数以及Servo库的东西等一系列东西

 

1.pinMode(端口,模式)

在最初使用pinMode可以把接入的端口进行不同模式的设定,大概有三类INPUT(输入模式),OUTPUT(输出模式),INPUT_PULLUP(输入上拉模式)

输入上拉模式,选择一个相应的接口,进行输入上拉,mega板子上默认的开始都为高电压,上拉到5V,可以使用digitalRead()读取高低电位,和按钮相结合可以控制相应的亮灭

void setup() {
  // put your setup code here, to run once:
     pinMode(2,INPUT_PULLUP);
     pinMode(13,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
   int val = digitalRead(2);       //读取引脚2的状态,在mega板子上会上拉到5V(高电平)
   if(val == HIGH)
   {
    digitalWrite(13,LOW);
   }
   else                            //按下开关,和GND相连,变为低电平
   {
    digitalWrite(13,HIGH);
   }
}

2.digital系列

在使用pinMode将相应的引脚设置OUTPUT后需要digitalWrite()进行使其输出高电平或者低电平的输出。

digitalRead(),可以检测该引脚的的模式,返回相应的数字(高电平是1[HIGH],低电平是0[lLOW])

3.analog系列(digitalWrite()和digitalRead()函数已经完成了初始化,不需要在set up 进行初始化)

analogRead(PIN),这个接口只能选用模拟数字接口(eg.  A0),简单理解就是将不可视的电压变为可视化,读取引脚的模拟值,在mega开发板上,可以将0-5v的电压分为0-255的形式,在uno开发板上因为板子的精度是10,所以可以将0-5V的电压分为0-1023的形式,这样就可以光敏电阻读取阻值从而知道目前光线的强度了。

analogWrite(PIN,Val),在制作小车的阶段需要使用这个函数进行PWM进行一个调速设置,mega就在0-255,uno就在0-1023之间,便可这个也就是呼吸灯的原理了(借助for循环进行操作)。

4.Serial系列

digital.avaliable()读出串口监视器的字节个数(一般是在蓝牙模块进行读取命令)

Serial.Read()读取串口的一个字节.

Serial.begin(),设置波特率,保证发出端和接收端的频率相同,保证信息的准确传送

Serial.println()在串口输出信息并换行,Serial.print()在串口输出信息

pulseIn用于读取引脚脉冲的时间长度,脉冲可以是HIGH或LOW。如果是HIGH,函数将先等引脚变为高电平,然后开始计时,一直到变为低电平为止。返回脉冲持续的时间长短, 单位为ms。如果超时还没有读到的话, 将返回0。

知识大概就是这些,还有一些小点.......

组装方面:我选用的是 arduino Mega 2560开发板,L298N电机,红外循迹模块,舵机,超声波模块,以及hc-05蓝牙模块,主要就这几个模块。

我选用的是四驱小车,因为是四驱所以使用了两个L298N的电机,但只有一个电源所以我选择将两个电机并联在一起,电源电压大概最低都要9V(不要问为什么,因为我有血的教训),别的就是接线了。

最后的效果图如下:

第一部分:小车的前进,后退,左右转弯

将小车四个轮子的直流电机驱动和L298N电机相连接,并且清楚哪个接口对应哪个轮子,借助PWM进行调速。

#define FORWARD 0
#define BACKWARD 1
#define LEFT 2 
#define RIGHT 3
#define STOP 4
 //前面的两个轮子
int rightMotor1 = 36;
int rightMotor2 = 34;
int leftMotor1 = 30;
int leftMotor2 = 32;
//后面两个轮子
int rightMotor3 = 22;
int rightMotor4 = 24;
int leftMotor3 = 28;
int leftMotor4 = 26;
//前面两个的PWM
int leftPWM1 = 10;
int rightPWM2 =11 ;
//后面两个轮子的PWM
int leftPWM3 = 8;
int rightPWM4 = 9;

注意:当拔掉PWM跳帽的时候,如果不进行使用,小车将无法运动(解决方法:1.把跳帽插上2.使用PWM进行调速)

void Control_direction(int dir,int val1,int val2,int val3,int val4)  //val4右后轮 val3左后轮  val2右前轮  val1 左前轮
{
    analogWrite(leftPWM1,val1);   //设置PWM,设置速度
    analogWrite(rightPWM2,val2);
    
    analogWrite(leftPWM3,val3);   //设置PWM,设置速度
    analogWrite(rightPWM4,val4);
    switch(dir)
    {
      case FORWARD:
      Serial.println("FORWARD");
      digitalWrite(leftMotor1,HIGH);
      digitalWrite(leftMotor2,LOW);
      digitalWrite(rightMotor1,HIGH);
      digitalWrite(rightMotor2,LOW);
      digitalWrite(leftMotor3,LOW);
      digitalWrite(leftMotor4,HIGH);
      digitalWrite(rightMotor3,LOW);
      digitalWrite(rightMotor4,HIGH);
      break;
      case BACKWARD:
      Serial.println("BACKWARD");
      digitalWrite(leftMotor1,LOW);
      digitalWrite(leftMotor2,HIGH);
      digitalWrite(rightMotor1,LOW);
      digitalWrite(rightMotor2,HIGH);
      digitalWrite(leftMotor3,HIGH);
      digitalWrite(leftMotor4,LOW);
      digitalWrite(rightMotor3,HIGH);
      digitalWrite(rightMotor4,LOW);
      break;
      case LEFT:
      Serial.println("LEFT");
      digitalWrite(leftMotor1,HIGH);
      digitalWrite(leftMotor2,LOW);
      digitalWrite(rightMotor1,HIGH);
      digitalWrite(rightMotor2,LOW);
      digitalWrite(leftMotor3,LOW);
      digitalWrite(leftMotor4,HIGH);
      digitalWrite(rightMotor3,LOW);
      digitalWrite(rightMotor4,HIGH);
      break;
      case RIGHT:
      Serial.println("RIGHT");
      digitalWrite(leftMotor1,HIGH);
      digitalWrite(leftMotor2,LOW);
      digitalWrite(rightMotor1,HIGH);
      digitalWrite(rightMotor2,LOW);
      digitalWrite(leftMotor3,LOW);
      digitalWrite(leftMotor4,HIGH);
      digitalWrite(rightMotor3,LOW);
      digitalWrite(rightMotor4,HIGH);
      break;
    }
}

虽然代码过于长,但实际大部分都是复制粘贴,只需要改一下(HIGHorLOW)。当你需要轮子前转的时候,需要将该轮子的两极一个置高,一个置低,形成电位差(电压)【后转则和前转刚好相反】,但在实际中,你需要调试看哪一极该置高,哪一极该置低。

当你需要轮子静止,则只需要将两端同时置高或者置低。

第二部分:(超声波避障)

原理(使用 Arduino 采用数字引脚给 SR04 的 Trig 引脚至少 10 μ s 的高电平信号,触发 SR04 模块测距功能,触发后,模块会自动发送 8 个 40KHz 的超声波脉冲,并自动检测是否有信号返回。这步会由模块内部自动完成,如有信号返回, Echo 引脚会输出高电平,高电平持续的时间就是超声波从发射到返回的时间。此时,我们能使用 pulseIn() 函数获取到测距的结果,并计算出距被测物的实际距离。因为声速在空气中的速度大约为340m/s,用时间/2再乘以速度,大约就是距离,然后将距离实时的返回给板子。

pulseln()检测高低电平的脉冲宽度。

int getDistance()
{
  digitalWrite(outputPin, LOW); // 使发出发出超声波信号接口低电平2μs
  delayMicroseconds(2);
  digitalWrite(outputPin, HIGH); // 使发出发出超声波信号接口高电平10μs,这里是至少10μs
  delayMicroseconds(10);
  digitalWrite(outputPin, LOW); // 保持发出超声波信号接口低电平
  int distance = pulseIn(inputPin, HIGH); // 读出脉冲时间
  distance= distance/58; // 将脉冲时间转化为距离(单位:厘米)
  Serial.println(distance); //输出距离值
 
  if (distance >=50)
  {
    //如果距离小于50厘米返回数据
    return 50;
  }//如果距离小于50厘米小灯熄灭
  else
    return distance;
}

除此之外还需要舵机,通过舵机可以将SR04进行一个全方位的转动,从而可以测得各个方向的距离,从而让小车完成最优选择路径。 

舵机的使用需要调用库函数#include <Servo.h>,而且需要初始化引脚myServo.attach(引脚)。还需要定义舵机变量

void avoidance()
{
  int pos;
  int dis[3];//距离
  myServo.write(95);           //将舵机正对前面
  motorRun(FORWARD,60,60,60,60);
  dis[1]=getDistance(); //中间
  if(dis[1]<30)
  {
    motorRun(STOP,0,0,0,0);
    for (pos = 95; pos <= 150; pos += 1)
    {
      myServo.write(pos);               
      delay(20);                        
    }
    dis[2]=getDistance(); //左边
    for (pos = 150; pos >= 30; pos -= 1)
    {
      myServo.write(pos);              
      delay(20);                       
      if(pos==95)
        dis[1]=getDistance(); //中间
    }
    dis[0]=getDistance();  //右边
    for (pos = 30; pos <= 95; pos += 1)
    {
      myServo.write(pos);               
      delay(20);                       
    }
    if(dis[0]<dis[2]) //右边距离障碍的距离比左边近
    {
      //左转
      motorRun(TURNLEFT,0,60,0,60);
      delay(1000);
    }
    else if(dis[0]>dis[2]) //右边距离障碍的距离比左边远
    {
      //右转
      motorRun(TURNRIGHT,60,0,60,0);
      delay(1000);
    }
  }
}

3.循迹部分(借助红外模块检测黑线,若检测到黑线返回1----低电平,否则返回0---高电平)

将每一个信号都存在数组里面

我做的小车只是用了三个红外模块

int date[3];
  date[0]=digitalRead(left);
  date[1]=digitalRead(mid);
  date[2]=digitalRead(right);
  if(date[0]==0&&date[1]==1&&date[2]==0)
    go(60,60,60,60);
  if(date[0]==1&&date[1]==1)
  {
    left_(0,60,0,60);
    delay(50);
  }
  if(date[1]==0&&date[2]==1)
  {
    right_(60,0,60,0);
    delay(50);
  }
  if(date[0]==1&&date[1]==1&&date[2]==1)
  {
    stop_(0,0,0,0);
    delay(2000);
  }

4.蓝牙部分,我使用的是HC-05蓝牙模块,首先需要明白蓝牙和小车之间借助串口通信的方式进行信息交互,手机和蓝牙模块相连接,就可以控制小车了。

Arduino 5V - VCC
Arduino GND - GND
Arduino Pin10 - TXD
Arduino Pin11 - RXD

第一步:蓝牙模块的AT模式:长按蓝牙模块上的小黑按钮,然后将usb接口插入电脑,此时蓝牙模块会两秒亮灭的形式(进入了AT模式)

#include <SoftwareSerial.h> 

// Pin11为RX,接HC05的TXD
// Pin12为TX,接HC05的RXD
SoftwareSerial BT(11,12); 
char val;

void setup() {
  Serial.begin(38400); 
  Serial.println("BT is ready!");
  // HC-05默认,38400
  BT.begin(38400);
}

void loop() {
  if (Serial.available()) {
    val = Serial.read();
    BT.print(val);
  }

  if (BT.available()) {
    val = BT.read();
    Serial.print(val);
  }
}
 

借助这个代码则可以在arduino串口监视器进行AT指令的操作,当然你也可以借助Xcom或者sscom进行串口调试。记得将蓝牙模块设为从机

将蓝牙和小车连接好之后,代码的书写很简单(读取串口监视器的数字或者字母,然后将字母的对应功能设计出来就行)

 if(Serial.available()>0)
  {
    char cmd = Serial.read();//读取蓝牙模块发送到串口的数据
             switch(cmd)
                  {
                      /*相应的功能设计*/
                  }
  }

大概思路模板就是这样(具体控制代码想要的可以私聊哦!!!)

在这里拓展一下,当你需要读入一个字符串的时候,可以定义一个字符串变量,然后将串口Serial.read()存到字符串中,然后每次读取后,将字符串数组置空就行了

string pp = "";

void loop()
{
	while(Serial.available()>0)
	{
		pp += char(Serial.read());
        delay(2);
	}
	target = pp.toInt();  //将(char)数字转化为(int/float/double)数字 
	if(pp.length>0)
	{
		pp = "";  //置空数组,进入下一次循环 
	}
 } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夜路难行々

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

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

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

打赏作者

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

抵扣说明:

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

余额充值