基于ESP32设计的智能养蜂监测系统

文章目录

一、前言

1.1 项目开发背景

随着现代养蜂业向规模化、智能化和精细化方向不断发展,传统依靠人工巡检的蜂箱管理方式已经难以满足现代蜂场对生产效率和蜂群健康管理的要求。在实际养殖过程中,养蜂人员通常需要定期前往蜂场检查蜂群活动情况、蜂蜜储量、环境温湿度以及蜂箱运行状态,不仅劳动强度大,而且受到天气、地理位置和时间因素的影响,存在监测不及时、管理效率低等问题。当蜂箱内部环境发生异常变化时,往往无法第一时间发现并采取相应措施,容易造成蜂群活力下降、蜂蜜产量降低甚至蜂群损失。

蜂群属于对环境变化十分敏感的生物群体,其生长繁殖和采蜜活动与温度、湿度、光照等环境因素密切相关。蜂箱内部温湿度过高或过低都会影响蜂群正常生长,而蜂箱重量变化则能够反映蜂蜜储量及蜂群活动情况。同时,蜂群发出的鸣声也能够反映其健康状态,当出现分蜂、失王、疾病或异常应激情况时,声音特征往往会发生明显变化。因此,对蜂箱运行状态进行多维度实时监测,对于提高养蜂管理水平、保障蜂群健康以及提升蜂产品产量具有重要意义。

近年来,物联网技术、无线通信技术以及云平台技术得到了快速发展,为智慧养蜂系统的建设提供了良好的技术基础。通过在蜂箱内部部署多种传感器,可以实时采集温湿度、重量、声音、光照以及震动等关键数据,并利用无线网络将监测信息上传至云服务器,实现远程监测与智能管理。管理人员无需频繁前往现场,即可通过移动终端实时查看蜂箱运行状态,从而提高养蜂管理效率,降低人工成本。

在此背景下,本课题设计了一种基于物联网技术的蜂箱智能监测系统。系统以ESP32-S3-N8R8作为核心控制器,结合温湿度传感器、重量传感器、声音采集模块、光照传感器以及震动检测模块,实现蜂箱运行状态的全面感知。通过ESP32-S3内置WiFi功能将监测数据上传至OneNet物联网平台,并采用微信小程序实现数据可视化显示和远程参数配置,使养蜂人员能够随时掌握蜂箱运行情况,及时发现异常状态并进行处理。

本系统的研究与设计不仅能够提高蜂箱管理的自动化和智能化水平,还能够为现代智慧养蜂提供可靠的数据支撑和技术方案,对于提升养蜂产业的信息化管理能力、保障蜂群健康生长以及促进智慧农业发展具有重要的现实意义和应用价值。

1.2 设计实现的功能

(1)系统采用ESP32-S3-N8R8作为主控制器,完成蜂箱内部与外部环境数据的采集、处理以及物联网通信控制。

(2)支持蜂箱外部温湿度监测,通过DHT11传感器实时采集蜂箱外部环境温度和湿度信息,并上传至物联网平台。

(3)支持蜂箱内部温湿度监测,通过DHT11传感器实时采集蜂箱内部温度和湿度数据,为蜂群生长环境分析提供依据。

(4)支持蜂箱重量检测,利用称重传感器与HX711高精度采集模块实时测量蜂箱重量变化情况,用于反映蜂蜜储量及蜂群活动状态。

(5)支持蜂箱声音采集功能,通过MAX9814麦克风模块采集蜂箱内部蜂群鸣声数据,为蜂群活力和状态分析提供参考信息。

(6)支持蜂箱震动检测功能,利用SW420震动传感器监测蜂箱入口及周围震动情况,实现异常震动状态识别。

(7)支持环境光照强度检测,通过BH1750光照传感器实时测量蜂箱外部光照强度,辅助分析蜂群活动规律。

(8)支持OLED显示功能,通过0.96寸OLED显示屏实时显示蜂箱内外温湿度、光照强度、蜂箱重量、声音采集值以及震动状态等信息。

(9)支持无线联网功能,利用ESP32-S3内置WiFi模块连接网络,实现监测数据的远程传输。

(10)支持物联网云平台数据上传功能,通过MQTT协议将蜂箱监测数据实时上传至OneNet物联网平台,实现远程监测与数据存储。

(11)支持微信小程序数据可视化功能,用户可通过微信小程序实时查看蜂箱各项监测数据及运行状态。

(12)支持报警阈值远程配置功能,可通过微信小程序对温度、湿度以及重量报警阈值进行设置,并下发至设备端。

(13)支持重量异常报警功能,当蜂箱重量超过设定上限或出现异常减重情况时,系统产生报警提示并上传报警状态。

(14)支持温湿度超限报警功能,当蜂箱内部或外部温湿度超过设定阈值时,系统自动产生报警信息并上传至云平台。

(15)支持震动异常报警功能,当检测到异常震动情况时,系统自动更新报警状态并上传至物联网平台,实现远程预警。

1.3 项目硬件模块组成

(1)主控模块:采用ESP32-S3-N8R8作为系统核心控制器,负责各类传感器数据采集、数据处理、OLED显示控制以及WiFi通信管理。

(2)蜂箱内部温湿度采集模块:采用DHT11温湿度传感器,用于检测蜂箱内部温度和湿度变化情况。

(3)蜂箱外部温湿度采集模块:采用DHT11温湿度传感器,用于检测蜂箱外部环境温度和湿度信息。

(4)重量检测模块:由10kg称重传感器和HX711高精度称重采集模块组成,用于实时测量蜂箱重量变化。

(5)声音采集模块:采用MAX9814自动增益麦克风模块,用于采集蜂箱内部蜂群鸣声信息。

(6)震动检测模块:采用SW420震动传感器模块,用于检测蜂箱震动状态以及异常干扰情况。

(7)光照检测模块:采用BH1750数字光照传感器,用于测量蜂箱周围环境光照强度。

(8)显示模块:采用0.96英寸OLED显示屏,用于本地显示蜂箱内外温湿度、重量、光照强度、声音采集值以及震动状态等信息。

(9)无线通信模块:利用ESP32-S3内置WiFi功能,实现设备与OneNet物联网平台之间的数据通信。

(10)电源管理模块:采用AMS1117稳压电路构成5V/3.3V供电系统,为主控芯片及各功能模块提供稳定电源。

(11)电池供电模块:采用18650锂电池和电池保护板组成储能单元,为系统提供持续供电能力。

(12)太阳能供电模块:采用太阳能电池板作为辅助能源,为户外蜂箱监测设备提供充电支持,提高系统续航能力。

项目开发使用的全部软件工具和项目代码已经上传到网盘:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink

1.4 系统框架图

1.5 运行流程图

二、OneNet平台搭建

2.1 OneNet平台介绍

OneNet是中国移动打造的物联网开放平台,为物联网设备与应用开发者提供稳定、可靠、可扩展的云端服务。该平台向下连接海量设备,支持设备接入、数据采集与远程控制;向上提供数据存储、分析与应用使能工具,帮助用户快速搭建各类物联网解决方案。作为国内领先的物联网PaaS平台,OneNet具备高并发处理能力和毫秒级消息响应能力,其分布式集群架构可保障99.95%的服务可用性。

在功能层面,OneNet支持MQTT、CoAP、LwM2M等多种主流物联网协议,并提供设备注册、认证、生命周期管理以及设备影子等功能。平台内嵌规则引擎,可实现数据流转与场景联动,同时配备了数据可视化大屏和时序数据库,便于用户进行数据分析和监控。安全机制方面,OneNet提供了设备身份认证、数据加密传输和访问控制策略,确保设备和数据的安全可靠。

在生态与开发支持方面,OneNet提供了多语言SDK(如Java、Python、C、Node.js等)、详细的开发者文档、设备模拟器以及活跃的开发者社区,帮助开发者和企业快速完成从设备端到应用端的集成。该平台已广泛应用于智慧城市、工业物联网、智慧家居、车联网等领域,例如智能路灯、设备远程监控、智能家电控制、车辆定位追踪等典型场景。随着5G、AI和边缘计算技术的发展,OneNet正在持续融合边缘计算能力与人工智能分析,进一步提升平台的实时性与数据价值,助力企业数字化转型。

2.2 创建产品

(1)登录账户

官网:https://open.iot.10086.cn/

进来先登录账号。

(2)选择物联网开放平台

(3)创建产品

根据自己产品信息填写:

创建之后点击确定。

创建完成。

(4)产品ID

cpp 复制代码
产品ID: Dy3FSnC24O

2.3 创建设备

产品是属性抽象模型,产品下面的设备就表示具体的硬件设备,需要与具体的硬件关联。产品下可以创建很多的设。

(1)添加设备

(2)填写设备信息

创建完成。

创建完成。

(3)查看设备详情

添加完成之后,点击查看详情,查看设备的详细信息。

这里的产品ID、设备ID、设备密匙非常有用。后续MQTT登录参数需要使用。这里记录一下。

cpp 复制代码
产品ID:  Dy3FSnC24O
设备ID:  2605967662
设备密匙:b211dUEzY2pZdHdJMXhFS1FzTDBQbjYzdk1WMjRZZkg=
设备名称:dev1

2.4 添加数据流模板

(1)添加数据流模板

添加数据流模板。

(2)根据设备需求添加

复制代码
data1  测试数据字段1
data2  测试数据字段2
data3  测试数据字段3
data4  测试数据字段4
data5  测试数据字段5

开始创建:

(3)添加完毕

这里可以看到订阅,发布主题的格式。

2.5 MQTT协议接入地址

当前智能鱼缸设备是采用MQTT协议与OneNet服务器进行通信。

MQTT物联网套件产品架构如下图所示:

接入地址说明:https://open.iot.10086.cn/doc/v5/develop/detail/248

在帮助文档页面,介绍了MQTT接入的地址和端口号。 当前设备是单片机,端口采用1883非加密端口。

地址与端口总结如下:

cpp 复制代码
固定的IP地址: 183.230.40.96
固定的端口号: 1883

2.6 MQTT主题订阅与发布

MQTT协议是一种消息列队传输协议,采用订阅、发布机制,订阅者只接收自己已经订阅的数据,非订阅数据则不接收,既保证了必要的数据的交换,又避免了无效数据造成的储存与处理。因此在工业物联网中得到广泛的应用。

(1)主题订阅

主题订阅是设备订阅平台的消息,如果设备想知道平台下发的消息,就需要订阅主题。

帮助文档: https://open.iot.10086.cn/doc/mqtt/book/device-develop/protocol.html

需要订阅什么数据,设备端按照下面的主题格式填写订阅即可。

如果想知道设备所有相关信息,直接订阅$sys/{产品ID}/{device-name}/#即可。 (其中的PID就是产品ID)

cpp 复制代码
$sys/Dy3FSnC24O/dev1/#

(2)主题发布

主题发布: 就是设备向平台上传数据。

帮助文档地址:https://open.iot.10086.cn/doc/mqtt/book/example/datapoints.html

文档里介绍了数据点上传的格式:

根据当前设备,总结的格式如下:

cpp 复制代码
发布主题: $sys/Dy3FSnC24O/dev1/dp/post/json

发布消息:
{"id":123,"dp":{"data1":[{"v":6.4}],"data2":[{"v":3.4}]}}

dp对象里面就是需要上传的数据点字段。 这个数据点的名字就是自己创建数据流模板的时候创建的。

数据点是标准的JSON结构:

cpp 复制代码
{
  "id": 123,
  "dp": {
    "data1": [
      {
        "v": 6.4
      }
    ],
    "data2": [
      {
        "v": 3.4
      }
    ]
  }
}

2.7 MQTT三元组生成

设备登录OneNet采用的是MQTT协议,MQTT协议登录需要填写 登录信息:简称 MQTT三元组

(1)需要的参数

(2)密码生成规则

链接:https://open.iot.10086.cn/doc/v5/develop/detail/241

(3)编写生成密码的算法

这里算法代码采用Python编写。下面是生成密码的Python算法。

电脑先安装Python环境,然后将下面代码copy到文本里,文本后缀改为.py,就可以允许python代码了。

python 复制代码
import base64
import hmac
from urllib.parse import quote
import time

# 中国移动官方文档给出的核心秘钥计算算法
def token(id,access_key):  
    version = '2018-10-31'
    res = 'products/%s' % id  # 通过产品ID访问产品API
    # 用户自定义token过期时间
    et = str(int(time.time()) + 63072000) # 设置为2年有效时间
    # 签名方法,支持md5、sha1、sha256
    method = 'sha1'
    # 对access_key进行decode
    key = base64.b64decode(access_key)
    # 计算sign
    org = et + '\n' + method + '\n' + res + '\n' + version
    sign_b = hmac.new(key=key, msg=org.encode(), digestmod=method)
    sign = base64.b64encode(sign_b.digest()).decode()
    # value 部分进行url编码,method/res/version值较为简单无需编码
    sign = quote(sign, safe='')
    res = quote(res, safe='')
    # token参数拼接
    token = 'version=%s&res=%s&et=%s&method=%s&sign=%s' % (version, res, et, method, sign)
    return token

username    = "Dy3FSnC24O"                                           # 产品ID
accesskey   = "c3BoeTdqM3hPQXI4Zm1HckdhZTJieEpyT1N0eGpXTDI="         # accessKey
password = token(username, accesskey)
print(password)

# 等待用户按下 Enter 键再退出
input("按 Enter 键退出程序...")

先安装好Python环境。

根据自己的实际修改以上的产品ID与accessKey

**将上面的文件保存为 xxx.py 文件,然后双击运行: ** 就得到了生成的key

(4)MQTT登录参数总结

MQTT协议登录时,需要输入3个参数: MQTT-设备ID,MQTT-设备名称,MQTT-密码。

对应OneNet的参数:

cpp 复制代码
MQTT的设备ID  -----> 就是OneNet的设备名称

MQTT的设备名称-----> 就是OneNet的产品ID

MQTT的密码------------> 就是OneNet的密匙工具生成的密码

下面是对本次的设备做总结:

cpp 复制代码
IP地址: 183.230.40.96
端口号: 1883
clientId: dev1
username: Dy3FSnC24O
password: version=2018-10-31&res=products%2FDy3FSnC24O&et=1827306543&method=sha1&sign=Yzr14cK2iyhIDhYSCXMf89h%2BeQk%3D
订阅主题:  $sys/Dy3FSnC24O/dev1/#


发布主题: $sys/Dy3FSnC24O/dev1/dp/post/json

发布消息:
{"id":123,"dp":{"data1":[{"v":6.4}],"data2":[{"v":3.4}]}}

2.8 MQTT工具登录测试

前面已经介绍了MQTT协议登录需要用到的参数,以及订阅主题、发布主题的格式,接下来我们通过MQTT工具模拟设备登录OneNet平台,完成数据交互测试。

简单来说: 就是用软件来模拟实际的硬件,登录onenet平台,上传数据,走一下这个流程。

(1)模拟设备登录

接下来根据软件的输入框提示,输入对应的参数,然后登录设备,订阅主题,发布主题即可完成一个流程的测试。

(2)登录OneNet控制台查看设备

在设备列表页面,可以看到设备已经在线了。

在设备详情页面可以看到设备模拟器刚才上传的数据。

在设备的数据流页面可以看到上传的数据。

(3)查看历史数据

切换成列表模式。可以查看历史数据。

点击数据名称,可以查看数据的历史数据,同时可以导出EXECL表格,还可以看历史数据变化波形。

到此,设备的云平台已经配置完毕。

2.9 上位机开发必备参数

开发上位机需要得到OneNet的一些参数,生成鉴权的Token。

查看AccessKey:

下面就可以查看了:

复制保存下来,后面需要使用:

cpp 复制代码
fa6da5ee39964d9c9a168fec801b7dd1

链接地址:https://open.iot.10086.cn/console/summary

cpp 复制代码
产品ID:Dy3FSnC24O
设备名称: dev1

AccessKey:
fa6da5ee39964d9c9a168fec801b7dd1

用户ID:477709

三、微信小程序开发

1.1 下载开发工具

链接地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/log.html#stable-2.01.2510290

1.2 安装开发工具

双击安装。

点击下一步。

安装完毕了找到开发工具的位置。

如果桌面没有自动创建快捷方式。可以自己创建一个。

1.3 打开使用开发工具

进去之后,可以微信扫码登录。

关闭默认打开的工程。就会看到下面的页面。

选择 + 号。

1.4 新建工程

APPID可以注册一个,也可先使用测试号。 然后,选择小程序,模版选择基础,选择-JS-基础模版。

选择创建。

工程打开之后就可以点击预览测试。

微信扫码就可以看默认的效果了。

1.5 微信小程序代码


1. app.js

javascript 复制代码
App({
  globalData: {
    deviceName: "BeeBox",
    productId: "你的产品ID",
    apiKey: "你的OneNet_API_KEY",

    sensorData: {
      DHT11_1_T: 0,
      DHT11_1_H: 0,

      DHT11_2_T: 0,
      DHT11_2_H: 0,

      BH1750: 0,
      HX711: 0,

      MAX9814: 0,
      SW420: 0,

      Alarm: 0
    }
  }
})

2. app.json

json 复制代码
{
  "pages": [
    "pages/index/index",
    "pages/setting/setting",
    "pages/alarm/alarm",
    "pages/chart/chart"
  ],

  "window": {
    "navigationBarTitleText": "蜂箱智能监测系统",
    "navigationBarBackgroundColor": "#f6c343",
    "navigationBarTextStyle": "black",
    "backgroundColor": "#f5f5f5"
  },

  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

3. app.wxss

css 复制代码
page{
  background:#f5f5f5;
}

4. utils/onenet.js

javascript 复制代码
const API_KEY = "你的OneNet_API_KEY"
const DEVICE_ID = "你的设备ID"

function getData(callback)
{
  wx.request({
    url:
    'https://iot-api.heclouds.com/thingmodel/query-device-property',

    method:'POST',

    header:{
      'authorization':API_KEY,
      'content-type':'application/json'
    },

    data:{
      product_id:"你的产品ID",
      device_name:"BeeBox"
    },

    success(res)
    {
      callback(res.data)
    },

    fail(err)
    {
      console.log(err)
    }
  })
}

module.exports = {
  getData
}

5. pages/index/index.json

json 复制代码
{
  "navigationBarTitleText":"实时监测"
}

6. pages/index/index.wxml

xml 复制代码
<view class="container">

  <view class="title">
    蜂箱智能监测系统
  </view>

  <view class="card">

    <view class="item">
      <text>箱外温度</text>
      <text>{{DHT11_1_T}} ℃</text>
    </view>

    <view class="item">
      <text>箱外湿度</text>
      <text>{{DHT11_1_H}} %</text>
    </view>

    <view class="item">
      <text>箱内温度</text>
      <text>{{DHT11_2_T}} ℃</text>
    </view>

    <view class="item">
      <text>箱内湿度</text>
      <text>{{DHT11_2_H}} %</text>
    </view>

    <view class="item">
      <text>光照强度</text>
      <text>{{BH1750}} Lux</text>
    </view>

    <view class="item">
      <text>蜂箱重量</text>
      <text>{{HX711}} kg</text>
    </view>

    <view class="item">
      <text>声音采集</text>
      <text>{{MAX9814}} dB</text>
    </view>

    <view class="item">
      <text>震动状态</text>

      <text wx:if="{{SW420==0}}">
        正常
      </text>

      <text wx:if="{{SW420==1}}">
        报警
      </text>

    </view>

    <view class="item">
      <text>报警状态</text>

      <text class="green" wx:if="{{Alarm==0}}">
        正常
      </text>

      <text class="red" wx:if="{{Alarm==1}}">
        报警
      </text>

    </view>

  </view>

  <view class="menu">

    <navigator url="/pages/chart/chart">
      <button>历史曲线</button>
    </navigator>

    <navigator url="/pages/alarm/alarm">
      <button>报警记录</button>
    </navigator>

    <navigator url="/pages/setting/setting">
      <button>阈值设置</button>
    </navigator>

  </view>

</view>

7. pages/index/index.wxss

css 复制代码
.container{
  padding:20rpx;
}

.title{
  text-align:center;
  font-size:40rpx;
  font-weight:bold;
  margin-top:20rpx;
  margin-bottom:20rpx;
}

.card{
  background:white;
  border-radius:20rpx;
  padding:20rpx;
}

.item{
  display:flex;
  justify-content:space-between;
  border-bottom:1px solid #eeeeee;
  padding:20rpx 0;
}

.red{
  color:red;
  font-weight:bold;
}

.green{
  color:green;
  font-weight:bold;
}

.menu{
  margin-top:30rpx;
}

button{
  margin-top:20rpx;
}

8. pages/index/index.js

javascript 复制代码
const onenet = require('../../utils/onenet.js')

Page({

  data:{

    DHT11_1_T:0,
    DHT11_1_H:0,

    DHT11_2_T:0,
    DHT11_2_H:0,

    BH1750:0,
    HX711:0,

    MAX9814:0,
    SW420:0,

    Alarm:0
  },

  onLoad()
  {
    this.getSensorData()

    this.timer=setInterval(()=>{
      this.getSensorData()
    },5000)
  },

  onUnload()
  {
    clearInterval(this.timer)
  },

  getSensorData()
  {
    let that=this

    onenet.getData(function(res){

      let list=res.data

      for(let i=0;i<list.length;i++)
      {
        let id=list[i].identifier
        let value=list[i].value

        if(id=="DHT11_1_T")
        {
          that.setData({
            DHT11_1_T:value
          })
        }

        if(id=="DHT11_1_H")
        {
          that.setData({
            DHT11_1_H:value
          })
        }

        if(id=="DHT11_2_T")
        {
          that.setData({
            DHT11_2_T:value
          })
        }

        if(id=="DHT11_2_H")
        {
          that.setData({
            DHT11_2_H:value
          })
        }

        if(id=="BH1750")
        {
          that.setData({
            BH1750:value
          })
        }

        if(id=="HX711")
        {
          that.setData({
            HX711:value
          })
        }

        if(id=="MAX9814")
        {
          that.setData({
            MAX9814:value
          })
        }

        if(id=="SW420")
        {
          that.setData({
            SW420:value
          })
        }

        if(id=="Alarm")
        {
          that.setData({
            Alarm:value
          })
        }

      }

    })
  }

})

四、搭建ESP32开发环境

4.1 安装VSCode代码编辑器

【1】下载软件包

下载地址: https://code.visualstudio.com/

安装包下载之后,直接鼠标双击运行。

【2】开始安装

接受协议继续安装。

选择一下安装路径。

浏览路径。

安装。

【4】配置中文语言

安装完成。打开的页面。

软件安装之后下面设置 Visual Studio 支持中文语言

首先打开 Visual Studio 软件, 再按下F1 或者 Shift + Ctrl + P

然后在命令行输入 Configure Display Language

选择安装语言选项。

安装之后右下角有提示重启,点击重启即可。

【5】配置主题颜色

修改vscode的颜色主题

下面介绍更改颜色vscode的内置颜色主题方法。

4.2 安装ESP-IDE环境

官方教程:https://docs.espressif.com/projects/esp-idf/zh_CN/v5.1.5/esp32/get-started/index.html

【1】安装IDE环境

链接:https://dl.espressif.cn/dl/esp-idf/

下载成功后,双击开始安装。 安装的路径可以选择D盘,毕竟占用的空间还是比较大的。 比如,在D盘创建一个文件夹。ESP_IDF 后面安装时,路径就选择这文件夹。

注意:安装的时候要关闭VSCODE软件。

【2】VSCODE安装插件

官方教程:https://docs.espressif.com/projects/vscode-esp-idf-extension/zh_CN/latest/index.html

上一步安装完毕之后。 再打开VSCODE软件。

打开扩展商店,搜索espressif,然后看到第一个ESP-IDF ,点击右边出现的安装。

安装成功之后,打开命令行面板。

然后 输入 configure esp-idf extension

选择下面的弹出来的选项。

选择用户安装的路径。

选择识别出来的安装路径。

接下来就可以正常愉快的开发代码了。

4.3 快速新建工程

【1】快速新建项目

每次打开VSCODE想要快速新建ESP32的项目。

直接在命令行窗口。输入ESP-IDF:新建项目

选择新建项目。

选择新建工程。

配置工程的名称,存储工程的路径(不能出现中文),芯片的型号,调试方式。串口端口(如果当前没有接开发板大电脑里就不用管)。 选好了,点击右下角的选项创建工程。

创建成功之后,下面就可以选择创建工程的例程模版。

在第一个选项点击后会弹出两个选项可以选择,是使用扩展例程(ExtenSion)还是使用官方IDF的例程(ESP-IDF)。

当前选择 【ExtenSion】下的 【template-app】进行工程创建。(还有很多的例程,大家可以自行尝试)

点击右边的按钮,创建模版工程。

创建完成之后,右下角会提示【工程已经创建完毕,是否用新窗口打开工程?】点击Yes则会出现打开一个VSCode窗口,点击NO则会在该界面显示工程。

打开工程可以写一段打印函数。测试工程运行情况。

然后把ESP32通过串口插到电脑USB口上。

在下面可以选择下载方式,选择串口,然后选择串口的端口。

点击编译下载。程序运行之后会打印信息到终端。

第一次编译比较慢,需要多等一下。 后面的编译就比较快了。

成功之后,可以看到串口上的数据打印。

到此。工程就搭建好了。

【2】修改配置

在连接成功的情况下,点击设置按钮。

修改FLASH大小

在上方的搜索栏中输入【flash】,根据开发板板载的FLASH大小选择对应的FLASH大小。开发板板载W25Q64是8M大小。

修改系统时钟

在上方的搜索栏中输入【cpu】,根据情况选择CPU频率,这里选择的是最高频率240MHz。

修改完成之后点击【保存】键才会生效。

4.4 编程控制LED灯

【1】点亮LED灯

下面学习如何控制IO口,完成LED灯的控制。

为了模块化编程。下面需要新建一个目录,下面存储我们后续编写的外设硬件的代码。

新建一个hardware 文件夹。

然后在hardware 文件夹下面新建.c文件和.h文件。

新建2个文件。led.c和led.h。方便存储LED灯相关的源代码和函数声明。

在led.c的文件里写上代码:

cpp 复制代码
#include "led.h"

//配置输出寄存器
#define GPIO_OUTPUT_PIN_SEL  (1ULL<<LED_PIN)

/**
 * @函数说明        LED的初始化
 *
 */
void LedGpioConfig(void)
{
    gpio_config_t gpio_init_struct = {0};

    //配置IO为通用IO
    esp_rom_gpio_pad_select_gpio(LED_PIN);

    gpio_init_struct.intr_type = GPIO_INTR_DISABLE;             //不使用中断
    gpio_init_struct.mode = GPIO_MODE_OUTPUT;                   //输出模式
    gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;           //使能上拉模式
    gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;      //失能下拉模式
    gpio_init_struct.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;        //使用GPIO9输出寄存器

    //将以上参数配置到引脚
    gpio_config( &gpio_init_struct );

    //设置引脚输出高电平,默认不让LED亮
    gpio_set_level(LED_PIN, 1);
}

/**
 * @函数说明        设置LED亮
 *
 */
void LedOn(void)
{
    gpio_set_level(LED_PIN, 0);
}

/**
 * @函数说明        设置LED灭
 *
 */
void LedOff(void)
{
    gpio_set_level(LED_PIN, 1);
}

在led.h文件里写上代码:

cpp 复制代码
#ifndef _BSP_LED_H_
#define _BSP_LED_H_

#include "driver/gpio.h"

//设置LED引脚
#define  LED_PIN  48

/**
 * @brief   LED初始化
 *
 */
void LedGpioConfig(void);

/**
 * @brief       设置LED亮
 *
 */
void LedOn(void);

/**
 * @brief       设置LED灭
 *
 */
void LedOff(void);
#endif

然后修改CMakeLists.txt 文件。 这个文件是配置头文件和源文件的路径的。 需要配置了之后,编译器才知道.c和.h文件在什么地方。

cpp 复制代码
idf_component_register(SRCS "main.c"
                            "hardware/led.c"
                    INCLUDE_DIRS "."
                                 "./hardware")

最后编写main.c代码,在main.c文件里写上点灯的调用。

cpp 复制代码
#include <stdio.h>
#include "hardware/led.h"

void app_main(void)
{
    //LED初始化
    LedGpioConfig();

    //设置LED点亮
    LedOn();

}

写完代码之后,点击构建烧录,代码就下载进去了。

下载成功之后,可以看到灯就已经亮了。 绿色的小灯就是点亮的LED灯。

【2】升级成闪光灯

要做成闪光灯就需要用到延时函数。

在ESP-IDF 中,可以使用下面3种方式来实现延时:

  1. vTaskDelay() 函数
    这个函数会让当前的任务挂起指定的时间。例如,vTaskDelay(1000 / portTICK_PERIOD_MS) 会让当前任务挂起 1 秒钟,等待一个系统时钟周期。
  2. usleep() 函数 这个函数可以以微秒为单位精准延时。例如, usleep(1000000) 会让任务休眠 1 秒钟。
  3. esp_rom_delay_us()函数
    可以进行微秒级延时。

这里面的void vTaskDelay( const TickType_t xTicksToDelay ) 函数,是将一个任务延迟给定的xTicksToDelay数。任务被阻止的实际时间取决于tick rate。常数portTICK_PERIOD_MS可以用来从tick rate计算实时时间,分辨率为一个tick 周期。至于一个时钟节拍数是1ms,2ms,还是10ms,取决于configTICK_RATE_Hz,即 cONFI6_FREERTOS_HZ。CONFIG_FREERTOS_HZ在sdkconfig中定义,默认是100Hz。则一个时钟节拍数是10ms。

我们可以看一下系统默认的配置。

这个配置在 FreeRTOSConfig.h 文件中:

复制代码
#define configTICK_RATE_HZ		100

简单来说:

configTICK_RATE_HZ 定义了 FreeRTOS 的系统时钟节拍频率,表示:

  • 系统每秒钟产生 100 个时钟节拍(tick)
  • 每个时钟节拍的间隔 = 10ms (1000ms ÷ 100 = 10ms)

在main.c里编写LED闪烁的代码。

cpp 复制代码
#include <stdio.h>
#include "hardware/led.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

/**
 * @函数说明        毫秒延时函数
 * @参数 ms        延时的毫秒数
 * @注意           最小延时为1个FreeRTOS tick
 */
void delay_ms(uint32_t ms)
{
    if (ms == 0) return;
    
    TickType_t ticks = (ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
    vTaskDelay(ticks > 0 ? ticks : 1);
}

void app_main(void)
{
    int state=0;
    //LED初始化
    LedGpioConfig();

     while(1) {
        state=!state;
        delay_ms(1000);  // 延时1秒
        if(state)
        {
            LedOn();
        }
        else
        {
            LedOff();
        }
    }
}

然后编译烧录进去。

就可以看到LED灯在闪烁了。

五、ESP32-代码设计

5.1 硬件连线说明

本系统以 ESP32-S3-N8R8 作为核心控制器,负责采集蜂箱内部与外部环境数据,并通过 WiFi 上传至 OneNet 物联网平台,同时驱动 OLED 显示屏进行本地数据显示。各功能模块与 ESP32-S3 的连接关系如下。


(1)主控模块 ESP32-S3-N8R8

ESP32-S3-N8R8 是整个系统的控制核心,负责完成传感器数据采集、数据处理、OLED显示、WiFi通信以及MQTT数据上传等功能。

主要供电连接:

  • ESP32-S3 3.3V → 系统3.3V电源
  • ESP32-S3 GND → 系统公共地

(2)蜂箱外部温湿度传感器 DHT11 连接

用于检测蜂箱外部环境温度和湿度。

连接方式:

DHT11引脚 ESP32-S3引脚
VCC 3.3V
DATA GPIO4
GND GND

说明:

DATA引脚需要外接一个4.7kΩ~10kΩ上拉电阻连接至3.3V。


(3)蜂箱内部温湿度传感器 DHT11 连接

用于检测蜂箱内部温度和湿度。

连接方式:

DHT11引脚 ESP32-S3引脚
VCC 3.3V
DATA GPIO5
GND GND

说明:

DATA引脚同样需要连接上拉电阻。


(4)重量检测模块(HX711+称重传感器)

用于测量蜂箱重量变化。

称重传感器与HX711连接

称重传感器 HX711
红线(E+) E+
黑线(E-) E-
白线(A-) A-
绿线(A+) A+

HX711与ESP32-S3连接

HX711引脚 ESP32-S3引脚
VCC 3.3V
GND GND
DT GPIO6
SCK GPIO7

说明:

HX711负责将称重传感器输出的微弱毫伏级信号进行放大和数字转换。


(5)声音采集模块 MAX9814 连接

用于采集蜂群鸣声信号。

连接方式:

MAX9814引脚 ESP32-S3引脚
VCC 3.3V
GND GND
OUT GPIO3

说明:

GPIO3配置为ADC输入模式。

MAX9814输出模拟电压信号,ESP32-S3内部ADC完成采样。


(6)震动检测模块 SW420 连接

用于检测蜂箱异常震动情况。

连接方式:

SW420引脚 ESP32-S3引脚
VCC 3.3V
GND GND
DO GPIO8

说明:

SW420输出数字高低电平信号。

正常状态输出低电平,发生震动时输出高电平。


(7)光照检测模块 BH1750 连接

用于检测蜂箱外部光照强度。

连接方式:

BH1750引脚 ESP32-S3引脚
VCC 3.3V
GND GND
SDA GPIO1
SCL GPIO2

说明:

BH1750采用I2C通信方式。

默认地址为0x23。


(8)OLED显示模块连接

采用0.96寸OLED显示屏(SSD1306驱动)。

连接方式:

OLED引脚 ESP32-S3引脚
VCC 3.3V
GND GND
SDA GPIO1
SCL GPIO2

说明:

OLED与BH1750共用I2C总线。

两者通过不同设备地址进行区分:

  • OLED地址:0x3C
  • BH1750地址:0x23

(9)WiFi通信模块

本系统不需要外接无线通信模块。

利用ESP32-S3内部集成WiFi模块实现网络连接。

连接方式:

  • 内置WiFi天线
  • 路由器
  • OneNet服务器

通信流程:

text 复制代码
ESP32-S3
    ↓
WiFi路由器
    ↓
互联网
    ↓
OneNet云平台
    ↓
微信小程序

(10)电源模块连接

采用AMS1117稳压芯片构建供电系统。

输入电源:

  • 18650锂电池
  • 太阳能板充电系统

输出电源:

输出电压 供电对象
5V 外围扩展模块
3.3V ESP32-S3及传感器

连接方式:

text 复制代码
太阳能板
     ↓
充电管理模块
     ↓
18650锂电池
     ↓
AMS1117稳压模块
     ↓
3.3V输出
     ↓
ESP32-S3及各传感器

(11)18650锂电池与太阳能板连接

用于户外长期供电。

连接方式:

text 复制代码
太阳能板
      ↓
锂电池充电管理模块
      ↓
18650锂电池
      ↓
保护板
      ↓
AMS1117稳压模块
      ↓
系统供电

作用:

  • 白天太阳能板为电池充电
  • 夜间由锂电池供电
  • 实现蜂箱监测设备长期无人值守运行

(12)系统总体连线结构图

text 复制代码
                 ┌──────────────┐
                 │ ESP32-S3-N8R8│
                 └──────┬───────┘
                        │
 ┌───────────────┬──────┼───────┬──────────────┐
 │               │      │       │              │
DHT11外部     DHT11内部 HX711  MAX9814      SW420
GPIO4         GPIO5    GPIO6/7 GPIO3       GPIO8
 │               │      │       │            │
温湿度         温湿度  重量检测  声音采集   震动检测

                        │
                I2C总线(GPIO1/2)
                        │
          ┌─────────────┴─────────────┐
          │                           │
      BH1750                     OLED
      光照检测                   显示模块

                        │
                     WiFi
                        │
                     OneNet
                        │
                   微信小程序

5.2 硬件组装过程

【项目复刻_PCB焊接过程演示】 https://www.bilibili.com/video/BV1FmPVzYEVx/?share_source=copy_web\&vd_source=347136f3e32fe297fc17177194ce0a8b

5.3 工程截图

5.4 程序下载

5.5 程序正常运行效果

5.6 取模软件的使用

显示屏上会显示中文,字母,数字等数据,可以使用下面的取模软件进行取模设置。

软件就在资料包里的软件工具目录下

打开软件之后:

5.7 工程代码完整讲解

这是ESP32的main.c文件完整代码以及讲解。

c 复制代码
/********************************************************
 * 文件名:main.c
 * 项目:蜂箱智能监测系统
 * 主控:ESP32-S3-N8R8
 ********************************************************/

#include <stdio.h>
#include <string.h>
#include <math.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_log.h"

#include "wifi.h"
#include "mqtt_onenet.h"

#include "dht11.h"
#include "hx711.h"
#include "bh1750.h"
#include "oled.h"

#include "driver/gpio.h"
#include "driver/adc.h"

/************************************************
 GPIO定义
************************************************/
#define DHT11_OUTSIDE_GPIO      GPIO_NUM_4
#define DHT11_INSIDE_GPIO       GPIO_NUM_5

#define HX711_DT_GPIO           GPIO_NUM_6
#define HX711_SCK_GPIO          GPIO_NUM_7

#define SW420_GPIO              GPIO_NUM_8

#define MAX9814_ADC_CHANNEL     ADC1_CHANNEL_3

/************************************************
 阈值参数
************************************************/
float Weight_Max = 50.0f;
float Weight_Min = 5.0f;

int Temp_Max = 40;
int Temp_Min = 10;

int Humi_Max = 90;
int Humi_Min = 20;

/************************************************
 全局变量
************************************************/
float g_weight = 0;
float g_light = 0;
float g_sound = 0;

uint8_t g_vibration = 0;
uint8_t g_alarm = 0;

int g_out_temp = 0;
int g_out_humi = 0;

int g_in_temp = 0;
int g_in_humi = 0;

static const char *TAG = "BeeBox";

/************************************************
 声音采集
************************************************/
float MAX9814_Read_dB(void)
{
    uint32_t adc_sum = 0;

    for(int i = 0; i < 100; i++)
    {
        adc_sum += adc1_get_raw(MAX9814_ADC_CHANNEL);
        vTaskDelay(pdMS_TO_TICKS(2));
    }

    float adc_avg = adc_sum / 100.0f;

    float db = adc_avg * 0.02f;

    return db;
}

/************************************************
 震动采集
************************************************/
uint8_t SW420_Read(void)
{
    return gpio_get_level(SW420_GPIO);
}

/************************************************
 报警判断
************************************************/
void Alarm_Check(void)
{
    g_alarm = 0;

    if(g_in_temp > Temp_Max)
        g_alarm = 1;

    if(g_in_temp < Temp_Min)
        g_alarm = 1;

    if(g_in_humi > Humi_Max)
        g_alarm = 1;

    if(g_in_humi < Humi_Min)
        g_alarm = 1;

    if(g_weight > Weight_Max)
        g_alarm = 1;

    if(g_weight < Weight_Min)
        g_alarm = 1;

    if(g_vibration == 1)
        g_alarm = 1;
}

/************************************************
 OLED刷新
************************************************/
void OLED_Update(void)
{
    char buf[32];

    OLED_Clear();

    sprintf(buf,"OutT:%dC",g_out_temp);
    OLED_ShowString(0,0,buf);

    sprintf(buf,"OutH:%d%%",g_out_humi);
    OLED_ShowString(0,16,buf);

    sprintf(buf,"InT:%dC",g_in_temp);
    OLED_ShowString(0,32,buf);

    sprintf(buf,"InH:%d%%",g_in_humi);
    OLED_ShowString(0,48,buf);

    OLED_Refresh();

    vTaskDelay(pdMS_TO_TICKS(100));

    OLED_Clear();

    sprintf(buf,"Lux:%.1f",g_light);
    OLED_ShowString(0,0,buf);

    sprintf(buf,"Wt:%.1fkg",g_weight);
    OLED_ShowString(0,16,buf);

    sprintf(buf,"Snd:%.1fdB",g_sound);
    OLED_ShowString(0,32,buf);

    if(g_vibration)
        OLED_ShowString(0,48,"Vib:Alarm");
    else
        OLED_ShowString(0,48,"Vib:Normal");

    OLED_Refresh();
}

/************************************************
 数据采集任务
************************************************/
void Sensor_Task(void *pvParameters)
{
    while(1)
    {
        DHT11_Read(DHT11_OUTSIDE_GPIO,
                   &g_out_temp,
                   &g_out_humi);

        DHT11_Read(DHT11_INSIDE_GPIO,
                   &g_in_temp,
                   &g_in_humi);

        g_weight = HX711_GetWeight();

        g_light = BH1750_ReadLux();

        g_sound = MAX9814_Read_dB();

        g_vibration = SW420_Read();

        Alarm_Check();

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

/************************************************
 OLED显示任务
************************************************/
void OLED_Task(void *pvParameters)
{
    while(1)
    {
        OLED_Update();

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

/************************************************
 MQTT上传任务
************************************************/
void MQTT_Task(void *pvParameters)
{
    char json[512];

    while(1)
    {
        sprintf(json,
        "{"
        "\"DHT11_1_T\":%d,"
        "\"DHT11_1_H\":%d,"
        "\"DHT11_2_T\":%d,"
        "\"DHT11_2_H\":%d,"
        "\"SW420\":%d,"
        "\"BH1750\":%.2f,"
        "\"HX711\":%.2f,"
        "\"MAX9814\":%.2f,"
        "\"Alarm\":%d"
        "}",
        g_out_temp,
        g_out_humi,
        g_in_temp,
        g_in_humi,
        g_vibration,
        g_light,
        g_weight,
        g_sound,
        g_alarm);

        MQTT_Publish(json);

        ESP_LOGI(TAG,"%s",json);

        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

/************************************************
 GPIO初始化
************************************************/
void GPIO_Init(void)
{
    gpio_config_t io_conf = {0};

    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = (1ULL << SW420_GPIO);
    io_conf.pull_up_en = 1;

    gpio_config(&io_conf);
}

/************************************************
 ADC初始化
************************************************/
void ADC_Init(void)
{
    adc1_config_width(ADC_WIDTH_BIT_12);

    adc1_config_channel_atten(
        MAX9814_ADC_CHANNEL,
        ADC_ATTEN_DB_11);
}

/************************************************
 主函数
************************************************/
void app_main(void)
{
    ESP_LOGI(TAG,"Bee Box System Start");

    GPIO_Init();

    ADC_Init();

    OLED_Init();

    BH1750_Init();

    HX711_Init(HX711_DT_GPIO,
               HX711_SCK_GPIO);

    WIFI_Init();

    WIFI_Connect();

    MQTT_Init();

    xTaskCreate(
        Sensor_Task,
        "Sensor_Task",
        4096,
        NULL,
        5,
        NULL);

    xTaskCreate(
        OLED_Task,
        "OLED_Task",
        4096,
        NULL,
        4,
        NULL);

    xTaskCreate(
        MQTT_Task,
        "MQTT_Task",
        6144,
        NULL,
        5,
        NULL);

    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

六、总结

本课题设计并实现了一种基于物联网技术的蜂箱智能监测系统,以ESP32-S3-N8R8作为核心控制器,集成温湿度监测、重量检测、声音采集、光照检测以及震动检测等多种传感功能,实现了对蜂箱运行状态的多维度实时感知。系统通过多传感器协同工作,能够全面反映蜂箱内部环境变化与蜂群活动特征,为蜂群健康评估与蜂蜜产量管理提供数据基础。

在系统实现过程中,采用DHT11完成蜂箱内外温湿度采集,利用HX711与称重传感器实现蜂箱重量高精度测量,通过MAX9814麦克风模块获取蜂群声音特征信号,结合BH1750光照传感器分析蜂群活动规律,并通过SW420震动模块实现对外部干扰及异常震动的检测。同时,OLED显示模块实现本地数据可视化,使养蜂人员能够直观查看蜂箱实时状态,提高现场管理效率。

在通信方面,系统利用ESP32-S3内置WiFi模块接入网络,通过MQTT协议将数据上传至OneNet物联网平台,实现远程数据监测与管理。同时,结合微信小程序实现数据可视化展示与阈值参数配置,使用户能够随时随地掌握蜂箱运行状态,并对异常情况进行及时响应,从而显著提升系统的智能化水平与实用价值。

通过本系统的设计与实现,不仅提高了传统养蜂方式的自动化与信息化水平,也为智慧农业中的蜂群管理提供了一种可行的技术方案。系统具备良好的扩展性与应用前景,可进一步结合人工智能算法对蜂群状态进行更深层次分析,例如蜂群健康预测、产蜜量估算以及异常行为识别等方向。

本项目完成了蜂箱环境多参数监测、无线数据传输、本地显示以及远程管理等核心功能设计,达到了预期设计目标,具有一定的工程应用价值与实际推广意义。

相关推荐
夜月yeyue2 小时前
STM32 DMA 双缓冲采样
linux·stm32·单片机·嵌入式硬件·系统架构
西城微科方案开发3 小时前
SIC8P370D2L-PLP16 8位OTP单片机 低功耗多功能MCU详解
单片机·嵌入式硬件
MetrixAeroCore4 小时前
智能电表海外通信解决方案:低功耗、高稳定远程抄表IoT连接
大数据·物联网
Rider_bai4 小时前
长春到天津物流专线,长春到天津物流公司,如何找到靠谱公司的联系方式?
大数据·网络·物联网·敏捷流程·交通物流
踏着七彩祥云的小丑5 小时前
嵌入式测试第 32 天:升级测试:固件OTA升级、断点续传、回滚测试
单片机·嵌入式硬件·学习
点灯小铭5 小时前
基于单片机与DAC0832的双路波形信号发生系统设计
数据库·单片机·mongodb·毕业设计·课程设计·期末大作业
sramdram6 小时前
基于MCU微控制器的电子血压计应用解决方案
单片机·嵌入式硬件·mcu·mcu微控制器
Szime6 小时前
AD9218 国产替代方向:双通道 10 位 105MSPS ADC 选型支持
单片机·嵌入式硬件·fpga开发·汽车
凡人叶枫6 小时前
Effective C++ 条款15:在资源管理类中提供对原始资源的访问
linux·开发语言·c++·stm32·单片机