【物联网毕业设计】基于STM32的森林土壤温湿度数据采集与存储系统优化方案

目录导航

  • 一、前言
  • 二、准备工作
  • 三、实现流程
  • 1.keil编程
  • 2.机智云台开发
  • 3.Android开发
  • 四、数据可视化分析
  • 五、小结

  • 一、前言

        上一篇博客提到《正点原子STM32f103ZE精英开发板实现基于ESP8266 WIFI模块温湿度数据上传至乐联网平台》,通过单片机获取采集的温湿度数据信息结合ESP8266-WIFI模块上传至乐联网平台。但是,平台的缺陷比较多: 数据上传经常中断,稳定性差;不支持双向收发控制;无Android移动端app支持,便捷性有待提升等。
        为了优化这种情况,本文选用的硬件在原有的基础上增加了YL-69土壤湿度传感器,用于采集土壤湿度信息;硬件显示模块为TFT-LCD显示屏,对采集的土壤温湿度数据实时显示以及查看ESP8266-WiFi模块的运行状;云端物联网平台选用性价比更高的机智云平台,附带Android二次开发app实现数据信息的采集+存储+可视化功能。
        注意,与上一篇博客不同的是,ESP8266-WIFI模块是烧录“机智云固件”—本质是基于TCP/IP通信的MQTT协议,再深挖就是客户端与服务器的双向通信,MQTT协议基本上是各大物联网平台都支持的通信协议,包括阿里云平台、百度云平台、腾讯云平台等等。
        本系统旨在利用单片机和各种传感器实现数据采集,结合相应的通信协议将采集的数据上传至云端,并且开发app接收云端数据信息,能够实现数据双向控制、移动端数据的存储、查询等可视化分析功能。初步可应用于林业物联网,本设计灵感源于常州茅山森林土测(导师项目)。
        本系统建议掌握基于c语言的keil嵌入式软件编程、Java语言开发、Web前端基础、Android开发、MYSQL数据库语言等。


    二、准备工作

        本系统兼具硬件、云平台和移动终端app三大方向,总体流程主要包括数据的采集、传输、接收、控制、存储、查询等功能。硬件模块包括STM32F103ZET6开发板,选用YL-69土壤湿度传感器、DHT11温湿度传感器、LED指示灯、警报器以及ESP8266-WIFI模块,采集数据显示模块为TTL-LCD显示屏。具体模块实物图如下:

        1.一块正点原子STM32f103ZET6精英开发板


        2.正点原子的ATK-ESP8266 -WIFI串口模块


    3.DH11温湿度传感器


    4.YL-69土壤湿度模块


    5.TFT-LCD显示模块


    6.ATK-USB-TTL模块

    用于为ESP8266烧录使用,电脑上需安装CH340驱动程序
    ·注意:烧录需要使用USB-UART模块与ESP8266-WIFI模块连接;开始烧录的时候它会要求你给WIFI模块复位,如设备无自动复位,只需要使RST接一下低电平触发即可,IO-0需置低电平


    ·ESP8266烧录机智云固件

    通过flash下载工具ESPFlashDownloadTool烧录机智云固件

    机智云GAgent固件链接请点击[(GAgent for ESP8266 04020034)]:https://download.gizwits.com/zh-cn/p/92/94
    烧录工具及固件链接:https://pan.baidu.com/s/1xp6mlmHo2xwitFcn7FiVQw
    提取码:dprr

    附硬件总工程原理图:


    三、实现流程

    1.keil编程

         基本的机智云注册不再熬述,可以参考其他博客。那么接下来生成MCU代码包,MCU开发中:硬件方案为独立MCU方案,选择其他平台,输入基本信息中的密钥即可下载代码包了。注意,代码包中几个文件(Gizwits文件和Utils文件)需要移植到原有工程中去。


         ·keil中主函数代码块如下:

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"
    #include "adc.h"
    #include "timer.h"
    #include "usart3.h"
    #include "gizwits_product.h"
    #include "dht11.h"
    #include "lcd.h"
    #include "beep.h"
    /* 用户区当前设备状态结构体*/
    dataPoint_t currentDataPoint;
    u8 temperature;
    u8 humidity;
    //WIFI连接状态
    //wifi_sta 0: 断开
    //         1: 已连接
    u8 wifi_sta=0;
    
    float soil_moisture_temp_avrg=0;
    int soil_moisture;
    /* -------------------------------- begin  -------------------------------- */
    /**
      * @Name    Gizwits_Init
      * @brief  
      * @param   None
      * @retval
      * @author  JackyFeng
      * @Data    2022-01-16
      * 1. ...
      * <modify staff>:
      * <data>        :
      * <description> :协议初始化
      * 2. ...
     **/
    /* -------------------------------- end -------------------------------- */
    void Gizwits_Init(void)
    {
        TIM3_Int_Init(9,7199);//1MS系统定时
        usart3_init(9600);//WIFI初始化
        memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));//设备状态结构体初始化
        gizwitsInit();//缓冲区初始化
    }
    /* -------------------------------- begin  -------------------------------- */
    /**
      * @Name    userHandle
      * @brief  
      * @param   None
      * @retval
      * @author  JackyFeng
      * @Data    2022-01-16
      * 1. ...
      * <modify staff>:
      * <data>        :
      * <description> :用户WiFi处理
      * 2. ...
     **/
    /* -------------------------------- end -------------------------------- */
    
    void userHandle(void)
    {
        u8 t=0;
        static u8 time=10;
        if(wifi_sta)
        {
            time++;
            if(time==10)
            {
                time=0;
                gizwitsGetNTP();//请求网络时间
            }
            delay_ms(80);
        }
        if(!wifi_sta)
        {
            if(time!=0) time=0;
        }
      	soil_moisture=Get_Adc_Average(1,10);			 
        if(t%10==0)			
        {
    		POINT_COLOR=BLUE;
            DHT11_Read_Data(&temperature,&humidity);	//读取温湿度值
            LCD_ShowNum(30+40,190,temperature,2,16);	//显示温度
            LCD_ShowNum(30+40,230,humidity,2,16);		//显示湿度
    	    LCD_ShowNum(30+40,270,soil_moisture,2,16);	//显示土壤湿度
            currentDataPoint.valuetemp= temperature;
            currentDataPoint.valuewet=humidity;
    	    currentDataPoint.valuesoil_moisture=soil_moisture;
        }
        delay_ms(10);
        t++;
        if(t==20)
        {
            t=0;
        }
    }
    
    int main(void)
    {//需要接入稳定电压
    	    int key;
    	    u8 wifi_con=0;//记录wifi连接状态 1:连接 0:断开
    	    delay_init();	    	 
    	    BEEP_Init();          
    	    KEY_Init( );
    	    LED_Init();		  		 
    	    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
    		uart_init(9600);	 
    	    DHT11_Init();
    	    Gizwits_Init();        
    		T_Adc_Init();		 
    	    LCD_Init();			  
    	    printf("KEY1:AirLink连接模式\t KEY_UP:复位\r\n\r\n");
    	    LCD_ShowString(160,70,200,16,16,"Forest soil temp and humi");  
    	    POINT_COLOR=RED;		 
    	    LCD_ShowString(30,110,200,16,16,"DHT11 OK");
    		LCD_ShowString(30,150,200,16,16,"YL-69 OK");
    	    POINT_COLOR=BLUE; 
    	    LCD_ShowString(30,190,200,16,16,"Temp:  C");
    	    LCD_ShowString(30,230,200,16,16,"Humi:  %");	
    		LCD_ShowString(30,270,200,16,16,"Soil:  %");
        while(1)
        {
            userHandle();
    	 	printf("当前温度:%d度  当前湿度:%d  土壤湿度:%d\r\n",temperature,humidity,soil_moisture);
    	 	if(wifi_con!=wifi_sta)
            {
                wifi_con=wifi_sta;
                wifi_con?printf("connect"):printf("close");
            }
            gizwitsHandle((dataPoint_t *)&currentDataPoint);//上报当前数据协议处理
            key = KEY_Scan(0);
            if(key==KEY1_PRES)//KEY1按键
            {
    	        BEEP=0;
    	        LED0 = 0;
    	        LED1 = 1;
    	     	printf("WIFI进入SOFTAP连接模式\r\n");
    		 	gizwitsSetMode(WIFI_SOFTAP_MODE);
    			LCD_ShowString(30,310,200,16,16,"WIFI_SOFTAP_MODE");
    	        delay_ms(30);
            }
            if(key==WKUP_PRES)//KEY_UP按键
            {
                BEEP=1;
                LED1 = 0;
                LED0 = 1;
                printf("WIFI复位,请重新配置连接\r\n");
                gizwitsSetMode(WIFI_RESET_MODE);
                wifi_sta=0;		
                delay_ms(50);
            }
            delay_ms(30);
    				
    			if(wifi_sta==0)
    			{
    			POINT_COLOR=BLUE;
    			LCD_ShowString(30,350,250,16,24,"WIFI OFF DISCONNECT");
    			}
    			else
    			{
    				POINT_COLOR=RED;
    				LCD_ShowString(30,350,250,16,24,"WIFI OK CONNECT    ");
    			}
        }
    }
    
    

    2.机智云台开发

    1.布置相关节点,确保所用的温湿度传感器、土壤湿度传感器、LED、蜂鸣器等参数设置正确。

    2.启动开发板及插入ESP8266-WiFi模块,配置入网后可以看到,Web云端可视化界面:


    3.Android开发

    1.云平台需要生成Android框架包,主要用于后期二次开发。在“应用开发”中选择Android平台,选择相应的应用名称和密钥生成代码包并下载。


    2.接下来需要用到Android Studio(AS)开发环境对app界面开发设计,对重要布局文件activity_gos_device_control.xml开发设计,最外层布局为线下布局,内部各节点(LED、Beep、Wet、Temp、soil_moisture)为相对布局,设置好各个位置的TextView组件、Button按钮、EditText组件等等

    3.xml布局代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <include layout="@layout/header_toolbar" />
    	<LinearLayout
    		android:layout_width="match_parent"
    		android:layout_height="100dp"
    		android:orientation="horizontal"
    		android:background="@drawable/esp"
    		>
    	</LinearLayout>
    	<ScrollView
    		android:layout_width="match_parent"
    		android:layout_height="match_parent"
    		android:background="@color/background_color"
    		android:fadingEdge="vertical"
    		android:paddingTop="5dp"
    		android:paddingBottom="5dp"
    		android:scrollbars="vertical">
    		<LinearLayout
    			android:layout_width="match_parent"
    			android:layout_height="wrap_content"
    			android:orientation="vertical"
    			android:scrollbars="vertical">
    			<!-- LED1(布尔可写) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_led1"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_led_dark" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="LED1" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="240dp"
    					android:text="关闭" />
    				<Switch
    					android:id="@+id/sw_bool_LED1"
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="270dp"
    					android:textOff="关闭"
    					android:textOn="开启" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="315dp"
    					android:text="开启" />
    			</RelativeLayout>
    			<-- LED2(布尔可写) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_led2"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_led_dark" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="LED2" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="240dp"
    					android:text="关闭" />
    				<Switch
    					android:id="@+id/sw_bool_LED2"
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="270dp"
    					android:textOff="关闭"
    					android:textOn="开启" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="315dp"
    					android:text="开启" />
    			</RelativeLayout>
    			<!-- beep(布尔可写) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_beep"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_beep" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="警报器" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="240dp"
    					android:text="关闭" />
    				<Switch
    					android:id="@+id/sw_bool_beep"
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="270dp"
    					android:textOff="关闭"
    					android:textOn="开启" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="315dp"
    					android:text="开启" />
    			</RelativeLayout>
    			<!-- temp(数值只读) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_temp"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_temp_dark" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="温  度 " />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="308dp"
    					android:text="℃" />
    				<TextView
    					android:id="@+id/tv_data_temp"
    					android:layout_width="110dp"
    					android:layout_height="match_parent"
    					android:layout_marginLeft="240dp"
    					android:gravity="center"
    					android:textColor="@color/alert_blue"
    					android:textSize="16sp" />
    			</RelativeLayout>
    			<!-- wet(数值只读) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_wet"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_humidity_dark" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="湿  度 " />
    				<TextView
    					android:id="@+id/tv_data_wet"
    					android:layout_width="110dp"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="240dp"
    					android:gravity="center"
    					android:textColor="@color/green"
    					android:textSize="16sp" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="308dp"
    					android:text=" %" />
    			</RelativeLayout>
    			<!-- soil_moisture(数值只读) -->
    			<RelativeLayout
    				android:layout_width="match_parent"
    				android:layout_height="wrap_content"
    				android:layout_marginBottom="1dp"
    				android:background="@drawable/border_body_iot"
    				android:padding="10dp">
    				<TextView
    					android:id="@+id/tv_pic_soil_moisture"
    					android:layout_width="28dp"
    					android:layout_height="28dp"
    					android:layout_marginLeft="10dp"
    					android:background="@drawable/ic_soil_moisture_dark" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="58dp"
    					android:text="土  湿 " />
    				<TextView
    					android:id="@+id/tv_data_soil_moisture"
    					android:layout_width="110dp"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="240dp"
    					android:gravity="center"
    					android:textColor="@color/green"
    					android:textSize="16sp" />
    				<TextView
    					android:layout_width="wrap_content"
    					android:layout_height="match_parent"
    					android:layout_centerVertical="true"
    					android:layout_marginLeft="308dp"
    					android:text=" %" />
    			</RelativeLayout>
    			<ScrollView
    				android:layout_width="match_parent"
    				android:layout_height="match_parent">
    				<LinearLayout
    					android:layout_width="match_parent"
    					android:layout_height="match_parent"
    					android:orientation="vertical">
    					<LinearLayout
    						android:layout_width="match_parent"
    						android:layout_height="wrap_content"
    						android:background="@drawable/btn_nor_down"
    						android:orientation="horizontal">
    						<TextView
    							android:layout_width="55dp"
    							android:layout_height="match_parent"
    							android:background="@drawable/ic_green_energy_logo"
    						/>
    						<TextView
    							android:layout_width="55dp"
    							android:layout_height="match_parent"
    							android:background="@drawable/ic_green_energy_logo"
    						/>
    						<TextView
    							android:layout_width="55dp"
    							android:layout_height="match_parent"
    							android:background="@drawable/ic_green_energy_logo"
    							/>
    						<TextView
    							android:layout_width="55dp"
    							android:layout_height="match_parent"
    							android:background="@drawable/ic_green_energy_logo"
    							/>
    				
    						<Button
    							android:id="@+id/startTimer"
    							android:layout_width="50dip"
    							android:layout_height="50dip"
    							android:layout_gravity="center"
    							android:layout_marginLeft="2dp"
    							android:background="@drawable/btn_cycle_red"
    							android:text="更新"
    							android:textColor="@color/blue" />
    						<Button
    							android:id="@+id/startTimer2"
    							android:layout_width="40dip"
    							android:layout_height="40dip"
    							android:layout_gravity="center"
    							android:layout_marginLeft="2dp"
    							android:background="@drawable/btn_cycle_red"
    							android:gravity="center"
    							android:onClick="dialog_judge"
    							android:text="删库"
    							android:textColor="@color/blue" />
    						<Button
    							android:id="@+id/music_btn"
    							android:layout_width="40dip"
    							android:layout_height="40dip"
    							android:layout_gravity="center"
    							android:layout_marginLeft="2dp"
    							android:background="@drawable/btn_cycle_red"
    							android:text="其他"
    							android:textColor="@color/blue" />
    					</LinearLayout>
    					<RelativeLayout
    						android:layout_width="match_parent"
    						android:layout_height="wrap_content"
    						android:layout_gravity="center"
    						android:focusable="true"
    						android:focusableInTouchMode="true">
    						<EditText
    							android:id="@+id/edit1"
    							android:layout_width="410dp"
    							android:layout_height="wrap_content"
    							android:background="@drawable/border_edit"
    							android:hint="请输入查询ID..."
    							android:imeOptions="actionDone"
    							android:inputType="textVisiblePassword"
    							android:paddingStart="60dp"
    							android:paddingLeft="60dp"
    							android:paddingTop="10dp"
    							android:paddingEnd="10dp"
    							android:paddingRight="10dp"
    							android:paddingBottom="10dp"
    							android:singleLine="true" />
    						<ImageView
    							android:id="@+id/image"
    							android:layout_width="wrap_content"
    							android:layout_height="wrap_content"
    							android:layout_alignStart="@id/edit1"
    							android:layout_alignLeft="@id/edit1"
    							android:layout_alignTop="@id/edit1"
    							android:layout_alignBottom="@id/edit1"
    							android:layout_marginEnd="10dp"
    							android:layout_marginRight="10dp"
    							android:padding="12dp"
    							android:src="@drawable/ic_id_card" />
    					</RelativeLayout>
    					<include
    						android:id="@+id/tableItem"
    						layout="@layout/wettemp_theme" />
    					<ListView
    						android:id="@+id/listview_body"
    						android:layout_width="match_parent"
    						android:layout_height="210dp"
    						android:background="@color/white"
    						android:divider="@color/gray"
    						android:dividerHeight="1dp" />
    				</LinearLayout>
    			</ScrollView>
    		</LinearLayout>
    	</ScrollView>
    </LinearLayout>
    

    4.Java代码较多,重点需了解Handler处理机制,故不讲解。

    四、数据可视化分析

    1.LCD显示采集数据+app显示采集数据
         LCD显示屏可显示采集的空气温度、空气湿度、土壤湿度信息,可以检查ESP8266的联网状态,若配置入网成功则显示 红色字体 WIFI OK CONNECT字符。


    2.app显示采集数据+app数据库显示:
         内置SQLite数据库,此数据库支持查询功能,更新数据支持ID自增,可显示采集数据时间点、空气温度、空气湿度、土壤湿度信息


    实测视频:https://www.bilibili.com/video/bv15t4y1H7N3


    五、小结

    (1)结合STM32单片机、传感器来采集土壤温湿度数据,数据上传云端,云平台能够实现数据的存储和可视化功能,用户通过移动终端app接收机智云平台下发的数据包,并且手机端app拥有独立数据库,以便于对采集数据进行快速检索和分析。
    (2)提高数据采集的便携性,大大减少了数据处理的时间损耗,极大提高了数据采集的效率。
    (3)本系统旨在利用单片机和各种传感器实现数据采集,结合相应的通信协议将采集的数据上传至云端,并且开发app接收云端数据信息,能够实现数据双向控制、移动端数据的存储、查询等可视化分析功能,各大模块相互独立又相辅相成作为一个物联网控制系统。初步可应用于林业。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【物联网毕业设计】基于STM32的森林土壤温湿度数据采集与存储系统优化方案

    发表评论