【物联网毕设】基于STM32的森林土壤温湿度数据采集和存储系统


一、前言

    上一篇博客提到《正点原子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接收云端数据信息,能够实现数据双向控制、移动端数据的存储、查询等可视化分析功能,各大模块相互独立又相辅相成作为一个物联网控制系统。初步可应用于林业。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值