1.1 项目背景
近几年,物联网、智能家居、AI人工智能技术发送非常快。在物联网技术的支持下,农业逐渐走向现代化,自动化和智能农业生产已成为主流。告别刀耕火种的传统农业后,现代农业也在向智慧转型。目前,智能农业模式已深入农业生产的各个环节。灌溉、施肥、植物保护等细分将与物联网、信息技术等先进技术相结合,效率和效果将大大提高。
我们应该知道,所谓的智能农业是充分利用现代信息技术成果,整合计算机技术和网络技术、物联网技术、无线通信技术、专家智能和知识的应用,实现农业可视化远程诊断、远程控制、灾害预警等智能管理。因此,整合物联网的智能农业具有以下优势:
1、低成本化
众所周知,购买综合智能农业设备的成本很高,这对普通农民来说是难以承受的。因此,要实现综合智能农业,低成本智能农业设备将成为智能农业的趋势之一。
2.操作简单 智能农业的基础是为农业和农民服务。因此,要使农民更快地与智能农业接轨,就必须使系统易于操作和学习。我们应该知道,目前中国农民的普遍文化水平较低。只有简化操作,每个农民才能熟练操作。
智能农业也是一个很大的范围,比如: 智慧鱼塘、智慧温室、智慧园林、城市绿化、智慧果园等都属于智慧农业的范围。
在智能设备的支持下,可实现自动浇水灌溉、土壤养分实时检测、水分、环境温度、自动补光等一系列联动操作。
本文利用华为云IOT物联网平台实践构建智能农业智能大脑,设备平台采用熊开发板搭载CPU是意法半导体STM32L431芯片是意大利半导体推出的低功耗芯片;根据种植区的空气温湿度数据,通过一些外部专业传感器,可以获取空气中的温湿度数据和光照度数据,判断是否灌溉。
1.2 实现功能
本项目是,结合外部传感器采集的数据,利用这些数据判断灌溉、补光等信息提示。
目前的项目考虑了学习和实践的目的ESP8266无线WIFI网卡作为网络设备,ESP8266便宜,支持串口编程,有标准套AT资料,资料多,作为学习而言,非常适合。可以通过对ESP8266编程实验,了解TCP、MQTT网络编程相关知识点。
显示模块。
(1)基础系统模块:接收转发各种数据,控制扫水作业是否进行。浇水作业是用板载电机模拟的
(2)温度采集模块:采集监测区域的温度数据,传输到微控制器
(3)湿度采集模块:收集监测区域的湿度数据,传输到微控制器
(4)照明采集模块:收集监测区域的照明数据,传输到微控制器
(5)无线传感器网络模块:数据上传到云平台,数据发送交互等
(6)LCD显示模块:实时显示监控数据
熊开发板的扩展板配备了光敏传感器、温湿度传感器和直流电机模块,可以轻松满足上述功能要求。
在本项目设备的源代码中,连接华为云MQTT协议是按照MQTT的官方中文手册编写的,不依赖任何外部SDK,不依赖ESP只要能连接到华为云,8266设备就可以连接IOT,非常适合移植到其非常适合移植到其它单片机平台;STM32F1系列可直接参考代码移植。
华为云物联网平台提供API接口,可通过API开发配套上位机,方便数据查看、手动灌溉等操作。
提供的API除了查询设备属性信息外,还可以创建产品、设备,非常方便上位机的开发,从底层设备到云服务器再到应用APP完成三层数据交互的软件。
(1)创建云产品和设备
(2)设备上云,完成服务器登录和数据上传
(3)手机APP、计算机上位机软件的开发可以通过云开发API接口与设备、服务器通信前
1.3 设备实物图
目前采用联网设备ESP8266(手上没有现成的NBIOT暂时使用模块ESP8266代替,核心原理是一样的),正常项目里会使用NBIOT数据传输源采用模块联网。
2. 创建IOT服务器端产品
在创建设备之前,需要先创建产品。产品是一个大框架,产品下可以有很多设备,可以通过华为云平台在应用层提供API创建设备,删除设备,查询设备属性。在制作产品时,软件端可以制作设备注册的指导界面,完成产品下的设备注册,然后将数据传输到设备端。这个过程被称为网络,具体的逻辑需要与设备端一起完成。最终完成自动化设备创建、注册、在线等操作。
以下是如何手动创建产品和设备,了解在创建产品和设备的过程中需要填写哪些参数,然后使用API更好地理解参数的含义。
2.1 创建产品
直接打开物联网产品页面: https://www.huaweicloud.com/product/iothub.html
打开产品页面,选择右上角创建产品。
根据自己的情况填写信息。就是填写自己产品的一些参数信息。
创建成功后,打开产品详细信息页面,拉到底部,点击创建自定义模型文件。
在这里创建模型文件主要是为了MQTT客户端可以正确上传传感器数据,每个传感器设置一个属性,表示传感器的数据值类型。
比如: 先添加一个电机,这个电机就是浇水电机,能上报开关状态,云端也能下发命令控制电机,所以需要添加属性和下发的命令。
添加属性:
添加命令: 由于电机需要云远程控制。
电机、温度、湿度、光强度共四个属性:
2.2 创建设备
选择设备页面,注册设备。
保持设备密钥等信息,然后登录服务器生成MQTT这些参数需要帐户密钥。
{
"device_id": "61cd1d97078a93029b84e7b6_1126626497", "secret": "1126626497" }
2.3 生成MQTT登录帐户信息
官方微信提供的在线小工具: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
按提示填写数据,生成,非常方便。
ClientId 61cd1d97078a93029b84e7b6_1126626497_0_0_2021123003 Username 61cd1d97078a93029b84e7b6_1126626497 Password b219f3a0099fa0284a2671a5c699b67a7cf6d5f7355d9ee8190011f3b64f71b5
3. 使用MQTT模拟客户端测试
为了验证服务器配置是否OK,先使用MQTT客户端软件进行连接测试。
3.1 华为云IOT服务器地址与端口
端口: 1883
域名: a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
IP地址: 121.36.42.100
3.2 订阅主题
在产品页面,可以看到主题管理页面,能看到当前设备可以订阅的主题有哪些。
一般订阅下发的数据:
格式: $oc/devices/{
device_id}/sys/messages/down
//订阅主题: 平台下发消息给设备
$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/messages/down
3.3 上报主题数据
官方文档介绍: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html
服务ID,属性ID在产品页面查看,2.1小节创建产品里就讲了这个属性的作用。
每次可以单个属性上报,也可以一起上报。
格式: $oc/devices/{
device_id}/sys/properties/report
//设备上报主题请求
$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/properties/report
//上报的数据格式如下
//电机开状态反馈
{
"services": [{
"service_id": "motor","properties":{
"motor":1}}]}
//电机关状态反馈
{
"services": [{
"service_id": "motor","properties":{
"motor":0}}]}
//温度上报
{
"services": [{
"service_id": "motor","properties":{
"SHT30_H":14}}]}
//湿度上报
{
"services": [{
"service_id": "motor","properties":{
"SHT30_L":70}}]}
//光照强度上报
{
"services": [{
"service_id": "motor","properties":{
"BH1750":80}}]}
//也可以一起上报
{
"services": [{
"service_id": "motor","properties":{
"motor":1}},{
"service_id": "motor","properties":{
"SHT30_H":15}},{
"service_id": "motor","properties":{
"SHT30_L":70}},{
"service_id": "motor","properties":{
"BH1750":80}}]}
3.4 登录服务器
按照软件提示,填入相关数据即可。
如需要也需要使用和我一样的同款软件,打开百度搜索MQTT客户端_v2.4(协议3.1.1).exe
即可找到下载地址。
发送数据后查看云端,已经登录成功,数据已经上传成功。
3.5 下发命令
电机设备支持读写,支持下发命令,在设备页面测试。
点击确定之后,参看MQTT客户端软件,已经收到了下发的数据。
len:174,Data:l$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/commands/request_id=390ce15d-6e69-4021-b83a-5e953eea874c{
"paras":{
"motor":1},"service_id":"motor","command_name":"motor"}
4. 设备端上华为云IOT
4.1 安装keil软件
MCU采用的STM32芯片,设备端代码编写开发就采用的keil5。
keil5安装包下载地址: http://www.myir-tech.com/download.asp
安装keil时,软件要放在英文目录下,电脑的用户名必须是英文,否则会出现一些奇怪问题。
安装过程中,根据提示下一步下一步点击即可。
4.2 编写代码
STM32连接华为云IOT的工程代码Get: https://download.csdn.net/download/xiaolong1126626497/81993720
工程代码:
#include "main.h" #include "stm32l4xx_hal.h" #include "i2c.h" #include "usart.h" #include "gpio.h" #include "E53_IA1.h" #include "lcd.h" #include "spi.h" #include "mqtt.h" #include "esp8266.h" /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ void SystemClock_Config(void); #define ESP8266_WIFI_AP_SSID "CMCC-Cqvn" //将要连接的路由器名称 --不要出现中文、空格等特殊字符 #define ESP8266_AP_PASSWORD "99pu58cb" //将要连接的路由器密码 //华为云IOT物联网服务器的设备信息 #define MQTT_ClientID "61cd1d97078a93029b84e7b6_1126626497_0_0_2021123003" #define MQTT_UserName "61cd1d97078a93029b84e7b6_1126626497" #define MQTT_PassWord "b219f3a0099fa0284a2671a5c699b67a7cf6d5f7355d9ee8190011f3b64f71b5" //订阅与发布的主题 #define SET_TOPIC "$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/messages/down" //订阅 #define POST_TOPIC "$oc/devices/61cd1d97078a93029b84e7b6_1126626497/sys/properties/report" //发布 //保存温湿度、光照强度 E53_IA1_Data_TypeDef E53_IA1_Data; //显示文本 char lcd_text_str[50]; UART_HandleTypeDef at_usart; //低功耗串口初始化 int32_t at_usart_init(void) { at_usart.Instance = LPUART1; at_usart.Init.BaudRate = 115200; at_usart.Init.WordLength = UART_WORDLENGTH_8B; at_usart.Init.StopBits = UART_STOPBITS_1; at_usart.Init.Parity = UART_PARITY_NONE; at_usart.Init.HwFlowCtl = UART_HWCONTROL_NONE; at_usart.Init.Mode = UART_MODE_RX | UART_MODE_TX; if(HAL_UART_Init(&at_usart) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } // __HAL_UART_CLEAR_FLAG(usart, UART_FLAG_TC); __HAL_UART_ENABLE_IT(&at_usart, UART_IT_IDLE); __HAL_UART_ENABLE_IT(&at_usart, UART_IT_RXNE); HAL_NVIC_EnableIRQ(LPUART1_IRQn); //使能USART1中断通道 HAL_NVIC_SetPriority(LPUART1_IRQn, 3, 3); //抢占优先级3,子优先级3 return 0; } unsigned char ESP8266_RecvBuf[MAX_RECV_CNT]; unsigned int ESP8266_Recv_cnt=0; unsigned int ESP8266_Recv_flag=0; void LPUART1_IRQHandler() { //接收到数据 if(__HAL_UART_GET_FLAG(&at_usart, UART_FLAG_RXNE) != RESET) { if(ESP8266_Recv_cnt<MAX_RECV_CNT-1) { ESP8266_RecvBuf[ESP8266_Recv_cnt++] = (uint8_t)(at_usart.Instance->RDR & 0x00FF); } else { ESP8266_Recv_flag=1; } } else if (__HAL_UART_GET_FLAG(&at_usart, UART_FLAG_IDLE) != RESET) { __HAL_UART_CLEAR_IDLEFLAG(&at_usart); ESP8266_Recv_flag=1; } } void AT_SendData(unsigned char *p,unsigned int len) { int i=0; for(i=0;i<len;i++) { while((LPUART1->ISR & 0X40) == 0); //循环发送,直到发送完毕 LPUART1->TDR = p[i]; } } char mqtt_message[200]; int main(void) { int i=0; int cnt=0; int motor_state=0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); MX_SPI2_Init(); MX_USART1_UART_Init(); at_usart_init(); //初始化硬件 Init_E53_IA1(); LCD_Init(); LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "Init ESP8266");//显示字符串,字体大小32*32 if(ESP8266_Init()) { printf("ESP8266硬件检测错误.\n"); LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "ESP8266 ERROR");//显示字符串,字体大小32*32 } else { LCD_Clear(BLACK);//清屏为黑色 LCD_ShowString(0, 00, 240, 32, 32, "ESP8266 OK");//显示字符串,字体大小32*32 printf("准备连接到指定的服务器.\n"); //非加密端口 printf("WIFI:%d\r\n",ESP8266_STA_TCP_Client_Mode(ESP8266_WIFI_AP_SSID,ESP8266_AP_PASSWORD,"106.55.124.154",1883,1)); } //2. MQTT协议初始化 MQTT_Init(); //3. 连接华为云IOT服务器 while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord)) { printf("服务器连接失败,正在重试...\n"); HAL_Delay(500); } printf("服务器连接成功.\n"); //3. 订阅主题 if(MQTT_SubscribeTopic(SET_TOPIC,0,1)) { printf("主题订阅失败.\n"); } else { printf("主题订阅成功.\n"); } while (1) { if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)//查询按键KEY1低电平 { HAL_Delay(10);//消抖 if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)//查询按键KEY1低电平 { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);//亮 //补光灯亮 HAL_GPIO_WritePin(IA1_Light_GPIO_Port, IA1_Light_Pin, GPIO_PIN_SET); //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); motor_state=1; } } if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)//查询按键KEY2低电平 { HAL_Delay(10);//消抖 if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)//查询按键KEY2低电平 { HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);//灭 //补光灯灭 HAL_GPIO_WritePin(IA1_Light_GPIO_Port, IA1_Light_Pin, GPIO_PIN_RESET); //电机停 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_RESET); motor_state=0; } } cnt++; HAL_Delay(10); if(cnt>=100) { cnt=0; E53_IA1_Read_Data(); printf("光照强度:%d %%\r\n", (int)E53_IA1_Data.Lux); printf("湿度:%d %%\r\n",(int)E53_IA1_Data.Humidity); printf("温度:%d ℃\r\n", (int)E53_IA1_Data.Temperature); sprintf(lcd_text_str,"L: %d %%",(int)E53_IA1_Data.Lux); LCD_ShowString(40, 50+10+32*1, 240, 32, 32,lcd_text_str); sprintf(lcd_text_str,"H: %d %%",(int)E53_IA1_Data.Humidity); LCD_ShowString(40, 50+10+32*2, 240, 32, 32,lcd_text_str); sprintf(lcd_text_str,"T: %d C",(int)E53_IA1_Data.Temperature); LCD_ShowString(40, 50+10+32*3, 240, 32, 32,lcd_text_str); //切换引脚的状态 HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); //上传数据 sprintf(mqtt_message,"{\"services\": [{\"service_id\": \"motor\",\"properties\":{\"motor\":%d}}," "{\"service_id\": \"motor\",\"properties\":{\"SHT30_H\":%d}},{\"service_id\": \"motor\",\"properties\":" "{\"SHT30_L\":%d}},{\"service_id\": \"motor\",\"properties\":{\"BH1750\":%d}}]}", motor_state,(int)E53_IA1_Data.Humidity,(int)E53_IA1_Data.Temperature,(int)E53_IA1_Data.Lux); MQTT_PublishData(POST_TOPIC,mqtt_message,0); //根据湿度自动灌溉 if((int)E53_IA1_Data.Humidity<50) //小于50自动灌溉 { printf("自动灌溉....\n"); motor_state=1; //电机状态更新 //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); } } //接收到数据 if(ESP8266_Recv_flag) { //如果是下发了属性,判断是开
锁还是关锁 if(ESP8266_Recv_cnt>5) { ESP8266_RecvBuf[ESP8266_Recv_cnt]='\0'; //使用字符串查找函数 if(strstr((char*)&ESP8266_RecvBuf[5],"\"machine\":1")) { motor_state=1; //电机状态更新 //电机转 HAL_GPIO_WritePin(IA1_Motor_GPIO_Port, IA1_Motor_Pin, GPIO_PIN_SET); printf("开启电机...\n"); } else if(strstr((char*)&ESP8266_RecvBuf 标签: 传感器搭载构造e3t系列传感器温湿度传感器ee375e3akavlico位移传感器a5b00600传感器5e0100200112传感器