O_基于树莓派的智能避障小车设计
O_嵌入式专题目录
课程设计时间 2018.10.29~2018.11.9
课程设计地点 D2-602
课程设计目的 熟悉嵌入式开发流程,掌握嵌入式开发设计方法,结合具体问题,培养嵌入式开发能力。
摘要
本作品是基于 Raspberry 系统设计的青科智能车,整车以 Raspberry 3B 为核心控制单元。车体运行通过红外模块和超声波避障模块检测识别赛道,利用 PWM 调制波控制调节四个驱动电机的转速,对模型车运动速度和运动方向控制,实现了智能车自主走迷宫的功能。
关键词:智能车控制;迷宫探索;自动检测;智能识别;
1 系统定义
1.1 设计实现的功能
采用C/C++或Python语言编程,实现小车在迷宫内自动直行、转弯、检测障碍的功能,通过红外传感器减少小车碰壁次数并以最短时间到达迷宫终点,并在基础功能的适当拓展实现用键盘控制小车运动的功能。
1.2 可行性分析
智能车是以汽车电子为背景,涵盖控制、模式识别、传感技术、电子、电气、计算机、机械等多学科的科技创意性设计,一般主要由路径识别、速度采集、角度控制及车速控制等模块组成。其设计与开发涉及控制、模式 识别、传感技术、汽车电子、电气、计算机、机械等多个学科,可以分为三大部分:传感器检测部分,执行部分,CPU。
Raspberry 是一款基于 ARM 的微型电脑主板,以 SD/MicroSD 卡为内存硬盘,卡片主板周围有1/2/4个USB接口和一个10/100 以太网接 口(A 型没有网口),可连接键盘、鼠标和网线,整合在一张仅比信用卡稍大的主板上, 具备所有 PC 的基本功能[1],只需接通屏幕和键盘,就完全能够作为一台 PC 使用。
基于此背景搭造了一台以树莓派为主控板,在上位机实现多种功能运算的智能遥控小车,通过以 Raspberry 板为服务器搭建内网连接,进行远程交互,实现远程操控[2]。之后,以该小车 的 pwm 驱动模块程序为基础,加入检测算法,实现小车自动避障的功能。
青科智能小车超声波传感器和红外传感器可以实现避障功能,底部的光传感器可以实现循迹功能。
1.3 需求分析
PC机一台、青科智能小车一部、2节5000mA大容量26650电池、板子搭建的迷宫一套。
2 系统总体设计
2.1 总体设计方案的确定
利用小车的超声波传感器进行大略转向判定,同时同红外线传感器进行方向矫正,以实现小车无碰撞走出迷宫。
2.2 软硬件功能划分
硬件部分:树莓派的芯片是程序正常运行的核心,芯片的运算指令控制四个马达实现车轮的停转和速度以及运动的时间,前侧和两侧的超声波传感器能够对小车的位置进行实时测量,以确定是否有障碍物并及时调整路线实现自动避障,前端两个红外线传感器进行转向微调。另外,两节锂电池提供稳定持续的动力来源。
软件部分:通过wifi,在电脑端对小车的树莓派进行代码编写、调试,观察小车返回的超声波传感器的测试距离。
2.3 硬件体系架构设计
青科智能小车主要由一块树莓派核心控制板、四个直流减速电机、两节锂电池、三个超声波传感器、两个不怕光红外传感器和两个底部的光传感器组成。
超声波传感器和红外传感器可以实现避障功能,底部的光传感器可以实现循迹功能。
2.4 软件体系架构设计
障碍物检测是智能小车导航研究中很重要的一个部分。在小车实际运行中,传感器相 当于小车的“眼睛",必须得到障碍物及其距离的信息,才能相应的规划自动避障导航算 法。目前用于障碍物检测的传感器主要有超声波传感器、红外光电传感器和激光测距仪 等。
激光测距一般通过量测激光在发射点和目标点之间的传输时间来计算得到距离,它的原理和结构相对简单,但价格高。
超声波测距是通过测量超声波从发射到遇到障物反射到被接收这整个过程中的时间差来确定距离,超声波传感器使用比较方便且价格便宜, 具有信息处理简单,实时性强和价格低廉等特点,但实际使用中由于超声波发射束角过大,方向性差,只能得到障碍物简单的距离信息,无法得到障碍物的边界信息。
而红外光电传感器具有探测视角小,方向性强等特点,但无法确定障碍物的距离信息。因此在本作品中,使用了超声波传感器和红外光电传感器,使用数据融合的方法得到障碍物方位及其距离信息[3]。此模块是为智能小车提供一种多用途的红外线+超声波探测系统的解决方案。使用红外线发射和接收管等分立元器件组成红外探头,与超声波模块一同进行迷宫探测,在小车探索的方式选择上,选择“贴墙”的行进方式。
3 系统详细设计
3.1 硬件详细设计
核心控制板:
青科智能车核心控制板采用树莓派三代 B 型主板,速度更快、性能更强大,是为学生计算机编程教育而设计,只有信用卡大小的卡片式电脑,其系统基于 Linux。
核心控制板参数配置:
1.2 GHz 四核 Broadcom BCM2837 64 位 ARMv8 处理器;
板载BCM43143 WiFi;
板载低功耗蓝牙 4.1 适配器(BLE);
1 GB RAM;
4 个 USB 2 端口;
微型SD 端口,用于存储操作系统及数据;
CSI摄像头端口用于连接树莓派摄像头。
电机:
L298N 电机驱动芯片(可直接驱动智能车底盘四个电机并可提供PWM使能信号);
4 个 1:48 抗干扰直流减速电机(工作电压 3-6 V)。
电源:
LM2596S 开关电源稳压电路(支持 6-12 V 宽电压输入,5 V输出);
1 个船型电源控制开关(可对整个系统起到很好的电源管理作用);
2 节 5000 mA 大容量 26650 电池,支持小车持续运转一个小时以上;
带充电模块,可边充电边使用。
红外传感器:
抗干扰性能强,在室外阳光直射下也能正常工作,实现精确避障;
探测距离为1-30 CM(探测距离的长短和供电电压、电流与周围环境有关)。
红外传感器调试方法:
首先确定传感器正前方20cm 距离内不要有障碍物。
将502可调电阻逆时针调节到底,注意不能用力过度,否则可能会损坏可调电阻;
将103可调电阻逆时针慢慢调到底,然后顺时针慢慢旋转,检测这一圈之中是否存在一个临界点能使传感器 LED 信号灯变亮,信号灯亮后,将103可调电阻逆时针往回调1毫米即可,此时这里为模块探测的最远距离(如需距离变短,逆时针调节103电阻即可);
如果上述操作没有点亮LED信号灯,那么将502电阻顺时针调节一毫米左右,再拧一圈103电阻器看看 led 亮了没有,如果没亮,再将502可调电阻顺时针调节1毫米左右,再拧一圈103电阻,如此反复,直到找到那个亮点;
将传感器对着被测物体(不能对黑色物体),物体和传感器之间的距离为你想要测的距离;实际检测距离根据自己所需探测距离调节为准。
超声波传感器:
电压:DC 5V;静态电流:小于 2 mA;
感应角度:不大于15 度;探测距离:2 cm-450 cm;
高精度:可达 0.3 cm。
3.2 软件详细设计
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <time.h>
#include <softPwm.h>
#include <unistd.h>
#include <sys/types.h>
#define HW_LEFT 11
#define HW_RIGHT 10
#define Trig 28
#define Echo 29
#define TrigL 24
#define EchoL 25
#define TrigR 21
#define EchoR 22
#define Turn 6
#define TurnLow 0.5
#define SP 500
float disMeasure(double Loca)
{
struct timeval tv1;
struct timeval tv2;
long start, stop;
float dis;
digitalWrite(Loca, LOW);
delayMicroseconds(2);
digitalWrite(Loca, HIGH);
delayMicroseconds(10); //发出超声波脉冲
digitalWrite(Loca, LOW);
while(!(digitalRead(Loca+1) == 1));
gettimeofday(&tv1, NULL); //获取当前时间
while(!(digitalRead(Loca+1) == 0));
gettimeofday(&tv2, NULL); //获取当前时间
start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间
stop = tv2.tv_sec * 1000000 + tv2.tv_usec;
dis = (float)(stop - start) / 1000000 * 34000 / 2; //求出距离
return dis;
}
void run(int time) // 前进
{
softPwmWrite(1,SP); //左轮前进
softPwmWrite(4,0);
softPwmWrite(5,SP); //右轮前进
softPwmWrite(6,0);
delay(time * 100);
}
void brake(int time) //刹车,停车
{
softPwmWrite(1,0); //左轮stop
softPwmWrite(4,0);
softPwmWrite(5,0); //右轮stop
softPwmWrite(6,0);
delay(time * 20);
}
void left(int time) //左转(左轮不动,右轮前进)
{
softPwmWrite(1,0); //左轮stop
softPwmWrite(4,SP);
softPwmWrite(5,SP); //右轮前进
softPwmWrite(6,0);
delay(time * 100);
}
void right(int time) //右转(右轮不动,左轮前进)
{
softPwmWrite(1,SP); //左轮前进
softPwmWrite(4,0);
softPwmWrite(5,0); //右轮stop
softPwmWrite(6,SP);
delay(time * 100);
}
int main(int argc, char *argv[])
{
int SR;
int SL;
float disF,disL,disR;
/*RPI*/
wiringPiSetup();
/*WiringPi GPIO*/
pinMode (1, OUTPUT); //IN1
pinMode (4, OUTPUT); //IN2
pinMode (5, OUTPUT); //IN3
pinMode (6, OUTPUT); //IN4
pinMode(HW_LEFT, INPUT);
pinMode(HW_RIGHT, INPUT);
pinMode(Echo, INPUT);
pinMode(Trig, OUTPUT);
pinMode(EchoL, INPUT);
pinMode(TrigL, OUTPUT);
pinMode(EchoR, INPUT);
pinMode(TrigR, OUTPUT);
softPwmCreate(1,1,500);
softPwmCreate(4,1,500);
softPwmCreate(5,1,500);
softPwmCreate(6,1,500);
while(1)
{
//有信号为LOW 没有信号为HIGH
SR = digitalRead(HW_RIGHT);
SL = digitalRead(HW_LEFT);
disF = disMeasure(Trig);
disL = disMeasure(TrigL);
disR = disMeasure(TrigR);
printf("distanceF = %0.2f cm\n",disF);//输出当前超声波测得的距离
printf("distanceL = %0.2f cm\n",disL);
printf("distanceR = %0.2f cm\n",disR);
if(disF<30&&disF>0.3){ //测得前方障碍的距离小于30cm时做出如下响应
if(disL<=disR){
printf("TurnRight\n");
brake(1);
right(Turn);
}
else if(disL>disR){
printf("TurnLeft\n");
brake(1);
left(Turn);
}
}
else{
if(SL == LOW){
printf("SL...\n");
brake(1);
right(TurnLow);
}
else if(SR == LOW){
printf("SR...\n");
brake(1);
left(TurnLow);
}
else{
printf("RUN\n");
run(1); //无障碍时前进
}
}
}
return 0;
} 4 功能测试
青科智能小车采用树莓派核心板,安装了 Linux 系统,内置 GCC编译器及相关函数库,已经搭建了完整的开发环境。利用 PC 机,通过Wifi 登录智能车系统,操作步骤如下:
第一步:连接智能小车
搜索无线网络 QUST-ROBOT-xxx,输入密码: 12345678 进行连接。
第二步:登陆远程桌面
第三步:输入账号密码
第四步:打开终端
第五步:关闭自启动程序
自启动程序为了兼容VIPLE编程但是会影响python程序的正常运行,如果想使用 python 编程每次重新启动小车时都要关闭自启动程序。
1.ps –aux|grep rpi
2.寻找./rpi_robot 的 id 号
3.sudo kill -9 id 号
第六步:在 Linux的终端内,使用程序编译指令
$gcc bz.c -o bz -lwiringPi -lpthread
编译完成,可以利用下列命令执行程序
$sudo ./bz
参考文献
[1] CarrieAnnePhilbin. 零基础学 Raspberry Pi:图文版[M]. 人民邮电出版社, 2015.
[2] 门伯里, 豪斯张志博, 孙峻文. 树莓派学习指南 : 基于 Linux[M]. 人民邮电出版社, 2014.
[3] 王江伟, 刘青. 玩转树莓派 Raspberry Pi[M]. 北京航空航天大学出版社, 2013.
拓展功能核心代码
char getch()
{
char c;
system("stty -echo");
system("stty -icanon");
c=getchar();
system("stty icanon");
system("stty echo");
return c;
}
//main函数内
while(1){
key=getch();
printf("Key=%d\n",key);
if(key==65)
run();
else if(key==66)
back();
else if(key==67)
right();
else if(key==68)
left();
else if(key==32)
brake();
}
评论已关闭