题目 智能警用无人巡逻车
视频演示地址:树莓派暑期工程培训-模拟警用无人巡逻车_哔哩哔哩_bilibili
本实验使用 Yahboom 生产的覆盆子派 4B,组员需要了解覆盆子车的每个模块,然后利用每个模块的实现原理设计一个实用的场景来解决可能出现的问题。对树莓派的理解包括:对四路红外巡线模块、超声波模块等传感器的理解; 了解舵机知识;远程控制和连接树莓派wifi拍摄提取网络、树莓派摄像头、树莓派小车扬声等。
本实验设计的场景是智能警用无人巡逻小车,可以自动巡线,精准避障,遇到障碍物时实现S型绕弯,同时闪烁LED灯提醒,智能检测障碍物是车牌还是无关障碍物,完成识别和相应行动,完成信息发送、车牌归档等操作,然后准确避开车牌。如果四面八方都有障碍物,原路返回,巡逻直到检测到停车线、停车仓库等。
1.2 实验要求
综合应用覆盆子芯片上各模块的功能,设计智能警车巡逻车,可自动巡逻、自动避障、自动识别车牌。
①巡线分为以下要求:
- 准确把握对应代码与小车转动电机的关系;
- 准确设置转弯等不寻常路线的电机参数,实现精确转弯;
- 完成自动巡线功能,在规定的黑线上自动驾驶,确保不会驶出规定的路线。
②避障模块具体分为下面几个要求:
- 超声检测正前方的障碍物,在一定距离后停止;
- 停车时,启动摄像头,先拍照,保存图片;
- 要实现超声避障,首先检查左右方是否有障碍物;
- 选择无障碍一侧旋转,采用超声波检测,使汽车与障碍物之间的距离更大,相对远离障碍物,向相反的方向行驶,确保能够返回原轨道;
- 启动自动巡线,确保车辆在规定线路上自动巡逻。
③车牌识别模块具体分为以下要求
- 调用百度API识别照片;
- 百度API如果无法识别结果,则将其视为障碍物,并命令发出提示信息;
- 将识别的车牌与可疑车牌进行比较。如果是可疑车牌,会发出报警声,手机会发出警告信息使用server酱汁等轻质接口;
- 记录正常车辆的车牌,也发送给手机
④语音输出模块具体分为下面这几个要求
- 具备3.5mm有线扬声器插头
- 设置音频的音量大小
- 调用pygame输出准备好的音频
⑤实验硬件与软件环境要求:
- 掌握python基本语法,写作能力
- 安装实验所需的包(pygame和baidu-api等)
- 配备汽车摄像头
- 可熟练完成VNC与本机电脑的文件传输
1. 3 实验目的
构建基于树莓派的智能警察巡逻车。巡逻车首先启动自动巡逻线,进入预定轨道,模拟警车的正常状态,通过代码调整车辆的直线和弯曲范围和速度,使车辆能够非常平稳地巡逻线路。巡逻车的超声波模块一直在工作,其次如若遇到障碍物,巡逻车在距离一定时停下,对该物体进行识别。如果识别后未获得车牌号,巡逻车将其视为无关障碍物(行人、大型物体等)。如若识别出了车牌号,则巡逻车马上将其与嫌疑车辆车牌号进行比对,如果吻合,巡逻车立刻发出报警信息,同时发送微信通知,告知要嫌疑车辆在附近;如若不吻合,则记录下该车车牌号,发送微信通知,同时注明为正常车辆。
二、实验原理与硬件连接
2.1 实验原理
本实验使用的树莓派4B 如图1所示:
图1 树莓派4B 主控板
下图2实物接线板对应的每个模块图.
图2 树莓派4B 接线板对应模块图
下图3:树莓车40Pin引脚对照表
图3树莓派管脚对应接口图
因为本实验中代码使用python语言编写,使用BCM编码,开启GPIO功能。下图4为BCM编码模式下,引脚对应的功能接口图。
图4 BCM编码的功能接口图
本实验模块结构图如图5,右边部分为输入部分,左边部分为输出部分,树莓派作为整个功能中的中央处理器。即通过右边的输入模块调整输出各个模块,以满足实验要求。
图 5 实验模块结构图
(1)自动循迹原理
红外传感器巡线的基本实现原理是利用物体的反射性质,我们本次实验是基于巡黑线行驶,当红外线发射到黑线上时会被黑线吸收掉,发射到其他的颜色的材料上会有反射到红外的接受管上。本实验中,主要使用黑胶带作为小车的轨迹路线,LED灯亮起时对应引脚为低电平,不亮则为高电平。即巡线模块需要实现巡线的LED检测到黑色区域时亮,为低电平,检测到白色区域时灭,为高电平。我们根据这点写相应的代码完成小车巡线功能。
小车寻迹四路寻迹模块的实物图如图5,调节SW2,SW1,SW3,SW4,可改变L2,L1,L3,L4的亮灭情况。实验中,需要调节这几个电位器,使的在黑色区域亮,白色区域灭,才能使用寻路功能。
图6循迹模块实物图
我们本次实验采用的是四路红外传感器分别连接在树莓派主控板上的GPIO编码的20,21,19,26口上。接口如图7。
图7 循迹模块接口图
BCM编码下对应的引脚如下表1
表1 循迹模块硬件接口表
功能 |
原理图编号 |
BCM编码对应引脚 |
左1 |
IN2 |
21 |
左2 |
IN1 |
20 |
右1 |
IN3 |
19 |
右2 |
IN4 |
26 |
(2)LED七彩探照灯原理
本实验中采用的RGB LED灯是共阴LED,一个引脚接地,其余的三个RGB引脚分别接在树莓派主控板上的BCM编码22,27,24引脚上。同时每个LED灯需要串联一个220欧的电阻作为限流电阻(在模块上硬件体现,R1,R2和R3),我们只需在树莓派主控板上控制相应的引脚为高电平,即可点亮相应的LED。LED灯本实验中主要起指示作用,下图8为七彩探照灯的实物图。
图8 七彩探照灯实物图
RGB对应的引脚如下表 2。
表2 LED_RGB对应引脚
LED灯 |
BCM编码对应引脚 |
LED_R |
22 |
LED_G |
27 |
LED_B |
24 |
(3)超声波模块
超声波模块是利用超声波特性检测距离的传感器。其带有两个超声波探头,分别用作发射和接收超声波。小车的超声波测量的范围是3-450cm。
下图9为超声波模块发射和接受的示意图,可以形象体现测距原理。该超声波模块用于实时监测障碍物的距离。
图9超声波发射和接收示意图
先使用树莓派的BCM编码引脚1向TRIG脚输入至少10us的高电平信号,触发超声波模块的测距功能。如下图10所示:
图10 超声波模块发送触发信号
测距功能触发后,模块将自动发出 8 个 40kHz 的超声波脉冲,并自动检测是否有信号返回,这一步由模块内部自动完成。
图11超声波脉冲示意图
一旦检测到有回波信号则ECHO引脚会输出高电平。高电平持续的时间就是超声波从发射到返回的时间。此时可以使用时间函数计算出ECHO引脚高电平的持续时间,即可计算出距被测物体的实际距离。公式:
距离=高电平时间*声速(340M/S)/2。
下图12为超声波模块实物图,长54mm,宽47mm,安装在小车的顶板上实时测距。
图12 超声波模块实物图
下图13为超声波接线图.
图13 超声波接线图
下表3为超声波对应引脚说明
表3超声波模块引脚说明
引脚名称 |
功能 |
说明 |
树莓派 |
BCM对应接口 |
Trig |
发送 |
触发引脚 |
SCL_C |
1 |
Echo |
接收 |
回馈引脚 |
SDA_C |
0 |
(4)摄像头拍照模块
树莓派中,有两个摄像头接口,一个CSI和USB接口,相比较CSI,USB摄像头有比较长,比较灵活的USB线,即插即用,实现更为方便灵活。所以本实验使用树莓派摄像头USB 2.0将树莓派开发板与摄像头连接。
下图14为USB摄像头接线接口图。
图14 摄像头接线接口图
树莓派要使用USB摄像头,需要在命令行输入指令打开树莓派的配置界面,输入以下命令:
sudo raspi-config1
依次按照指导步骤找到摄像头选项,并打开树莓派的摄像头功能,从而达到激活摄像头的目的。
打开摄像头后,修改摄像头的配置,使用cmake编译工程并打开图像,重启后在PC端输入可以实时查看的网址,可以看到摄像机实时摄影的静态图。
本实验安装的摄像头具有二自由度,使用两个舵机调整摄像头的角度,找到最佳摄像位置。
(5)舵机模块
树莓派小车的舵机实物图如图15
图15 舵机实物图
舵机工作原理:控制信号由接收机的通道进入信号调制芯片,获得直流的偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速此轮带动电位器旋转,使得电压差为0,电机停止转动。
舵机的控制:一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分。本次实验的采用的舵机是180度伺服,控制关系如下:
脉冲时间和对应的控制关系如下表4。
表4 脉冲时间和角度对照表
脉冲时间 |
角度 |
0.5ms |
0度 |
1.0ms |
45度 |
1.5ms |
90度 |
2.0ms |
135度 |
2.5ms |
180度 |
需要设置舵机的频率和起始占空: pwm_servo = GPIO.PWM(ServoPin, 50)
在BCM编码方式下。舵机引脚对应为23(ServoPin ),舵机接线头如下图16。
图16 舵机接线头
对应引脚如下
表5 舵机对应引脚
模块 |
引脚 |
舵机 |
23 |
(6)发送微信模块 实现推送告警信息到微信的方法有如下几种 1、通过企业公众号实现,收费: 2、通过QQ邮箱,在微信平台上开启收到邮件进行提醒; 3、第三方告警平台API,一般也是收费的; server酱应用,其原理属于第一种和第三种的结合,具体流程如下: 1.在企业微信注册一个企业,获得企业ID 2.在企业微信内创建一个内部应用,获得应用ID和应用secret 3.配置server酱推送通道,同时开启微信插件 4.往http://sctapi.ftqq.com/SCKEY.send 发GET请求,就可以在微信里收到消息
server酱配置界面如图17
图17 server酱发送工具
发送消息非常简单,只需要向以下URL发一个GET或者POST请求https://sctapi.ftqq.com/SCKEY.send接受两个参数:
text:消息标题,最长为256,必填。
desp:消息内容,最长64Kb,可空,支持MarkDown。
最简单的消息发送方式是通过浏览器,在地址栏输入以下URL,回车后即可发送,例如:
https://sctapi.ftqq.com/SCKEY.send?text=恭喜发财&desp=www.361way.com站点还是不错的
在具体调用的时候可以直接curl 直接调用该URL,也可以使用 shell 做一个简单的函数封装,例如:
send(){
key=your key id
title=运维之路可用性监控
content=www.361way.com暂时不可用,赶快检查
curl "http://sc.ftqq.com/$key.send?text=$title&desp=$content" >/dev/null 2>&1 &
}
在使用的时候,直接send调用就行了。
serverchan官方页面也提供了php调用的示例。本身get方法无论在任何语言里调用都不复杂。其很方便的可以在任何语言下进行接口连接。
sererchan也提供了一对多的发送服务 ------ PushBear ,不过其每天只有1000条发送的上限。
运行以上代码就可以将写好的标题和内容发送给所有小组成员,每个人都可以收到server酱发送的提示信息。
(7)车牌识别功能模块;
在百度智能云人脸识别项目中创建应用,创建完毕后,下载SDK文档,因为是在树莓派中运行,所以选中python HTTP SDK下载到本地。查看应用详情,记录下AppID、API Key和Secret Key,在后面的代码中会用到。在车牌库管理中新建车牌组,再从组中新建车牌名称和照片。
首先完成摄像头模块的相关配置。识别功能主要由百度智能云平台的支持实现,自己训练的模型精度过差,百般考虑之后,我们小组决定调用百度API的车牌识别功能,我们首先在百度创建了应用,同时选用了其文字识别等等相关功能,这样我们就可以获得应用的APP_ID 、API_KEY、 SECRET_KEY将其填入对应的代码,固定好图片的路径,调用下面的代码:
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
#注册baidu-api的车牌识别应用
def get_license_plate(filePath):
APP_ID = '######'
API_KEY = '################'
SECRET_KEY = '#######################'
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
#识别摄像头拍摄的图片
image = get_file_content(filePath)
res = client.licensePlate(image)
return res
返回的res即是识别的结果。不过实验若是捕捉不到车牌信息,可能会发送KeyError,因此一定要写好代码,捕捉到这个错误,执行对应操作,这样才不会打断程序的进行。
(8)报警模块
树莓派小车中有蜂鸣器,有源蜂鸣器内置振荡源,所以通电时会发出声音。但无源蜂鸣器没有这种内置振荡源,所以如果使用直流信号,不会发出轰鸣声;相反,你需要使用频率在2k到5k之间的方波来驱动它。由于有内置振荡电路,所以有源蜂鸣器通常比无源蜂鸣器昂贵。
将两个蜂鸣器的引脚朝上,可以看到带有绿色电路板的引脚是一个无源蜂鸣器。而另一个带有黑色塑料外壳,而不是电路板的蜂鸣器是有源蜂鸣器。
利用终端命令行选择音频,将.mp3文件放置在树莓派桌面上,并播放出警报音频。
本实验中选择3.5mm耳机接口输出报警音频,下图18为3.5mm音响接口实物图,编写函数使之可以播放报警的.mp3音频。
图18 3.5mm音频接线口
(9)电机驱动模块
四路直流减速电机的控制采用的电机驱动芯片为TB6612FNG 。芯片结构图如下图19
图19 电机驱动芯片TB6612FNG
通过控制驱动芯片的 AIN1,AIN2,BIN1,BIN2,PWMA,PWMB 的电平高低来实现电机的正转、反转和停止。实验主要是控制 AIN1 为高电平,AIN2 为低电平,BIN1 为高电平,BIN2 为低电平,进而通过调节 PWMA,PWMB的大小控制小车的速度。
其中PWMA和PWMB分别对应BCM编码的16,13接口。
2.2 硬件连线
四路红外巡线模块、超声波模块、红外探测模块、舵机、电机、LED 灯、用排线直接与树莓派对应引脚相连,音响接线头插入3.5mm耳机孔。具体引脚对应设置和模块接入如图20所示。
图20树莓派主控板电路图
三、设计思路、步骤和程序流程图
3.1 设计思路
本实验主要由自动寻迹、超声波避障、车牌识别、发送微信推送、语音报警和倒车模块组成。 自动寻迹主要由四路寻迹模块完成。四路寻迹的根据地下四个LED等的亮灭情况,通过电机驱动小车,使小车完成左转、右转、前进、后退等等操作,使得小车在规定的轨道上自动驾驶。 超声波避障主要由超声波模块和前舵机模块构成。超声波模块不断发出信号,通过信号到达的时间来计算障碍物的距离,当距离小于一定值时,则通过舵机来控制超声波探头的转动,使其检测左右方有无障碍物,并朝无障碍物的一方行驶,完成避障再回归到固定轨道。 车牌识别再硬件上由摄像头模块组成,主要由软件代码进行控制。控制摄像头拍照并且将图片存在固定路径里,然后再调用代码,将图片取出,应用百度API传送到云端,对图片进行车牌识别。输出一个车牌号或者障碍物提示。将车牌号进行匹配,以便后续操作。 发送微信推送主要由代码控制,通过server酱将车牌信息发送到微信。同时也可以发送其他固定的信息。 语音报警通过3.5mm的接口将音频输出到音箱,再通过代码控制在对应的地方输出音频。 倒车模块主要由四路寻迹模块控制。此时的输入为四个LED灯都检测到了黑线,控制电机完成倒车动作,同时结束寻迹。
3.2 实验步骤
步骤总括:我们小组首先是研究了本次课设提供的代码,在其原有的基础上进行修改,实现
了超声波的精准避障、自动寻线、倒车入库的分布实现,然后对这些基础模块进行了一个整合,在不断实验调参的努力下,比较准确实现了这些功能的整合。再之后,我们首先在PC端实现了server酱信息的发送、OpenCV摄像头拍照以及调用百度API实现车牌识别,在自己的Python环境实现的基础上,做了一些整改,使其可以在小车的python环境中运行,但是因为opencv的环境配置过于困难,最后我们用实时摄像头的捕捉实现拍照存图功能,发送信息与车牌识别模块没有做太大整改。最后我们实现了语音的报警模块,主要设备是有线音响,通过连接树莓派芯片上的3.5mm耳机插口实现,使用pygame支持音频的输出。具体步骤如下:
(1) 组装智能小车
根据说明书的指导和组装视频,组装智能小车。在组装时应注意,先将SD卡插入对应位置,
再组装上层树莓派,利用螺丝螺帽组合将其固定在智能小车上层挡板。音响通过 3.5mm 耳机孔线接入树莓派,因为是有线的音响,只测试一次。需要注意各个螺丝和螺栓,螺母的匹配还有铜柱的选择,不然在后续实验容易出各种小问题导致重装。其他对应模块按照说明书正确接入小车主控板。
(2)测试小车功能
根据提供的实验代码测试小车能否正常运行,主要测试了四路巡线实验、超声波避障实验、带舵机的超声波避障实验,经过初步测试,使其可以以一个良好的状态运行。根据实验指导书,成功实现手机与树莓派小车蓝牙的连接,通过不同模式的测试,小车都能够成功完成。
(3)阅读代码和其注释,基于四路巡线和带舵机的超声波避障的实验代码初步实现避障,巡线和停车入库的内容。对代码进行初步的调试,使得小车整体可以完整运行不出错。
自动巡线时,四路引脚的输入状态和小车对应反应如下表6。
表6 四路巡线电平对应反应
输入状态(四路寻迹电平) |
小车对应反应 |
0000 |
停车,入库 |
00X0 |
原地右转 |
10X0 |
|
01X0 |
|
00X0 |
原地左转 |
0X01 |
|
输入状态(四路寻迹电平) |
小车对应反应 |
0X10 |
原地左转 |
0XXX |
小角度原地左转 |
XXX0 |
小角度原地右转 |
X01X |
左转 |
X10X |
右转 |
X00X |
前进 |
1111 |
保持上一个运行状态 |
避障时,需要测量出三个方向的障碍物距离,写函数控制舵机的旋转,用于精准避障。本实验中舵机只涉及三个角度,即只控制三个方向。
表7舵机控制和对应旋转方向
旋转函数参数 |
对应方向 |
0 |
右侧 |
180 |
左侧 |
90 |
正前方 |
利用小车的超声波模块进行避障设计,超声波模块在整个小车巡线过程中都是保持开启的状态,需要在空旷障碍物离得较远的场地测试,用舵机控制超声波特测器的旋转,测出各个方向的障碍物距离。测试距离和小车反应对应如下表8。
表8 障碍物距离检测
当前障碍物状态 |
小车反应 |
distance<=20(正前方障碍物) |
进入避障模式,LED灯亮红色 |
leftdistance < 30 and rightdistance < 30 and frontdistance < 30 |
三方都有障碍,小车掉头,原路线返回 LED亮品红色 |
leftdistance>=30 and rightdistance>=30 and frontdistance<=30 and x==1 |
小车右半圆形绕弯避障 先亮品红色灯,再亮蓝色灯 |
leftdistance>=30 and rightdistance>=30 and frontdistance<=30 and x==0 |
小车左半圆形绕弯避障 先亮品红色灯,再亮蓝色灯 |
其他 |
正常寻迹,不亮灯 |
(4)在自己的PC端实现server酱发送信息和车牌识别功能
使用server酱和baidu api的功能调用,具体原理在实验原理中已有介绍。先实现在电脑PC端可以正常发送企业微信消息和车牌识别内容及标题,再在电脑端安装baidu api,通过修改识别图片的路径选择不同车牌照识别,初步测试识别结果非常准确,因为需要把代码移植到小车上,我们写了函数在PC端实现打开摄像头,通过摄像头捕捉当前影像进行识别,结果也不错。
(5)将核心代码写入小车SD卡,编译运行
小车上编译python的版本为2.7,会存在各种问题,其中摄像头的打开方式会不一样,需要我们对照树莓派小车打开摄像头实时捕捉影像存入相应位置进行识别,还需要给小车配置wifi信号的接入,使它可以正常上网,调用API进行识别。另外,要改变一些编码方式,python2.7和python3.5的一些编码方式不一样,需要我们自己去修改,使之可以成功匹配。我们使用的API函数进行车牌识别时,若是识别图片不是车牌号,就会中断报错,需要去捕捉这个错误防止在程序还没运行完就中断。
大概调整了这几个问题后,小车可以正常实现通过摄像头捕捉影像识别黑名单车牌并成功发送对应的提醒信息。
(6)连接音响设备
命令行是可以直接调用实现音频输出,但是要实现代码控制,我们下载了pygame工具。通过主线板上3.5mm的音频输出口接孔连上有线的音响设备,先使小车的可以正常鸣声,命令行输入speaker-test-t sine,音响设备正常播放蜂鸣声。通过 import pygame ,在小车中导入报警音频到位置//home//pi//Desktop,music.play()输出音频,同时还要通过命令行输入alsamixer命令设置音量大小。编写函数使的报警音频可以播放,声音音量调整。
(7)整合代码
将我们已经实现的几个模块整合在一起,自动巡线避障,车牌检测,音频报警功能根据程序的流程图将每个的代码贴入合适位置,警用无人巡逻小车的智能模拟场景基本得以实现。
(8)道路设计
设计直线行驶,弯道行驶路线,和停车库。注意贴黑胶带当路线时不应贴太宽,也不应贴太窄,要使小车中间两个寻迹灯可以同时亮,但正常寻迹时不可以出现四个寻迹灯同时亮的情况,在设计路线时应注意这种问题。要综合考虑直道和弯道的设计。
(9)障碍物设计
为了方便实现与操作,共设计了三个障碍物:一个无关障碍物,测试小车可以正常检测出非车牌障碍物,并且成功避障后巡线;一个可疑车牌障碍物,测试小车可以检测黑名单车牌;一个正常车牌障碍物,测试小车可以检测正常车牌。
表9 不同障碍物对应反应
障碍物 |
反应 |
矿泉水瓶 |
无关障碍物,绕开 |
黑名单车牌 |
检测并报警提示,再绕开 |
正常车牌 |
检测并提示,再绕开 |
(10)最后调整阶段
不断的测试在跑道上运行小车,调整参数,核心代码问题不大,主要是要使整个小车在线路上运行连贯且不出错。
3.3 程序流程图
实验程序流程图如图21
图21 整体流程图
车牌识别功能+语音报警功能流程图如图22
图22 车牌识别流程图
停车入库流程图如图23
图23 停车入库流程图
图24 避障流程图
4.1 程序清单
#-*- coding:UTF-8 -*-
import sys
#改变编码格式,使字符串可以比较
reload(sys)
sys.setdefaultencoding('utf8')
from aip import AipOcr
import json
import requests
#使可以播放指定音乐
import pygame
import RPi.GPIO as GPIO
import time
#小车电机引脚定义
IN1 = 20
IN2 = 21
IN3 = 19
IN4 = 26
ENA = 16
ENB = 13
#小车按键定义
key = 8
#x用于S形绕弯的控制,x等于1右绕圈避障,等于0则左绕弯避障
x=1
#超声波引脚定义
EchoPin = 0
TrigPin = 1
#RGB三色灯引脚定义
LED_R = 22
LED_G = 27
LED_B = 24
#舵机引脚定义
ServoPin = 23
#循迹红外引脚定义
#TrackSensorLeftPin1 TrackSensorLeftPin2 TrackSensorRightPin1 TrackSensorRightPin2
# 3 5 4 18
#定义左边第一个循迹红外传感器引脚为3口
TrackSensorLeftPin1 = 3
#定义左边第二个循迹红外传感器引脚为5口
TrackSensorLeftPin2 = 5
#定义右边第一个循迹红外传感器引脚为4口
TrackSensorRightPin1 = 4
#定义右边第二个循迹红外传感器引脚为18口
TrackSensorRightPin2 = 18
#设置GPIO口为BCM编码方式
GPIO.setmode(GPIO.BCM)
#忽略警告信息
GPIO.setwarnings(False)
#电机引脚初始化为输出模式
#按键引脚初始化为输入模式
#寻迹引脚初始化为输入模式
#超声波,RGB三色灯,舵机引脚初始化为输入模式
def init():
global pwm_ENA
global pwm_ENB
global pwm_servo
GPIO.setup(ENA,GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(IN1,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(IN2,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(ENB,GPIO.OUT,initial=GPIO.HIGH)
GPIO.setup(IN3,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(IN4,GPIO.OUT,initial=GPIO.LOW)
GPIO.setup(key,GPIO.IN)
GPIO.setup(TrackSensorLeftPin1,GPIO.IN)
GPIO.setup(TrackSensorLeftPin2,GPIO.IN)
GPIO.setup(TrackSensorRightPin1,GPIO.IN)
GPIO.setup(TrackSensorRightPin2,GPIO.IN)
GPIO.setup(EchoPin,GPIO.IN)
GPIO.setup(TrigPin,GPIO.OUT)
GPIO.setup(LED_R, GPIO.OUT)
GPIO.setup(LED_G, GPIO.OUT)
GPIO.setup(LED_B, GPIO.OUT)
GPIO.setup(ServoPin, GPIO.OUT)
#设置pwm引脚和频率为2000hz
pwm_ENA = GPIO.PWM(ENA, 2000)
pwm_ENB = GPIO.PWM(ENB, 2000)
pwm_ENA.start(0)
pwm_ENB.start(0)
#设置舵机的频率和起始占空比
pwm_servo = GPIO.PWM(ServoPin, 50)
pwm_servo.start(0)
#小车前进
def run(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.HIGH)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.HIGH)
GPIO.output(IN4, GPIO.LOW)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车后退
def back(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN2, GPIO.HIGH)
GPIO.output(IN3, GPIO.LOW)
GPIO.output(IN4, GPIO.HIGH)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车左转
def left(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.HIGH)
GPIO.output(IN4, GPIO.LOW)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车右转
def right(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.HIGH)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.LOW)
GPIO.output(IN4, GPIO.LOW)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车原地左转
def spin_left(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN2, GPIO.HIGH)
GPIO.output(IN3, GPIO.HIGH)
GPIO.output(IN4, GPIO.LOW)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车原地右转
def spin_right(leftspeed, rightspeed):
GPIO.output(IN1, GPIO.HIGH)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.LOW)
GPIO.output(IN4, GPIO.HIGH)
pwm_ENA.ChangeDutyCycle(leftspeed)
pwm_ENB.ChangeDutyCycle(rightspeed)
#小车停止
def brake():
GPIO.output(IN1, GPIO.LOW)
GPIO.output(IN2, GPIO.LOW)
GPIO.output(IN3, GPIO.LOW)
GPIO.output(IN4, GPIO.LOW)
#按键检测
def key_scan():
while GPIO.input(key):
pass
while not GPIO.input(key):
time.sleep(0.01)
if not GPIO.input(key):
time.sleep(0.01)
while not GPIO.input(key):
pass
#超声波函数检测距离
def Distance_test():
GPIO.output(TrigPin,GPIO.HIGH)
time.sleep(0.000015)
GPIO.output(TrigPin,GPIO.LOW)
while not GPIO.input(EchoPin):
pass
t1 = time.time()
while GPIO.input(EchoPin):
pass
t2 = time.time()
print "distance is %d " % (((t2 - t1)* 340 / 2) * 100)
time.sleep(0.01)
return ((t2 - t1)* 340 / 2) * 100
#舵机旋转到指定角度
def servo_appointed_detection(pos):
for i in range(18):
pwm_servo.ChangeDutyCycle(2.5 + 10 * pos/180)
#舵机旋转超声波测距避障,led根据车的状态显示相应的颜色
def servo_color_carstate():
global x
##检测到障碍物先亮红灯
GPIO.output(LED_R, GPIO.HIGH)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.LOW)
#后退一定距离
back(20, 20)
time.sleep(0.08)
brake()
#舵机旋转到0度,即右侧,测距
servo_appointed_detection(0)
time.sleep(0.8)
#右侧障碍物的距离
rightdistance = Distance_test()
#舵机旋转到180度,即左侧,测距
servo_appointed_detection(180)
time.sleep(0.8)
#左侧障碍物的距离
leftdistance = Distance_test()
#舵机旋转到90度,即前方,测距
servo_appointed_detection(90)
time.sleep(0.8)
#正前方障碍物的距离
frontdistance = Distance_test()
#四面除了后方都有障碍,掉头
if leftdistance < 30 and rightdistance < 30 and frontdistance < 30:
#LED灯亮品红色
GPIO.output(LED_R, GPIO.HIGH)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.HIGH)
#原地右转掉头
spin_right(85, 85)
time.sleep(0.58)
#该物体在正前方,实现半圆绕弯,默认绕弯到正前方
elif leftdistance>=30 and rightdistance>=30 and x==1:
#障碍物在正前方,亮品红色,向右转
GPIO.output(LED_R, GPIO.HIGH)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.HIGH)
#实现向右半圆形型绕弯
right(40, 0)
time.sleep(0.5)
run(20,20)
time.sleep(0.2)
brake()
#亮蓝色灯
GPIO.output(LED_R, GPIO.LOW)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.HIGH)
left(0, 40)
time.sleep(0.7)
run(20,20)
time.sleep(0.1)
#下一次遇到障碍物则向左绕弯
x=1-x
print('avoid--end')
return
#实现向左绕弯躲避障碍物
else:
#障碍物在正前方,亮品红色,向右转
GPIO.output(LED_R, GPIO.HIGH)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.HIGH)
#实现向左半圆形型绕弯
left(0,40)
time.sleep(0.5)
run(20,20)
time.sleep(0.2)
brake()
#LED灯亮蓝色
GPIO.output(LED_R, GPIO.LOW)
GPIO.output(LED_G, GPIO.LOW)
GPIO.output(LED_B, GPIO.HIGH)
right(50,0)
time.sleep(0.7)
run(20,20)
time.sleep(0.1)
#下一次遇到障碍物则向右绕弯
x=1-x
print('avoid--end')
return
#报警函数,遇到可疑车牌先报警
def voice1():
pygame.mixer.init()
pygame.mixer.music.load("//home//pi//Desktop//22.mp3")
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
pass
提示音函数,遇到可疑车牌报警后提示
def voice2():
pygame.mixer.init()
pygame.mixer.music.load("//home//pi//Desktop//11.mp3")
#time.sleep(3)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy() == True:
pass
#摄影函数,当检测到前方有障碍时,停下拍照,用于车牌识别
def takepoto():
from pip._vendor import requests
with open("img.png",'wb') as f:
f.write(requests.get("http://192.168.50.1:8080/?action=snapshot").content)
#图片存在当前路径下
pos="img.png"
print("getImgSuccess!")
#server酱发送企业微信提示函数
def send(s1,s2):
api = "https://sctapi.ftqq.com/SCT52936TMFWh7a1g5u2elvB21wdLiuRU.send"
title = s1
content = s2
#发送的标题及内容为可疑车牌识别的结果和车牌号
data = {
"text":title,
"desp":content
}
req = requests.post(api,data = data)
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
#注册baidu-api的车牌识别应用
def get_license_plate(filePath):
APP_ID = '######'
API_KEY = '#########################'
SECRET_KEY = '############################'
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
#识别摄像头拍摄的图片
image = get_file_content(filePath)
res = client.licensePlate(image)
return res
#黑名单车牌号为粤A55555
Blacklist='粤A55555'
#车牌识别函数
def recongize():
try:
res = get_license_plate('/home/pi/python/img.png')
#获取车牌号的车牌
s2=res['words_result']['number']
#若与黑名单车牌号匹配
if Blacklist==s2:
s1='注意黑名单车辆'
#报警
voice1()
voice2()
else:
s1='正常车辆'
#发送可疑车牌识别结果和车牌号到手机端企业微信
send(s1,s2)
#若障碍物不是车牌,提示It is not a car
except KeyError as e:
print('It is not a car')
#入库函数
def ruku():
left(0,62)
time.sleep(0.4)
back(48,48)
time.sleep(0.35)
brake()
#入库后停止不在运行
#主函数
try:
init()
key_scan()
while True:
distance=Distance_test()
#超声波检测到有障碍物
if(distance<=20):
#小车停止前进
brake()
#摄像头拍照
takepoto()
#车牌识别
recongize()
#S型避障
servo_color_carstate()
#四路寻迹模式
TrackSensorLeftValue1 = GPIO.input(TrackSensorLeftPin1)
TrackSensorLeftValue2 = GPIO.input(TrackSensorLeftPin2)
TrackSensorRightValue1 = GPIO.input(TrackSensorRightPin1)
TrackSensorRightValue2 = GPIO.input(TrackSensorRightPin2)
# 0 0 0 0入库
if(TrackSensorLeftValue1 == False and TrackSensorRightValue2== False and TrackSensorLeftValue2 == False and TrackSensorRightValue1 == False):
print("go--back--back")
ruku()
break
#四路循迹引脚电平状态
# 0 X 0 0
# 0 X 0 1
# 0 X 1 0
elif(TrackSensorLeftValue1 == False or TrackSensorLeftVa