跟着我完成一个简单的项目:物联网环境监测系统esp8266+stm32(持续更新中)

目录

概要

 效果图展示

整体架构流程

esp8266模块初始化

ADC数据采集函数

DHT11 模块采集

stm32与esp8266上下行通信

esp8266_send_cmd

esp8266_config_network

esp8266_receive_msg

阿里云平台相关配置

系统功能解释

按键篇        

技术细节

小结

概要

本题研究基于STM32f103c8t6开发板,设计一个集成温湿度、光照、烟雾、噪声等多种环境传感器的物联网智能仓库环境管理系统。传感器实时采集仓库环境中的关键数据,并通过WIFI模块(ESP8266)将数据传输至远程服务器或云平台,实现远程监控、数据存储与分析。当仓库环境数据超出设定的安全阈值时,系统自动发出报警或做出相应操作,提醒管理者采取措施。

核心内容包括:数据采集、数据传输、数据报警与处理、硬件电路搭建

使用到的软件:Keill5、STM32CubeMX、浏览器、ESP8266 Flash Download Tool工具、sscom串口工具 

 效果图展示

整体完成效果(后续会制作pcb优化走线,请持续关注)

运行效果

阿里云平台端实时数据显示
阿里云平台端实时数据显示
手机端云智能app数据显示、控制功能展示

整体架构流程

如果你看到了这里,想必对本项目也有了 一定的了解,下面我来讲述一下本项目的实现原理。

        本系统采用分层架构设计,其中STM32微控制器作为数据采集单元,负责从连接的传感器中周期性地收集环境参数,并将原始数据进行初步处理后,通过串行通信接口(UART)按照预定义的协议发送至网络传输单元——ESP8266 Wi-Fi模块。

        ESP8266模块扮演着网关的角色,它接收来自STM32的数据包,对其进行解析并转换为符合JSON标准的数据格式,随后利用其内置的Wi-Fi功能将这些结构化的信息上传到指定的云服务平台。在此过程中,ESP8266确保了数据的安全性和完整性,并管理与云端的TCP/IP连接,实现可靠的数据传输。

esp8266模块初始化

        首先启动ESP8266 Flash Download Tool工具进行 (1471)ESP8266-AT_MQTT-1M.bin固件的烧写,这个固件包含了预编程的AT指令集,允许用户通过发送简单的文本命令来配置和控制模块的功能。在使用之前烧写这样的固件文件是为了确保模块按照预期工作,并且能够满足项目的特定需求。

        烧写完成之后就可以用串口工具对模块进行测试,以串口的形式传送at指令,测试esp8266模块的联网功能。

ADC数据采集函数

//ADC传感器的读取
	{
			lux_value = adc_read();			//5516光线传感器读值
			ppm_value = adc_read();	  	//mq2气体传感器读值
			sy01_value = adc_read();			//sy01噪声传感器读值
	}

//上述代码中的adc_read()函数的解释,通过for循环,依次读取定义的三个adc输入端口

uint16_t adc_read()
{
	int i;
			for(i=0;i<3;i++)
		{
			HAL_ADC_Start(&hadc1);
			HAL_ADC_PollForConversion(&hadc1, 10);
			adc_value [i] = HAL_ADC_GetValue(&hadc1);
			return adc_value[i];
		}
}

STM32CubeMX中adc输入端口配置

DHT11 模块采集

由于DHT11传感器模块读取数据的方式较为特殊,因此单独列出其数据采集函数。

         微控制器想要采集DHT11传感器数据,必须先将数据线拉低至少18毫秒以发送开始信号,然后将数据线拉高并等待DHT11响应。DHT11检测到主机发出的开始信号后,会拉低数据线大约80微秒作为应答信号,随后再将数据线拉高80微秒准备发送数据。DHT11会依次发送40位数据,每位数据由50微秒的低电平和不同长度的高电平组成。高电平的时间长度决定了该位是0还是1。40位数据包括湿度整数部分(8位)、湿度小数部分(8位)、温度整数部分(8位)、温度小数部分(8位)以及校验和(8位)。校验和是前四个字节的二进制加和的最低8位。如果接收到的数据中这五个字节的和的最低8位为0,那么说明数据传输无误;否则,可能存在错误。

//此处仅列举主要函数
uint8_t dht11_read_data(uint8_t *temp,uint8_t *humi)
{
  uint8_t buf[5];
  uint8_t i;
  dht11_rst();//DHT11端口复位,发出起始信号
  if(dht11_check()==0)
  { //等待DHT11回应
    for(i=0;i<5;i++)
    {//读取5位数据
      buf[i]=dht11_read_byte(); //读出数据
    }
    if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
    {	//数据校验
      *humi = buf[0]; //将湿度值放入指针1
      *temp = buf[2]; //将温度值放入指针2
    }
  }
  else 
  {
    return 1;
  }
  return 0;
}




/**
  * @brief          DHT11端口复位,发出起始信号(IO发送)
  * @param[in]      none
  * @retval         none
  */
void dht11_rst (void)
{
	dht11_io_out();
	HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin, GPIO_PIN_RESET);
	HAL_Delay(20); //拉低至少18ms
	HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin, GPIO_PIN_SET);
	delay_us(30); //主机拉高20~40us
}






**
  * @brief          等待DHT11回应
  * @param[in]      none
  * @retval         返回1:未检测到DHT11,返回0:成功(IO接收)
  */
uint8_t dht11_check(void)
{ 
  uint8_t retry=0;
  dht11_io_in();//IO到输入状态
  while (HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin)&&retry<100)
  {//DHT11会拉低40~80us
    retry++;
    delay_us(1);
  }
  if(retry>=100)return 1; else retry=0;
  while (!HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin)&&retry<100)
  {//DHT11拉低后会再次拉高40~80us
    retry++;
    delay_us(1);
  }
  if(retry>=100)return 1;
  return 0;
}






/**
  * @brief          从DHT11读取一个字节  
  * @param[in]      none
  * @retval         返回值:读到的数据
  */
uint8_t dht11_read_byte(void)
{
	uint8_t i,dat;
    dat=0;
    for (i=0;i<8;i++){
        dat<<=1;
        dat|=dht11_read_bit();
    }
    return dat;
}

 dht11_read_data函数使用方法

int main(void)
{
    while(1)
        {
            dht11_read_data(&temp_value,&humi_value);    //假设你已经定义温湿度数据接收对象
        }
}

   

stm32与esp8266上下行通信

上传数据:通过格式化数据为JSON格式并使用AT+MQTTPUB命令发布到指定的MQTT主题。

接收数据:通过订阅特定的MQTT主题,接收来自云端的消息,解析这些消息中的JSON数据,并更新设备状态

  • esp8266_send_cmd
  • esp8266_send_cmd函数用于向ESP8266发送AT命令,并等待响应。它使用HAL_UART_Transmit发送命令,并通过检查receive_start标志位来判断是否收到响应。esp8266_send_msg函数通过AT+MQTTPUB命令将数据发布到指定的MQTT主题。
  • /**
      * @brief          向esp8266发送命令函数,成功返回0,失败返回1
      * @param[in]      cmd:发送的命令,len:命令的长度,rec_data:期望接收数据
      * @retval         none
      */
    uint8_t esp8266_send_cmd(unsigned char *cmd,unsigned char len,char *rec_data)	
    {
      unsigned char retval =0;
      unsigned int count = 0;
    
      HAL_UART_Transmit(&huart2, cmd, len, 1000);	                                   
      while((receive_start == 0)&&(count<1000))
      {
        count++;
        HAL_Delay(1);
      }
    
      if(count >= 1000)	
      {
        retval = 1;	
      }
      else	
      {
        do
        {
          receive_finish++;
          HAL_Delay(1);
        }
        while(receive_finish < 500);
        retval = 2;
        if(strstr((const char*)receive_buf, rec_data))	
        {
          retval = 0;	
        }
      }
      uart2_receiver_clear(receive_count);
      return retval;
    }

  • esp8266_config_network
  • esp8266_config_network函数通过发送AT+CWJAP命令配置ESP8266连接到指定的Wi-Fi网络。
    /**
      * @brief          esp8266配置wifi网络
      * @param[in]      none
      * @retval         网络配置成功返回0,否则返回1
      */
    uint8_t esp8266_config_network(void)
    {
    	uint8_t retval =0;
    	uint16_t count = 0;
    	
    	HAL_UART_Transmit(&huart2, (unsigned char *)"AT+CWJAP=\""WIFI_SSID"\",\""WIFI_PASSWD"\"\r\n",strlen("AT+CWJAP=\""WIFI_SSID"\",\""WIFI_PASSWD"\"\r\n"), 1000);
    	
    	while((receive_start == 0)&&(count<1000))
    	{
    		count++;
    		HAL_Delay(1);
    	}
    	
    	if(count >= 1000)	
    	{
    		retval = 1;	
    	}
    	else
    	{
    		HAL_Delay(8000);
    		if(strstr((const char*)receive_buf, "OK"))	
    		{
    			retval = 0;	
    		}
        else
        {
          retval = 1;
        }
    	}
      uart2_receiver_clear(receive_count);
    	return retval;
    }

  • esp8266_receive_msg
  • esp8266_receive_msg函数处理从MQTT订阅的主题接收到的消息,解析JSON数据并更新设备状态。
    /**
      * @brief          通过esp8266接收数据   接收来自MQTT代理服务器的控制消息,并解析这些消息。
      * @param[in]      none
      * @retval         返回0接收数据正常,返回1接收数据异常或无数据
      */
    uint8_t esp8266_receive_msg(void)	
    {
      uint8_t retval =0;
    	int msg_len=0;
    	uint8_t msg_body[128] = {0};
      
    	if(receive_start == 1)	
    	{
    		do
        {
    			receive_finish++;
    			HAL_Delay(1);
    		}
        while(receive_finish < 5);	
    		
    		if(strstr((const char*)receive_buf,"+MQTTSUBRECV:"))
    		{
    			sscanf((const char *)receive_buf,"+MQTTSUBRECV:0,\""SUB_TOPIC"\",%d,%s",&msg_len,msg_body);
          printf("len:%d,msg:%s\r\n",msg_len,msg_body);
    			if(strlen((const char*)msg_body)== msg_len)
    			{
            retval = parse_json_msg(msg_body,msg_len);
    			}
          else
          {
            retval = 2;
          }
    		}
        else 
        {
          retval = 2;
        }
    	}
      else
      {
        retval = 2;
      }
      uart2_receiver_clear(receive_count);	
      return retval;
    }
  •         上述极端代码仅展示STM32如何通过UART与ESP8266模块进行串口通信,实现Wi-Fi连接和MQTT协议的应用。通过发送AT命令控制ESP8266的行为,接收ESP8266的响应,并处理MQTT消息,STM32能够实现远程控制和数据传输的功能。整个过程涉及到串口通信的配置、数据的发送与接收、以及对ESP8266响应的解析和处理。 

    最后放一张主函数程序图

    阿里云平台相关配置

  • 登录阿里云平台,左上角找到产品——物联网——生活物联网平台(飞燕平台),在飞燕平台中新建自己的项目、添加产品,并且在功能定义选项卡下根据实际项目添加功能。
  •  人机交互选项卡下选择云智能app控制,产品展示选项卡随意填写即可,下方的设备面板选项卡中,可根据实际需要显示的数据功能添加数据可视化界面。产品说明书选项卡下的“下载配网二维码”中输入所对应的设备名称即可获得配对二维码,用于云智能app的设备配对。
  • 设备调试选项卡,在此选项卡中可以新建设备选项,在此处显示的productkey、devicesecret、devicename、是mqtt协议连接三要素,十分重要,填写到代码中esp8266.c相应位置,作为wifi模块上云要素。
  •  最后一步批量投产选项卡中点击发布产品,即可完成产品发布,完成此步骤后可以用云智能app进行配网连接。
  • 系统功能解释

    按键篇        

            对于本项目暂时设置了四枚按键,在函数中的名称分别为button_mode、button_enter、button_up、button_down。

            程序上电运行后首先运行在main_manual(手动模式),在本模式中,系统自动采集环境数据并且上传至云端,通过app可以进行数据读取或者进行灯光功能、舵机功能的控制,这些主动下发任务的功能都需要手动操作。

            按下button_mode按键,程序将切换到main_auto(自动模式),此时系统将自行判定光照强度、温湿度、气体弄得等环境值,达到阈值后会自动打开或关闭led等一系列模块操作。

            在main_auto模式中,如果按下button_enter按键,oled屏幕将依次显示温度最大值、温度最低值、湿度最大值……等环境数据,此时就可以按button_up或button_down按键进行阈值的设置。非常人性化

    技术细节

    小结

    后续会继续补充文章内容 

    作者:Keenn4ss

    物联沃分享整理
    物联沃-IOTWORD物联网 » 跟着我完成一个简单的项目:物联网环境监测系统esp8266+stm32(持续更新中)

    发表回复