一、前言
随着社会的发展,人们的生活水平不断提高对安防问题的关注度越来越高,因而各类防盗设备也层出不穷,本文采用红外测距传感器、摄像头、STM32单片机以及ESP8266无线通信模块设计一种车库防盗报警器,其可安装在车库的里,通过红外线测距检测是否有人入侵,产生报警信号,提醒相关人员采取应急防御措施。该防盗报警器成本低,功能优,防盗效果好,是家居防盗的优良选择。
二、具体需求
(一)主要模块:密码锁开门模块 检测模块 报警模块 拍摄模块 主控制模块 传输存取模块
检测模块:红外测距传感器
报警模块:灯 蜂鸣器
拍摄模块:摄像头
传输存取模块:WIFI模块实现传输,用SD卡存取
主控制模块:TFT显示屏 主控制器(STM32单片机)
最后整体呈现方式:矩形的微型车库构造
主要用途:主要解决电瓶车在车库内被盗和电瓶车长时间充电引起火灾等不良安全隐患。
二、具体流程想法
一开始门(由能运转90°的舵机和一个小木板构建成的)和限位开关一直触碰着
(二)、输入正确密码进入车库:
门打开(即舵机运转90°,门和限位开关脱离)时,灯常亮,其他模块装置不运转;关闭车库门时,门没关紧(即门没有触碰到限位开关)时,通过WIFI模块发送信息至手机端,提醒门没关紧;门关紧后灯灭,报警系统全部正常运转。
(三)、不能输入正确密码反而也能进入车库:
不正常进入车库内时,当红外测距系统检测到人时,灯亮起和蜂鸣器响起,同时触发摄像装置,触发后的摄像装置会连续拍摄两次(注:红外测距系统没有检测到人,摄像装置是不运行的,以达到一个低功耗的目的,连续拍摄两次也可改为一次,两次是为了保证抓拍效果),拍摄的图片保存至存储模块,手机端也会收到报警信息和图片,提醒有非本人进入车库。
(四)拟所用器件
类型 | 数量 | 预期达到的效果 | 备注 |
---|---|---|---|
STM32F103 | 1 | 主控制系统 | |
TFT液晶屏 | 1 | 实现输入四位密码开门及调整红外测距的测距距离和查看图片、显示车库内的温度等 | |
LED灯 | 10个或以上 | ||
ov7670摄像头 | 2 | 两个摄像头同时拍摄 | |
温度传感器 | 1 | ||
一种转运90°的舵机 | 1 | 用于开关门装置 | |
限位开关 | 1 | 门是否关紧感应装置 | |
蜂鸣器 | 1 | ||
存储装置 | 1 | 存储图片 | |
WIFI模块 | 1 | ESP8266 | |
红外测距装置 | 1 | 可实现自主调整测距感应 | 做设置10cm测距调试 |
(五)、想象的液晶屏效果图
二、功能拆解
(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上实时显示。
数据传输的格式:
代码语言:javascript复制$update,16,23,23.5
温度、湿度、测量的距离
(2)手机APP上可以设置红外报警检测距离,在手机页面上点击设置之后,会传递给STM32。
数据传输的格式:
代码语言:javascript复制#5 5的单位是厘米,表示设置5cm的检测距离。
当实际测量的距离小于了设置的报警距离,就会产生报警信息,手机APPA上会自动响起报警铃声。
(3)在STM32上有一个RTC时钟,需要实时记录当前时间,手机APP有一个时间校准按钮,点击之后,会校准STM32开发板上的时间。
数据通信格式:
代码语言:javascript复制*20220309114156 传递过去的就是年月日时分秒时间
下面是在win10系统下运行软件的效果。
下面是在Android系统下运行软件的效果。
3.4 模拟测试
现在先不连接设置设备,采用网络调试助手来模拟ESP8266 STM32,测试通信效果,通信过程是否正常。 左边是TCP调试助手,右边是上位机软件,可以使用TCP调试助手模拟ESP8266,与上位机之间通信。
(1)搭建模拟化环境
(2)温度、湿度、检测距离上传
数据格式协议:
上位机时间校准–向ESP8266发送:*20220309114156
上位机设置报警距离-向ESP8266发送:#5
ESP8266向上位机发送:
代码语言:javascript复制$update,16,23,23.5
温度、湿度、测量的距离
(3)APP设置报警距离
(4)APP报警提示演示
四、设备端开发
如果需要完整工程,可以去这里下载: https://download.csdn.net/download/xiaolong1126626497/85894457
4.1 硬件效果图
4.2 OV7725摄像头核心代码
代码语言:javascript复制#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:%drn",reg);
return 1;
}
reg=SCCB_RD_Reg(0X0a); //读取厂家ID 高八位
reg<<=8;
reg|=SCCB_RD_Reg(0X0b); //读取厂家ID 低八位
if(reg!=OV7725_PID)
{
printf("HID:%drn",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)|((height&0x01)<<2));
SCCB_WR_Reg(EXHCH,temp);
}
4.3 ESP8266核心代码
代码语言:javascript复制#include "esp8266.h"
u8 ESP8266_IP_ADDR[16]; //255.255.255.255
u8 ESP8266_MAC_ADDR[18]; //硬件地址
/*
函数功能: ESP8266命令发送函数
函数返回值:0表示成功 1表示失败
*/
u8 ESP8266_SendCmd(char *cmd)
{
u8 i,j;
for(i=0;i<10;i ) //检测的次数--发送指令的次数
{
USARTx_StringSend(USART3,cmd);
for(j=0;j<5;j ) //等待的时间
{
delay_ms(50);
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='