基于ESP8266的环境监测系统

简介: 基于ESP8266的环境监测系统

项目代码下载:

代码下载 效果如视频中演示

各种模块的混合使用

(1)温度、湿度的测量;             DHT11
(2)温度、湿度等参数的显示;         LCD屏幕
(3)报警数据的设定(按键);           EXIT中断服务函数
(4)温度、湿度控制;                风扇,舵机,加热片模块
(5)数据传输(无线通信传输);           ESP8266
(6)声光报警提醒。
                LED,蜂鸣器

注:本文在正点原子的ESP8266的代码上进行了一些额外操作来完成一些功能,以便自己更加了解这些模块的套用

模块1:DHT11

DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,并与一个高性能 8

位单片机相连接。通过单片机等微处理器简单的电路连接就能够 实时的采集本地湿度和温度。DHT11

与单片机之间能采用简单的单总线进行通信,仅仅需要一 个 I/O 口。传感器内部湿度和温度数据 40Bit

的数据一次性传给单片机,数据采用校验和方式 进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大 电流

0.5mA。

也就是如果在低电平持续12-14us后,高电平被拉高26-28us,代表这一位是0。

如果在低电平持续12-14us后,高电平被拉高116-118us,代表这一位是1。

以上便是DHT11的简单介绍,网络上不缺乏DHT11的代码,就不贴出。(正点原子永远的神)

模块2:LCD显示温湿度

TFTLCD的配置,正点原子已经为我们配置好了(ESP8266代码自带屏幕),而要做到显示温度,我们就必须先得到温度,得到温度后通过函数显示在屏幕上。具体操作如下

sprintf((char*)p,"t%s%02dh%s%02dtr%s%02d%02dhr%s%02d%02d\r\n",CHARACTER[0],temperature_t,CHARACTER[0],humidity_t,CHARACTER[0],setval_l,setval_h,CHARACTER[0],setvall_l,setvall_h);//测试数据  CHARACTER[0]是 = 号
            Show_Str(30+54,100,400,12,p,12,0);
• 1
• 2

模块3:报警数值的设定(按键控制)

我们知道既然要对一个数值进行报警设定,那么它可能就是超过了某个数值范围,因此我们需要定义上下限值,且上下限的值可以调节,这就需要用到板子上的四个按键。那么如何通过检测按键来改变范围呢,这就需要用到按键的中断服务函数。

简单介绍,STM32的一部分外设对应着一些中断线,当你配置了这些中断线所对应的IO口,那么当这些外设被检测到触发后,便会触发中断服务函数,并进入其中执行相应的代码,代码结束后便会跳出服务函数继续执行下面的代码。正是这一点使得继续进入了中断服务函数也不会干扰程序的正常运行。代码如下:

#include "exti.h"
#include "delay.h" 
#include "led.h" 
#include "key.h"
//   
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//外部中断 驱动代码    
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/5/4
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved                   
// 
//外部中断0服务程序
extern u8 setval_h;
extern u8 setval_l;
extern u8 setvall_h;
extern u8 setvall_l;
void EXTI0_IRQHandler(void)
{
  delay_ms(10); //消抖
  if(WK_UP==1)   
  {
setvall_h+=2;
  }    
   EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 
} 
//外部中断2服务程序
void EXTI2_IRQHandler(void)
{
  delay_ms(10); //消抖
  if(KEY2==0)   
  {        
setvall_l-=2;
  }    
   EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE2上的中断标志位 
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)
{
  delay_ms(10); //消抖
  if(KEY1==0)  
  {
  }    
   EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
}
//外部中断4服务程序
void EXTI4_IRQHandler(void)
{
  delay_ms(10); //消抖
  if(KEY0==0)  
  {        
setval_l+=2;
  }    
   EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位  
}
//外部中断初始化程序
//初始化PE2~4,PA0为中断输入.
void EXTIX_Init(void)
{
  NVIC_InitTypeDef   NVIC_InitStructure;
  EXTI_InitTypeDef   EXTI_InitStructure;
  KEY_Init(); //按键对应的IO口初始化
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//PE2 连接到中断线2
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE3 连接到中断线3
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//PE4 连接到中断线4
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PA0 连接到中断线0
  /* 配置EXTI_Line0 */
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
  EXTI_Init(&EXTI_InitStructure);//配置
  /* 配置EXTI_Line2,3,4 */
  EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
  EXTI_Init(&EXTI_InitStructure);//配置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级0
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断2
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;//抢占优先级3
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断3
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置
  NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);//配置   
}

通过检测按键来执行温度上下限的改变。

模块4:温湿度控制

使用风扇降温,使用加热片升温,使用舵机挤压喷壶喷水加湿。

风扇和加热片都非常简单,给个电平便开始工作,主要的是舵机的配置与使用。

舵机接收的是PWM信号,能使舵机内部电路产生一个偏置电压,触发电机通过减速齿轮带动电位器移动,当电压差为零时,电机停转,从而达到伺服的效果。

即,给舵机提供一个特定的PWM信号,舵机就可以旋转到指定的位置。

舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。

为了更好地理解其信号,和编写代码,把PWM关键点转换如下:

PWM信号周期: 20000us

0度时,高电平时长: 500us

180度时, 高电平时长:2500us

每增加1 °,需增加高电平时长:(2500-500)÷180 = 11.1us

某角度值A,需要的总高电平时长:(A x11.1 +500)us

特别地说明: 把所有ms值, 转换为us值, 是为了方便代码的编写和理解.

————————————————

原文链接:https://blog.csdn.net/zhouml_msn/article/details/116142124

#include "PWM.h"
#include "led.h"
void TIM1_PWM_Init(u32 arr,u32 psc)
{              
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);   //TIM1????    
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);   //??PORT??  
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); //GPIOA8??????1
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11;           //GPIOF9
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //????
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //??100MHz
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //??????
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //??
  GPIO_Init(GPIOA,&GPIO_InitStructure);              //???PA
  TIM_TimeBaseStructure.TIM_Period=arr;   //??????
  TIM_TimeBaseStructure.TIM_Prescaler=psc;  //?????
  TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //??????
  TIM_TimeBaseStructure.TIM_ClockDivision=0;  //TIM_CKD_DIV1; 
  TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//??????1
  //???TIM14 Channel1 PWM??  
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //???????:TIM????????2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //??????
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //????:TIM???????
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);//??T??????????TIM1 4OC1
  TIM_OC4Init(TIM1, &TIM_OCInitStructure);
  TIM_CtrlPWMOutputs(TIM1,ENABLE);
  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //??TIM1?CCR1????????
  TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE?? 
  TIM_Cmd(TIM1, ENABLE);  //??TIM1  
  int main()
  {
TIM1_PWM_Init(200-1,8400-1);  //84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 
1M/2000=50hz.     
} 
        TIM_SetCompare1(TIM1,190);           //??0?
                delay_ms(500);
          TIM_SetCompare1(TIM1,185);           //????45?    (???)
                delay_ms(500);
                TIM_SetCompare1(TIM1,180);           //????90?
                delay_ms(500);
                TIM_SetCompare1(TIM1,175);           //????135?
                delay_ms(500);
                TIM_SetCompare1(TIM1,170);           //????180?
                delay_ms(500);          
}

PSC:TIM时钟的分频系数:内部时钟经PSC值分频后, 传给CNT计数器使用;

CNT:计数器,CNT每计数一次的脉冲时长为:1÷(CLK÷PSC)

ARR:自动重装载值:CNT计数器经过多少次脉冲就重新开始计数。用这个值可控制需要的PWM信号周期

CCR:用于控制周期内高电平时长, 当CNT<CCR时, 为有效电平. 而有效电平的高低, 则是通过CCER寄存器设置的, 默认的有效电平为高电平.通过TIM_SetCompare设置.

知道了以上这些,假设我们设置CCRx为190,低电平输出,那么低电平时间为190/200*20ms=19ms,高电平为1s。这便是舵机的基础配置。

模块5:ESP8266 WIFI模块

我选择的是使用STA WIFI模式,因此我们进入相应的代码部分

通过再这段代码下面的代码进行修改,便可以做到通过再上位机发送指令来控制相应的外设。

while(1)
          {
          if(timex==0)    //TCP Server
          { 
            DHT11_Read_Data(&temperature_t,&humidity_t);    //读取温湿度值            
            if(setval_l<temperature_t<setval_h||setvall_l<humidity_t<setvall_h)  // 20
            {
            GPIO_ResetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
            //GPIO_SetBits(GPIOF,GPIO_Pin_8);//蜂鸣器叫
              //delay_ms(2000);
              //GPIO_SetBits(GPIOF,GPIO_Pin_8);//亮灯
            GPIO_SetBits(GPIOF,GPIO_Pin_8);//  控制蜂鸣器
            }
            //  BEEP_Init();
            //GPIO_ResetBits(GPIOF,GPIO_Pin_8); //蜂鸣器对应引脚 GPIOF8 拉低,
            //GPIO_ResetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
            sprintf((char*)p,"t%s%02dh%s%02dtr%s%02d%02dhr%s%02d%02d\r\n",CHARACTER[0],temperature_t,CHARACTER[0],humidity_t,CHARACTER[0],setval_l,setval_h,CHARACTER[0],setvall_l,setvall_h);//测试数据
            Show_Str(30+54,100,400,12,p,12,0);
            atk_8266_send_cmd("AT+CIPSEND=0,25","OK",200);  //发送指定长度的数据
            delay_ms(200);
            atk_8266_send_data(p,"OK",100);  //发送指定长度的数据
            timex=1000;
            time=0;
          }
        //else
        //  time=time+1;    
        if(timex)timex--;
        if(timex==1)LCD_Fill(30+54,100,239,112,WHITE);
        t++;
        delay_ms(10);
        if(USART3_RX_STA&0X8000)    //接收到一次数据了
        { 
          rlen=USART3_RX_STA&0X7FFF;  //得到本次接收到的数据长度
          USART3_RX_BUF[rlen]=0;    //添加结束符 
          printf("%s",USART3_RX_BUF); //发送到串口   
          sprintf((char*)p,"收到%d字节,内容如下",rlen);//接收到的字节数 
          LCD_Fill(30+54,115,239,130,WHITE);
          POINT_COLOR=BRED;
          Show_Str(30+54,115,156,12,p,12,0);      //显示接收到的数据长度
          POINT_COLOR=BLUE;
          LCD_Fill(30,130,239,319,WHITE);
          Show_Str(30,130,180,190,USART3_RX_BUF,12,0);//显示接收到的数据
          //if(strcmp((const char*)(USART3_RX_BUF+11),"0")==0)LED1=0;          //打开LED1 
          //if(strcmp((const char*)(USART3_RX_BUF+11),"1")==0)LED1=1;        //关闭LED1
          //if(strcmp((const char*)(USART3_RX_BUF+11),"2")==0)LED1=0;        //打开LED1
         // if(strcmp((const char*)(USART3_RX_BUF+11),"1")==0)LED1=1;        //关闭LED1
          if(USART3_RX_BUF[11]==0)  //0
          {
          LED0=0; //亮灯
          GPIO_SetBits(GPIOF,GPIO_Pin_1);//GPIOF9,F10设置高,灯灭 风扇开启  
          }
          else if(USART3_RX_BUF[11]==1)  //1
          {
          LED0=1;   //灭灯
          GPIO_ResetBits(GPIOF,GPIO_Pin_1);//GPIOF9,F10设置高,灯灭
          }
          else if(USART3_RX_BUF[11]==2) 
          {
          LED1=0;
          GPIO_ResetBits(GPIOF,GPIO_Pin_3);//GPIOF9,F10设置高,灯灭  开启加热片
          }
          else if(USART3_RX_BUF[11]==3)
          { 
          LED1=1;
          GPIO_SetBits(GPIOF,GPIO_Pin_3);//GPIOF9,F10设置高,灯灭
          }
          else if(USART3_RX_BUF[11]==4)     //等于4喷水
          {    TIM_SetCompare1(TIM1,190);           //??0?
                delay_ms(500);
                TIM_SetCompare1(TIM1,185);           //????45?    (???)
                delay_ms(500);
                TIM_SetCompare1(TIM1,180);           //????90?
                delay_ms(500);
                TIM_SetCompare1(TIM1,175);           //????135?
                delay_ms(500);
                TIM_SetCompare1(TIM1,170);           //????180?
                delay_ms(500);
                TIM_SetCompare1(TIM1,175);           //????45?,??135????
                delay_ms(500);
                TIM_SetCompare1(TIM1,180);           //?????90????
                delay_ms(500);
                TIM_SetCompare1(TIM1,185);           //??45?
                delay_ms(500);
                TIM_SetCompare1(TIM1,190);           //??0?
                delay_ms(500);
          }
          else;
          USART3_RX_STA=0;
          if(constate!='+')t=1000;    //状态为还未连接,立即更新连接状态
          else t=0;                   //状态为已经连接了,10秒后再检查
        }  
        if(t==1000)//连续10秒钟没有收到任何数据,检查连接是不是还存在.
        {
//      //    LCD_Fill(30+54,125,239,130,WHITE);
//          LCD_Fill(60,80,120,92,WHITE);
          constate=atk_8266_consta_check();//得到连接状态
          if(constate=='+')Show_Str(30+30,80,200,12,"连接成功",12,0);  //连接状态
          else Show_Str(30+30,80,200,12,"连接失败",12,0);    
          t=0;
        }
        //if((t%20)==0)LED0=!LED0;
        atk_8266_at_response(1);
      }

模块6:声光报警提醒(蜂鸣器,LED)

蜂鸣器和LED灯的配置过于简单,给个电平即可。

总结:

以上便是全部内容,本篇文章只是大概提供一些模块嵌套使用思路,内容简单,希望能对大家有所帮助。附上视频链接

使用ESP8266wifi模块控制开发板上的各种外设


相关文章
|
5月前
|
传感器 数据采集 数据处理
基于STM32的温湿度监测系统设计与实现
基于STM32的温湿度监测系统设计与实现
732 1
|
5月前
|
网络协议 数据处理 数据格式
51单片机ESP8266云端通信的实现
51单片机ESP8266云端通信的实现
374 1
|
5月前
|
物联网
STC51单片机-中断控制LED-物联网应用系统设计项目开发
STC51单片机-中断控制LED-物联网应用系统设计项目开发
81 0
|
12月前
ESP-01S连接OneNET上报温湿度信息
本文介绍了如何利用ESP-01S连接OneNET上报温湿度信息,其中包括如何烧录固件,如何配置OneNET平台,如何进行连接测试。最后,给出了一部分程序设计。
273 0
ESP-01S连接OneNET上报温湿度信息
|
传感器 网络协议 物联网
基于STM32设计的智能家居系统(采用ESP8266+OneNet云平台)
基于STM32设计的智能家居系统(采用ESP8266+OneNet云平台)
1415 1
基于STM32设计的智能家居系统(采用ESP8266+OneNet云平台)
|
5月前
|
传感器 数据采集 监控
船用低速发动机缸压在线监测系统
船用低速发动机缸压在线监测系统
33 3
|
传感器 编解码 物联网
STC89C52+DHT20设计的环境温湿度检测仪
本项目基于STC89C52单片机和DHT20温湿度传感器,实现了一款环境温湿度检测仪。通过传感器采集环境的温度和湿度数据,利用IIC接口的OLED显示屏显示出来,便于用户实时监测环境温湿度状态。
176 1
|
5月前
|
传感器 物联网
esp8266cp2102的远程控制代码有没有节能好用的
esp8266cp2102的远程控制代码有没有节能好用的
|
物联网
工程监测无线中继采集仪的寄存器(参数)汇总详解
无线中继采集发送仪有很多参数(寄存器),对于一些简单的应用,用户无需关心这些参数,使用默认参数值即可。仅列出较为常用的参数,当需要配置设备完成复杂、特殊的应用时,请查看“无线中继采集发送仪寄存器汇总说明” 。
工程监测无线中继采集仪的寄存器(参数)汇总详解
|
数据采集 运维 监控
NLM无线无源采发仪与DLS11网关组成的岩土工程监测解决方案
NLM无线无源采发仪是一种基于无线射频技术的数据采集设备,无需外接电源(内置电池),通过接收外部无线信号实现能量采集和数据传输,广泛应用于工业、安防、环保等领域。在岩土工程监测中,NLM无线无源采发仪可以用于测量地表运动、土体沉降、土压力等参数,减少了布线和维护的成本和难度。
NLM无线无源采发仪与DLS11网关组成的岩土工程监测解决方案