尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

ESP32 + 传感器:手把手教你做土壤监测终端

ESP32 + 传感器:手把手教你做土壤监测终端
📅 发布时间:2026/7/1 2:24:30

ESP32 + 传感器:手把手教你做土壤监测终端

上一篇给了硬件清单,这篇直接上代码。从 GPIO 初始化到传感器读数,再到 MQTT 上发,最后低功耗优化——每一行都有注释,复制到 Arduino IDE 里就能跑。


前置准备

软件环境:

  • Arduino IDE 2.x(装好 ESP32 开发板支持)
  • 库:WiFiPubSubClientDHT sensor libraryOneWireDallasTemperatureBH1750ModbusMaster

硬件接线:按上一篇的引脚表接好,USB 线插电脑。


第一步:基础采集——五个传感器一把梭

#include<WiFi.h>#include<DHT.h>#include<OneWire.h>#include<DallasTemperature.h>#include<BH1750.h>#include<Wire.h>#include<ModbusMaster.h>// ==================== 引脚定义 ====================#defineDHT_PIN25#defineONE_WIRE_PIN4#defineRS485_DE_RE18// MAX485 方向控制引脚#defineSOIL_SENSOR_132// ADC1 读模拟量土壤湿度(备选方案)// ==================== 传感器对象 ====================DHTdht(DHT_PIN,DHT22);OneWireoneWire(ONE_WIRE_PIN);DallasTemperaturesoilTempSensor(&oneWire);BH1750 lightMeter;ModbusMaster modbus;// ==================== 数据结构 ====================structSensorData{floatairTemp;// 空气温度 ℃floatairHumidity;// 空气湿度 %floatsoilTemp;// 土壤温度 ℃floatsoilMoisture;// 土壤湿度 %(RS485 读数)floatlightLux;// 光照强度 Lux};// ==================== 初始化 ====================voidsetup(){Serial.begin(115200);// DHT22dht.begin();// DS18B20 土壤温度soilTempSensor.begin();// BH1750 光照Wire.begin(21,22);// SDA=21, SCL=22lightMeter.begin();// RS485 (Serial2: RX=16, TX=17)Serial2.begin(9600,SERIAL_8N1,16,17);modbus.begin(1,Serial2);// 从机地址 = 1pinMode(RS485_DE_RE,OUTPUT);Serial.println("=== 土壤监测终端启动 ===");}// ==================== RS485 读土壤湿度 ====================floatreadSoilMoistureRS485(){// 切换到发送模式digitalWrite(RS485_DE_RE,HIGH);delay(10);// 读保持寄存器 0x0000(湿度值),读 1 个寄存器uint8_tresult=modbus.readHoldingRegisters(0x0000,1);// 切回接收模式digitalWrite(RS485_DE_RE,LOW);if(result==modbus.ku8MBSuccess){returnmodbus.getResponseBuffer(0)/10.0;// 传感器返回 0-1000,除以 10}return-1.0;// 读取失败}// ==================== 读土壤温度(DS18B20) ====================floatreadSoilTemp(){soilTempSensor.requestTemperatures();floattemp=soilTempSensor.getTempCByIndex(0);// DS18B20 在 -127 时表示读取异常if(temp==DEVICE_DISCONNECTED_C)return-127;returntemp;}// ==================== 采集全部数据 ====================SensorDatacollectAll(){SensorData data;// DHT22 空气温湿度data.airTemp=dht.readTemperature();data.airHumidity=dht.readHumidity();// DS18B20 土壤温度data.soilTemp=readSoilTemp();// RS485 土壤湿度data.soilMoisture=readSoilMoistureRS485();// BH1750 光照data.lightLux=lightMeter.readLightLevel();returndata;}voidloop(){SensorData data=collectAll();Serial.println("════════════════════════════");Serial.printf("空气温度: %.1f ℃\n",data.airTemp);Serial.printf("空气湿度: %.1f %%\n",data.airHumidity);Serial.printf("土壤温度: %.1f ℃\n",data.soilTemp);Serial.printf("土壤湿度: %.1f %%\n",data.soilMoisture);Serial.printf("光照强度: %.0f Lux\n",data.lightLux);delay(5000);// 调试阶段 5s 一次,实际部署改 5min}

这段代码用 Arduino IDE 编译下载到 ESP32,打开串口监视器(115200 波特率),你应该能看到每隔 5 秒打印一组传感器读数。


第二步:接上 MQTT,数据上云端

光串口打印没意义,数据得上云。MQTT 部分只需要在setup()里连 WiFi + 连 EMQX,在loop()里把采集到的数据 publish 出去。

#include<PubSubClient.h>// ==================== WiFi & MQTT 配置 ====================constchar*WIFI_SSID="你的WiFi名";constchar*WIFI_PASS="你的WiFi密码";constchar*MQTT_BROKER="你的服务器IP";constintMQTT_PORT=1883;constchar*MQTT_CLIENT_ID="esp32_greenhouse_01";constchar*MQTT_TOPIC="farm/greenhouse/01/data";WiFiClient espClient;PubSubClientmqtt(espClient);// 连接 WiFivoidconnectWiFi(){WiFi.begin(WIFI_SSID,WIFI_PASS);Serial.print("连接 WiFi");intretry=0;while(WiFi.status()!=WL_CONNECTED&&retry<40){delay(500);Serial.print(".");retry++;}if(WiFi.status()==WL_CONNECTED){Serial.println("\nWiFi 已连接");Serial.print("IP: ");Serial.println(WiFi.localIP());}}// 连接 MQTTvoidconnectMQTT(){while(!mqtt.connected()){Serial.print("连接 MQTT...");if(mqtt.connect(MQTT_CLIENT_ID)){Serial.println("成功");}else{Serial.print("失败, rc=");Serial.print(mqtt.state());Serial.println(" 5 秒后重试");delay(5000);}}}// 发送 JSON 数据(不用 ArduinoJson 库也行,手动拼)voidpublishData(SensorData data){charpayload[256];snprintf(payload,sizeof(payload),"{\"t\":\"%.1f\",\"h\":\"%.1f\",\"st\":\"%.1f\",\"sm\":\"%.1f\",\"l\":\"%.0f\"}",data.airTemp,data.airHumidity,data.soilTemp,data.soilMoisture,data.lightLux);if(mqtt.publish(MQTT_TOPIC,payload)){Serial.println("✅ 数据已上发");}else{Serial.println("❌ 发送失败");}}voidsetup(){Serial.begin(115200);// ... 传感器初始化(同上,省略)...connectWiFi();mqtt.setServer(MQTT_BROKER,MQTT_PORT);connectMQTT();}voidloop(){if(!mqtt.connected())connectMQTT();mqtt.loop();SensorData data=collectAll();publishData(data);delay(300000);// 5 分钟上报一次}

到这里,你的 ESP32 已经能做到:每 5 分钟采集一组数据 → JSON 格式化 → MQTT 上发到 EMQX。


第三步:低功耗优化——一节电池用半年

ESP32 全速跑起来大约 150-200mA,18650 一节 3400mAh 撑不到 24 小时。必须做低功耗优化。

思路

ESP32 大部分时间在睡觉(深度睡眠模式,电流 ~10μA),定时醒来(RTC 闹钟),花 5 秒采数据 + 连 WiFi + 发 MQTT,然后倒头接着睡。

时间线: ┌───── 睡眠(295s) ─────┬─ 唤醒(5s) ─┐ │ 约 10μA │ WiFi+采集+发送 │ └───────────────────────┴──────────────┘ 平均电流 ≈ (295*0.01 + 5*150) / 300 = 2.5mA 一节 3400mAh → 约 56 天

加太阳能板 + TP4056 充电,白天充电晚上耗电,基本无限续航。

#defineuS_TO_S_FACTOR1000000ULL#defineSLEEP_SECONDS300// 5 分钟voidsetup(){// ... 前面初始化 ...// 采集一次并上报SensorData data=collectAll();publishData(data);// 断开 WiFi(省电)WiFi.disconnect(true);WiFi.mode(WIFI_OFF);// 配置唤醒源:定时器esp_sleep_enable_timer_wakeup(SLEEP_SECONDS*uS_TO_S_FACTOR);Serial.println("进入深度睡眠...");esp_deep_sleep_start();}voidloop(){// 深度睡眠模式下永远不会执行到这里// setup() 执行完后 ESP32 自动关机,RTC 闹钟触发后重启 → 再次进 setup()}

注意:用了深度睡眠后,setup()就是你的主循环——每次醒来跑一遍,跑完就睡。loop()成了摆设。

进一步省电技巧

  • 去掉串口打印:Serial.begin()和Serial.print()在部署时全删掉,能省 5-10mA
  • WiFi 快速连接:提前存 WiFi 信道,连接时间从 3 秒降到 1 秒
  • 静态 IP:DHCP 握手省 0.5 秒
  • MQTT QoS 0:不等待服务器确认,发完就走

优化后平均电流可以压到 1.5mA 以下,一节 18650 撑 90+ 天。


常见问题

Q: RS485 读数总是 -1(失败)?
A: 检查 DE/RE 引脚电平——发送时拉高、接收时拉低。时序:拉高后要 delay(10) 再发指令。另外确认 MAX485 的 RO/DI 交叉接对。

Q: DHT22 偶尔返回 NaN?
A: DHT22 的单总线时序很敏感,读取间隔不能短于 2 秒。如果连续读太快,加delay(2500)或者换 DHT22 库里带超时处理的版本。

Q: 太阳能板阴天能充进去吗?
A: 能,但很慢。5V 1W 的多晶硅在阴天输出只有 0.1-0.3W。如果你在四川、贵州这种阴天多的地区,建议上 2W 的板子或者两片并联。


下一篇:《MQTT 物联网通信:100 个传感器的数据怎么传到云端?》——部署 EMQX、设计 topic 规范、设备上下线监控、断网重连机制。

相关新闻

  • 软件工程从业所需的技能:正确认识行业,并走出可持续的职业生涯
  • 可视化学科发展脉络浅梳(学习笔记)
  • sdfsfds

最新新闻

  • X账号被冻结或受限怎么办?常见原因、处理步骤与团队管理建议
  • 国产 ZCC5030 | 100V 高压推挽电流模式 PWM 控制器 完美兼容 LM5030
  • 零壹教育:全球开源生态的差异化发展之路
  • 图像缓存总带宽与单位时间带宽计算
  • win11搭建appium开发环境,配置Appium Inspector
  • 脑部AAV实验设计指南:血清型、注射方式和剂量如何选择?

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号