赞
踩
RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。适用于家电、消费电子、医疗设备、工控等领域大量使用的 32 位 ARM 入门级 MCU 的场合。
参考官方文档https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-nano/an0038-nano-introduction
//任务线程
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是一项新型的无线通信技术,适用于传输范围短数据传输速率低的一系列电子元器件设备之间。 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联盟的主要发展方向是建立一个基础构架,这个构架基于互操作平台以及配置文件,并拥有低成本和可伸缩嵌入式的优点。搭建物联网开发平台,有利于研究成果的转化和产学研对,是实现物联网的 简单途径。
把协调器与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); }
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);
}
一般除了检测烟雾,还可以检测异常的气体,天然气,嘴巴哈气
工作电压:直流5伏
我们在使用的时候,为了获取气体浓度值,就通过连接模拟电压输出端,即可通过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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。