0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 毕业设计基于OpenMV的火灾检测及人员搜寻智能车
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:4分
🧿 选题指导, 项目分享:
1 简介
本系统以 K60 单片机为控制核心的面向发生火灾高风险的危险环境中能自动探测智能火灾检测及人员搜寻的智能小车。随着经济的发展,大量的高层、地下建筑与大型的石化等发生火灾高风险的企业不断涌现。由于这些建筑的特殊性,发生火灾时不能快速高效的灭火。然而火灾的发生是非常普遍的在消防员进入火灾现场之前,利用自带的OpenMV进行计算机视觉处理,实现记录火势蔓延位置,搜寻火源以及寻找幸存者的功能,并通WiFi通信,传达信息便于使用更有效的消防方式进行灭火。小车对毒气检测和结合天气、地形对风速风向进行预测的功能,为消防员做足救援前的准备提供充足的信息。此外,为了保障火灾探测车自身的耐用性,小车利用光电对管,实现自动避障的功能,同时通过温度检测,自主决定是否超过本身耐受度,是否继续前进。由于安全性、程控性、智能性,本系统具有良好的市场前景和应用价值。
2 主要器件
- K60单片机
- OpenMV Cam 模块,基于STM32的机器人视觉摄像机
- 光电对管,实现自动避障
- 温度传感器
- 烟雾传感器
- 风速风向传感模块
- 显示屏
- WIFI模块
3 实现效果
4 设计原理
小车的硬件组成和功能设计与实现
以温度传感器、烟雾传感器、OpenMV,风速风向传感模块为信号的输入,显示屏为信号的输出,大功率的WIFI模块建立WIFI连接,将摄像头中的图像识别数据,和烟雾、温度等数据传送给控制中心的中继端,WiFi模块将地面中继端传过来的信号传送给小车的芯片,用来控制小车的运动状态。
K60MCU
简介
Kinetis是基于ARM Cortex-M4具有超强可扩展性的低功耗、混合信号微控制器。第一阶段产品由五个微控制器系列组成,包含超过两百种器件,在引脚、外设和软件上可兼容。每个系列提供了不同的性能,存储器和外设特性。通过通用外设、存储器映射和封装的一致性来实现系列内和各系列间的便捷移植。
Kinetis 微控制器基于飞思卡尔创新的90纳米薄膜存储器(TFS)闪存技术,具有独特的Flex存储器(可配置的内嵌EEPROM)。Kinetis微控制器系列融合了最新的低功耗革新技术,具有高性能、高精度的混合信号能力,宽广的互连性,人机接口和安全外设。飞思卡尔公司以及其他大量的ARM第三方应用商提供对Kinetis 微控制器的应用支持。
OpenMV Cam 模块
Open MV 简介
此模块是基于STM32的机器人视觉摄像机,可以在Python3中进行编程,并附有大量的图像处理功能,如面部检测和跟踪,关键点描述符,彩色斑点跟踪,QR和条形码支持,AprilTags,GIF和MJPEG记录等等。OpenMV摄像机板内置RGB和红外LED,用于编程和视频流的USB FS,uSD插座和I / O头,可以分解PWM,UART,SPI和I2C。此外,OpenMV还支持使用诸如WiFi,BLE,Thermal(FIR)和LCD屏蔽等I / O头的扩展模块(屏蔽)。OpenMV配备了专门用于支持OpenMV摄像机的跨平台IDE(基于QT创建者)。IDE允许查看帧缓冲区,访问传感器控制,上传脚本并通过串行通过USB(或WiFi / BLE)在相机上运行它们。
OpenMV摄像头的特点
-
STM32H743II ARM Cortex M7 处理器,480 MHz ,1MB RAM,2 MB flash. 所有的 I/O 引脚输出 3.3V 并且 5V 耐受。这个处理器有以下的IO接口。
- 全速 USB (12Mbs) 接口,可以连接到电脑。但是需要注意的是连接的必须是能够传输数据的线。当插入OpenMV摄像头后,你的电脑会出现一个虚拟COM端口和一个“U盘”。
- μSD卡槽拥有100Mbs读写,这允许你的OpenMV摄像头录制视频,和把机器视觉的素材从SD卡提取出来。
- 一个SPI总线高达100Mbs速度,允许你简单的把图像流数据传给LCD扩展板,WiFi扩展板,或者其他控制器。
- 一个 I2C总线,CAN总线, 和2两个异步串口总线 (TX/RX) ,用来链接其他控制器或者传感器。
- 一个12-bit ADC 和一个12-bit DAC。
- 2个 I/O 引脚用于舵机控制.
- 所有的IO口都可以用于,中断和PWM(板子上有10个I/O引脚)。
- 一个RGB LED(三色), 两个高亮的 850nm IR LED(红外)。
- 32 MB 外置的 32-bit SDRAM ,100 MHz的时钟,达到 400 MB/s 的带宽。
- 32 MB 外置的 quadspi flash, 100 MHz的时钟,4-bit DDR模式达到 100 MB/s 的带宽。
-
可拆卸的摄像头模块系统,允许OpenMV Cam H7 Plus与不同的感光元件模组连接:
- OpenMV4 H7 Plus默认配置的OV5640 感光元件处理2592×1944 (5MP)图像。在QVGA (320×240)及以下的分辨率时,大多数简单的算法可以运行(25~50)FPS。
- 对于专业的机器视觉应用
- 对于红外热成像机器视觉应用
-
3.7V 锂离子电池接口
小车的地形环境调试
地形测试:使小车在人为设定的不同的地形下运动,不断地调试,尽可能多的录入阻碍信息,使小车能够适应复杂地形;
火源检测:对不同情况下的实验火源进行探测、分析,使小车更为灵敏的探测火灾起势,做出相关反应;
风向测试:是小车在不同天气下,对风向和风速进行探测,结合天气对风向风速进行预测,让小车能够在不同环境条件下保证功能的正常实现;
救援测试:对不同性别、年龄的人群在不同天气、光线和风速情况下,对人进行提问测量和识别,丰富小车对人数据,增强小车的记忆,使其识别更为灵敏、准确。
WIFI通信传输协议
采用2.4G频段,实现基站与终端的点对点无线通讯,链路层采用以太网协议为核心,以实现信息传输的寻址和校验。可以实现通讯距离从几十米到两、三百米的多设备无线组网。
WiFi是现有通信系统的补充,可看作是3G的一种补充,无线接入技术则主要包括IEEE的802.11、802.15、802.16和802.20标准,分别指WLAN、无线个域网WPAN:蓝牙与uwb、无线城域网WMAN:WIMAX和宽带移动接入WBMA等。一般地说WPAN提供超近距离的无线高数据传输速率连接;WMAN提供城域覆盖和高数据传输速率;WBMA提供广覆盖、高移动性和高数据传输速率;WiFi则可以提供热点覆盖、低移动性和高数据传输速率。
设计优点
-
基于K60芯片的智能车性能相对于基于其他平台的智能车性能更好。
-
与传统火灾检测系统不同,智能火灾探测小车,可以进入火灾现场,灵活的辅助消防员找到火源。利用人脸识别功能,可以在火灾现场找到受灾人员。减轻消防员的负担以及降低受伤的风险。
-
通过无线通信可快速定位火源及人员,与传统手段相比,更加快更准确。
-
采用新型图像识别模块,是小车探测火灾更加准确迅速。
-
小车通过探测周围环境信息,可确保自身正常稳定的工作,具有自我保护的能力。
-
在复杂的火灾环境下,本火灾检测及人员检测小车可利用各传感器的输送回的信号可以预测火灾的发生,在火势萌芽状态就可以将其灭掉源头,例如小车测量出烟雾和温度等均有即将起火,便可以报警,第一时间将其源头消灭;同时可以测量风向、分析地形并作出预测,预测出的突变的风向,使救援人员及时转移,减少伤亡、损失。
5 部分核心代码
#include "uart.h"
#include "oled.h"
#include "stdio.h"
static u8 Cx=0,Cy=0,Cw=0,Ch=0;
void USART1_Init(void)
{
//USART1_TX:PA 9
//USART1_RX:PA10
GPIO_InitTypeDef GPIO_InitStructure; //串口端口配置结构体变量
USART_InitTypeDef USART_InitStructure; //串口参数配置结构体变量
NVIC_InitTypeDef NVIC_InitStructure; //串口中断配置结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打开PA端口时钟
//USART1_TX PA9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设定IO口的输出速度为50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//USART1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ; //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = 115200; //串口波特率为115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能中断
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC); //清串口1发送标志
}
//USART1 全局中断服务函数
void USART1_IRQHandler(void)
{
u8 com_data;
u8 i;
static u8 RxCounter1=0;
static u16 RxBuffer1[10]={0};
static u8 RxState = 0;
static u8 RxFlag1 = 0;
if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) //接收中断
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志
com_data = USART_ReceiveData(USART1);
if(RxState==0&&com_data==0x2C) //0x2c帧头
{
RxState=1;
RxBuffer1[RxCounter1++]=com_data;OLED_Refresh();
}
else if(RxState==1&&com_data==0x12) //0x12帧头
{
RxState=2;
RxBuffer1[RxCounter1++]=com_data;
}
else if(RxState==2)
{
RxBuffer1[RxCounter1++]=com_data;
if(RxCounter1>=10||com_data == 0x5B) //RxBuffer1接受满了,接收数据结束
{
RxState=3;
RxFlag1=1;
Cx=RxBuffer1[RxCounter1-5];
Cy=RxBuffer1[RxCounter1-4];
Cw=RxBuffer1[RxCounter1-3];
Ch=RxBuffer1[RxCounter1-2];
}
}
else if(RxState==3) //检测是否接受到结束标志
{
if(RxBuffer1[RxCounter1-1] == 0x5B)
{
USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);//关闭DTSABLE中断
if(RxFlag1)
{
OLED_Refresh();
OLED_ShowNum(0, 0,Cx,3,16,1);
OLED_ShowNum(0,17,Cy,3,16,1);
OLED_ShowNum(0,33,Cw,3,16,1);
OLED_ShowNum(0,49,Ch,3,16,1);
}
RxFlag1 = 0;
RxCounter1 = 0;
RxState = 0;
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
}
else //接收错误
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00; //将存放数据数组清零
}
}
}
else //接收异常
{
RxState = 0;
RxCounter1=0;
for(i=0;i<10;i++)
{
RxBuffer1[i]=0x00; //将存放数据数组清零
}
}
}
}
import sensor, image, time,math,pyb
from pyb import UART,LED
import json
import ustruct
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
red_threshold_01=(10, 100, 127, 32, -43, 67)
clock = time.clock()
uart = UART(3,115200) #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
def find_max(blobs): #定义寻找色块面积最大的函数
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
def sending_data(cx,cy,cw,ch):
global uart;
#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
#data = bytearray(frame)
data = ustruct.pack("<bbhhhhb", #格式为俩个字符俩个短整型(2字节)
0x2C, #帧头1
0x12, #帧头2
int(cx), # up sample by 4 #数据1
int(cy), # up sample by 4 #数据2
int(cw), # up sample by 4 #数据1
int(ch), # up sample by 4 #数据2
0x5B)
uart.write(data); #必须要传入一个字节数组
while(True):
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs([red_threshold_01])
cx=0;cy=0;
if blobs:
max_b = find_max(blobs)
#如果找到了目标颜色
cx=max_b[5]
cy=max_b[6]
cw=max_b[2]
ch=max_b[3]
img.draw_rectangle(max_b[0:4]) # rect
img.draw_cross(max_b[5], max_b[6]) # cx, cy
FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
#sending_data(cx,cy,cw,ch)
uart.write(FH)
print(cx,cy,cw,ch)