目录
总结:轮询用于以轮询方式发送数据,以防止数据争用。 以开发板为核心,需要定时器中断、外部中断、串口接受中断等资源。 定时器负责轮询发送到模块的关键字,并发送到每个终端节点上的模块。
任务目标
实现功能:
(1)实时检测并显示土壤湿度,需要浇水时自动开启灌溉系统。灌溉系统。 土壤湿度达到要求后。
(2)检测出二氧化碳浓度过高。 如果过高,则通过继电器打开通风、排气扇,并将二氧化碳浓度值发送至终端进行指示。
(3)实时检测并显示土壤pH超标情况。 可以随时进行提醒和提示。
(4)远程遥感与控制:传感器采集的信息通过LoRa模块发送至网关,网关有线连接通过WiFi模块发送到云端,您可以用APP随时查看温室内的二氧化碳浓度、土壤湿度、pH值。
(5) 系统正常运行在自动模式下。 如果需要更改参数,可以进入手动模式并使用电话和前端按钮更改手动控制并设置阈值。 更改后,它将根据新参数运行。
系统设计方案
该系统由三部分组成:LoRa节点、LoRa网关和智能手机。 整体结构如图2-1所示。 两个温室通过LoRa模块将数据发送到网关,网关将所有数据分类并上传到云端。
三个LoRa模块的通信逻辑设计
这次我们将使用Punctual Atom的LoRa模块。 具体设置请参考说明书。 为了方便起见,我使用的模式是广播。 要进行通信,您只需将三个 LoRa 模块设置为相同的地址、通道和速率即可。 由于采用广播模式,当一个模块发送一条指令时,另外两个模块都会接收到信息,因此开发板在接收到数据时必须进行验证过程。 轮询用于以轮询方式发送数据,以防止数据争用。 举例:设置终端节点A1、A2 的关键字为“DataA1”、“DataA2”。 网关向终端节点A1和A2发送关键字“DataA1”,同时接收关键字“DataA1”。 此时终端节点进入串口。 暂停期间,我们将确定您是否需要回复您的关键字。 如果终端A1判断为是,则将采集到的数据发送回网关。
LoRa转WiFi网关的设计与实现
网关的主要功能是接收终端节点的数据,通过WiFi模块将数据发送到云端,并提供。 转到终端节点。 使用STMF407作为核心开发板,需要定时器中断、外部中断、串口接受中断等资源。
按钮的任务是增加或减少发送阈值
串口2中断接受并处理LoRa模块发送的数据,串口3中断接受并处理LoRa模块发送的数据 WiFi模块发送的数据(设计思路与串口2相同)。
定时器4为负值它负责轮询并发送给LoRa模块,LoRa将关键字发送给各个终端节点的LoRa模块。 定时器3负责定期向WiFi模块发送数据,然后WiFi模块将数据发送到云端。
代码
LoRa模块初始化(部分)
#include " lora. h"void LoRa_Init( void){ GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF(RCC_AHB1Periph_GPIOF,启用);//启用GPIOC、GPIOF时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE) ;//启用SYSCFG时钟 GPIO_InitStructure. span>GPIO_Pin = GPIO_Pin_0; //MD0 引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M GPIO_InitStructure。 GPIO_PuPd = GPIO_PuPd_DOWN;//下拉 GPIO_Init(GPIOC , &GPIO_InitStructure);//初始化GPIOE2,3,4 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //AUX 引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式 GPIO_InitStructure .GPIO_Speed = GPIO_Speed_100MHz;/ / 100M GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉GPIO_Init(GPIOF<span class = “令牌标点”, &GPIO_InitStructure) //初始化 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOF, EXTI_PinSource6);//PC0连接到中断线0 /* Set EXTI_Line0 */ NVIC_InitStructure .NVIC_IRQChannel = EXTI9_5_IRQn;//外部中断0 span> NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00 ;//抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;/ /子优先级 2 NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; span>//启用外部中断通道 NVIC_Init( span >&NVIC_InitStructure);//设置 LORA_MD0=0; LORA_AUX=0; 同时(LORA_AUX)//确保LORA模块空闲(LORA_AUX=0) { lay_ms(100 ); } Lora_uart_init(115200);//初始化串口3LORA_MD0=1;//进入AT模式 lay_ms(15 );while(Lora_setCmd("AT/r/ n","确定", 0)); lay_ms(5);Lora_Clear ();lay_ms(5)5);while(Lora_setCmd("AT+ADDR=01,23/r/n","确定" ,0));lay_ms(5);而(Lora_setCmd("AT+WLRATE=24,5/r/n","OK ” ,0));lay_ms(5); LORA_MD0=0; //透明回车发送模式Lora_uart_init(9600);lay_ms(10) ;}
串口3接受中断
void USART3_IRQHandler () //串口3中断服务程序 {u8 Res;if( USART_GetITStatus(USART3, USART_IT_RXNE) != 重置) //接收中断(接收到的数据必须以0x0d 0x0a结尾){Res =USART_ReceiveData(USART3) ;//(USART1->DR);//读取接收到的数据 //printf("%d",Res);if(计数 == 0){Lora_Clear();}read_bufs[counts++] = Res;//确定格式if (Res == 0xfe){计数 = 0;}其他 if(Res == "}"){数字 = 0;USART_Cmd(USART3,禁用) ; //关闭#if 0 printf(" %s/r/n",read_bufs); #endifLora_Rx_data();//解析数据USART_Cmd(USART3,启用);//打开}如果(计数>>500 span> ){计数 = 0;}USART_ClearFlag(USART3, 美国ART_IT_RXNE); }}
串口 2 接受中断
void USART2_IRQHandler(void ) //串口2中断服务例程{ u8解析 ;if(USART_GetITStatus (USART2, USART_IT_RXNE) != 重置) //接收中断(接收到的数据必须以0x0d 0x0a结尾){Res =USART_ReceiveData(USART2);//(USART1->DR);//读取接收到的数据 if(counts_2 == 0){wifi_Clear();}read_bufs_HC[counts_2++] = Res; // 确定数据格式if(Res == "{"){counts_2 = 0;}else if (Res == "}"){counts_2 = 0;USART_Cmd(USART2, 禁用); //关闭printf("%s/r/n",read_bufs_HC) ;HC25_Rx_Data( ); //解析数据USART_Cmd (USART2,启用);//打开} if span>(counts_2>200){counts_2 = 0; }USART_ClearFlag(USART2, USART_IT_RXNE ); } }
定时器3中断
void TIM3_IRQHandler(span>void){if(TIM_GetITStatus( TIM3,TIM_IT_Update)==SET) //溢出中断{ if(STA==0 ){//Jason数据格式sprintf(jason," {/n " "/"CO2_1/":%d," "/"CO2pre_1/":%d," "/"PH_1/":%d," "/"PHpre_1/":%d," "/"SoilHum_1/":%d," "/"SoilHumpre_1/":%d," "/"CO2_2/":%d," "/"CO2pre_2/":%d," "/"PH_2/":%d," " /“PHpre_2/”:%d," "/"SoilHum_2/":%d," "/"SoilHumpre_2/":%d ""/n}",数据。 CO2_data,数据。CO2_data_Pre,数据<span class= “令牌标点”。PH,数据。PH_Pre , 数据。土壤,数据。 Soil_Pre,data1ctuation">.CO2_data,data1.CO2_data_Pre,data1.PH,data1.PH_Pre,data1。土壤,data1.Soil_Pre);HC25_setData(jason); //发送数据}}TIM_ClearITPendingBit( TIM3,TIM_IT_Update); //清除中断标志}
定时器4中断
void TIM4_IRQHandler( void){char tx_buff[80];字符 tx_buf2[80];if(TIM_GetITStatus (TIM4,TIM_IT_Update)==SET) //溢出中断 {TX_time++; //轮询标志开关 (TX_time){case TX_TIME://等于1if(TX_1){//判断预置发送标志的值sprintf(tx_buff, span>"0xfeDATA:%d:%d:%d:%d:%d:%d}", CO2Pre1, SoilPre1, PHPre1, Water_IT1,Fan_IT1,Beef_IT1);Lora_setData(tx_buff);TX_1=0TXcope1=1;}其他Lora_setData("0xfeTX1:A}/r/n ");//轮询关键字1中断;case TX_TIME+TIME_ADD://等于2 if(TX_2){//确定默认值发送标志 sprintf(tx_buf2,"0xfedataer:%d:%d:%d:%d:%d: %d}",CO2Pre2,SoilPre2,span>PHPre2、Water_IT2、Fan_IT2、Beef_IT2 );Lora_setData( tx_buf2);TX_2= 0;TXcope2=1;} span> else Lora_setData("0xfetxer:b}/r/n"); TX_time=0;//round查询标志位break;默认: 中断;}}TIM_ClearITPendingBit (TIM4,TIM_IT_Update); //清除中断标志}
如有疑问请私信或评论区留言-_-
评论前必须登录!
注册