[作品提交] 基于物联网的学生宿舍公寓监控系统

青春最好时   2022-10-17 11:20 楼主

一、作品背景:

近年来,高校宿舍安全事故频发,给同学们造成了不必要的人身伤害和财产损失,故宿舍安全问题是学生安全生活的基本保障。宿舍的安全问题主要在于学生是否使用了违规电器,那么对用电设备的监测是重要的一环,所以本设计应运而生。

本设计用STM32单片机做主控芯片,对宿舍用电情况进行了智能监测,对火灾信号进行检测,利用OneNet物联网云平台对用电参数进行实时监测;同时拥有人脸识别功能,实现人走断电,对寝室智能的通断电进行控制;拥有指纹识别功能,实现宿舍门的开关;还设计了终端系统,可以看到各宿舍用电情况,包括是否着火、是否使用大功率设备,当有异常情况时,系统可以自动进行断电操作。

本设计自己认为很有实际意义,因为自己家旁边的学校就因为学生违规使用电器导致宿舍着火。

 

作品照片

image-20221017103217-1.jpeg image-20221017103310-2.jpeg image-20221017103322-3.jpeg image-20221017103337-4.jpeg  

使用到的元器件主要有:

宿舍终端:2块STM32F1RCT6核心板、2个ZigBee模块、2个指纹模块、2个蜂鸣器、2个IM1281B电参数采集模块、2个WIFI模块、2个开关电源、2个断路器、2个继电器、电源模块以及其他元件杜邦线若干。

宿舍管理员控制终端:1块STM32F7508—DK开发板、1个ZigBee模块、1块Linux开发板、摄像头、电源模块、串口屏等元件。

因为这些元件自己都有,所以也就顺便用上了,希望做一个简易的DEMO出来。

 

二、系统结构

2.1 系统框图

学生侧框图

学生侧.jpg 终端侧结构

终端侧.jpg 学生侧端使用STM32核心板、WIFI、ZigBee、继电器以及传感器等其他元件组成,STM32核心板用来采集宿舍内的用电情况以及烟雾,火焰等信息。信号采集完以后使用STM32驱动WIFI模块把信号发送给中国移动OneNet物联网云平台,后在平台显示出各个宿舍用电,烟雾,火焰等信息,同时STM32还驱动ZigBee模块把宿舍信号发给控制终端,以便进行监控。

 

终端使用STM32F7508-DK开发板、ZigBee、串口屏、摄像头、Linux开发板等组成。因为嫌STM32F7508-DK开发板上自带的屏幕太小,所以手头有的串口屏也使用到本项目中。

STM32F7508-DK开发板作为ZigBee信号协调器的控制器,接收各个宿舍传来的各个信息,以便驱动串口屏显示。由于STM32F7508-DK开发板做人脸识别的时候速度比较慢,所以使用Linux开发板进行人脸识别,人脸识别完以后,STM32F7508-DK通过ZigBee信号协调器向宿舍发送命令,以便可以学生在离开宿舍的时候可以自行进行断电。

注:由于学生侧驱动代码比较完善,在学生侧设备的代码使用标准库编写,由于STM32F7508-DK有板载外设,且STM32CubeIDE中有对应配套的BSP,所以管理员终端侧设备使用HAL库开发。

2.2 系统硬件结构

image-20221017103542-5.png  

三、各部分功能说明

 

3.1学生侧

学生侧设备的主要功能是:1、采集宿舍的用电信息;2、使用WIFI模块将电参数传到中国移动OneNet物联网云平台上;3、宿舍终端设备与宿舍管理员控制终端设备采用ZigBee进行数据交互,宿舍终端ZigBee作为终端节点向宿舍管理员控制终端发送宿舍的电参数,火焰、烟雾等信号,宿舍管理员控制终端的ZigBee作为协调器接收宿舍传来的信号;4、有指纹模块,可以实现指纹开门。

电参数的采集,电参数采集使用艾锐达公司的IM1281B电参数采集模块,见文档
IM1281B 模块技术手册 V1.3.pdf (789.39 KB)
(下载次数: 0, 2022-10-16 12:47 上传)

其中硬件接口如下:

1.jpg

电参数采集代码

void read_data(void)
{
			union	crcdata
			{
			unsigned int word16; 
			unsigned char	byte[2];
			}crcnow;
			
			if(read_enable==1)	// 到时间抄读模块,抄读间隔 1 秒钟(或其他)
			{
				read_enable=0;
				Tx_Buffer1[0]=Read_ID;	//模块的 ID 号,默认 ID 为 0x01 
				Tx_Buffer1[1]=0x03;
				Tx_Buffer1[2]=0x00; 
				Tx_Buffer1[3]=0x48;
				Tx_Buffer1[4]=0x00; 
				Tx_Buffer1[5]=0x08; 
				crcnow.word16=chkcrc(Tx_Buffer1,6);
				Tx_Buffer1[6]=crcnow.byte[1];	//CRC 效验低字节在前
				Tx_Buffer1[7]=crcnow.byte[0];

			}
																
					for(j=0;j<i;j++)						//循环发送数据01 03 00 48 00 08 C4 1A
					{
						while(USART_GetFlagStatus(UART5,USART_FLAG_TC)==RESET); //串口三 循环发送,直到发送完毕   
						USART_SendData(UART5,Tx_Buffer1[j]);
						
						
//						while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
//						USART_SendData(USART1,Tx_Buffer1[j]); //用   串口一   来检测是否发送的一样
					}
					Anysis_data_bit = 1;
//					UsartPrintf(USART1,"read data_IM1281B\r\n");
}

当电参数数据采集完毕以后,需要进行解包,因为电参数模块使用的是ModBus协议,需要解包供系统使用。其中数据解包的代码如下

void Analysis_data(void)
	{
			union	crcdata
			{
			unsigned int word16;
			unsigned char	byte[2];
			}crcnow;
		if(receive_finished==1)	//接收完成
		{
				reveive_numbe=USART3_RX_STA;
				receive_finished=0; 
			
				if((Rx_Buffer1[0]==0x01)||(Rx_Buffer1[0]==0x00))	//确认 ID 正确
			{
					crcnow.word16=chkcrc(Rx_Buffer1,reveive_numbe-2);	//reveive_numbe 是接收数据总长度
					if((crcnow.byte[0]==Rx_Buffer1[reveive_numbe-1])&&(crcnow.byte[1]==Rx_Buffer1[reveive_numbe-2]))//确认 CRC 校验正确
					{
						
						/////*********电压
//						UsartPrintf(USART1,"%X,%X,%X,%X",Rx_Buffer1[3],Rx_Buffer1[4],Rx_Buffer1[5],Rx_Buffer1[6]);
						Electric.Voltage_data=(((unsigned long)(Rx_Buffer1[3]))<<24)|(((unsigned long)(Rx_Buffer1[4]))<<16)|(((unsigned	long)(Rx_Buffer1[5]))<<8)|Rx_Buffer1[6];
						Electric.Voltage_data1 = (float)(Electric.Voltage_data*0.0001);		//得到小数值
						
						UsartPrintf(USART1,"\r\n电压值:%fV\r\n",Electric.Voltage_data1);//串口一来打印电压值
						
						/////*********电流
						Electric.Current_data=(((unsigned long)(Rx_Buffer1[7]))<<24)|(((unsigned long)(Rx_Buffer1[8]))<<16)|(((unsigned	long)(Rx_Buffer1[9]))<<8)|Rx_Buffer1[10];
						Electric.Current_data1 = (float)(Electric.Current_data*0.0001);	
						UsartPrintf(USART1,"电流:%fA\r\n",Electric.Current_data1);//串口一来打印电流
						
						/////*********功率
						Electric.Power_data=(((unsigned	long)(Rx_Buffer1[11]))<<24)|(((unsigned long)(Rx_Buffer1[12]))<<16)|(((unsigned	long)(Rx_Buffer1[13]))<<8)|Rx_Buffer1[14];
						Electric.Power_data1 = (float)(Electric.Power_data*0.0001);
						UsartPrintf(USART1,"功率:%fW\r\n",Electric.Power_data1);//串口一来打印功率
						
						/////*********电能
						Electric.Energy_data=(((unsigned	long)(Rx_Buffer1[15]))<<24)|(((unsigned long)(Rx_Buffer1[16]))<<16)|(((unsigned	long)(Rx_Buffer1[17]))<<8)|Rx_Buffer1[18];
						Electric.Energy_data1 = (float)(Electric.Energy_data*0.0001);
//						UsartPrintf(USART1,"电能:%f\r\n",Electric.Energy_data1);//串口一来打印电能
//						
						/////*********功率因数
						Electric.Pf_data=(((unsigned	long)(Rx_Buffer1[19]))<<24)|(((unsigned long)(Rx_Buffer1[20]))<<16)|(((unsigned	long)(Rx_Buffer1[21]))<<8)|Rx_Buffer1[22];
						Electric.Pf_data1=(float)(Electric.Pf_data*0.001);
//						UsartPrintf(USART1,"功率因数:%.3lf\r\n",Electric.Pf_data1); //串口一来打印接受功率因数

						//////*********CO2浓度
						Electric.CO2_data=(((unsigned long)(Rx_Buffer1[23]))<<24)|(((unsigned long)(Rx_Buffer1[24]))<<16)|(((unsigned	long)(Rx_Buffer1[25]))<<8)|Rx_Buffer1[26];
						Electric.CO2_data1 = (float)(Electric.CO2_data*0.0001);
//						UsartPrintf(USART1,"二氧化碳:%f\r\n",Electric.CO2_data1);//串口一来打印接受二氧化碳
						///*************频率
						Electric.HZ=(((unsigned long)(Rx_Buffer1[31]))<<24)|(((unsigned long)(Rx_Buffer1[32]))<<16)|(((unsigned	long)(Rx_Buffer1[33]))<<8)|Rx_Buffer1[34];
						Electric.HZ1=	Electric.HZ*0.01;	
//						UsartPrintf(USART1,"赫兹:%.2lfHZ\r\n",Electric.HZ1);//串口一来打印接受单相交流电的赫兹

						USART3_RX_STA=0;
						
						Malignant_load_identfiy();		///负载识别
						
					}
//				else UsartPrintf(USART1,"// CRC 校验错误\r\n");//串口一来打印接受电压值
			}
			ZigBee_UP_Date();		//更新完数据就开始ZigBee 数据传输。
			
			wifi_null();		
		}
//			else	UsartPrintf(USART1,"\r\nreceive_finished标志位为0\r\n");
		
	}

数据解析完毕以后,得到解析后的电参量结构体。

电参量采集的流程图如下所示

4.jpg

为了简单起见,设定功率达到一定值时继电器断开给宿舍进行断电,这里并没有对负载是阻性、容性还是感性类型进行识别。继电器控制框图如下图所示。

2.jpg 解包完以后数据变成浮点型,此时单片机系统可以控制WIFI模块向中国移动OneNet物联网云平台上传数据。

其WIFI模块硬件接口如下:

3.jpg

 

学生侧数据上传OneNet使用的是MQTT方式,具体可以从OneNet官网下载SDK使用。

8.ESP8266-MQTT_TYPE5-温湿度.zip (3.19 MB)
(下载次数: 1, 2022-10-16 12:13 上传)

下载完SDK以后,更改自己的WIFI热点以及密码。并在平台上创建设备信息,具体信息可以见OneNet文档

https://open.iot.10086.cn/doc/v5/develop/detail/easy-manual

建立的产品界面如下,可以看到产品和宿舍信息

image-20221017104712-2.png

image-20221017104702-1.png  

完事以后,更改自己的产品ID、设备ID等参数。

#define ESP8266_WIFI_INFO		"AT+CWJAP=\"ONENET\",\"IOT@Chinamobile123\"\r\n"

#define PROID		"77247"

#define AUTH_INFO	"test"

#define DEVID		"5616839"

这一部分以及数据上传到平台以后如何进行数据流显示可以从OneNet官网入门资料入手。

数据打包上传

unsigned char OneNet_FillBuf(char *buf)
{

	
	char text[512];
	
	memset(text, 0, sizeof(text));
	
	strcpy(buf, "{");
	///****电压
	memset(text, 0, sizeof(text));
	sprintf(text, "\"Voltage\":%lf,", Electric.Voltage_data1);
	strcat(buf, text);
	///*****电流
	memset(text, 0, sizeof(text));
	sprintf(text, "\"Current\":%lf,",  Electric.Current_data1);
	strcat(buf, text);
	////*****宿舍ID
	memset(text, 0, sizeof(text));
	sprintf(text, "\"DEV_ID\":%d,", DEVID1);
	strcat(buf, text);
	////*****有功功率
	memset(text, 0, sizeof(text));
	sprintf(text, "\"PWOER\":%lf,", Electric.Power_data1);
	strcat(buf, text);
	//////*******功率因数
	memset(text, 0, sizeof(text));
	sprintf(text, "\"PF\":%lf,", Electric.Pf_data1);
	strcat(buf, text);
	/////*****电能
	memset(text, 0, sizeof(text));
	sprintf(text, "\"Energy\":%lf", Electric.Energy_data1);
	strcat(buf, text);
	memset(text, 0, sizeof(text));
	
	strcat(buf, "}");
	

//	UsartPrintf(USART_DEBUG,"\r\n");
	return strlen(buf);

}
WIFI向平台发送数据的流程图如下所示。
image-20221017104835-3.png  

中国移动OneNet物联网云平台上显示的界面如下所示。

image-20221017104900-4.png  
当WIFI数据发送完毕以后,ZigBee同时将数据发送给ZigBee协调器,供管理员控制终端使用。
其中宿舍中ZigBee配置成终端节点模式,宿舍管理员控制终端的ZigBee配置成协调器模式,ZigBee数据接收与发送,ZigBee使用的是成都亿佰特公司的E18-MS1PA2见文档
E18-MS1PA2-IPX_UserManual-H_CN_v1.1.pdf (1.08 MB)
(下载次数: 0, 2022-10-16 12:32 上传)
E18+快速入门指导.pdf (1.65 MB)
(下载次数: 0, 2022-10-16 12:32 上传)
其ZigBee硬件接口如下:
6.jpg
Zigbee模块进行数据传输时所定义的数据帧为下表所示
image.png
学生宿舍终端的ZigBee数据打包上传代码片段  
1.	void ZigBee_UP_Date(void) 
2.	{ 
3.	int i = 0,j = 0; 
4.	unsigned char send_date[100]; 
5.	unsigned char send_temp1[100];///电能数据 
6.	memset(send_date,0,sizeof(send_date)); //清0 
7.	memset(send_temp1,0,sizeof(send_temp1)); 
8.	send_temp1[0]= DEVID1; //设备ID 
9.	send_temp1[1]= 0x03; 
10.	/////******拷贝电压数据 
11.	for(j = 0;j < 20;j++) //20位电参数 
12.	{ 
13.	send_temp1[j+2]= Rx_Buffer1[j+3]; 
14.	} 
15.	/////// 
16.	send_date[0] = 0xFC; 
17.	send_date[1] = 0x21; //数据长度 不包括 0XFC 和长度位 一定要对!!!! 
18.	send_date[2] = 0x03;send_date[3] = 0x01; //zigbee功能码 0x03 0x01 透传 
19.	send_date[4] = 0x00;send_date[5] = 0x00; // 协调器短地址 
20.	for(j = 0;j < 22;j++) //22位zigbee模块参数放到 帧头后面 
21.	{ 
22.	send_date[j+6]= send_temp1[j]; 
23.	} 
24.	send_date[28] = renti[0];send_date[29] = dagonglv[0];send_date[30] =yanwu[0]; 
25.	send_date[31] = duandian[0];send_date[32] = huoyan[0]; 
26.	send_date[33] = ShortAdress1[0];send_date[34] = ShortAdress1[1]; //设备自己短地址 
27.	for(i = 0;i < 35;i++) 
28.	{ 
29.	while(USART_GetFlagStatus(M6312_USART, USART_FLAG_TC) == RESET); //等待发送完成 
30.	USART_SendData(M6312_USART,send_date); 
31.	UsartPrintf(USART1,"%X",send_date); 
32.	} 
33.	UsartPrintf(USART1,"\r\n"); 
34.	UsartPrintf(USART1,"ZigBee_buf_Len send successful!\r\n"); 
35.	}

宿舍管理员控制终端的ZigBee当做协调器,对宿舍传来的数据进行解析。其中解包代码如下。

36.	void ZigBee_data(void)
37.	{
38.			
39.			if(M6312_WaitRecive()==REV_OK)		//说明串口接受完成
40.			{
41.				if(((m6312[0] == 0x01)&&(m6312[1] == 0x03))==1)		//说明是需要的数据
42.				{				
43.					DEV_ID = m6312[0];		//设备ID
44.					////
45.					voltage = (unsigned long)(m6312[2]<<24)|(unsigned long)(m6312[3]<<16)|(unsigned long)(m6312[4]<<8)|m6312[5];	//电压数据
46.					voltage1 = (float)(voltage*0.0001);
47.					////
48.					Current = (unsigned long)(m6312[6]<<24)|(unsigned long)(m6312[7]<<16)|(unsigned long)(m6312[8]<<8)|m6312[9];
49.					Current1 = (float)(Current*0.0001);
50.					/////
51.					POWER = (unsigned long)(m6312[10]<<24)|(unsigned long)(m6312[11]<<16)|(unsigned long)(m6312[12]<<8)|m6312[13];
52.					POWER1 = (float)(POWER*0.0001);
53.					////
54.					Enery = (unsigned long)(m6312[14]<<24)|(unsigned long)(m6312[15]<<16)|(unsigned long)(m6312[16]<<8)|m6312[17];
55.					Enery1 = (float)(Enery*0.0001);
56.					////
57.					PF = (unsigned long)(m6312[18]<<24)|(unsigned long)(m6312[19]<<16)|(unsigned long)(m6312[20]<<8)|m6312[21];
58.					PF1 = (float)(PF*0.001);
59.					////
60.					renti[0] = m6312[22];dagonglv[0] = m6312[23];yanwu[0] = m6312[24];duandian[0] = m6312[25];huoyan[0] = m6312[26];
61.					
62.					///设备短地址
63.					Short_Adress1[0] = m6312[27];Short_Adress1[1] = m6312[28];
64.				}
65.				if(((m6312[0] == 0x02)&&(m6312[1] == 0x03))==1)		//说明是需要的数据
66.				{			
67.					DEV_ID = m6312[0];				
68.					////
69.					voltage = (unsigned long)(m6312[2]<<24)|(unsigned long)(m6312[3]<<16)|(unsigned long)(m6312[4]<<8)|m6312[5];	//电压数据
70.					voltage2 = (float)(voltage*0.0001);
71.					////
72.					Current = (unsigned long)(m6312[6]<<24)|(unsigned long)(m6312[7]<<16)|(unsigned long)(m6312[8]<<8)|m6312[9];
73.					Current2 = (float)(Current*0.0001);
74.					/////
75.					POWER = (unsigned long)(m6312[10]<<24)|(unsigned long)(m6312[11]<<16)|(unsigned long)(m6312[12]<<8)|m6312[13];
76.					POWER2 = (float)(POWER*0.0001);
77.					////
78.					Enery = (unsigned long)(m6312[14]<<24)|(unsigned long)(m6312[15]<<16)|(unsigned long)(m6312[16]<<8)|m6312[17];
79.					Enery2 = (float)(Enery*0.0001);
80.					////
81.					PF = (unsigned long)(m6312[18]<<24)|(unsigned long)(m6312[19]<<16)|(unsigned long)(m6312[20]<<8)|m6312[21];
82.					PF2 = (float)(PF*0.001);
83.					///////
84.					renti1[0] = m6312[22];dagonglv1[0] = m6312[23];yanwu1[0] = m6312[24];duandian1[0] = m6312[25];huoyan1[0] = m6312[26];
85.					
86.					///设备短地址
87.					Short_Adress2[0] = m6312[27];Short_Adress2[1] = m6312[28];		
88.				}		
89.				M6312_Clear();		
90.			}
91.	}

ZigBee工作在终端节点模式和协调器下的主要工作流程图如下图所示

image-20221017105341-1.png image-20221017105345-2.png 以上就是宿舍终端侧的三大主要模块。但是宿舍终端设备还集成了指纹锁,可以通过按键或者刷指纹的方式对宿舍门进行开关。详解如下。

指纹识别功能移植野火的例程,F103_MINI指纹模块.zip,具体可以查看作品提交论坛帖子中的附件
F103_MINI指纹模块.zip (6.34 MB)
(下载次数: 0, 2022-10-16 12:36 上传)

其指纹接口的硬件接口如下

7.jpg

92.	void Compare_FR(void)  
93.	{  
94.	  uint16_t  ID=0;                    /*初始化ID值*/  
95.	  uint16_t  sure;
96.		
97.	//  AS608_INFO("******命令:对比指纹,请按手指******\r\n");
98.		OLED_Clear();
99.		OLED_ShowString(0,16,"Contrast finger:",16,1);
100.		OLED_ShowString(0,32,"Press finger:",8,1);
101.		OLED_Refresh();
102.	  sure=PS_GetImage();
103.	  if(sure == 0x00)
104.	  {
105.	    sure=PS_GenChar(CHAR_BUFFER1);    /*生成特征1*/
106.	    if(sure==0x00)
107.	    {  
108.				/*高速搜索指纹库*/
109.	      sure=PS_HighSpeedSearch(CHAR_BUFFER1,0,PS_MAXNUM,&ID);
110.	      if(sure==0x00)
111.	      {
112.	//        AS608_INFO ("对比指纹成功,指纹ID:%d!!!\r\n\r\n",ID);
113.					 UsartPrintf(DEBUG_USARTx,"对比指纹成功,指纹ID:%d!!!\r\n\r\n",ID);
114.					AS608_Com_Fig_Num = ID;
115.					AS608_Com_Error_bit = 0;	//检测正确
116.					AS608_success_bit = 2;
117.					
118.	      }
119.	      else 
120.	      {
121.				AS608_Com_Error_bit = 1;	//检测错误	
122.				ShowErrMessage(sure);
123.				}
124.	    }
125.	    else 
126.	    {   
127.	      ShowErrMessage(sure);	
128.	    }
129.	  }
130.		else  
131.		{
132.		  ShowErrMessage(sure);
133.		}
134.	 
135.	}

当对比指纹成功以后,开门标志置1,此时Stm32驱动电机旋转,门开启。其模块比如蜂鸣器、火焰、烟雾等传感器直接使用单片机驱动或者采集响应的ADC信号,然后根据采集的信号进行报警或者其他操作,由于逻辑比较简单,所以代码不再贴出,只给出程序设计的流程图。

image-20221017105620-1.png

到此,学生宿舍端设备各个功能已经讲解完毕。下面是宿舍管理员控制终端的功能介绍。

 

3.2 宿舍管理员控制终端

宿舍管理员控制终端的功能主要是:ZigBee数据接收、命令下发、人脸识别。

其中,1、ZigBee数据接收是ZigBee工作在协调器模式,接收宿舍传来的数据,供显示设备显示,这点已经在上一部分ZigBee工作流程中讲到了。2、命令下发是指管理员通过串口屏(带触摸触摸以后可以自定义数据输出)来对宿舍的电源进行开关,以及当摄像头检测到人员离开或者进入宿舍时对宿舍进行断、来电。3、人脸识别后的结果发送给宿舍管理员控制终端,然后宿舍管理员控制终端下发命令。

其中ZigBee数据下发的代码片段如下。

136.	void ZigBee_DOWN_Date(void)
137.	{		
138.			int i = 0;
139.			unsigned char send_date[100];
140.			if(cmd_down_bit == 1)
141.	//		if(usart1_WaitRecive() == REV_OK)
142.			{
143.				buf_len = 0;
144.				cmd_down_bit = 0;
145.				DEV_ID1 = usart1Buf[1];		//设备ID
146.				DEV_ID_Cmd = usart1Buf[2];	//命令
147.				buf[0] = usart1Buf[0];buf[1] = usart1Buf[1];buf[2] = usart1Buf[2];buf[3] = usart1Buf[3];
148.					usart1Buf_Clear();
149.					memset(send_date,0,sizeof(send_date));		//清0		
150.					if(buf[1] == 0x01)
151.					{
152.						send_date[4] = Short_Adress1[0];send_date[5] = Short_Adress1[1];		// 终端短地址 
153.					}
154.					if(buf[1] == 0x02)
155.					{
156.						send_date[4] = Short_Adress2[0];send_date[5] = Short_Adress2[1];		// 终端短地址 
157.					}
158.				send_date[0] = 0xFC;
159.				send_date[1] = 0x06;				//数据长度   不包括 0XFC
160.				send_date[2] = 0x03;send_date[3] = 0x01;		//zigbee功能码 0x03 0x01 			
161.				send_date[6] = DEV_ID1;		//设备ID  1号对应0x01   2号对应0x02
162.				send_date[7] = DEV_ID_Cmd;		// 命令 0x01开灯    0x02 关灯
163.		 }
164.	}

串口屏使用的是迪文串口屏,带触摸,触摸时候可以自定义数据输出,所以可以在屏幕上点击对宿舍进行来电和通电。其中串口屏数据更新程序如下所示。

165.	void Reflash_UI(void)
166.	{
167.		char Enery_temp[300];
168.		memset(Enery_temp,0,sizeof(Enery_temp));
169.		if(DEV_ID == 0x01)
170.		{
171.				SetTextValue(0,16,"已连接");		///显示电压
172.				SetTextValue(0,48,"1");		///显示电压
173.				sprintf(Enery_temp,"%.2f",voltage1);
174.				SetTextValue(0,8,Enery_temp);		///显示电压
175.				memset(Enery_temp,0,sizeof(Enery_temp));
176.			///
177.				sprintf(Enery_temp,"%.4f",Current1);
178.				SetTextValue(0,9,Enery_temp);		///显示电压
179.				memset(Enery_temp,0,sizeof(Enery_temp));
180.			/////
181.				sprintf(Enery_temp,"%.3f",POWER1);
182.				SetTextValue(0,10,Enery_temp);		///显示电压
183.				memset(Enery_temp,0,sizeof(Enery_temp));
184.			//////
185.				sprintf(Enery_temp,"%.3f",Enery1);
186.				SetTextValue(0,11,Enery_temp);		///显示电压
187.				memset(Enery_temp,0,sizeof(Enery_temp));
188.			////////
189.				sprintf(Enery_temp,"%f",PF1);
190.				SetTextValue(0,44,Enery_temp);		///显示电压
191.				memset(Enery_temp,0,sizeof(Enery_temp));
192.			////**
193.			if(renti[0] == 0x00)
194.			{
195.				SetTextValue(0,31,"无");		
196.			}else SetTextValue(0,31,"有");		
197.				////**
198.			if(dagonglv[0] == 0x00)
199.			{
200.				SetTextValue(0,40,"无");		
201.			}else SetTextValue(0,40,"有");	
202.				////**
203.			if(duandian[0] == 0x00)
204.			{
205.				SetTextValue(0,36,"无");		
206.			}else SetTextValue(0,36,"有");	
207.				////**
208.			if(huoyan[0] == 0x00)
209.			{
210.				SetTextValue(0,53,"无");		
211.			}else SetTextValue(0,53,"有");	
212.			/////****
213.			if(yanwu[0] == 0x00)
214.			{
215.				SetTextValue(0,51,"无");		
216.			}else SetTextValue(0,51,"有");	
217.			
218.			
219.		}
220.		if(DEV_ID == 0x02)
221.		{
222.				SetTextValue(0,64,"已连接");		///显示电压
223.				SetTextValue(0,49,"2");		///显示电压
224.				sprintf(Enery_temp,"%.2f",voltage2);
225.				SetTextValue(0,22,Enery_temp);		///显示电压
226.				memset(Enery_temp,0,sizeof(Enery_temp));
227.			///
228.				sprintf(Enery_temp,"%.4f",Current2);
229.				SetTextValue(0,23,Enery_temp);		///显示电压
230.				memset(Enery_temp,0,sizeof(Enery_temp));
231.			/////
232.				sprintf(Enery_temp,"%.3f",POWER2);
233.				SetTextValue(0,24,Enery_temp);		///显示电压
234.				memset(Enery_temp,0,sizeof(Enery_temp));
235.			//////
236.				sprintf(Enery_temp,"%.3f",Enery2);
237.				SetTextValue(0,25,Enery_temp);		///显示电压
238.				memset(Enery_temp,0,sizeof(Enery_temp));
239.			////////
240.				sprintf(Enery_temp,"%f",PF2);
241.				SetTextValue(0,46,Enery_temp);		///显示电压
242.				memset(Enery_temp,0,sizeof(Enery_temp));
243.					////**
244.			if(renti1[0] == 0x00)
245.			{
246.				SetTextValue(0,37,"无");		
247.			}else SetTextValue(0,37,"有");		
248.				////**
249.			if(dagonglv1[0] == 0x00)
250.			{
251.				SetTextValue(0,42,"无");		
252.			}else SetTextValue(0,42,"有");	
253.				////**
254.			if(duandian1[0] == 0x00)
255.			{
256.				SetTextValue(0,38,"无");		
257.			}else SetTextValue(0,38,"有");	
258.				////**
259.			if(huoyan1[0] == 0x00)
260.			{
261.				SetTextValue(0,57,"无");		
262.			}else SetTextValue(0,57,"有");	
263.			///////******
264.			if(yanwu1[0] == 0x00)
265.			{
266.				SetTextValue(0,55,"无");		
267.			}else SetTextValue(0,55,"有");
268.		}
269.		DEV_ID = 0;
270.	}

串口屏参数显示UI界面如下:

image-20221017103337-4.jpeg 人脸识别使用的是百度云识别方案,因为比较省事,不用在Linux板子上移植机器视觉算法。首先从百度云上下载SDK,下载Python-SDK版本。见地址

https://ai.baidu.com/ai-doc/FACE/ek37c1qiz

把SDK在Linux解包以后就得到目录

272.	├── README.md
273.	├── aip                   //SDK目录
274.	│   ├── __init__.py       //导出类
275.	│   ├── base.py           //aip基类
276.	│   ├── http.py           //http请求
277.	│   └── face.py //人脸识别
278.	└── setup.py              //setuptools安装

运行以下命令进行安装 

279.	python setup.py install 

SDK安装好以后,就可以编写代码了。其中一些API参数可以参考百度云脸识别文档,见地址

280.	https://ai.baidu.com/ai-doc/FACE/ek37c1qiz
281.	https://ai.baidu.com/ai-doc/FACE/yk37c1u4t

然后进行在百度云建立一个人脸识别的应用

8.jpg 然后点击应用列表,添加一个应用,我这里已经添加过了,然后点击可视化人脸库新建一个组,点击新建的组。

9.jpg

然后新建组以后,会看到新建用户,这里的用户就是需要对比的照片,一个照片算一张用户,这里的用户名注意不能写成英文,写成数字,英文均可。

新建应用以后就可以在应用列表中看到一个应用,见下图

image-20221017110138-2.png  人脸识别流程部分代码如下,此代码使用Linux开发板进行跑的,使用的是Python语言。如果使用下面提供的代码的话,需要在代码中更改APP_ID、API_KEY、SECRET_KEY这3个参数。

1.	import os 
2.	import sys 
3.	import re 
4.	from aip import AipFace 
5.	import urllib.request 
6.	import base64 
7.	import time 
8.	import serial 
9.	#百度人脸识别API账号信息 
10.	APP_ID = '245554564' 
11.	API_KEY = 'ZM6c6lrOo4554544PYMkK6rGNT' 
12.	SECRET_KEY ='GtqNyc5lepqI2y44545Y454dtFg6oasokSO0U' 
13.	client = AipFace(APP_ID, API_KEY, SECRET_KEY)#创建一个客户端用以访问百度云 
14.	#图像编码方式 
15.	IMAGE_TYPE='BASE64' 
16.	#用户组 
17.	GROUP = '2' 
18.	##串口通信 
19.	ser = serial.Serial('/dev/ttyUSB1',115200) 
20.	def Send_Message(): 
21.	# ser = serial.Serial('/dev/ttyUSB1',115200) 
22.	ser.write('Face_discern_successful'.encode()) 
23.	
24.	
25.	def Send_Message1(): 
26.	# ser = serial.Serial('/dev/ttyUSB1',115200) 
27.	ser.write('Face_discern_succeassfu'.encode()) 
28.	
29.	#照相函数 
30.	def getimage(): 
31.	os.system("fswebcam -d /dev/video0 -S 30 image1.jpg") 
32.	time.sleep(5) 
33.	
34.	
35.	#对图片的格式进行转换 
36.	def transimage(): 
37.	f = open('image1.jpg','rb') 
38.	img = base64.b64encode(f.read()) 
39.	# img = (f.read()) 
40.	return img 
41.	#上传到百度api进行人脸检测 
42.	def go_api(image1): 
43.	result = client.search(str(image1, 'utf-8'), IMAGE_TYPE, GROUP);#在百度云人脸库中寻找有没有匹配的人脸 
44.	# name = result['result']['user_list'][0]['user_id']#获取名字 
45.	# score = result['result']['user_list'][0]['score']#获取相似度 
46.	# print("欢迎%s 相似度%d!" % name %score) 
47.	if result['error_msg'] != 'SUCCESS': 
48.	result11 = result['error_msg'] 
49.	print("%s" %result11) 
50.	if result['error_msg'] == 'SUCCESS':#如果成功了 
51.	name = result['result']['user_list'][0]['user_id']#获取名字 
52.	score = result['result']['user_list'][0]['score']#获取相似度 
53.	if score > 60:#如果相似度大于80 
54.	if name == '1_Zhang': 
55.	print("欢迎%s,相似度为:%s !" %(name,score)) 
56.	time.sleep(3) 
57.	if name == '1_Zhang': 
58.	print("欢迎%s !" % name) 
59.	time.sleep(3) 
60.	if name == "_01quhao": 
61.	print("欢迎%s !" % name) 
62.	else: 
63.	print("对不起,我不认识你!") 
64.	name = 'Unknow' 
65.	return 0 
66.	curren_time = time.asctime(time.localtime(time.time()))#获取当前时间 
67.	
68.	#将人员出入的记录保存到Log.txt中 
69.	f = open('Log.txt','a') 
70.	f.write("Person: " + name + " " + "Time:" + str(curren_time)+'\n') 
71.	f.close() 
72.	return 1 
73.	if result['error_msg'] == 'pic not has face': 
74.	print('检测不到人脸') 
75.	time.sleep(2) 
76.	return 0 
77.	else: 
78.	#print(name+str(score)) 
79.	return 0 
80.	#主函数 
81.	if __name__ == '__main__': 
82.	while True: 
83.	print('准备') 
84.	if True: 
85.	getimage()#拍照 
86.	img = transimage()#转换照片格式 
87.	res = go_api(img)#将转换了格式的图片上传到百度云 
88.	
89.	if(res == 1):#是人脸库中的人 
90.	print("开门") 
91.	Send_Message() 
92.	else: 
93.	print("关门") 
94.	Send_Message1() 
95.	print('稍等三秒进入下一个') 
96.	time.sleep(2) 
对应的代码文件:
test.py (2.79 KB)
(下载次数: 0, 2022-10-17 11:07 上传)

人脸识别的程序设计流程如下图所示。人脸结果识别完以后,Linux板子通过串口将识别结果发送给宿舍管理员控制终端控制器,即STM32F7508—DK开发板,然后开发板根据识别结果驱动ZigBee协调器向对应宿舍发送指令。

10.jpg

 

四、作品源码

由于作品源码上传以后两天了,看还是没审核,所以把视频展示与代码放到一块,整理成百度云连接上传。代码也会当做附件放在帖子下面,由于视频比较大,就不放了。

总体代码.zip (32.02 MB)
(下载次数: 3, 2022-10-17 11:14 上传)

 

五、作品功能演示视频

 点击查看 >> 演示视频

 

六、项目总结

 经过这次项目学习我学会了如何用简单的方法实现人脸识别,以及使用ZigBee做一个小项目,将物联网与当前社会热点问题结合,使我明白了物联网给生活带来的方便,同时对物联网的发展有一定的思考。目前物联网的发展已经不是当初简单的终端设备+平台,目前IoT和AI技术紧密结合,能干的事越来越多,生活也越来越智能化。由于平时学习和工作忙没有时间发帖,作品是国庆假期期间憋出来的,发帖这方面和论坛其他坛友相比自己工作量有所不足,但是最终的作品来说,自己认为还是很有工作量的。由于时间原因,最终作品并不完美,大多数线都是用杜邦线连的,后续估计有时间会优化一些。这次申请的STM32F7508—DK性能很强大,资料也不少,后面有时间自己也会慢慢用这块板子做一些其他的事情。

回复评论 (1)

看了楼主的demo演示,确实考虑的挺周全的。

加油!在电子行业默默贡献自己的力量!:)
点赞  2022-11-16 11:35
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复