基于ardunio的避障.跟随小车(带有魔术手)

       避障小车的制作方法大概有两种:一个是利用超声波制作,一个是光电开关(避障模块),而跟随小车便一个是利用超声波和光电开关配合制作,一个是光电开关(避障模块)制作。

所以本篇博客,最终决定:用超声波模块制作避障、小车的避障部分;用超声波和光电开关配合制作跟随部分。


1、避障小车的制作

(1)伪代码部分:


主函数

{

    舵机摆正

    循环部分

    {   

        c如果超声波采集的数据<X

         {

             电机停转

             舵机左摆

             b如果超声波采集的数据<X  

              {

                  舵机右摆

                 a如果超声波采集的数据<X  

                 {

                    舵机摆正

                    倒车

                    }

                     aelse

                     {

                       舵机摆正

                       电机右转--->停下---->直行

                        }

                   baelse

                     {

                       舵机摆正

                       电机左转--->停下---->直行

                        }

                      }

           celse

           {

            电机直行

              }

       }

}


.(2)滤波部分(超声波滤波):算术平均滤波法

/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:sumjess  2018-07-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 算术平均滤波法
#define FILTER_N 12
int Filter() {
  int i;
  int filter_sum = 0;
  for(i = 0; i < FILTER_N; i++) {
    filter_sum += Get_AD();
    delay(1);
  }
  return (int)(filter_sum / FILTER_N);
}

(3)舵机转向:

调节出中值和左右摆的值,写一个按键程序,每按一次旋转一定角度,便可轻易记录下各个位置的数据,操作简单,此处就不再赘述。

(4)电机接线方式如下:

https://jingyan.baidu.com/article/75ab0bcbcb5320d6864db2e4.html

(5)按照伪代码写程序:

电源板目前没画完,程序写完了,但是没有调试,回来过几天会进行跟进调试。

#include <Servo.h>
#include <NewPing.h>


///目前使用的引脚: 4-5-6-9-10-12-13
//////////////舵机设置//////////////
Servo myservo;        // 创建车体转向(X轴)舵机对象
#define servo_pin 4   // 定义车体转向舵机信号线接口
/*int servopin = 7;    //定义舵机接口数字接口7
  void servopulse(int angle)//定义一个脉冲函数
  {
  int pulsewidth=(angle*11)+500;  //将角度转化为500-2480的脉宽值
  digitalWrite(servopin,HIGH);    //将舵机接口电平至高
  delayMicroseconds(pulsewidth);  //延时脉宽值的微秒数
  digitalWrite(servopin,LOW);     //将舵机接口电平至低
  delayMicroseconds(20000-pulsewidth);
  }*/
////////////超声波设置//////////////
//#define PING_PIN  12  // Arduino pin tied to both trigger and echo pins on the ultrasonic sensor.
#define MAX_DISTANCE 450 // 设置最大距离(厘米)。最大传感器距离为400-500cm。
#define TRIG_PIN 12    //超声波引脚配置
#define ECHO_PIN 13    //超声波引脚配置
int Filter_Value;//滤波后的数值
int Filter();//用于滤波计算
int Get_ultra();//用于获取一个目前的超声波值
#define FILTER_N 10   //超声波均值滤波(去多少次做平均数)
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE); // 调整引脚和最大距离
////////////电机设置//////////////
#define leftA_PIN 5
#define leftB_PIN 6
#define righA_PIN 9
#define righB_PIN 10

void motor_pinint(void);  //引脚初始化
void forward( );          //前进
void back( );             //后退
void turnLeft( );         //左转
void turnRight( );        //右转
void turnbackLeft( );     //左后
void turnbackRight( );    //右后
void turnLeftOrigin( );   //原地左
void turnRightOrigin( );  //原地右
void _stop();             //停车

void setup()
{

  Serial.begin(115200); //串口波特率115200(PC端使用)
  myservo.attach(servo_pin, 1000, 2500);    // min 默认1000,max 默认2500     1200  1800  2300
  myservo.writeMicroseconds(1200);          //摆正舵机
  pinMode(TRIG_PIN, OUTPUT);  // 要检测引脚上输入的脉冲宽度,需要先设置为输入状态
  pinMode(ECHO_PIN, INPUT);  // 要检测引脚上输入的脉冲宽度,需要先设置为输入状态
  motor_pinint();        //电机引脚初始化
}

void loop()
{
if(Filter()<20)//危险
{
  _stop();//电机停转
  myservo.writeMicroseconds(2300);//向左转舵机
  if(Filter()<20)//危险
  {
    myservo.writeMicroseconds(1200);//向右转舵机
    if(Filter()<20)//危险
    {
      myservo.writeMicroseconds(1800);//向中间舵机
      back( );             //后退
    }
    else
    {
      myservo.writeMicroseconds(1800);//向中间舵机
      turnRight( );        //右转
      delay(30);
      _stop();//电机停转
      forward( );          //前进
    }
  }
    else 
    {
      turnLeft( );        //左转
      delay(30);
      _stop();//电机停转
      forward( );          //前进
    }
   }
  else 
  {
    forward( );          //前进
  }
}


//  Filter_Value = Filter();       // 获得滤波器输出值
//  Serial.println(Filter_Value); // 串口输出
//  delay(50);
//  if((int)Filter_Value>100)
//  myservo.writeMicroseconds(1200);//向右转舵机
//  else if((50<(int)Filter_Value)&&((int)Filter_Value<100))
//  myservo.writeMicroseconds(2300);//向左转舵机
//  else if((0<(int)Filter_Value)&&((int)Filter_Value<49))
//  myservo.writeMicroseconds(1800);//向中间舵机


/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:sumjess  2018-07-01
*/
 
// 用于获得一个超声波的当前值
int Get_ultra() 
{
      // 产生一个10us的高脉冲去触发TrigPin
        digitalWrite(TRIG_PIN, LOW);
        delayMicroseconds(2);
        digitalWrite(TRIG_PIN, HIGH);
        delayMicroseconds(10);
        digitalWrite(TRIG_PIN, LOW);
    // 检测脉冲宽度,并计算出距离
        return pulseIn(ECHO_PIN, HIGH) / 58.00;
        
}
int Filter() 
{
  int i;
  int filter_sum = 0;
  for(i = 0; i < FILTER_N; i++) 
  {
    filter_sum += Get_ultra();
    delay(30);//超声波采集用一般为30ms间隔
  }
  return (int)(filter_sum / FILTER_N);
}


//电机引脚初始化
  void motor_pinint(void)
  {
  pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚
  pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚
  }
/**************************************************
forward子函数——前进子函数
函数功能:控制车前进
**************************************************/
 void forward( )
{
  analogWrite(leftA_PIN,120);      
  analogWrite(leftB_PIN,0);         //左轮前进
  analogWrite(righA_PIN,120);      
  analogWrite(righB_PIN,0);         //右轮前进
}

/**************************************************
back子函数——后退子函数
函数功能:控制车后退
**************************************************/
void back( )
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,120);        //左轮后退
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,120);        //右轮后退
}

/**************************************************
turnLeft子函数——左转子函数
函数功能:控制车左转
**************************************************/
void turnLeft( )
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,0);         //左轮静止不动
  analogWrite(righA_PIN,120);      
  analogWrite(righB_PIN,0);         //右轮前进
}

/**************************************************
turnbackLeft子函数——左后转弯子函数
函数功能:控制车左后转弯
**************************************************/
void turnbackLeft( )
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,0);         //左轮静止不动
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,120);         //右轮后退
}

/**************************************************
turnRight子函数——右后转弯转子函数
函数功能:控制车右后转弯
**************************************************/
void turnRight( )
{
  analogWrite(leftA_PIN,120);      
  analogWrite(leftB_PIN,0);         //左轮前进
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,0);         //右轮静止不动
}

/**************************************************
turnbackRight子函数——右转子函数
函数功能:控制车右转
**************************************************/
void turnbackRight( )
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,120);         //左轮后退
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,0);         //右轮静止不动
}

/**************************************************
turnLeftOrigin子函数——原地左转子函数
函数功能:控制车原地左转
**************************************************/
void turnLeftOrigin( )
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,120);        //左轮后退
  analogWrite(righA_PIN,120);      
  analogWrite(righB_PIN,0);         //右轮前进
}

/**************************************************
turnRightOrigin子函数——原地右转子函数
函数功能:控制车原地右转
**************************************************/
void turnRightOrigin( )
{
  analogWrite(leftA_PIN,120);      
  analogWrite(leftB_PIN,0);        //左轮前进
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,120);       //右轮后退
}

/**************************************************
stop子函数—停止子函数
函数功能:控制车停止
**************************************************/
void _stop()
{
  analogWrite(leftA_PIN,0);      
  analogWrite(leftB_PIN,0);         //左轮静止不动
  analogWrite(righA_PIN,0);      
  analogWrite(righB_PIN,0);         //右轮静止不动
}

2、跟随小车的制作

(1)伪代码部分:

其实和避障小车程序极其类似


主函数

{

    舵机摆正

    循环部分

    {   

        c如果左右避障模块未检测到障碍物

         {

             前进

             }

          否则如果左右避障模块都检测到障碍物

              {

                后退

                  }

          否则如果左有右没有

                 {

                    如果超声波数据>X

                            那么左前

                   否则 右后

                    }

          否则如果右有左没有

                 {

                    如果超声波数据>X

                            那么右前

                   否则 右后

                    }  

          }

}


(2)滤波部分(超声波滤波):算术平均滤波法

(3)舵机转向:

(4)电机接线方式如下:

     以上与上面相对应的相同     

(5)按照伪代码写程序:

未完待续

猜你喜欢

转载自blog.csdn.net/qq_38351824/article/details/81055728
今日推荐