Arduino四驱四路循迹小车:单片机原理及应用详解

摸摸鱼,把大二的课堂作业总结一下发出来,很基础的小白代码,希望能给入门的同学一点参考。

由于实物卖掉啦,只能尽量用文字配上接线图等,写详细一点。

一、元器件清单

Arduino UNO R3开发板(带USB)

1个

XD-201 4路红外传感器

1个

DRV8833  2路直流电机驱动

2个

母对母、公对母杜邦线

若干

直流减速电机

4个

4WD底盘

1个

接插件

若干

二、硬件连线图

根据实际接线情况绘制,需要配合代码使用的端口进行接线。

三、主要硬件介绍

3.1 Arduino UNO R3开发板

使用前需了解清楚每个端口的作用哦~

3.2 DRV8833电机驱动模块

为了控制转速和满足功率,所以需要电机驱动模块。老师要求,所以选了这一款,但拿到手蛮小巧可爱的,就是比起常用的L298多花了一番功夫寻找控制原理。

四、代码介绍

       首先定义引脚,设置输出和输入情况,同时进行初始化。

      使用到的5,6,10,11号脚不仅是I/O口,还可以输出PWM。则搭配7,8,12,13号引脚控制四个电机。PWM控制转速,普通I/O口输出高低电平控制转向。

       连续从红外循迹模块读取四个传感器的高低电平,输入到单片机,motorRun函数根据传感器相应数据,输出不同的PWM值和高低电平,控制电机的转向和转速,以适应不同的情况。

五、整体代码

#include <Servo.h>  
//函数调用说明:调用servo.h里的库函数,类似stdio.h是标准输入输出,常用的 printf scanf 这些输入输出函数 以及fopen fclose一系列的文件操作函数都是在这个头文件里面的,所以这个最常见
#define STOP      0
#define FORWARD   1
#define BACKWARD  2
#define TURNLEFT  3
#define TURNRIGHT 4

const int leftMotor1_1 = 5;      // 定义5引脚为左前侧电机,PWM控制速度
const int leftMotor1_2 = 7;      // 定义7引脚为左前侧电机控制方向
const int leftMotor2_1 = 6;      // 定义6引脚为左后侧电机,PWM控制速度
const int leftMotor2_2 = 8;      // 定义8引脚为左后侧电机控制方向

const int rightMotor1_1 = 10;      // 定义10引脚为右前侧电机,PWM控制速度
const int rightMotor1_2 = 12;      // 定义12引脚为右前侧电机控制方向
const int rightMotor2_1 = 11;      // 定义11引脚为右后侧电机,PWM控制速度
const int rightMotor2_2 = 13;      // 定义13引脚为右后侧电机控制方向

const int trac1 = 9; //从车头方向的最左边开始排序 (传感器)
const int trac2 = 2; 
const int trac3 = 3; 
const int trac4 = 4; 

void setup() {

  Serial.begin(9600);  //串口初始化
 
  pinMode(leftMotor1_1, OUTPUT);// 配置引脚为输出或输出模式,它是一个无返回值函数,函数有两个参数pin和mode
  pinMode(leftMotor1_2, OUTPUT);
  pinMode(leftMotor2_1, OUTPUT);
  pinMode(leftMotor2_2, OUTPUT);

  pinMode(rightMotor1_1, OUTPUT);
  pinMode(rightMotor1_2, OUTPUT);
  pinMode(rightMotor2_1, OUTPUT);
  pinMode(rightMotor2_2, OUTPUT);
 
  pinMode(trac1, INPUT);
  pinMode(trac2, INPUT);
  pinMode(trac3, INPUT);
  pinMode(trac4, INPUT);
}

void loop()
{
  tracing();   //是一个函数,在下面有对这个函数的定义
}



void tracing()           // tracing()函数定义:上面void loop里面只有tracing这一个函数,arduino标准程序必须包含setup函数和loop函数,loop函数其实是一个循环,因为这个程序很简单没循环做的事情,所以循环函数为空,但必须要保留,这是arduino的语法规范。
{
  int data[4];                //定义一个数组data[]包含四个数据,读取来自9,2,3,4引脚的信号存储到这个数组中,而9,2,3,4引脚连接的就是四个传感器,因此这个数组的功能就是记录四个传感器的信号,由下面的程序可以知道,通过对这几个传感器信号的判断,并根据这几个不同的情况作出不同的反应
  data[0] = digitalRead(9);
  data[1] = digitalRead(2);
  data[2] = digitalRead(3);
  data[3] = digitalRead(4);
  
  //高电平-关断状态(没有反射)-有黑线-灯不亮;低电平-接收(反射)-无黑线-灯亮
  
  //左右都没有检测到黑线,直行
  if(!data[0] && !data[1] && !data[2] && !data[3])     //0000,灯亮
  {
    motorRun(FORWARD, 220);
  }
  if(!data[0] && data[1] && data[2] && !data[3])   //0110
  {
    motorRun(FORWARD, 220);
  }

  //右边检测到黑线,右转
  if(!data[0] && !data[1] && data[2] && !data[3])    //小转 0010
  {
    motorRun(TURNRIGHT, 150);
  }
  if(!data[0] && !data[1] && data[2] && data[3])   //中转 0011
  {
    motorRun(TURNRIGHT, 200);
  }
  if(!data[0] && !data[1] && !data[2] && data[3])    //大转 0001
  {
    motorRun(TURNRIGHT, 220);
  }
  
  //左边检测到黑线,左转
  if(!data[0] && data[1] && !data[2] && !data[3])    //小转 0100
  {
    motorRun(TURNLEFT, 120);
  }
  if(data[0] && data[1] && !data[2] && !data[3])   //中转 1100
  {
    motorRun(TURNLEFT, 150);
  }
  if(data[0] && !data[1] && !data[2] && !data[3])    //大转 1000
  {
    motorRun(TURNLEFT, 200);
  }
  
  //左右都检测到黑线是停止
  if(data[0] && data[1] && data[2] && data[3])     //0000
  {
    motorRun(STOP, 0);
    while(1);
  }

  Serial.print(data[0]);
  Serial.print("---");
  Serial.print(data[1]);
  Serial.print("---");
  Serial.print(data[2]);
  Serial.print("---");
  Serial.println(data[3]);
}

void motorRun(int cmd,int value) // 定义一个函数motorRun()
{

  // 设置PWM输出,即设置速度 analogWrite(pin, value) 通过PWM的方式在引脚上输出一个模拟量,较多的应用在LED亮度控制、电机转速控制等方面。该函数支持以下引脚:3、5、6、9、10、11。在Arduino控制板上引脚号旁边标注~的就是可用作PWM的引脚,analogWrite函数为无返回值函数,有两个参数pin和value,参数pin表示所要设置的引脚,只能选择函数支持的引脚;参数value表示PWM输出的占空比,范围在0~255的区间,对应的占空比为0%~100%
  analogWrite(leftMotor1_1, value);  
  analogWrite(leftMotor2_1, value); 
  analogWrite(rightMotor1_1, value);
  analogWrite(rightMotor2_1, value); 
  //方向
  switch(cmd)
{
   //判断cmd的状态:如果cmd==FOTWARD,输出“FORWARD/r/n”的状态,为LEFTMotor1设置为高电平,为leftMotor2设置为低电平,为RightMotor1设置为高电平,为RightMotor2设置为低电平
    case FORWARD:
      Serial.println("FORWARD"); //输出状态
   //Arduino 的输出基本就用两个函数 print 和 println,区别在于后者比前者多了回车换行,Serial.println(data)
   //从串行端口输出数据,跟随一个回车('r')和一个换行符('n')。这个函数所取得的值与 Serial.print()一样。
   //其作用为设置引脚的输出电压为高\低电平。该函数无返回值,有两个参数pin和value,pin参数表示所要设置的引脚,value参数表示输出的电压,HIGH为高电平,LOW为低电平。在使用digitalWrite(pin, value)函数之前要将引脚设置为OUTPUT模式。例:pinMode(x, OUTPUT);其中x为引脚编号。pinMode函数用于设置引脚模式。
      digitalWrite(leftMotor1_2,HIGH );
      digitalWrite(leftMotor2_2, LOW);
      digitalWrite(rightMotor1_2, HIGH);
      digitalWrite(rightMotor2_2, LOW);
      break; //完成以上一系列函数后结束这个函数
    
      break;
     case TURNLEFT:
      Serial.println("TURN  LEFT"); //输出状态
      digitalWrite(leftMotor1_2, LOW);
      digitalWrite(leftMotor2_2, HIGH);
      digitalWrite(rightMotor1_2, HIGH);
      digitalWrite(rightMotor2_2, LOW);
      break;
     case TURNRIGHT:
      Serial.println("TURN  RIGHT"); //输出状态
      digitalWrite(leftMotor1_2, HIGH);
      digitalWrite(leftMotor2_2, LOW);
      digitalWrite(rightMotor1_2, LOW);
      digitalWrite(rightMotor2_2, HIGH);
      break;
     default:
//如果以上情况都不是,输出STOP,所有电机输出为低电平
      Serial.println("STOP"); //输出状态
      digitalWrite(leftMotor1_2, LOW);
      digitalWrite(leftMotor2_2, LOW);
      digitalWrite(rightMotor1_2, LOW);
      digitalWrite(rightMotor2_2, LOW);
  }
}

六、实物图

只能找到咸鱼上视频截图了,前面那个白色块是充电宝。

七、展望

       现在看来,可以使用PID控制算法,当时写得太死板了,完全是一一对应的一个萝卜一个坑的速度,慢且机械,还是PID顺滑~~。同时咧,车车的四个轮,参照现实中的轿车,分为驱动轮方向轮,啊,我这写的嘛呀,四个轮又转向又驱动。很待改进,但摆烂了,在这里献丑了。

物联沃分享整理
物联沃-IOTWORD物联网 » Arduino四驱四路循迹小车:单片机原理及应用详解

发表评论