零知四轮小车入门版(ESP32主控)教程4-超声波避障

本系列教程讲解零知小车套件以零知esp32为主控,使用零知开源平台进行智能小车开发。

使用的硬件:零知智能小车套件

实现的功能:红外循迹、超声避障、直线运行、手机蓝牙控制等基本功能。

扩展:可以在小车上加入其它传感器模块进行扩展,比如加入摄像头模块进行监控、加入火焰传感器做灭火小车、加入更多超声波模块实现自动跟随...


本系列教程目录

零知四轮小车入门版(零知esp32主控)系列教程-小车组装


零知四轮小车入门版(零知esp32主控)系列教程-程序控制电机开跑


零知四轮小车入门版(零知esp32主控)系列教程-加入蓝牙实现手机控制


零知四轮小车入门版(零知esp32主控)系列教程-红外循迹走S弯


零知四轮小车入门版(零知esp32主控)系列教程-超声波自动避障


一、准备工作

我们需要如下工具和材料:

(1)组装好的智能小车


二、程序代码

避障小车主要是通过小车前面的超声波模块来感应障碍物并测量距离,舵机调整方向,选择无障碍的一边通行,4WD代码实现如下:

							
							
	/**********************************************************
	*    文件: 4wdcar_Avoidance.ino      by 零知实验室([url=http://www.lingzhilab.com]www.lingzhilab.com[/url])
	*    -^^- 零知开源,让电子制作变得更简单! -^^-
	*    时间: 2019/11/28 17:09
	*    说明: 
	************************************************************/
	#include <Servo.h>
	  
	//电机引脚
	#define LEFT_MOTO1  27
	#define LEFT_MOTO2  14
	#define LEFT2_MOTO1 33
	#define LEFT2_MOTO2 32
	#define RIGHT_MOTO1 12
	#define RIGHT_MOTO2 13
	#define RIGHT2_MOTO1 26
	#define RIGHT2_MOTO2 25
	  
	//超声波引脚
	#define SR04_TRIG 23
	#define SR04_ECHO 22
	  
	//舵机引脚
	#define SERVO_PIN 21
	  
	Servo myservo;
	// 复位或上电后运行一次:
	void setup() {
	    //在这里加入初始化相关代码,只运行一次:
	        Serial.begin(9600);
	        pinBegin();
	        motoStop();
	  
	}
	  
	//一直循环执行:
	void loop() {
	    // 在这里加入主要程序代码,重复执行:
	        avoidance(40);  //开始自动避障,设置避障距离为40cm
	  
	}
	  
	void pinBegin(){
	        pinMode(LEFT_MOTO1,OUTPUT);
	        pinMode(LEFT_MOTO2,OUTPUT);
	        pinMode(LEFT2_MOTO1,OUTPUT);
	        pinMode(LEFT2_MOTO2,OUTPUT);
	        pinMode(RIGHT_MOTO1,OUTPUT);
	        pinMode(RIGHT_MOTO2,OUTPUT);
	        pinMode(RIGHT2_MOTO1,OUTPUT);
	        pinMode(RIGHT2_MOTO2,OUTPUT);
	        //设置引脚输出PWM的通道
	        ledcAttachPin(LEFT_MOTO1,1);
	        ledcAttachPin(LEFT_MOTO2,2);
	        ledcAttachPin(LEFT2_MOTO1,3);
	        ledcAttachPin(LEFT2_MOTO2,4);
	        ledcAttachPin(RIGHT_MOTO1,5);
	        ledcAttachPin(RIGHT_MOTO2,6);
	        ledcAttachPin(RIGHT2_MOTO1,7);
	        ledcAttachPin(RIGHT2_MOTO2,8);
	        ledcSetup(1, 12000, 8);
	        ledcSetup(2, 12000, 8);
	        ledcSetup(3, 12000, 8);
	        ledcSetup(4, 12000, 8);
	        ledcSetup(5, 12000, 8);
	        ledcSetup(6, 12000, 8);
	        ledcSetup(7, 12000, 8);
	        ledcSetup(8, 12000, 8);
	          
	        pinMode(SR04_ECHO,INPUT);
	        pinMode(SR04_TRIG,OUTPUT);
	          
	        myservo.attach(SERVO_PIN);  //舵机连接引脚
	}
	  
	//电机控制,正值前进,负值后退
	void motoRun(int speedL,int speedR){
	        if(speedL>0){
	                ledcWrite(1,0);
	                ledcWrite(2,speedL);
	                ledcWrite(3,0);
	                ledcWrite(4,speedL);
	        }else{
	                ledcWrite(1,-speedL);
	                ledcWrite(2,0);
	                ledcWrite(3,-speedL);
	                ledcWrite(4,0);
	        }
	        if(speedR>0){
	                ledcWrite(5,0);
	                ledcWrite(6,speedR);
	                ledcWrite(7,0);
	                ledcWrite(8,speedR);
	        }else{
	                ledcWrite(5,-speedR);
	                ledcWrite(6,0);
	                ledcWrite(7,-speedR);
	                ledcWrite(8,0);
	        }
	          
	}
	  
	//停止
	void motoStop(){
	        ledcWrite(1,0);
	        ledcWrite(2,0);
	        ledcWrite(3,0);
	        ledcWrite(4,0);
	        ledcWrite(5,0);
	        ledcWrite(6,0);
	        ledcWrite(7,0);
	        ledcWrite(8,0);
	}
	  
	//超声波获取距离
	int getDistance()
	{
	        digitalWrite(SR04_TRIG, LOW);
	        delayMicroseconds(2);
	        digitalWrite(SR04_TRIG, HIGH);
	        delayMicroseconds(10);
	        digitalWrite(SR04_TRIG, LOW);
	          
	        int distance = pulseIn(SR04_ECHO, HIGH);
	        distance = distance/58;
	          
	        return distance;
	}
	  
	void avoidance(int avoidDistance){
	        int i = 0;
	        int time = 15;
	        int delay_time = 10;        //三个方向的距离
	        int disFor = 0;
	        int disLeft = 0;
	        int disRight = 0;
	        int pos = 90;  //舵机初始角度
	        int rollTime = 900;  //转弯时间,若转弯不理想,可调整
	          
	        myservo.write(pos);
	        //获取5次前方距离求平均值
	        for(i=0;i<5;i++)
	        {
	                disFor += getDistance();
	                delay(delay_time);
	        }
	        disFor = disFor/5;
	        Serial.print("前方距离:");
	        Serial.println(disFor);
	        if(disFor <= avoidDistance){  //检测前方距离是否小于设定距离
	                motoStop();
	                //舵机移动到左侧
	                for(i=pos;i<180;i++)
	                {
	                        myservo.write(i);
	                        delay(time);
	                }
	                //获取左侧距离
	                for(i=0;i<5;i++)
	                {
	                        disLeft += getDistance();
	                        delay(delay_time);
	                }
	                disLeft = disLeft/5;
	                  
	                Serial.print("左侧距离:");
	                Serial.println(disLeft);
	                //舵机移动至右侧
	                for(i=180;i>0;i--)
	                {
	                        myservo.write(i);
	                        delay(time);
	                }
	                //获取右侧距离
	                for(i=0;i<5;i++)
	                {
	                        disRight += getDistance();
	                        delay(delay_time);
	                }
	                disRight = disRight/5;
	                  
	                Serial.print("右侧距离:");
	                Serial.println(disRight);
	                  
	                for(i=0;i<pos;i++)
	                {
	                        myservo.write(i);
	                        delay(time);
	                }
	                if((disLeft <= avoidDistance) && (disRight <= avoidDistance))  //检测左右两边的距离是否小于设定距离
	                {
	                        motoRun(240,-240);  //若转弯不理想,可调整两边轮子的速度或调整转弯时间
	                        Serial.println("掉头");
	                        delay(rollTime/2);
	                }
	                else if(disLeft >= disRight)
	                {
	                        motoRun(80,190);  //左转
	                        Serial.println("左转");
	                        delay(rollTime);
	                }
	                else if(disLeft < disRight)
	                {
	                        motoRun(190,80);  //右转
	                        Serial.println("右转");
	                        delay(rollTime);
	                }
	                motoStop();  //停车
	        }else{
	                motoRun(160,160);
	        }
	}
								

将以上代码验证上传至零知ESP32开发板上,小车就可以自动避障了