一、前言
随着社会的发展,人们的生活水平越来越关注安全问题,各种防盗设备层出不穷。本文采用红外测距传感器、摄像头STM32单片机以及ESP8266无线通信模块设计了车库防盗报警器,可安装在车库内,通过红外测距检测是否有入侵,产生报警信号,提醒相关人员采取应急防御措施。防盗报警成本低,功能优良,防盗效果好,是家庭防盗的好选择。
二、具体需求
(1)主模块:密码锁开门模块 检测模块 报警模块 拍摄模块 主控制模块 传输存取模块
检测模块:红外测距传感器
报警模块:灯 蜂鸣器
拍摄模块:摄像头
传输存取模块:WIFI传输和使用模块SD卡存取
主控模块:TFT显示屏 主控制器(STM32单片机)
最后,整体呈现方式:矩形微型车库结构
主要用途:主要解决车库内电瓶车被盗、长期充电引起火灾等不良安全风险。
二、具体流程思路
一开始门(由能运转90°舵机和和小木板组成的)和限位开关一直被触摸
(2)输入正确密码进入车库:
打开门(即舵机运行90°,当门与限位开关分离时,灯通常亮着,其他模块装置不工作;当车库门关闭时,门没有关闭(即门没有位开关)WIFI模块将信息发送到手机端,提醒门未关闭;门关闭后灯熄灭,报警系统全部正常运行。
(3)不能输入正确的密码也可以进入车库:
当异常进入车库时,当红外测距系统检测到人时,灯亮起,蜂鸣器响起,触发摄像头装置。触发后的摄像头装置将连续拍摄两次(注:红外测距系统未检测到人,摄像头装置不运行,以达到低功耗的目的。连续拍摄两次也可以改为一次,两次是为了保证捕捉效果)。拍摄的图片将保存在存储模块中,手机端也将收到报警信息和图片,提醒非本人进入车库。
(四)拟使用的设备
类型 | 数量 | 预期效果 | 备注 |
---|---|---|---|
STM32F103 | 1 | 主控制系统 | |
TFT液晶屏 | 1 | 输入四位密码开门,调整红外测距距离,查看图片,显示车库温度等 | |
LED灯 | 10个或以上 | ||
ov7670摄像头 | 2 | 两个摄像头同时拍摄 | |
温度传感器 | 1 | ||
一种转运90°的舵机 | 1 | 用于开关门装置 | |
限位开关 | 1 | 感应装置是否关闭门 | |
蜂鸣器 | 1 | ||
存储装置 | 1 | 存储图片 | |
WIFI模块 | 1 | ESP8266 | |
红外测距装置 | 1 | 自主调节测距感应 | 做设置10cm测距调试 |
(5)想象液晶屏效果图
二、功能拆解
(1) 通过红外测距模块(超声波替换),检测是否有人通过。如果有人通过,请调用摄像头拍照并存储在中SD保存卡并通过ESP8266通知手机APP,有人闯入,手机APP会产生报警声。报警检测距离可以设置在手机上。 (2) 拍照时,保存的文件名称以当前时间为准,需要在开发板上使用RTC手机也需要时钟APP在校准开发板上增加一个时间校准功能,方便校准RTC实时时钟时间。 (3) 实时检测环境温湿度,将温湿度信息传递给手机APP显示
技术点:
- 需要移植FATFS构建文件系统BMP只有通过图片结果,才能保存相机拍摄的照片SD卡里。
- 需要启动RTC,当前时间作为系统时钟实时记录,手机,APP校准功能需要增加一个时间。
- 摄像头采用OV7670,通过SCCB时间交互需要收集RGB数据编码成BMP图片存放到SD卡。
三、上位机开发
上位机采用QT框架开发,分别开发Android、windows版本。
3.1 QT 框架简介
Qt是一个1991年由QtCompany跨平台开发C 图形用户界面应用程序开发框架。它可以开发GUI也可用于开发非程序GUI程序,如控制台工具和服务器。Qt它是一个面向对象的框架,使用特殊代码生成扩展(称为元对象编译器)(Meta Object Compiler, moc))以及一些宏,Qt它很容易扩展,并允许真正的组件编程。
在发布 Qt 4.6 同时,作为 Qt 开发跨平台 IDE 的Qt Creator更新版本也发布了。Qt Creator 1.3 和 Qt 4.6共同构成的 Qt SDK,它包括开发跨平台应用所需的所有功能。
Qt Creator是一个用于Qt轻量级跨平台集成开发环境。Qt Creator它可以带来两个关键好处:为支持跨平台开发提供第一个集成开发环境 (IDE),确保第一次接触Qt框架开发人员可以快速启动和操作。即使不开发Qt应用程序,Qt Creator也是一个简单易用且功能强大的IDE。
QT官网: https://resources.qt.io/cn
3.2 QT环境搭建
QT5.12.6安装包下载地址: https://download.qt.io/archive/qt/5.12/5.12.6/
QT学习专栏: https://blog.csdn.net/xiaolong1126626497/category_11400392.html QT环境建设文章:https://xiaolong.blog.csdn.net/article/details/120654599
3.3 软件运行效果
(1)STM32端通过DHT11通过红外测距传感器实时检测环境温湿度ESP8266传递到手机APP实时显示。
数据传输格式:
$update,16,23,23.5 测量的温度、湿度和距离
(2)手机APP红外报警检测距离可设置在上面。点击手机页面上的设置后,它将被传递给STM32。
数据传输格式:
#5 5单位为厘米,表示设置5cm检测距离。
当实际测量距离小于设定的报警距离时,会产生报警信息、手机APPA上会自动响起报警铃声。
(3)在STM32上有一个RTC手机需要实时记录当前时间APP有时间校准按钮,点击后会校准STM32开发板上的时间。
数据通信格式:
*20220309114156 传递过去的就是年月日时分秒时间
下面是在Android系统下运行软件的效果。
3.4 模拟测试
现在先不连接设置设备,采用网络调试助手来模拟ESP8266+STM32,测试通信效果,通信过程是否正常。 左边是TCP调试助手,右边是上位机软件,可以使用TCP调试助手模拟ESP8266,与上位机之间通信。
上位机时间校准–向ESP8266发送:*20220309114156
上位机设置报警距离-向ESP8266发送:#5
ESP8266向上位机发送:
$update,16,23,23.5
温度、湿度、测量的距离
四、设备端开发
如果需要完整工程,可以去这里下载: https://download.csdn.net/download/xiaolong1126626497/85894457
4.1 硬件效果图
4.2 OV7725摄像头核心代码
#include "sys.h" #include "ov7725.h" #include "ov7725cfg.h" #include "timer.h" #include "delay.h" #include "usart.h" #include "sccb.h" //JTAG模式设置,用于设置JTAG的模式 //mode:jtag,swd模式设置;00,全使能;01,使能SWD;10,全关闭; //#define JTAG_SWD_DISABLE 0X02 //#define SWD_ENABLE 0X01 //#define JTAG_SWD_ENABLE 0X00 void JTAG_Set(u8 mode) { u32 temp; temp=mode; temp<<=25; RCC->APB2ENR|=1<<0; //开启辅助时钟 AFIO->MAPR&=0XF8FFFFFF; //清除MAPR的[26:24] AFIO->MAPR|=temp; //设置jtag模式 } //初始化OV7725 //返回0:成功 //返回其他值:错误代码 u8 OV7725_Init(void) { u16 i=0; u16 reg=0; //设置IO RCC->APB2ENR|=1<<2; //先使能外设PORTA时钟 RCC->APB2ENR|=1<<3; //先使能外设PORTB时钟 RCC->APB2ENR|=1<<4; //先使能外设PORTC时钟 RCC->APB2ENR|=1<<5; //先使能外设PORTD时钟 RCC->APB2ENR|=1<<8; //先使能外设PORTG时钟 GPIOA->CRH&=0XFFFFFFF0; GPIOA->CRH|=0X00000008; //PA8 输入 GPIOA->ODR|=1<<8; GPIOB->CRL&=0XFFF00FFF; GPIOB->CRL|=0X00033000; //PB3/4 输出 GPIOB->ODR|=3<<3; GPIOC->CRL=0X88888888; //PC0~7 输入 GPIOC->ODR|=0x00ff; GPIOD->CRL&=0XF0FFFFFF; //PD6 输出 GPIOD->CRL|=0X03000000; GPIOD->ODR|=1<<6; GPIOG->CRH&=0X00FFFFFF; GPIOG->CRH|=0X33000000; GPIOG->ODR=7<<14; //PG14/15 输出高 JTAG_Set(1); SCCB_Init(); //初始化SCCB 的IO口 if(SCCB_WR_Reg(0x12,0x80))return 1; //复位SCCB DelayMs(50); reg=SCCB_RD_Reg(0X1c); //读取厂家ID 高八位 reg<<=8; reg|=SCCB_RD_Reg(0X1d); //读取厂家ID 低八位 if(reg!=OV7725_MID) { printf("MID:%d\r\n",reg); return 1; } reg=SCCB_RD_Reg(0X0a); //读取厂家ID 高八位 reg<<=8; reg|=SCCB_RD_Reg(0X0b); //读取厂家ID 低八位 if(reg!=OV7725_PID) { printf("HID:%d\r\n",reg); return 2; } //初始化 OV7725,采用QVGA分辨率(320*240) for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++) { SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]); } return 0x00; //ok } //OV7725功能设置 //白平衡设置 //0:自动模式 //1:晴天 //2,多云 //3,办公室 //4,家里 //5,夜晚 void OV7725_Light_Mode(u8 mode) { switch(mode) { case 0: //Auto,自动模式 SCCB_WR_Reg(0x13, 0xff); //AWB on SCCB_WR_Reg(0x0e, 0x65); SCCB_WR_Reg(0x2d, 0x00); SCCB_WR_Reg(0x2e, 0x00); break; case 1://sunny,晴天 SCCB_WR_Reg(0x13, 0xfd); //AWB off SCCB_WR_Reg(0x01, 0x5a); SCCB_WR_Reg(0x02, 0x5c); SCCB_WR_Reg(0x0e, 0x65); SCCB_WR_Reg(0x2d, 0x00); SCCB_WR_Reg(0x2e, 0x00); break; case 2://cloudy,多云 SCCB_WR_Reg(0x13, 0xfd); //AWB off SCCB_WR_Reg(0x01, 0x58); SCCB_WR_Reg(0x02, 0x60); SCCB_WR_Reg(0x0e, 0x65); SCCB_WR_Reg(0x2d, 0x00); SCCB_WR_Reg(0x2e, 0x00); break; case 3://office,办公室 SCCB_WR_Reg(0x13, 0xfd); //AWB off SCCB_WR_Reg(0x01, 0x84); SCCB_WR_Reg(0x02, 0x4c); SCCB_WR_Reg(0x0e, 0x65); SCCB_WR_Reg(0x2d, 0x00); SCCB_WR_Reg(0x2e, 0x00); break; case 4://home,家里 SCCB_WR_Reg(0x13, 0xfd); //AWB off SCCB_WR_Reg(0x01, 0x96); SCCB_WR_Reg(0x02, 0x40); SCCB_WR_Reg(0x0e, 0x65); SCCB_WR_Reg(0x2d, 0x00); SCCB_WR_Reg(0x2e, 0x00); break; case 5://night,夜晚 SCCB_WR_Reg(0x13, 0xff); //AWB on SCCB_WR_Reg(0x0e, 0xe5); break; } } //色度设置 //sat:-4~+4 void OV7725_Color_Saturation(s8 sat) { if(sat>=-4 && sat<=4) { SCCB_WR_Reg(USAT,(sat+4)<<4); SCCB_WR_Reg(VSAT,(sat+4)<<4); } } //亮度设置 //bright:-4~+4 void OV7725_Brightness(s8 bright) { u8 bright_value,sign; switch(bright) { case 4: bright_value = 0x48; sign = 0x06; break; case 3: bright_value = 0x38; sign = 0x06; break; case 2: bright_value = 0x28; sign = 0x06; break; case 1: bright_value = 0x18; sign = 0x06; break; case 0: bright_value = 0x08; sign = 0x06; break; case -1: bright_value = 0x08; sign = 0x0e; break; case -2: bright_value = 0x18; sign = 0x0e; break; case -3: bright_value = 0x28; sign = 0x0e; break; case -4: bright_value = 0x38; sign = 0x0e; break; } SCCB_WR_Reg(BRIGHT, bright_value); SCCB_WR_Reg(SIGN, sign); } //对比度设置 //contrast:-4~+4 void OV7725_Contrast(s8 contrast) { if(contrast >= -4 && contrast <=4) { SCCB_WR_Reg(CNST,(0x30-(4-contrast)*4)); } } //特效设置 //0:普通模式 //1,负片 //2,黑白 //3,偏红色 //4,偏绿色 //5,偏蓝色 //6,复古 void OV7725_Special_Effects(u8 eft) { switch(eft) { case 0://正常 SCCB_WR_Reg(0xa6, 0x06);//TSLB设置 SCCB_WR_Reg(0x60, 0x80);//MANV,手动V值 SCCB_WR_Reg(0x61, 0x80);//MANU,手动U值 break; case 1://负片 SCCB_WR_Reg(0xa6, 0x46); break; case 2://黑白 SCCB_WR_Reg(0xa6, 0x26); SCCB_WR_Reg(0x60, 0x80); SCCB_WR_Reg(0x61, 0x80); break; case 3://偏红 SCCB_WR_Reg(0xa6, 0x1e); SCCB_WR_Reg(0x60, 0x80); SCCB_WR_Reg(0x61, 0xc0); break; case 4://偏绿 SCCB_WR_Reg(0xa6, 0x1e); SCCB_WR_Reg(0x60, 0x60); SCCB_WR_Reg(0x61, 0x60); break; case 5://偏蓝 SCCB_WR_Reg(0xa6, 0x1e); SCCB_WR_Reg(0x60, 0xa0); SCCB_WR_Reg(0x61, 0x40); break; case 6://复古 SCCB_WR_Reg(0xa6, 0x1e); SCCB_WR_Reg(0x60, 0x40); SCCB_WR_Reg(0x61, 0xa0); break; } } //设置图像输出窗口 //width:输出图像宽度,<=320 //height:输出图像高度,<=240 //mode:0,QVGA输出模式;1,VGA输出模式 //QVGA模式可视范围广但近物不是很清晰,VGA模式可视范围小近物清晰 void OV7725_Window_Set(u16 width,u16 height,u8 mode) { u8 raw,temp; u16 sx,sy; if(mode) { sx=(640-width)/2; sy=(480-height)/2; SCCB_WR_Reg(COM7,0x06); //设置为VGA模式 SCCB_WR_Reg(HSTART,0x23); //水平起始位置 SCCB_WR_Reg(HSIZE,0xA0); //水平尺寸 SCCB_WR_Reg(VSTRT,0x07); //垂直起始位置 SCCB_WR_Reg(VSIZE,0xF0); //垂直尺寸 SCCB_WR_Reg(HREF,0x00); SCCB_WR_Reg(HOutSize,0xA0); //输出尺寸 SCCB_WR_Reg(VOutSize,0xF0); //输出尺寸 }else { sx=(320-width)/2; sy=(240-height)/2; SCCB_WR_Reg(COM7,0x46); //设置为QVGA模式 SCCB_WR_Reg(HSTART,0x3f); //水平起始位置 SCCB_WR_Reg(HSIZE, 0x50); //水平尺寸 SCCB_WR_Reg(VSTRT, 0x03); //垂直起始位置 SCCB_WR_Reg(VSIZE, 0x78); //垂直尺寸 SCCB_WR_Reg(HREF, 0x00); SCCB_WR_Reg(HOutSize,0x50); //输出尺寸 SCCB_WR_Reg(VOutSize,0x78); //输出尺寸 } raw=SCCB_RD_Reg(HSTART); temp=raw+(sx>>2);//sx高8位存在HSTART,低2位存在HREF[5:4] SCCB_WR_Reg(HSTART,temp); SCCB_WR_Reg(HSIZE,width>>2);//width高8位存在HSIZE,低2位存在HREF[1:0] raw=SCCB_RD_Reg(VSTRT); temp=raw+(sy>>1);//sy高8位存在VSTRT,低1位存在HREF[6] SCCB_WR_Reg(VSTRT,temp); SCCB_WR_Reg(VSIZE,height>>1);//height高8位存在VSIZE,低1位存在HREF[2] raw=SCCB_RD_Reg(HREF); temp=((sy&0x01)<<6)|((sx&0x03)<<4)|((height&0x01)<<2)|(width&0x03)|raw; SCCB_WR_Reg(HREF,temp); SCCB_WR_Reg(HOutSize,width>>2); SCCB_WR_Reg(VOutSize,height>>1); SCCB_RD_Reg(EXHCH); temp = (raw|(width&0x03)