赞
踩
本文分享自华为云社区《基于STM32的智慧农业管理系统设计与实现》,作者: DS小龙哥。
随着全球农业现代化进程的加快,以及物联网、人工智能等先进技术的发展与应用,智慧农业已经成为现代农业发展的新趋势。基于精准感知、智能控制和远程管理的智慧农业系统能够显著提升农作物生产效率,降低资源消耗,实现环境友好型可持续农业生产。
在当前背景下,我国正大力推进数字乡村建设,智慧农业管理系统作为其中的重要组成部分,对于提高农业生产精细化管理水平,解决传统农业中信息获取不及时、人工管理成本高、决策缺乏科学依据等问题具有重要作用。
本设计开发一套基于STM32F103RCT6主控芯片的智慧农业管理系统,通过集成DHT11温湿度传感器、BH1750光照强度传感器以及土壤湿度检测传感器,实时监测农田环境和作物生长状态,并在超出阈值时通过蜂鸣器报警,提醒管理人员进行灌溉、施肥等操作。同时,采用NBIoT通信技术(BC26模块)将采集到的数据上传至云端,利用EMQX开源MQTT服务器框架部署于华为云ECS服务器上的MQTT服务器,实现数据的远程展示与处理。
系统支持微信小程序远程控制功能,使得农户或管理者可以随时随地查看农田环境参数、接收预警信息,并能远程手动控制灌溉设备、补光灯等,大大提高了农业生产的智能化和便捷性。此项目的实施不仅有助于推动我国农业信息化水平的提升,也有利于农业资源的高效利用,对保障国家粮食安全、促进农业增效、农民增收具有重要意义。
(1)实时环境监测:系统通过集成的DHT11温湿度传感器、BH1750光照强度传感器以及土壤湿度检测传感器,实时监测农田环境中的温度、湿度、光照强度和土壤含水量等关键参数。当这些参数超过或低于预设阈值时,系统将自动触发蜂鸣器报警,提醒管理人员关注并采取相应措施。
(2)自动化管理与预警:根据土壤湿度传感器检测的数据,如果土壤湿度低于设定的适宜作物生长的含水量阀值,则系统会自动提醒管理者进行灌溉操作。同时,可以按照预设周期发送施肥提醒,以确保农作物在最佳时期得到充足的水分和养分供应。
(3)远程控制功能:利用NBIoT通信技术(BC26模块)将现场采集到的各项数据上传至云端MQTT服务器,并通过微信小程序实现远程访问和展示。用户可以通过微信小程序查看实时监测数据,以及对农田设备进行远程手动控制,如启动或关闭5V抽水泵进行灌溉,开启或关闭白色LED补光灯调节光照条件。
(4)数据上云与分析:基于EMQX开源MQTT服务器框架搭建的MQTT服务器,能够接收并处理STM32主控板传输的农业环境数据,并对接微信小程序平台,为用户提供直观易懂的数据图表和分析结果,便于农户或农业技术人员进行科学决策和精准管理。
(1)主控模块: 采用STM32F103RCT6微控制器作为核心控制单元,负责整个系统的运行和管理。STM32F103RCT6具有丰富的外设接口、强大的处理能力和低功耗特性,能够实时处理传感器数据、执行逻辑判断,并通过无线通信模块发送和接收指令。
(2)环境监测模块:
(3)控制输出模块:
(4)无线通信模块: 集成NBIoT-BC26模块,实现与云端服务器的数据交互。该模块具备广覆盖、低功耗、大连接的特点,可确保在各种复杂农业环境中稳定地传输数据至MQTT服务器。
(5)报警模块: 系统配备蜂鸣器用于异常情况报警,当环境参数超出设定范围时,主控板会驱动蜂鸣器发出声音警报。
(1)系统需求分析:根据智慧农业管理的实际需求,确定需要监测的关键环境参数(温度、湿度、光照强度和土壤湿度),以及必要的控制功能(灌溉、补光灯控制等)。同时考虑远程监控与预警的需求,规划通过NBIoT通信技术实现数据上传及远程操控。
(2)硬件选型与设计:
(3)软件架构设计:
(1)DHT11温湿度传感器:
(2)BH1750光照强度传感器:
(3)土壤湿度检测传感器:
(4)蜂鸣器报警模块:
(5)5V抽水泵与继电器组合:
(6)NBIoT-BC26模块:
STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。
开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比如:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。如果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。
EMQX是一款开源的、云原生的分布式物联网MQTT消息服务器,设计目标是实现高可靠性,并支持承载海量物联网终端的MQTT连接,以及在海量物联网设备间实现低延时消息路由。基于Erlang/OTP平台开发,充分利用了Erlang/OTP的软实时、低延时和分布式特性。
以下是EMQX服务器框架的详细介绍:
(1)可扩展性:EMQX支持亿级的MQTT服务订阅,单节点能够支持500万MQTT设备连接,集群可扩展至1亿并发MQTT连接。这种强大的扩展能力使其能够适应不同规模的物联网应用。
(2)安全性:EMQX提供了多种安全机制,包括SSL/TLS、密码认证、增强认证和ACL(访问控制列表)等,以保障数据传输和访问的安全性。
(3)规则引擎:EMQX内置了基于SQL的规则引擎,能够实时过滤、转换和处理消息,提供灵活的消息处理机制。这使得应用程序能够根据业务需求对消息进行灵活处理。
(4)数据存储:EMQX企业版还提供了数据存储功能,将客户端上下线状态、订阅关系、离线消息、消息内容以及消息回执等操作记录到各种数据库中。这一功能在服务崩溃或客户端异常离线后,能够保留数据,确保数据的完整性和可靠性。
(5)集群设计:EMQX采用Masterless的大规模分布式集群架构,实现了系统的高可用性和水平扩展。集群设计包括维护订阅表、路由表和主题树等数据结构,以实现消息转发和投递给各节点上的订阅者。
(6)协议支持:EMQX完全支持MQTT 5.0和3.x协议标准,提供了更好的伸缩性、安全性和可靠性。同时,它还提供了对多种其他协议的支持,如WebSocket、TCP、SSL/TLS等。
(7)易用性:EMQX提供了丰富的API和插件管理功能,使得用户可以方便地查看在线客户端信息、踢出客户端、管理插件状态等。它还提供了可视化的管理界面和调试工具,方便用户进行监控和管理。
【1】选择ECS弹性服务器
【2】选择ECS服务器的区域、配置信息、操作系统(我选择的Ubuntu18.04 64位)。
【3】购买弹性公网IP,配置带宽。
【4】配置密码
【5】选择购买时长,我这里选择了1个月时长
【6】确认付费付款
收到邮件提醒,服务器创建成功。 (为了写教程,花费320元,买了一个月服务器)
【7】返回弹性服务器的控制台
【8】点击服务器名字,可以进入到详情页面。
要确保MQTT服务器常用的几个端口已经开放出出来。
Windows下安装 FinalShell 终端,方便使用SSH协议远程登录到云服务器。 (当然,使用其他方式登录也是一样的)
【1】新建连接,选择SSH连接。
【2】填入IP地址、用户名、密码
这里的主机就是填服务器的公网IP地址,密码就是创建服务器输入的密码,用户名直接用root。
【3】点击连接服务器
【4】第一次登录会弹出提示框,选择接受并保存
【5】接下来可以看到服务器已经登录成功了。
本章节将介绍如何在 Ubuntu 系统中下载安装并启动 EMQX。
支持的 Ubuntu 版本:
EMQX 支持通过 Apt 源安装,免除了用户需要手动处理依赖关系和更新软件包等的困扰,具有更加方便、安全和易用等优点。
在命令行终端,复制下面的命令过去,按下回车键。
【1】通过以下命令配置 EMQX Apt 源:
curl -s https://assets.emqx.com/scripts/install-emqx-deb.sh | sudo bash
【2】运行以下命令安装 EMQX:
sudo apt-get install emqx
【3】运行以下命令启动 EMQX:
sudo systemctl start emqx
过程如下:
- sudo systemctl emqx start 启动
- sudo systemctl emqx stop 停止
- sudo systemctl emqx restart 重启
EMQX 提供了一个内置的管理控制台,即 EMQX Dashboard。方便用户通过 Web 页面就能轻松管理和监控 EMQX 集群,并配置和使用所需的各项功能。
在浏览器里输入: http://122.112.225.194:18083 就可以访问EMQX的后台管理页面。可以管理以连接的客户端或检查运行状态。
这里面的IP地址,就是自己ECS云服务器的公网IP地址。
打开浏览器后,输入地址后打开的效果:
默认用户名和密码:
- 用户名:admin
- 密码:public
第一次登录会提示你修改新密码,如果不想设置,也可以选择跳过(公网服务器部署,还是要修改密码安全些)。
下面修改新密码:
登录成功的页面显示如下:
这里可以配置MQTT的一些参数,根据自己的需求进行配置。
新建一个客户端,点击连接。
连接之后,然后点击订阅,和发布,如果下面消息能正常的接收。说明MQTT服务器通信是已经正常,没问题了。
并且在这个页面也可以看到主题发布和主题订阅的格式。
接下来就打开我们自己的MQTT客户端登录MQTT服务器进行测试数据的通信。
端口选择: 1883
根据软件参数填入参数,登录,进行主题的发布和订阅。
说明: 目前还没有配置客户端认证,现在只要IP和端口输入正确,MQTT三元组可以随便输入,都可以登录上服务器的,服务器没有对三元组做校验。
EMQ X 默认配置中启用了匿名认证,任何客户端都能接入 EMQX。没有启用认证插件或认证插件没有显式允许/拒绝(ignore)连接请求时,EMQX 将根据匿名认证启用情况决定是否允许客户端连接。
然后打开EMQX的管理后台,可以看到我们的设备已经登录服务器了,名字为test1。
在订阅主题的页面也可以看到我们客户端设备订阅的主题。
EMQX 默认配置中启用了匿名认证,任何客户端都能接入 EMQX。没有启用认证插件或认证插件没有显式允许/拒绝(ignore)连接请求时,EMQX 将根据匿名认证启用情况决定是否允许客户端连接。
在正式产品里肯定是要启用认证的,不然任何设备都能接入。
下面就介绍如何配置 客户端认证。
【1】打开客户端认证页面
【2】选择密码认证
【3】选择内置数据库
【4】设置认证方式(都可以默认,不用改),直接点击创建。
【5】创建成功后,点击用户管理
【6】添加用户
【7】添加成功
【8】添加完毕之后,打开MQTT客户端可以进行测试。
登录的时候,MQTT用户名和密码必须输入正确,按照上一步添加的信息进行如实填写,否则是无法登录服务器的。
客户端授权页面可以配置每个客户端(设备)的主题发布,订阅权限。限制它是否可以发布主题,订阅主题。 如果有需要就可以进行配置。
http://127.0.0.1:18083/#/authorization/detail/built_in_database?tab=users
【1】创建数据源
【2】选择内置数据库
【3】完成创建
【4】点击权限管理
【5】选择客户端ID,点击添加
【6】配置权限
在集成选项里,可以对设备数据处理。 比如:转发到自己的HTTP服务器,转发到自己其他的MQTT服务器,创建规则,某些事件触发某些动作等等。
选择数据桥接。
可以把数据发送端自己的HTTP服务器,或者发送到其他的MQTT服务器。
选择HTTP服务 (如果自己有HTTP服务器,可以将数据转发给自己的HTTP服务器)。
为了方便测试设备间互相订阅主题,数据收发,在客户端认证页面至少添加2个设备。我这里分别添加了test1和test2。
设备A订阅设备B的主题,设备B订阅设备A的主题,实现数据互发。
设备A的MQTT信息:
- MQTT服务器地址:122.112.225.194
- MQTT服务器端口号:1883
- MQTT客户端ID:AAA
- MQTT用户名:test1
- MQTT登录密码:12345678
-
- 订阅主题:BBB/#
- 发布主题:AAA/1
- 发布的消息:{ "msg": "我是AAA设备" }
设备B的MQTT信息:
- MQTT服务器地址:122.112.225.194
- MQTT服务器端口号:1883
- MQTT客户端ID:BBB
- MQTT用户名:test2
- MQTT登录密码:12345678
-
- 订阅主题:AAA/#
- 发布主题:BBB/1
- 发布的消息:{ "msg": "我是BBB设备" }
BC20/BC26 开启GPS、连接MQTT服务器的AT指令发送流程。
(1)查询模块是否正常
- AT
-
- OK
(2)获取卡号,查询卡是否插好
- AT+CIMI
-
- 460041052911195
-
- OK
(3)激活网络
- AT+CGATT=1
-
- OK
(4)获取网络激活状态
- AT+CGATT?
-
- +CGATT: 1
-
- OK
(5)查询网络质量
- AT+CSQ
-
- +CSQ: 26,0
-
- OK
(6)检查网络状态
- AT+CEREG=? //检查网络状态
- +CEREG: 0,1 //找网成功
- OK
(7)激活GPS
- 激活GPS,要等一段时间
- AT+QGNSSC=1
-
- OK
(8)查询GPS激活状态
- 查询激活状态,1表示成功激活
- AT+QGNSSC?
-
- +QGNSSC: 1
-
- OK
(9)获取一次GPS定位语句
- AT+QGNSSRD="NMEA/RMC"
- +QGNSSRD: $GNRMC,120715.00,A,3150.78179,N,11711.93433,E,0.000,,310818,,,A,V*19
- OK
(10)连接MQTT服务器
- AT+QMTOPEN=0,"a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com",1883
-
- OK
-
- +QMTOPEN: 0,0
(11)登录MQTT服务器
- 命令格式: AT+QMTCONN=<tcpconnectID>,<clientID>,<username>,<password>
- AT+QMTCONN=0,"6210e8acde9933029be8facf_dev1_0_0_2022021913","6210e8acde9933029be8facf_dev1","6cea55404b463e666cd7a6060daba745bbaa17fe7078dfef45f8151cdf19673d"
-
- OK
-
- +QMTCONN: 0,0,0
(12)订阅主题
- 命令格式: AT+QMTSUB=<tcpconnectID>,<msgID>,"<topic1>”,<qos1>[,"<topic2>”,<qos2>…]
-
- AT+QMTSUB=0,1,"$oc/devices/6210e8acde9933029be8facf_dev1/sys/messages/down",2
-
- OK
-
- +QMTSUB: 0,1,0,2
(13)发布主题
- 命令格式:AT+QMTPUB=<tcpconnectID>,<msgID>,<qos>,<retain>,"<topic>","<msg>"
-
- 先发送指令:
- AT+QMTPUB=0,0,0,0,"$oc/devices/6210e8acde9933029be8facf_dev1/sys/properties/repor"
-
- 等待返回 ">"
- 接着发送数据.不需要加回车。
- "{"services": [{"service_id": "gps","properties":{"longitude":12.345,"latitude":33.345}}]}"
- 数据发送完毕,再发送结束符。 十六进制的值--0x1a 。某些串口调试助手可以适应ctrl+z 快捷键输入0xA
- 等待模块返回"OK",到此数据发送完成。
- OK
-
- +QMTPUB: 0,0,0
下面贴出的是 通过 I2C 接口与 BH1750 光照传感器通信,读取光敏值并通过串口打印的代码:
- #include "stm32f1xx_hal.h"
- #include "stdio.h"
-
- I2C_HandleTypeDef hi2c1;
- UART_HandleTypeDef huart1;
-
- #define BH1750_ADDRESS (0x23 << 1) // BH1750地址
-
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_USART1_UART_Init(void);
- static void MX_I2C1_Init(void);
-
- int main(void)
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- MX_I2C1_Init();
-
- uint8_t data[2];
- uint16_t lux;
-
- while (1)
- {
- HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDRESS, (uint8_t[]){0x10}, 1, HAL_MAX_DELAY); // 设置单次高分辨率模式
- HAL_Delay(180); // 等待传感器测量完成
-
- HAL_I2C_Master_Receive(&hi2c1, BH1750_ADDRESS, data, 2, HAL_MAX_DELAY); // 读取光照值
- lux = (data[0] << 8) | data[1];
-
- char buffer[20];
- sprintf(buffer, "Lux: %d\r\n", lux);
- HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY); // 通过串口打印光照值
-
- HAL_Delay(1000); // 延时1秒
- }
- }
-
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
-
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- static void MX_I2C1_Init(void)
- {
- hi2c1.Instance = I2C1;
- hi2c1.Init.ClockSpeed = 400000;
- hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
- hi2c1.Init.OwnAddress1 = 0;
- hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
- hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
- hi2c1.Init.OwnAddress2 = 0;
- hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
- hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
- if (HAL_I2C_Init(&hi2c1) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- static void MX_USART1_UART_Init(void)
- {
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- void Error_Handler(void)
- {
- while (1)
- {
- }
- }
-
- #ifdef USE_FULL_ASSERT
- void assert_failed(uint8_t *file, uint32_t line)
- {
- }
- #endif
下面贴出的是 DHT11 温湿度传感器读取环境温湿度数据并通过串口打印的代码:
- #include "stm32f1xx_hal.h"
- #include "stdio.h"
-
- TIM_HandleTypeDef htim2;
- UART_HandleTypeDef huart1;
-
- #define DHT11_GPIO_PORT GPIOA
- #define DHT11_GPIO_PIN GPIO_PIN_0
-
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_USART1_UART_Init(void);
- static void MX_TIM2_Init(void);
-
- int main(void)
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- MX_TIM2_Init();
-
- HAL_TIM_Base_Start(&htim2);
-
- while (1)
- {
- HAL_TIM_Base_Start(&htim2);
- HAL_Delay(2000); // 等待2秒
-
- // 发送开始信号
- HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_RESET);
- HAL_Delay(18);
- HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET);
- HAL_Delay(20);
-
- // 设置引脚为输入
- GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
-
- // 等待 DHT11 响应
- while (!HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN))
- ;
- while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN))
- ;
-
- // 读取数据
- uint8_t data[5] = {0};
- for (int i = 0; i < 5; i++)
- {
- for (int j = 0; j < 8; j++)
- {
- while (!HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN))
- ;
- HAL_TIM_Base_Start(&htim2);
- while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN))
- ;
- if (HAL_TIM_Base_GetCounter(&htim2) > 40)
- data[i] |= (1 << (7 - j));
- }
- }
-
- // 计算温度和湿度
- uint8_t humidity = data[0];
- uint8_t temperature = data[2];
-
- char buffer[50];
- sprintf(buffer, "Temperature: %d°C, Humidity: %d%%\r\n", temperature, humidity);
- HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY); // 通过串口打印温湿度数据
- }
- }
-
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
-
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- static void MX_TIM2_Init(void)
- {
- htim2.Instance = TIM2;
- htim2.Init.Prescaler = 72 - 1;
- htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
- htim2.Init.Period = 65535;
- htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- HAL_TIM_Base_Init(&htim2);
- }
-
- static void MX_USART1_UART_Init(void)
- {
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- void Error_Handler(void)
- {
- while (1)
- {
- }
- }
-
- #ifdef USE_FULL_ASSERT
- void assert_failed(uint8_t *file, uint32_t line)
- {
- }
- #endif
通过 ADC 模块读取土壤湿度并通过串口打印的代码:
- #include "stm32f1xx_hal.h"
- #include "stdio.h"
-
- ADC_HandleTypeDef hadc1;
- UART_HandleTypeDef huart1;
-
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_USART1_UART_Init(void);
- static void MX_ADC1_Init(void);
-
- int main(void)
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- MX_USART1_UART_Init();
- MX_ADC1_Init();
-
- uint16_t adc_value;
-
- while (1)
- {
- HAL_ADC_Start(&hadc1); // 启动 ADC 转换
- if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
- {
- adc_value = HAL_ADC_GetValue(&hadc1); // 读取 ADC 值
- char buffer[50];
- sprintf(buffer, "Soil Moisture: %d\r\n", adc_value);
- HAL_UART_Transmit(&huart1, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY); // 通过串口打印土壤湿度数据
- }
- HAL_Delay(1000); // 延时1秒
- }
- }
-
- void SystemClock_Config(void)
- {
- // 略,根据实际情况配置系统时钟
- }
-
- static void MX_ADC1_Init(void)
- {
- ADC_ChannelConfTypeDef sConfig = {0};
-
- hadc1.Instance = ADC1;
- hadc1.Init.ScanConvMode = DISABLE;
- hadc1.Init.ContinuousConvMode = DISABLE;
- hadc1.Init.DiscontinuousConvMode = DISABLE;
- hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
- hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- hadc1.Init.NbrOfConversion = 1;
- if (HAL_ADC_Init(&hadc1) != HAL_OK)
- {
- Error_Handler();
- }
-
- sConfig.Channel = ADC_CHANNEL_0; // 修改为实际连接的通道
- sConfig.Rank = 1;
- sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5; // 根据实际情况调整采样时间
- if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- static void MX_USART1_UART_Init(void)
- {
- huart1.Instance = USART1;
- huart1.Init.BaudRate = 115200;
- huart1.Init.WordLength = UART_WORDLENGTH_8B;
- huart1.Init.StopBits = UART_STOPBITS_1;
- huart1.Init.Parity = UART_PARITY_NONE;
- huart1.Init.Mode = UART_MODE_TX_RX;
- huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart1.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart1) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- void Error_Handler(void)
- {
- while (1)
- {
- }
- }
-
- #ifdef USE_FULL_ASSERT
- void assert_failed(uint8_t *file, uint32_t line)
- {
- }
- #endif
本智慧农业管理系统设计与实现项目基于STM32F103RCT6微控制器为核心,通过集成DHT11温湿度传感器、BH1750光照强度传感器和土壤湿度检测传感器等设备,构建了一套全面的农田环境监测系统。当环境参数超出预设阈值时,系统能够实时报警并自动或提醒进行灌溉、施肥等操作,同时利用蜂鸣器发出声音警报。
在远程控制方面,系统采用NBIoT-BC26模块实现了无线通信功能,将采集到的数据传输至云端MQTT服务器,并通过EMQX开源框架搭建的服务器处理数据。用户可通过微信小程序随时随地查看农田环境的各项实时数据,实现对农作物生长环境的远程监控,并能便捷地执行手动灌溉、开启补光灯等远程控制操作。
本项目的成功实施,不仅有效提升了农业生产过程中的智能化水平,降低了人工管理成本,而且为实现精准农业和智慧农业提供了有力的技术支持。未来,随着物联网技术、云计算和人工智能技术的进一步发展,这套智慧农业管理系统将有望在更多领域推广使用,助力我国现代农业朝着更高效、智能、可持续的方向迈进。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。