课程设计项目:基于物联网的智能透明度报警器
项目概述与设计目标
项目简介 本项目旨在设计并制作一个基于物联网的智能透明度报警器,该设备通过光学传感器实时检测液体(如水、牛奶、果汁等)的透明度,当透明度低于预设阈值时,系统会立即通过本地声光报警和远程网络推送(如手机APP、网页、微信公众号)等方式向用户发出警报,该系统可广泛应用于家庭鱼缸水质监测、工业液体浑浊度检测、实验室溶液纯度监控等场景。
设计目标

- 核心功能:实时、准确地测量液体透明度。
- 报警机制:
- 本地报警:当检测到液体浑浊时,驱动LED灯闪烁和蜂鸣器鸣叫。
- 远程报警:通过Wi-Fi/4G网络将报警信息(含设备ID、时间、透明度数值)发送至用户指定的平台。
- 人机交互:
- 配置OLED显示屏,实时显示当前透明度数值、设备状态和报警阈值。
- 提供按键或网页界面,允许用户调整报警阈值。
- 系统特性:
- 低功耗设计:在非报警状态下,系统可进入低功耗模式,延长电池寿命。
- 模块化设计:硬件和软件结构清晰,便于扩展和维护。
- 高性价比:选用常见、易采购的元器件,控制成本。
系统总体方案设计
系统架构图 系统主要由感知层、控制层、网络层和应用层组成。
graph TD
subgraph 感知层
A[光学传感器(TS-805)] --> B(信号调理电路)
end
subgraph 控制层
B --> C[主控制器(ESP32)]
D[按键] --> C
E[OLED显示屏] --> C
F[LED指示灯] --> C
G[蜂鸣器] --> C
end
subgraph 网络层
C -- Wi-Fi/4G --> H[互联网]
end
subgraph 应用层
H --> I[手机APP/网页/公众号]
end
C -- 控制信号 --> F
C -- 控制信号 --> G
C -- 数据显示 --> E
工作流程
- 初始化:系统上电后,ESP32进行硬件初始化,连接Wi-Fi网络,并从EEPROM或云端加载预设的报警阈值。
- 数据采集:光学传感器持续发射光线并接收穿过液体的光强,信号调理电路将光强信号转换为模拟电压信号。
- 数据处理:ESP32的ADC(模数转换器)读取该电压值,电压值与液体透明度成反比(液体越浑浊,电压值越低)。
- 逻辑判断:
- 将ADC值与预设的报警阈值进行比较。
- 如果ADC值 < 阈值(即液体浑浊),触发报警流程。
- 否则,正常显示数据,并可进入低功耗休眠一段时间后再次采集。
- 报警执行:
- 本地:控制GPIO引脚,使LED闪烁、蜂鸣器鸣响。
- 远程:通过MQTT或HTTP协议,将包含报警信息的JSON数据包发送到云服务器。
- 用户交互:用户可以通过OLED屏幕查看实时数据,通过按键或网页修改报警阈值,修改后的值可保存到EEPROM或云端。
硬件选型与电路设计
核心控制器:ESP32
- 型号推荐:ESP32-DevKitC或ESP32-CAM。
- 选择理由:
- 集成度高:自带Wi-Fi和蓝牙,无需额外模块。
- 性能强大:双核处理器,主频高达240MHz,足以处理数据采集和网络通信。
- 外设丰富:内置多个高精度ADC、GPIO、I2C、SPI接口,方便连接各种传感器和显示屏。
- 生态成熟:Arduino IDE、PlatformIO等开发支持完善,社区资源丰富。
光学传感器:TS-805 或类似型号

- 类型:对管式红外光电传感器。
- 工作原理:发射端发出特定波长的红外光,接收端检测接收到的光强,液体越浑浊,对光的散射和吸收越强,接收端收到的光信号越弱。
- 输出信号:模拟电压信号(0-3.3V),可直接连接ESP32的ADC引脚。
显示模块:0.96寸 OLED (I2C接口)
- 分辨率:128x64。
- 接口:I2C,占用引脚少。
- 功能:显示“Transparency: XX%”、“Status: Normal/Alarm”、“Threshold: YY”等信息。
输入模块:轻触按键
- 数量:1-2个。
- 功能:一个用于“模式切换/确认”,一个用于“数值增加/减少”,用于在本地设置阈值。
输出模块
- LED指示灯:高亮LED,用于视觉报警,可通过一个限流电阻(如220Ω)直接连接到ESP32的GPIO。
- 蜂鸣器:有源蜂鸣器(自带振荡源,通电即响)或无源蜂鸣器(需PWM信号驱动),有源蜂鸣器控制简单,直接连接GPIO即可。
电源模块

- 方案一(推荐):USB Type-C 5V供电,通过AMS1117-3.3V LDO降压模块为ESP32和传感器提供稳定的3.3V。
- 方案二(便携式):18650锂电池(3.7V)配合TP4056充电模块,使用3.3V降压模块供电。
电路连接图示例
| 传感器/模块 | ESP32 引脚 |
|---|---|
| TS-805 (信号输出) | GPIO 34 (ADC1_CH6) |
| OLED (SCL) | GPIO 22 |
| OLED (SDA) | GPIO 21 |
| 按键1 (设置) | GPIO 19 (内部上拉) |
| 按键2 (增加) | GPIO 18 (内部上拉) |
| LED (正极) | GPIO 2 (通过220Ω电阻) |
| 蜂鸣器 (正极) | GPIO 4 |
| VCC (3.3V) | 3V |
| GND | GND |
软件设计
开发环境
- IDE:Arduino IDE (安装ESP32开发板支持包) 或 VS Code + PlatformIO。
- 语言:C++。
核心算法
- ADC值与透明度换算:
- 校准:在纯净水(最高透明度)中读取ADC值,记为
ADC_MAX,在已知浑浊度的标准溶液(最低透明度)中读取ADC值,记为ADC_MIN。 - 换算公式:
Transparency (%) = ((ADC_Current - ADC_MIN) / (ADC_MAX - ADC_MIN)) * 100注意:这个公式是一个线性近似,对于高精度应用可能需要查表法或多项式拟合进行非线性校准。
- 校准:在纯净水(最高透明度)中读取ADC值,记为
代码模块化设计
// 伪代码示例
// --- 引入库文件 ---
#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h> // 用于本地存储阈值
// --- 引脚定义 ---
#define SENSOR_PIN 34
#define LED_PIN 2
#define BUZZER_PIN 4
#define SET_BTN_PIN 19
#define INC_BTN_PIN 18
// --- 对象定义 ---
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// --- 全局变量 ---
float threshold = 500.0; // 默认报警阈值 (ADC值)
bool isAlarm = false;
unsigned long lastAlarmTime = 0;
// --- 函数声明 ---
void connectWiFi();
void readSensor();
void updateDisplay();
void triggerAlarm();
void clearAlarm();
void handleButtons();
void sendNotification(String message);
void setup() {
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(SET_BTN_PIN, INPUT_PULLUP);
pinMode(INC_BTN_PIN, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
EEPROM.begin(512); // 初始化EEPROM
threshold = EEPROM.readFloat(0); // 从EEPROM读取阈值
connectWiFi();
}
void loop() {
readSensor(); // 1. 读取传感器数据
updateDisplay(); // 2. 更新显示屏
handleButtons(); // 3. 处理按键输入
// 4. 判断是否报警
if (adcValue < threshold && !isAlarm) {
triggerAlarm();
} else if (adcValue >= threshold && isAlarm) {
clearAlarm();
}
// 5. 远程报警(节流处理,避免频繁发送)
if (isAlarm && (millis() - lastAlarmTime > 30000)) { // 每30秒发送一次
sendNotification("警告:液体浑浊!");
lastAlarmTime = millis();
}
delay(500); // 控制采样频率
}
// --- 函数实现 ---
void readSensor() {
adcValue = analogRead(SENSOR_PIN);
// ... (可以添加数字滤波算法,如滑动平均滤波)
}
void triggerAlarm() {
isAlarm = true;
Serial.println("Alarm Triggered!");
// 启动本地报警
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000); // 发出1kHz的声音
}
void clearAlarm() {
isAlarm = false;
Serial.println("Alarm Cleared.");
// 停止本地报警
digitalWrite(LED_PIN, LOW);
noTone(BUZZER_PIN);
}
void sendNotification(String message) {
if (WiFi.status() == WL_CONNECTED) {
// 使用HTTP或MQTT协议发送数据到云平台
// 向Blynk、ThingSpeak、阿里云IoT、腾讯云IoT发送
Serial.println("Sending notification: " + message);
}
}
// 其他函数...
云平台对接(远程报警实现) 选择一个云平台,将设备连接上去,这里以MQTT协议和免费公共服务器为例。
-
云平台选项:
- MQTT Broker:EMQX, Mosquitto (可自建),或公共服务器如
broker.hivemq.com。 - IoT PaaS:阿里云IoT、腾讯云IoT、Blynk、ThingSpeak、Adafruit IO (更简单,适合初学者)。
- MQTT Broker:EMQX, Mosquitto (可自建),或公共服务器如
-
MQTT实现步骤:
-
在Arduino IDE中安装
PubSubClient库。 -
在
setup()中连接MQTT Broker:client.setServer(mqtt_server, 1883); client.setCallback(callback); // 设置回调函数
-
在
loop()中保持连接:if (!client.connected()) { reconnect(); } client.loop(); -
在
triggerAlarm()和clearAlarm()函数中发布消息:// triggerAlarm() 中 client.publish("your_device/alarm", "ON"); // clearAlarm() 中 client.publish("your_device/alarm", "OFF"); -
可以使用MQTT.fx等客户端软件订阅
your_device/alarm主题来接收报警信息。
-
系统测试与优化
功能测试
- 本地测试:将传感器放入清水和浑浊水中,观察OLED显示数值变化是否正常,倒入浑浊液体,测试本地声光报警是否触发。
- 远程测试:确认设备成功连接Wi-Fi和云平台,触发报警后,检查手机APP或网页是否收到通知。
- 阈值设置测试:通过按键或网页修改阈值,验证新阈值是否生效,报警逻辑是否正确。
性能优化
- 软件滤波:在ADC读取值上应用滑动平均滤波,以减少数据波动,提高稳定性。
- 低功耗优化:在
loop()的末尾使用deepSleep()模式,通过定时器或外部中断唤醒,极大降低待机功耗。 - 外壳设计:设计一个防水的外壳,只留出传感器探头的部分,保护电路板。
总结与展望
本项目成功设计并实现了一个功能完备的物联网透明度报警器,它集成了传感器技术、嵌入式系统开发和物联网通信技术,实现了从数据采集到本地和远程报警的完整闭环,通过模块化的设计,系统具有良好的可扩展性和可维护性。
展望与扩展
- 数据可视化:在云平台上创建数据看板,实时绘制透明度变化曲线,并记录历史数据。
- 多参数监测:集成pH值、温度传感器,实现多功能水质监测站。
- AI预测:收集长期数据,使用机器学习算法预测水质恶化的趋势,实现提前预警。
- LoRa/NB-IoT:对于远距离、低功耗的应用场景,可以将Wi-Fi模块替换为LoRa或NB-IoT模块,实现广域覆盖。
这个课程设计方案不仅提供了一个清晰的实现路径,也鼓励学生在每个环节进行思考和创新,是一个极佳的物联网入门和综合实践项目。