目录导航
- 一、前言
- 二、准备工作
- 三、实现流程
- 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中主函数代码块如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169#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*)¤tDataPoint, 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:复位rnrn"); 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 土壤湿度:%drn",temperature,humidity,soil_moisture); if(wifi_con!=wifi_sta) { wifi_con=wifi_sta; wifi_con?printf("connect"):printf("close"); } gizwitsHandle((dataPoint_t *)¤tDataPoint);//上报当前数据协议处理 key = KEY_Scan(0); if(key==KEY1_PRES)//KEY1按键 { BEEP=0; LED0 = 0; LED1 = 1; printf("WIFI进入SOFTAP连接模式rn"); 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复位,请重新配置连接rn"); 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布局代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363<?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接收云端数据信息,能够实现数据双向控制、移动端数据的存储、查询等可视化分析功能,各大模块相互独立又相辅相成作为一个物联网控制系统。初步可应用于林业。
最后
以上就是谦让刺猬最近收集整理的关于【物联网毕设】基于STM32的森林土壤温湿度数据采集和存储系统一、前言二、准备工作三、实现流程四、数据可视化分析五、小结的全部内容,更多相关【物联网毕设】基于STM32内容请搜索靠谱客的其他文章。
发表评论 取消回复