钓鱼水位与气压提醒
💡 划重点
- 主控采用 ESP32-S3,配合 BMP280 气压温度传感器与水位传感器,构建一套专为户外钓鱼场景设计的环境感知提醒装置。
- 硬件成本严格控制在 110 元以内,全系统支持 5V 太阳能板与 TP4056 锂电池双模供电,实现长时间户外无人值守运行。
- 核心功能包含:实时水位监测与超限报警、气压变化趋势预测鱼情、蜂鸣器与 OLED 现场反馈,以及通过 Wi-Fi 将数据上传至本地服务器或手机 APP。
- 系统支持低功耗休眠策略,水位或气压突变时立即唤醒,兼顾续航与响应实时性。
- 整体结构采用防水盒与不锈钢探杆一体方案,可直接固定在钓箱或岸边支架上,拆装便捷。
需求洞察
目标用户为经常在江河湖泊进行长时间野钓的钓鱼爱好者,尤其是单次作钓时长超过 6 小时、需要同时关注浮漂与天气变化的中重度玩家。真实的痛点在于:钓鱼时人眼需要长时间盯着浮漂,很难同时观测岸边水位是否上涨(尤其野外夜间暴雨后极易发生涨水困岛的危险情况),且气压变化对鱼口活跃度有显著影响,但普通钓友无法及时感知气压趋势。
此外,钓鱼过程中手机往往放在钓箱内,消息提醒容易被忽略。因此,该设备不依赖手机也能通过本地声音和屏幕告警,同时在有网络时自动上报数据,让钓鱼人在安心看漂的同时,后台自动记录完整的垂钓环境曲线。项目价值在于:以不到 110 元的成本,将安全预警(防涨水困人)与鱼情预测(气压趋势)两大核心需求一体化,显著提升户外垂钓的体验与安全性,具备极强的实用性和复制性。
方案设计
感知层:BMP280 负责气温与气压采集,精度±1hPa,采用 I2C 接口接入 ESP32-S3;水位传感器采用不锈钢探针式或电容式,通过 ADC 引脚读取模拟量,用于感知岸边水位相对变化。
控制层:ESP32-S3 运行主控逻辑,负责传感器轮询、数据滤波、趋势计算、阈值判断以及低功耗调度。系统采用 32 位浮点运算处理气压滑动平均与一阶差分,用于识别气压骤降(预示天气恶化或鱼口变化)。
执行层:0.96 英寸 OLED 显示实时水位、气压、温度与趋势图标;蜂鸣器在气压骤降或水位快速上升时发出不同频率的报警音;LED 状态灯用于指示系统工作状态。
日志/联网层:ESP32-S3 内置 Wi-Fi,定期将采集数据通过 HTTP POST 推送到钓鱼气象数据平台或局域网内 Node-RED 服务;同时将关键事件(水位越限、气压突变)写入手 MicroSD 卡,形成 CSV 日志,便于后期回放分析。
供电层:TP4056 模块负责 18650 锂电池充电,充电输入来自 6V/2W 小型太阳能板;电池输出经 AMS1117-3.3 稳压后为 ESP32-S3 与传感器供电,系统支持深度睡眠模式,电流可降至 80µA 左右。
物料清单
| 序号 | 物料名称 | 数量 | 用途说明 | 估算单价(元) |
|---|---|---|---|---|
| 1 | ESP32-S3-DevKitC-1 开发板 | 1 | 主控芯片与 Wi-Fi 通信 | 42 |
| 2 | BMP280 气压温度传感器模块 | 1 | 气压与温度采集 | 12 |
| 3 | 电容式水位传感器模块 | 1 | 水位模拟量检测 | 9 |
| 4 | 0.96 英寸 I2C OLED 显示屏 | 1 | 现场数据显示 | 18 |
| 5 | TP4056 充电模块(带保护) | 1 | 锂电池充电管理 | 4 |
| 6 | 18650 锂电池 2000mAh | 1 | 系统主供电 | 12 |
| 7 | 6V/2W 太阳能板 | 1 | 户外辅助充电 | 15 |
| 8 | 蜂鸣器模块(低电平触发) | 1 | 声光报警 | 2 |
| 9 | AMS1117-3.3 稳压模块 | 1 | 稳定 3.3V 供电 | 2 |
| 10 | 防水接线盒(IP65) | 1 | 电路防护 | 6 |
| 11 | 不锈钢探杆与导线 | 若干 | 水位传感器延长 | 3 |
| 12 | 杜邦线、热缩管、螺丝等 | 若干 | 组装辅料 | 4 |
| 13 | MicroSD 卡模块(可选) | 1 | 离线日志存储 | 5 |
合计约 134 元,若取消 OLED 屏改用 LCD 1602(8 元)并将太阳能板降至 1.5W(10 元),总价可压缩至 98 元以内,满足 110 元预算目标。
接线与结构
| ESP32-S3 引脚 | 外接设备 | 说明 |
|---|---|---|
| GPIO 8(SDA) | BMP280 SDA | I2C 数据线 |
| GPIO 9(SCL) | BMP280 SCL | I2C 时钟线 |
| GPIO 1(ADC1_CH0) | 水位传感器 OUT | 模拟量采样 |
| 3.3V | BMP280 VCC / OLED VCC | 供电 |
| GND | 所有模块 GND | 共地 |
| GPIO 4 | 蜂鸣器 I/O | 低电平触发 |
| GPIO 5 | OLED SDA | 复用 I2C 数据线(若与 BMP280 共用则改成 GPIO 8) |
| GPIO 6 | OLED SCL | 复用 I2C 时钟线(若共用则改成 GPIO 9) |
| GPIO 7 | LED 状态指示 | 闪烁指示工作状态 |
| GPIO 10 | MicroSD CS(可选) | 日志模块片选 |
接线理由:BMP280 与水位传感器为低频采样设备,共享 I2C 总线不会产生冲突;OLED 显示刷新频率较高,独立使用 GPIO 5/6 可避免显示刷新对传感器读取时序造成偶发干扰。水位传感器使用 GPIO 1 作为 ADC 输入,该引脚在 ESP32-S3 上支持衰减调节,可适配 0-3.3V 模拟量范围。
结构设计方面:全部电路板固定在防水盒内,BMP280 传感器通过短管引至盒外以便呼吸大气,感湿部位做透气防水处理;水位探杆通过防水格兰头引出至岸边,探杆下端距地面 5cm,用于检测水面相对高度;太阳能板固定于盒盖顶部,倾斜 30° 面向南方以获得最佳日晒角度;整个装置通过挂钩固定于钓箱侧边或地插支架上。
核心代码
以下为基于 Arduino 框架的 ESP32-S3 可编译骨架代码:
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <U8g2lib.h>
#include <WiFi.h>
#define WATER_ADC_PIN 1
#define BUZZER_PIN 4
#define LED_PIN 7
#define I2C_SDA 8
#define I2C_SCL 9
Adafruit_BMP280 bmp;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 9, /* data=*/ 8);
const char* ssid = "FishingAP";
const char* password = "12345678";
float baselinePressure = 1013.25;
float waterThreshold = 1.2;
unsigned long lastWake = 0;
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
Wire.begin(I2C_SDA, I2C_SCL);
if (!bmp.begin(0x76)) {
while (1) delay(10);
}
Adafruit_BMP280::SAMPLING_X2,
Adafruit_BMP280::SAMPLING_X16,
Adafruit_BMP280::FILTER_X16,
oled.begin();
oled.clearBuffer();
oled.sendBuffer();
baselinePressure = bmp.readPressure() / 100.0F;
WiFi.begin(ssid, password);
}
void loop() {
float pressure = bmp.readPressure() / 100.0F;
float temp = bmp.readTemperature();
float waterLevel = analogRead(WATER_ADC_PIN) / 4095.0F;
// 气压变化量计算(单位 hPa/min)
static float lastP = pressure;
static unsigned long lastT = millis();
float dp = (pressure - lastP) * 60000.0F / (millis() - lastT);
lastP = pressure;
lastT = millis();
// 水位越限报警
if (waterLevel > waterThreshold) {
for (int i = 0; i < 5; i++) {
digitalWrite(BUZZER_PIN, LOW);
delay(100);
delay(100);
}
}
// 气压骤降报警(> 1.5 hPa/min)
if (dp < -1.5) {
digitalWrite(BUZZER_PIN, LOW);
delay(500);
}
// OLED 显示刷新(每 2 秒)
if (millis() - lastWake > 2000) {
lastWake = millis();
oled.clearBuffer();
oled.setCursor(0, 15);
oled.print("P:");
oled.print(pressure, 1);
oled.print("hPa");
oled.setCursor(0, 30);
oled.print("T:");
oled.print(temp, 1);
oled.print("C");
oled.setCursor(0, 45);
oled.print("W:");
oled.print(waterLevel, 2);
oled.drawStr(70, 45, dp < 0 ? "Down" : "Up");
oled.sendBuffer();
// 数据上报
if (WiFi.status() == WL_CONNECTED) {
WiFiClient client;
if (client.connect("192.168.1.100", 8080)) {
client.print(String("GET /log?p=") + pressure + "&t;=" + temp + "&w;=" + waterLevel + " HTTP/1.1\r\nHost: localhost\r\n\r\n");
client.stop();
}
}
}
delay(500);
}
调试步骤
- 硬件上电前使用万用表确认 3.3V 与 GND 之间无短路,TP4056 输出端接锂电池时注意正负极方向。
- 单独烧录 I2C 扫描程序,确认 BMP280 地址为 0x76 或 0x77,必要时修改代码中地址参数。
- 用水杯模拟水位上升,读取串口输出的 waterLevel 值,标定阈值:默认 1.2 对应约 2cm 水位变化,可根据实际探杆长度调整。
- 使用压缩空气或塑料袋包裹 BMP280 后挤压,验证气压读数值变化是否灵敏;若数值跳动过大,检查 I2C 线长是否超过 20cm,并适当增加滤波算法。
- 测试蜂鸣器:短接 GPIO 4 到 GND 应能听到声音;确认低电平触发逻辑与代码匹配。
- 将太阳能板接至 TP4056 的 IN+/IN-,在自然光下测量充电电流,确保不超过 1A 充电上限;若阳光强烈时出现过温保护,可加装小型散热片。
- 整机放入防水盒后,使用喷壶模拟雨水淋洒,观察盒内是否有渗水现象;微型通风孔需覆盖防水透气膜。
- 长时间运行 24 小时,通过 SD 卡日志或串口曲线检查传感器数据是否漂移,必要时对 BMP280 进行零点校准。