避障小车的制作方法大概有两种:一个是利用超声波制作,一个是光电开关(避障模块),而跟随小车便一个是利用超声波和光电开关配合制作,一个是光电开关(避障模块)制作。
所以本篇博客,最终决定:用超声波模块制作避障、小车的避障部分;用超声波和光电开关配合制作跟随部分。
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)按照伪代码写程序:
未完待续