效果图
详戳>>>>>> 视频
一、前期准备
Arduino开发板一个,L293d驱动板一个,超声波传感器一个,MG90S舵机一个,直流电机两个,载体小车一个,杜邦线若干,电池1.5V x 8个;
二、电路连接
三、代码实现
3.1 主代码设计流程图
3.2 超声波测距原理和代码实现
超声波测距原理是通过超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播时碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。而超声波测距传感器,采用超声波回波测距原理,运用精确的时差测量技术,检测传感器与目标物之间的距离,采用小角度,小盲区超声波传感器,具有测量准确,无接触,防水,防腐蚀,低成本等优点。超声波测距传感器常用的方式是1个放射头对应1个接收头,也是多个发射头对应1个接收头基于超声波测距的简单、易于操作和无损伤等特点所以要测得超声波往返的时间,即可求得距离。这就是超声波测距传感器的工作原理。
如下图为超声波测距的数据;
超声波测距核心代码实现:
int TrgPin = A0;
int EcoPin = A1;
float dist;
void setup()
{
Serial.begin(9600);
//设置TrgPin为输出状态
pinMode(TrgPin, OUTPUT);
// 设置EcoPin为输入状态
pinMode(EcoPin, INPUT);
}
void loop()
{
digitalWrite(TrgPin, LOW);
delayMicroseconds(8);
digitalWrite(TrgPin, HIGH);
// 维持10毫秒高电平用来产生一个脉冲
delayMicroseconds(10);
digitalWrite(TrgPin, LOW);
// 读取脉冲的宽度并换算成距离
dist = pulseIn(EcoPin, HIGH) / 58.00;
Serial.print("Distance:");
Serial.print(dist);
Serial.println("cm");
delay(300);
}
3.3 舵机角度控制原理——PWM控制
舵机(Servo):它由直流电机、减速齿轮组、传感器和控制电路组成的一套自动控制系统。通过发送信号,指定输出轴旋转角度。舵机一般而言都有最大旋转角度(比如180度)。这里主要介绍怎样控制舵机角度的问题;
舵机的伺服系统由可变宽度的脉冲来进行控制,控制线是用来传送脉冲的。脉冲的参数有最小值,最大值,和频率。一般而言,舵机的基准信号都是周期为20ms,宽度为1.5ms。这个基准信号定义的位置为中间位置。舵机有最大转动角度,中间位置的定义就是从这个位置到最大角度与最小角度的量完全一样。最重要的一点是,不同舵机的最大转动角度可能不相同,但是其中间位置的脉冲宽度是一定的,那就是1.5ms。
角度是由来自控制线的持续的脉冲所产生。这种控制方法叫做脉冲调制(PWM)。脉冲的长短决定舵机转动多大角度。当控制系统发出指令,让舵机移动到某一位置,并让他保持这个角度,这时外力的影响不会让他角度产生变化,但是这个是由上限的,上限就是他的最大扭力。除非控制系统不停的发出脉冲稳定舵机的角度,舵机的角度不会一直不变。当舵机接收到一个小于1.5ms的脉冲,输出轴会以中间位置为标准,逆时针旋转一定角度。接收到的脉冲大于1.5ms情况相反。不同品牌,甚至同一品牌的不同舵机,都会有不同的最大值和最小值。一般而言,最小脉冲为1ms,最大脉冲为2ms。如下图:
代码实现:
//舵机右转
void servoRight() {
servopulse(9, 20);
}
//舵机左转
void servoLeft() {
servopulse(9, 180);
}
//舵机回正
void servoForward() {
servopulse(9, 90);
}
//舵机角度的设定
void servopulse(int servopin, int myangle) /*定义一个脉冲函数,用来模拟方式产生PWM值*/
{
for (int i = 0; i <= 50; i++) //产生PWM个数,等效延时以保证能转到响应角度
{
pulsewidth = (myangle * 11) + 500; //将角度转化为500-2480 的脉宽值
digitalWrite(servopin, HIGH); //将舵机接口电平置高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin, LOW); //将舵机接口电平置低
delay(20 - pulsewidth / 1000); //延时周期内剩余时间
}
}
3.4 整体代码实现
// Adafruit Motor shield library
// copyright Adafruit Industries LLC, 2009
// this code is public domain, enjoy!
#include <AFMotor.h>
#include <Servo.h>
//超声波
int TrgPin = A0;
int EcoPin = A1;
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
Servo servo;
//初始化距离数据
float dist;
void forward();
void backward();
void turnLeft();
void turnRight();
void stopCar();
void servoRight();
void servoLeft();
void servoForward();
int distance();
void servopulse(int servopin, int myangle);
void angle(int val);
int servopin = 9; //设置舵机驱动脚到数字口9
int myangle;//定义角度变量
int pulsewidth;//定义脉宽变量
void setup() {
Serial.begin(9600);
//设定舵机接口为输出接口
pinMode(servopin, OUTPUT);
//设置TrgPin为输出状态
pinMode(TrgPin, OUTPUT);
// 设置EcoPin为输入状态
pinMode(EcoPin, INPUT);
motor2.setSpeed(200);
motor3.setSpeed(200);
}
void loop() {
digitalWrite(TrgPin, LOW);
delayMicroseconds(8);
digitalWrite(TrgPin, HIGH);
// 维持10毫秒高电平用来产生一个脉冲
delayMicroseconds(10);
digitalWrite(TrgPin, LOW); // 读取脉冲的宽度并换算成距离
dist = pulseIn(EcoPin, HIGH) / 58.00;
Serial.print("Distance:");
Serial.print(dist);
Serial.println("cm");
delay(300);
if (dist< 35) //危险
{
stopCar();//电机停转
servoLeft();//向左转舵机
if (dist < 35) //危险
{
servoRight();//向右转舵机
if (dist < 35) //危险
{
servoForward();//向中间舵机
backward(); //后退
}
else
{
servoForward();//向中间舵机
turnRight( ); //右转
delay(30);
stopCar();//电机停转
forward(); //前进
}
}
else
{
turnLeft( ); //左转
delay(30);
stopCar();//电机停转
forward( ); //前进
}
}
else
{
forward(); //前进
}
}
//前进
void forward() {
motor2.run(FORWARD);
motor3.run(FORWARD);
}
//后退
void backward() {
motor2.run(BACKWARD);
motor3.run(BACKWARD);
}
//左转
void turnLeft() {
motor2.run(FORWARD);
motor3.run(RELEASE);
delay(50);
}
//右转
void turnRight() {
motor2.run(RELEASE);
motor3.run(FORWARD);
delay(50);
}
//停止
void stopCar() {
motor2.run(RELEASE);
motor3.run(RELEASE);
delay(100);
}
//舵机右转
void servoRight() {
servopulse(9, 20);
}
//舵机左转
void servoLeft() {
servopulse(9, 180);
}
//舵机回正
void servoForward() {
servopulse(9, 90);
}
//舵机角度的设定
void servopulse(int servopin, int myangle) /*定义一个脉冲函数,用来模拟方式产生PWM值*/
{
for (int i = 0; i <= 50; i++) //产生PWM个数,等效延时以保证能转到响应角度
{
pulsewidth = (myangle * 11) + 500; //将角度转化为500-2480 的脉宽值
digitalWrite(servopin, HIGH); //将舵机接口电平置高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin, LOW); //将舵机接口电平置低
delay(20 - pulsewidth / 1000); //延时周期内剩余时间
}
}