STM32F407ZE基于RT-Thread和ZigBee实现多传感器检测以及数据上传到oneNet

一、RT-Thread

1.简介

RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。

参考官方文档https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/an0038-nano-introduction

2.使用

声明任务线程、任务栈大小、任务函数

//任务线程
struct rt_thread smoke_thread;
struct rt_thread fire_thread;
struct rt_thread light_thread;
//任务栈
rt_uint8_t rt_smoke_thread_stack[512];
rt_uint8_t rt_fire_thread_stack[512];
rt_uint8_t rt_light_thread_stack[512];
//任务函数
void smoke_task_entry(void *parameter);
void fire_task_entry(void *parameter);
void light_task_entry(void *parameter);

创建线程以及开启线程调度

//初始化线程函数
void MX_RT_Thread_Init(void)
{
	//初始化线程
	/*
		静态线程对象
		线程名
		线程入口函数
		线程入口参数
		线程栈地址
		线程栈空间大小
		线程优先级
		线程时间片
		
	*/
	rt_thread_init(&smoke_thread,"smoke",smoke_task_entry,RT_NULL,&rt_smoke_thread_stack[0],sizeof(rt_smoke_thread_stack),2,60);
	rt_thread_init(&fire_thread,"fire",fire_task_entry,RT_NULL,&rt_fire_thread_stack[0],sizeof(rt_fire_thread_stack),3,60);
	rt_thread_init(&light_thread,"light",light_task_entry,RT_NULL,&rt_light_thread_stack[0],sizeof(rt_light_thread_stack),4,60);
	//开启线程调度
	rt_thread_startup(&smoke_thread);
	rt_thread_startup(&fire_thread);
	rt_thread_startup(&light_thread);
}

定义任务函数

//烟雾检测任务
void smoke_task_entry(void *parameter)
{
	//1000ms闪烁一次
	while(1)
	{
		Detect_Smoke();
		//异常
		if(!SmokeFlog){
			//对应指示灯亮起
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);
			//开启蜂鸣器
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_SET);
			
		}
		else{
			//对应指示灯熄灭
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);
			//均无异常关闭蜂鸣器
			if(SmokeFlog && FireFlag && LightFlag){
				HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_RESET);
			}
		}
		//延时1000ms
		rt_thread_mdelay(1000);
	}
}
//火焰检测任务
void fire_task_entry(void *parameter)
{
	//1000ms闪烁一次
	while(1)
	{
		Detect_Fire();
		//异常
		if(!FireFlag){
			//对应指示灯亮起
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
			//开启蜂鸣器
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_SET);
			
		}
		else{
			//对应指示灯熄灭
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);
			//均无异常关闭蜂鸣器
			if(SmokeFlog && FireFlag && LightFlag){
				HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_RESET);
			}
		}
		//延时1000ms
		rt_thread_mdelay(1000);
	}
}
//光照检测任务
void light_task_entry(void *parameter)
{
	//1000ms闪烁一次
	while(1)
	{
		Detect_Light();
		//异常
		if(!LightFlag){
			//对应指示灯亮起
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);
			//开启蜂鸣器
			HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_SET);
		}
		else{
			//对应指示灯熄灭
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET);
			//均无异常关闭蜂鸣器
			if(SmokeFlog && FireFlag && LightFlag){
				HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8,GPIO_PIN_RESET);
			}
		}
		//延时1000ms
		rt_thread_mdelay(1000);
	}
}

二、ZigBee

1.简介

ZigBee是一项新型的无线通信技术,适用于传输范围短数据传输速率低的一系列电子元器件设备之间。 ZigBee无线通信技术可于数以千计的微小传感器相互间,依托专门的无线电标准达成相互协调通信,因而该项技术常被称为Home RF Lite无线技术、FireFly无线技术。ZigBee无线通信技术还可应用于小范围的基于无线通信的控制及自动化等领域,可省去计算机设备、一系列数字设备相互间的有线电缆,更能够实现多种不同数字设备相互间的无线组网,使它们实现相互通信,或者接入因特网。

ZigBee译为"紫蜂",它与蓝牙相类似。是一种新兴的短距离无线通信技术,用于传感控制应用(Sensor and Control)。由IEEE 802.15工作组中提出,并由其TG4工作组制定规范。

ZigBee无线通信技术是基于蜜蜂相互间联系的方式而研发生成的一项应用于互联网通信的网络技术。 相较于传统网络通信技术,ZigBee无线通信技术表现出更为高效、便捷的特征。作为一项近距离、低成本、低功耗的无线网络技术,ZigBee无线通信技术其关于组网、 安全及应用软件方面的技术是基于IEEE批准的802 15.4无线标准。该项技术尤为适用于数据流量偏小的业务,可尤为便捷地在一系列固定式、便携式移动终端中进行安装,与此同时,ZigBee无线通信技术还可实现GPS功能。

ZigBee技术本质上是一种速率比较低的双向无线网络技术,其由IEEE.802.15.4无线标准开发而来,拥有低复杂度和短距离以及低成本和低功耗等优点。其使用了2.4GHz频段,这个标准定义了ZigBee技术在IEEE.802.15.4标准媒体上支持的应用服务。ZigBee联盟的主要发展方向是建立一个基础构架,这个构架基于互操作平台以及配置文件,并拥有低成本和可伸缩嵌入式的优点。搭建物联网开发平台,有利于研究成果的转化和产学研对,是实现物联网的 简单途径。

2.使用

把协调器与STM32F407的串口二进行相连,大约每五秒一次轮询接受终端发送的数据,再通过串口发送给STM32F407。STM32F407通过串口接受中断处理接受到的数据,再进行解析后通过esp8266WiFi模块通过透传的方式向oneNet服务器发送数据。

/接受中断处理回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//串口一
	if(huart==&huart1){
		com1[length1++]=c;
		if(com1[length1-2] == 0x0D && com1[length1-1] == 0x0A){
				HAL_UART_Transmit(&huart3, (uint8_t *)&com1, strlen(com1),0xFFFF);
				length1=0;
				printf("%s",com1);
				memset(com1,0,sizeof(com1));
		}

		//重新设置中断
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);  
	}
	
	//串口二
	else if(huart==&huart2){
		{
			com2[length2++]=c;
			if(length2>99){
				length2=0;
				memset(com2,0,sizeof(com2));
			}
			else{
				if(com2[length2-2] == 0x0D && com2[length2-1] == 0x0A){
					//获取温度
					t[0]=com2[2];
					t[1]=com2[3];
					t[2]='\r';
					t[3]='\n';
					//获取湿度
					h[0]=com2[6];
					h[1]=com2[7];
					h[2]='\r';
					h[3]='\n';
					SendDataFlag=1;
					//打印温湿度
					printf("温度: %d \t 湿度: %d",((com2[2]-'0')*10+(com2[3]-'0')),((com2[6]-'0')*10+(com2[7]-'0')));
					length2=0;
					memset(com2,0,sizeof(com2));

				}
			}
			
		}
					//重新设置中断
		HAL_UART_Receive_IT(&huart2, (uint8_t *)&c, 1); 
	}
	
	else if(huart==&huart3){
		buf[length3++]=c;
		if(buf[length3-2] == 0x0D && buf[length3-1] == 0x0A){
				for(int i=0;i<length3;i++){
						com3[i]=buf[i];
				}
				memset(buf,0,sizeof(buf));
				length3=0;
		}
		//重新设置中断
		HAL_UART_Receive_IT(&huart3, (uint8_t *)&c, 1); 
	}
}

main函数的while循环每500ms检测一次发送数据标志,当检测到后通过oneNet发送数据

while (1)
	{

		if(SendDataFlag==1){
			WIFI_SendTempData(t);
			memset(t,0,sizeof(t));
			WIFI_SendHumData(h);
			memset(h,0,sizeof(h));
			HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14);
			rt_thread_mdelay(500);
			HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14);
			rt_thread_mdelay(500);
			SendDataFlag=0;
		}
		rt_thread_mdelay(500);
	}

三、esp8266WiFi模块

WiFi模块连接在STM32F407串口三,当主线程接受到串口二发送的温湿度数据后通过WiFi模块发送数据到oneNet。
初始化WiFi模块

void WIFI_Init(void){
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT\r\n", strlen("AT\r\n"),0xFFFF);
	rt_thread_mdelay(100);
	printf("%s",com3);
	memset(com3,0,sizeof(com3));

	//配置成AP+STA模式
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+CWMODE=3\r\n", strlen("AT+CWMODE=3\r\n"),0xFFFF);
	rt_thread_mdelay(100);
	printf("%s",com3);	
	memset(com3,0,sizeof(com3));

	HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);
	
	//重启生效
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+RST\r\n", strlen("AT+RST\r\n"),0xFFFF);
	rt_thread_mdelay(5000);
	printf("%s",com3);
	memset(com3,0,sizeof(com3));

	HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
	
	//查询设备IP
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+CIFSR\r\n", strlen("AT+CIFSR\r\n"),0xFFFF);
	rt_thread_mdelay(1000);
	printf("%s",com3);
	memset(com3,0,sizeof(com3));

	//设置服务器IP地址端口号
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n", strlen("AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n"),0xFFFF);
	rt_thread_mdelay(2000);
	printf("%s",com3);
	memset(com3,0,sizeof(com3));

	HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);

	//开启透传模式
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+CIPMODE=1\r\n", strlen("AT+CIPMODE=1\r\n"),0xFFFF);
	rt_thread_mdelay(1000);
	printf("%s",com3);
	memset(com3,0,sizeof(com3));

	//开始透传
	HAL_UART_Transmit(&huart3, (uint8_t *)"AT+CIPSEND\r\n", strlen("AT+CIPSEND\r\n"),0xFFFF);
	rt_thread_mdelay(1000);
	HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_RESET);
}

发送数据
数据格式

POST /devices/设备ID/datapoints?type=5 HTTP/1.1
api-key: 设备密钥
Host:api.heclouds.com
Content-Length:数据长度

,;temp,89

void WIFI_SendTempData(char *data){
	HAL_UART_Transmit(&huart3, (uint8_t *)"POST /devices/你自己的设备ID/datapoints?type=5 HTTP/1.1\n", strlen("POST /devices/你自己的设备ID/datapoints?type=5 HTTP/1.1\n"),0xFFFF);
	HAL_UART_Transmit(&huart3, (uint8_t *)"api-key: 你自己的设备密钥\n", strlen("api-key: 你自己的设备密钥\n"),0xFFFF);
	HAL_UART_Transmit(&huart3, (uint8_t *)"Host:api.heclouds.com\n", strlen("Host:api.heclouds.com\n"),0xFFFF);
	HAL_UART_Transmit(&huart3, (uint8_t *)"Content-Length:10\n\n", strlen("Content-Length:10\n\n"),0xFFFF);
	HAL_UART_Transmit(&huart3, (uint8_t *)",;Temp,", strlen(",;Temp,"),0xFFFF);
	HAL_UART_Transmit(&huart3, (uint8_t *)data, strlen(data),0xFFFF);

}

四、传感器检测

MQ-2烟雾传感器

一般除了检测烟雾,还可以检测异常的气体,天然气,嘴巴哈气
工作电压:直流5伏

特点

  1. 具有信号输出指示。
  2. 双路信号输出(模拟量输出及TTL电平输出)
  3. TTL输出有效信号为低电平。(当输出低电平时信号灯亮,可直接接单片机)
  4. 模拟量输出0~5V电压,浓度越高电压越高。
  5. 对液化气,天然气,城市煤气有较好的灵敏度。
  6. 具有长期的使用寿命和可靠的稳定性
  7. 快速的响应恢复特性

读取

我们在使用的时候,为了获取气体浓度值,就通过连接模拟电压输出端,即可通过ADC把模拟信号转为数字信号,再对转换结果进行相应的判断。

#include "smoke.h"

double Smoke_Sensor_Value=0;
int SmokeFlog=1;

void Detect_Smoke(void){
	//启动ADC装换
	HAL_ADC_Start(&hadc1);  
	//等待转换完成,第二个参数是超时时间,单位是ms.
	HAL_ADC_PollForConversion(&hadc1, 50);  
	//判断转换完成标志位是否设置
	if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))  
	{
		/*开始获取转换值*/
		uint16_t value = HAL_ADC_GetValue(&hadc1);		
		Smoke_Sensor_Value=value/33.0;
//		printf("烟雾浓度为: %.2f\r\n",Smoke_Sensor_Value);
		//当烟雾指数高于20则触发异常
		if(Smoke_Sensor_Value>20){
			SmokeFlog=0;
		}
		else{
			SmokeFlog=1;
		}
	}
}

光敏电阻

使用STM32F407板子上面自带的光敏电阻进行检测

特点

光照时,电阻很小,无光照时,电阻很大,光照越强,电阻越小,光照停止,电阻又恢复原值。

读取

同样采用ADC进行转换再根据转换结果进行检测

#include "light.h"

double Light_Sensor_Value=0;
int LightFlag=1;
void Detect_Light(void){

	//启动ADC装换
	HAL_ADC_Start(&hadc3);  
	//等待转换完成,第二个参数是超时时间,单位是ms.
    HAL_ADC_PollForConversion(&hadc3, 50);  
	 //判断转换完成标志位是否设置
	if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc3), HAL_ADC_STATE_REG_EOC)) 
    {
      /*开始获取转换值*/
		uint16_t value = HAL_ADC_GetValue(&hadc3); 
		//光照越强,电压越小,光照百分比越大		
		Light_Sensor_Value=100*1.0-value*1.0/33;
//		printf("读取的光亮度为: %.2f\r\n",Light_Sensor_Value);
			//当光照百分比高于90或者低于30则触发异常
			if(Light_Sensor_Value>90 || Light_Sensor_Value<30){
				LightFlag=0;
			}
			else{
				LightFlag=1;

			}
    }
}

火焰传感器

特点

在这里插入图片描述

读取

根据传感器的文档介绍来看,只需要读取对应引脚的高低电平即可。

#include "fire.h"
#include "rtthread.h"
int FireFlag=1;

void Detect_Fire(void){
	//低电平正常
	if(HAL_GPIO_ReadPin(GPIOE,FIRE_Pin)==GPIO_PIN_RESET){
		FireFlag=1;
//		printf("正常\r\n");
	}
	//高电平异常
	 else if (HAL_GPIO_ReadPin(GPIOE,FIRE_Pin)==GPIO_PIN_SET){
		FireFlag=0;
//		printf("着火了\n");
	 }
}


五、效果

oneNet接受到的数据
在这里插入图片描述

六、源代码

https://github.com/TangtangSix/SensorDataCollection
https://gitee.com/tangtangsix/SensorDataCollection

概述 智能家居系统主要基于RT-threadZigBee开发,该系统主要分为五大部分,ZigBee无线传感器监控子系统,语音识别子系统,总控子系统,网关子系统,云端监控子系统。ZigBee无线传感器子系统通过各个传感器节点采集数据,将采集的数据通过无线网络系统传递给协调器,由协调器与总控系统进行数据交换,以完成数据的传递。总控系统通过网络将数据上传至网络,用户就能在远程进行查家中的各种环境信息,实时掌握家中的最新动态。语音识别子系统可实现人机交互,实现家电设备的智能化控制。网关子系统有两大作用,一是提供整个系统的网络;二是搭载摄像头来采集视频数据,实施远程监控的功能。云端监控子系统主要用于统计分析家中环境信息,通过可视化的界面了解家中最新动态。总控子系统为整个智能家居系统的核心所在,协调各个子系统正常运转。 开发环境硬件:ART-Pi,ZigBee终端,STM32F103最小系统板,MT7628最小系统板 传感器:DH11传感器,LD3320语音识别模块,SYN6288语音合成模块等 RT-Thread版本:RT-Thread V 4.0.3 开发工具及版本: MDK:5.30 Ubuntu:1604 IAR:8.20 RT-Thread使用情况概述该智能家居系统有两个子系统采用了RT-Thread系统,分别是语音识别子系统,总控子系统。 语音识别子系统使用的是RT-Thread Nano,使用了多线程,移植了FinSH组件,方便了该子系统调试。 总控子系统采用了完整版的RT-Thread系统,内核部分使用了调度器,信号量等;驱动部分使用了UART、SPI、BT、WiFi等;协议栈使用了MQTT等。软件包部分使用了Onenet、cJSON等。 系统架构本文所提出的智能家居系统解决方案整体框架如图所示。通过技术论证架构分析后,决定将系统划分为五个子系统:ZigBee无线传感器监控子系统,语音识别子系统,总控子系统,网关子系统,云端监控子系统。ZigBee无线传感器监控子系统通过各个传感器节点采集数据,将采集的数据通过无线网络系统传递给路由节点,再通过路由节点将收集的各个终端节点的数据进行二次传递给协调器,由协调器与总控系统进行数据交换,以完成数据的传递。总控系统通过无线网络将数据上传至网络,用户就能在远程进行查家中的各种环境信息,实时掌握家中的最新动态。语音识别子系统可实现人机交互,实现家电设备的智能化控制。网关子系统有两大作用,一是连接以太网;二是搭载摄像头采集视频数据,实施远程监控的功能。云端监控子系统主要用于统计分析家中环境信息,通过可视化的界面了解家中最新动态。总控子系统为整个智能家居系统的核心所在,协调各个子系统正常运转。 演示效果心得感悟通过本次比赛,我不仅丰富可项目实践经验,而且对RT-Thread有了深入的学习理解,我学习了RT-Thread的多线程及其调度、信号量、邮箱、消息队列、内存管理等,外设驱动以及各个组件等相关知识。通过这次比赛的项目实践,我又积累了不少调试经验,丰富了我的知识体系。 最后感谢主办方提供了这么好的一个平台,让我有机会展示自己,还让我学到很多知识。希望在以后的自己里也能为RT-Thread开源社区贡献自己的力量。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值