新晋码农一枚,小编会定期整理一些写的比较好的代码和知识点,作为自己的学习笔记,试着做一下批注和补充,转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!本章内容较多,可点击文章目录进行跳转!
小编整理和学习了机器学习的相关知识,可作为扫盲使用,后续也会更新一些技术类的文章,大家共同交流学习!您的点赞、关注、收藏就是对小编最大的动力!
系列文章目录
从 SLP 到 MLP:鸢尾花分类实验全解析 ------ 神经网络入门必做实验【万字长文,一文搞定!】
基于 ESP32 的冷链物流工业物联网(IIoT)监控系统|全流程实战
四种经典降维方法全实验:SVD、PCA、LDA、ISOMAP 从原理到代码
目录
目录
[1.1 行业痛点](#1.1 行业痛点)
[1.2 项目目标](#1.2 项目目标)
[Node A(主节点 / 数据网关)](#Node A(主节点 / 数据网关))
[Node C(从节点 1)](#Node C(从节点 1))
[Node D(从节点 2)](#Node D(从节点 2))
[3.1 多维度数据采集](#3.1 多维度数据采集)
[3.2 I2C 主从双向通信(核心亮点)](#3.2 I2C 主从双向通信(核心亮点))
[3.3 本地显示与云端可视化](#3.3 本地显示与云端可视化)
[本地 LCD 显示(14 针并行 0802)](#本地 LCD 显示(14 针并行 0802))
[3.4 三级分级报警逻辑](#3.4 三级分级报警逻辑)
[4.1 供电方案(独立供电,抗干扰)](#4.1 供电方案(独立供电,抗干扰))
[4.2 I2C 标准连接(通信稳定关键)](#4.2 I2C 标准连接(通信稳定关键))
[4.3 核心元器件选型](#4.3 核心元器件选型)
[5.1 Node A(主节点)接线表](#5.1 Node A(主节点)接线表)
[5.2 Node C(光照从节点)接线表](#5.2 Node C(光照从节点)接线表)
[5.3 Node D(倾斜从节点)接线表](#5.3 Node D(倾斜从节点)接线表)
[6.1 Node A 主节点完整代码](#6.1 Node A 主节点完整代码)
[6.2 Node C 光照从节点代码](#6.2 Node C 光照从节点代码)
[6.3 Node D 倾斜从节点代码](#6.3 Node D 倾斜从节点代码)
[8.1 遇到的问题与解决](#8.1 遇到的问题与解决)
[8.2 系统现存局限](#8.2 系统现存局限)
[8.3 未来优化方案](#8.3 未来优化方案)
前言
冷链物流作为医药疫苗、生鲜食品流通的关键环节,长期面临高能耗、高损耗的行业瓶颈,其能耗占物流行业总能耗 30% 以上,全球约 20% 的温控产品在运输中因冷链失效损坏。本项目基于工业物联网理念,搭建一套室内可演示、多节点协同、云端可监控的冷链运输智能监控系统,完整实现温湿度、光照、倾斜、模拟位置的实时采集、主从通信、本地显示、云端上传与分级报警功能。
本文从项目背景、系统架构、硬件选型、接线设计、代码实现、功能测试到挑战优化,完整保留全部技术细节,以纯技术博客形式呈现,可直接作为课程设计、毕设参考与 ESP32 多节点 IIoT 实战教程。
一、项目背景与设计目标
1.1 行业痛点
- 冷链物流能耗高、监管不透明,人工巡检无法做到实时监控。
- 温湿度、运输姿态、箱门状态缺乏统一数字化监管手段。
- 异常发生后无预警、无数据追溯,导致货物损耗率居高不下。
1.2 项目目标
搭建由3 个 ESP32 节点组成的工业物联网演示系统,实现以下核心能力:
- 多点温湿度、光照、倾斜状态数据采集
- I2C 主从双向非阻塞通信
- 本地 LCD 四页循环实时显示
- 模拟 GPS 轨迹与运动状态指示
- MQTT 协议数据上传至云端平台
- 三级分级异常报警
- 断网自动重连、异常加急上报
二、系统整体架构(一主两从)
本系统采用I2C 主从分布式架构,3 个节点分工明确、协同工作:
Node A(主节点 / 数据网关)
- 角色:I2C 主机、数据聚合网关、本地显示与报警中心
- 核心硬件:ESP32、DHT11、0802 LCD、交通灯、按键
- 核心功能:
- 采集本地温湿度,按键控制模拟 GPS 启停
- 轮询从节点 C、D,获取光照与倾斜数据
- 本地 LCD 实时显示所有参数
- 控制分级报警指示灯
- 通过 WiFi+MQTT 将数据上传云端
Node C(从节点 1)
- 角色:环境光监测节点
- 核心硬件:ESP32、TEMT6000 模拟光照传感器
- 核心功能:
- 采集环境光照强度,判断冷链箱门开闭状态
- 响应主节点请求,回传光照模拟量数据
Node D(从节点 2)
- 角色:运输姿态监测节点
- 核心硬件:ESP32、KS0025 数字倾斜传感器、LED 指示灯
- 核心功能:
- 检测车辆倾斜 / 震动状态
- 响应主节点查询,回传倾斜状态
- 主动读取 GPS 运行状态,通过 LED 指示启停

三、系统核心功能完整详解
3.1 多维度数据采集
系统支持 4 类关键参数并行采集,互不阻塞:
- 温湿度:DHT11 采集,量程 0--50℃,精度 ±2℃
- 环境光照:TEMT6000 模拟量,0--4095,>2000 表示箱门打开
- 倾斜状态:数字量输出,低电平表示倾斜报警
- 模拟 GPS:软件生成固定起点,按键启停,小范围平滑偏移
3.2 I2C 主从双向通信(核心亮点)
- 总线配置:SDA=GPIO21,SCL=GPIO22,100kHz,共地 + 4.7kΩ 上拉
- 主节点非阻塞轮询从节点,不等待响应即可执行下一任务
- 从节点 D 可主动作为主机读取主节点 A 的 GPS 状态,实现双向交互
- 正常状态:每 10 秒上传云端;报警状态:每 5 秒加急上传
3.3 本地显示与云端可视化
本地 LCD 显示(14 针并行 0802)
每 2 秒自动切换一页,共 4 页:
- 温湿度页面
- 光照强度 + 门状态页面
- 倾斜状态 + GPS 运动状态页面
- GPS 经纬度坐标页面
云端监控(MQTT+ThingsBoard)
- 协议:MQTT 1883 端口
- 上传内容:温湿度、光照、倾斜、GPS 状态、经纬度
- 云端能力:实时曲线、GPS 轨迹、报警历史、远程查看

3.4 三级分级报警逻辑
| 优先级 | 状态 | 触发条件 | 指示灯 |
|---|---|---|---|
| 最高 | 危险报警 | 倾斜 / 温度>30℃ | 红灯 |
| 中等 | 门开提醒 | 光照>2000 | 黄灯 |
| 最低 | 正常运行 | 温度≤30℃+ 门关 + 无倾斜 | 绿灯 |
四、硬件供电与总线连接设计
4.1 供电方案(独立供电,抗干扰)
- 3 个节点各自 5V 独立供电,I2C 总线仅传输数据,不供电
- 避免单节点供电不足导致整体通信故障
- 所有节点共地,保证电平参考一致
4.2 I2C 标准连接(通信稳定关键)
| 信号线 | Node A | Node C | Node D | 连接说明 |
|---|---|---|---|---|
| SDA | GPIO21 | GPIO21 | GPIO21 | 4.7kΩ 上拉至 3.3V |
| SCL | GPIO22 | GPIO22 | GPIO22 | 4.7kΩ 上拉至 3.3V |
| GND | GND | GND | GND | 统一共地 |
| 3.3V | 输出 | 输入 | 输入 | 外部稳压供电 |
4.3 核心元器件选型
| 器件 | 型号 | 功能 |
|---|---|---|
| 主控 | ESP32-WROOM-32U | 多节点互联、WiFi、MQTT |
| 温湿度 | DHT11 | 单总线数字温湿度采集 |
| 光照 | TEMT6000 | 模拟量光照检测 |
| 倾斜 | SW-520D/KS0025 | 运输姿态检测 |
| 显示 | 0802 LCD 14 针 | 本地数据轮显 |
| 报警 | 三色交通灯 | 分级状态指示 |
五、各节点完整引脚接线
5.1 Node A(主节点)接线表
| 器件 | 器件引脚 | ESP32 引脚 |
|---|---|---|
| 0802 LCD | VSS、VDD、VO、RS、RW、EN、D4--D7 | GND、5V、GND、16、GND、17、2/4/13/14 |
| DHT11 | VCC、GND、DATA | 5V、GND、5 |
| 交通灯 | 红、黄、绿、GND | 25、26、27、GND |
| 按键 | 信号、GND | 18、GND |
| I2C | SDA、SCL | 21、22 |
5.2 Node C(光照从节点)接线表
| 器件 | 引脚 | ESP32 引脚 |
|---|---|---|
| TEMT6000 | VCC、GND、OUT | 5V、GND、34 |
| I2C | SDA、SCL | 21、22 |
5.3 Node D(倾斜从节点)接线表
| 器件 | 引脚 | ESP32 引脚 |
|---|---|---|
| 倾斜传感器 | VCC、GND、DO | 5V、GND、19 |
| LED | 阳极、阴极、信号 | 3.3V、GND、23 |
| I2C | SDA、SCL | 21、22 |

六、系统完整代码实现
6.1 Node A 主节点完整代码
cpp
#include <Wire.h>
#include <LiquidCrystal.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_PASS";
const char* MQTT_BROKER = "demo.thingsboard.io";
const uint16_t MQTT_PORT = 1883;
const char* MQTT_TOKEN = "YOUR_TOKEN";
const char* MQTT_TOPIC = "v1/devices/me/telemetry";
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
unsigned long lastMqttUpload = 0;
long mqttUploadInterval = 10000;
#define SDA_PIN 21
#define SCL_PIN 22
#define NODE_C_ADDR 0x20
#define NODE_D_ADDR 0x21
LiquidCrystal lcd(16, 17, 2, 4, 13, 14);
#define DHTPIN 5
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
#define RED_LED 25
#define YELLOW_LED 26
#define GREEN_LED 27
#define KEY_PIN 18
volatile bool gpsMoving = false;
volatile bool keyPressed = false;
float lat = 31.2301f;
float lon = 121.4703f;
unsigned long lastGpsUpdate = 0;
const long GPS_UPDATE_INTERVAL = 500;
const float GPS_OFFSET = 0.00002f;
#define TEMP_LIMIT 30.0
#define LIGHT_THRESHOLD 2000
unsigned long lastPageTime = 0;
int pageIndex = 0;
void IRAM_ATTR handleKeyPress() {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime > 200) {
keyPressed = true;
}
lastInterruptTime = interruptTime;
}
void connectWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void reconnectMQTT() {
while (!mqttClient.connected()) {
if (mqttClient.connect("NodeA-ColdChain", MQTT_TOKEN, "")) break;
delay(2000);
}
}
void uploadToThingsBoard(float temp, float humi, int lightValue, bool tiltAlarm, bool gpsMoving, float lat, float lon) {
String jsonData = "{";
jsonData += "\"temperature\":" + String(temp,1) + ",";
jsonData += "\"humidity\":" + String(humi,0) + ",";
jsonData += "\"light_value\":" + String(lightValue) + ",";
jsonData += "\"is_tilted\":" + String(tiltAlarm?1:0) + ",";
jsonData += "\"gps_moving\":" + String(gpsMoving?1:0) + ",";
jsonData += "\"latitude\":" + String(lat,5) + ",";
jsonData += "\"longitude\":" + String(lon,5);
jsonData += "}";
mqttClient.publish(MQTT_TOPIC, jsonData.c_str());
}
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN);
lcd.begin(8,2);
dht.begin();
pinMode(RED_LED,OUTPUT);
pinMode(YELLOW_LED,OUTPUT);
pinMode(GREEN_LED,OUTPUT);
pinMode(KEY_PIN,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(KEY_PIN), handleKeyPress, FALLING);
mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
connectWiFi();
}
void loop() {
if (keyPressed) {
keyPressed = false;
gpsMoving = !gpsMoving;
Wire.beginTransmission(NODE_D_ADDR);
Wire.write(gpsMoving?0x01:0x00);
Wire.endTransmission();
}
float temp = dht.readTemperature();
float humi = dht.readHumidity();
int lightValue = 0;
Wire.requestFrom(NODE_C_ADDR, (uint8_t)sizeof(lightValue));
if (Wire.available() == sizeof(lightValue)) {
Wire.readBytes((uint8_t*)&lightValue, sizeof(lightValue));
}
delay(10);
uint8_t tiltValue = HIGH;
Wire.requestFrom(NODE_D_ADDR, 1);
if (Wire.available()) tiltValue = Wire.read();
if (gpsMoving && millis()-lastGpsUpdate > GPS_UPDATE_INTERVAL) {
lat += (random(-100,101)/100.0f)*GPS_OFFSET;
lon += (random(-100,101)/100.0f)*GPS_OFFSET;
lat = constrain(lat,31.2300f,31.2302f);
lon = constrain(lon,121.4702f,121.4704f);
lastGpsUpdate = millis();
}
bool tempAlarm = temp > TEMP_LIMIT;
bool lightAlarm = lightValue > LIGHT_THRESHOLD;
bool tiltAlarm = tiltValue == LOW;
if (tempAlarm || tiltAlarm) {
digitalWrite(RED_LED,HIGH);
digitalWrite(YELLOW_LED,LOW);
digitalWrite(GREEN_LED,LOW);
} else if (lightAlarm) {
digitalWrite(RED_LED,LOW);
digitalWrite(YELLOW_LED,HIGH);
digitalWrite(GREEN_LED,LOW);
} else {
digitalWrite(RED_LED,LOW);
digitalWrite(YELLOW_LED,LOW);
digitalWrite(GREEN_LED,HIGH);
}
if (millis()-lastPageTime > 2000) {
lastPageTime = millis();
pageIndex = (pageIndex+1)%4;
lcd.clear();
}
switch(pageIndex){
case 0:
lcd.print("Temp:");lcd.print(temp,1);lcd.print("C");
lcd.setCursor(0,1);lcd.print("Humi:");lcd.print(humi,0);lcd.print("%");
break;
case 1:
lcd.print("Light:");lcd.print(lightValue);
lcd.setCursor(0,1);lcd.print(lightAlarm?"BRIGHT":"DARK");
break;
case 2:
lcd.print("Tilt:");lcd.print(tiltAlarm?"TILTED":"NORMAL");
lcd.setCursor(0,1);lcd.print(gpsMoving?"MOVING":"STOP");
break;
case 3:
lcd.print("Lat:");lcd.print(lat,5);
lcd.setCursor(0,1);lcd.print("Lon:");lcd.print(lon,5);
break;
}
if (!WiFi.isConnected()) connectWiFi();
if (!mqttClient.connected()) reconnectMQTT();
mqttClient.loop();
bool isAlarm = tempAlarm||lightAlarm||tiltAlarm;
mqttUploadInterval = isAlarm?5000:10000;
if (millis()-lastMqttUpload > mqttUploadInterval) {
uploadToThingsBoard(temp,humi,lightValue,tiltAlarm,gpsMoving,lat,lon);
lastMqttUpload = millis();
}
delay(300);
}
6.2 Node C 光照从节点代码
cpp
#include <Wire.h>
#define I2C_ADDR 0x20
#define LIGHT_PIN 34
int lightValue = 0;
void onRequest() {
Wire.write((uint8_t*)&lightValue, sizeof(lightValue));
}
void setup() {
Serial.begin(115200);
pinMode(LIGHT_PIN, INPUT);
Wire.begin(I2C_ADDR);
Wire.onRequest(onRequest);
}
void loop() {
lightValue = analogRead(LIGHT_PIN);
delay(500);
}
6.3 Node D 倾斜从节点代码
cpp
#include <Wire.h>
#define I2C_ADDR 0x21
#define TILT_PIN 19
#define LED_PIN 23
volatile uint8_t tiltState = 0;
bool gpsIsMoving = false;
void receiveEvent(int bytes) {
if (bytes>0) {
byte recv = Wire.read();
gpsIsMoving = (recv == 0x01);
digitalWrite(LED_PIN, gpsIsMoving ? HIGH : LOW);
}
}
void onRequest() {
Wire.write(tiltState);
}
void setup() {
Serial.begin(115200);
pinMode(TILT_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Wire.begin(I2C_ADDR);
Wire.onReceive(receiveEvent);
Wire.onRequest(onRequest);
}
void loop() {
tiltState = digitalRead(TILT_PIN);
delay(200);
}
七、系统调试与运行日志
系统上电后运行稳定,串口输出典型日志:
- 主节点:WiFi 连接成功 → MQTT 连接成功 → 循环采集 → 定时上云
- 从节点 C:持续输出光照 ADC 值
- 从节点 D:响应主节点查询,同步 GPS 状态并控制 LED
八、项目挑战、局限与优化方向
8.1 遇到的问题与解决
- I2C 通信不稳定、丢包
- 原因:未共地、无上拉电阻
- 解决:统一共地 + SDA/SCL 加 4.7kΩ 上拉
- 模拟 GPS 轨迹跳变
- 解决:限制经纬度偏移范围,实现平滑移动
8.2 系统现存局限
- 传感器精度有限,DHT11 误差较大
- 网络中断时无数据缓存机制
- 数据传输未加密,云端权限简单
- 仅支持视觉报警,无声音报警
8.3 未来优化方案
- 升级传感器:DHT11 → DHT22/DS18B20
- 添加 SD 卡离线缓存,断网续传
- MQTT 启用 TLS 加密,增强云端安全
- 增加电源滤波,支持声光双报警
- 适配真实冷链低温场景
九、总结
本项目是一套完整、可复现、可扩展的 ESP32 多节点工业物联网冷链监控系统,覆盖传感器采集、I2C 主从通信、本地显示、MQTT 上云、分级报警全流程。硬件成本低、逻辑清晰、功能完整,非常适合课程设计、毕业设计与 IoT 入门实战,可直接迁移到智能仓储、冷链运输、环境监测等真实场景。
总结
以上就是今天要讲的内容,本文简单记录了机器学习学习内容,仅作为一份简单的笔记使用,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!