溪流山洪预警系统 —— 基于 Arduino + 曼宁公式的技术推导

技术方案与推导文档 · Arduino + 曼宁公式 版本:v1.0 | 编制日期:2026-08-11 | 适用范围:山区/丘陵天然溪流,梯形断面概化


1. 项目背景与目标

夏季溪流(天然河道,山区/丘陵地形)是游泳消暑的热门场所。然而,上游短历时强降雨(山洪暴发)可在数分钟内将涓涓细流变成汹涌洪流,令游泳者猝不及防。据中国气象局统计,山洪灾害年均致死人数占洪涝总死亡的 60% 以上,其中涉水游泳、溯溪是高风险行为。

本项目的目标是设计一套低成本、可现场部署的实时监测预警系统:

系统定位为辅助安全工具,不替代救生员与现场安全管理。

2. 技术方案总览

系统采用分层架构,数据自底向上流动:

感知层(传感器)        → 水位、流速、雨量等物理量采集
    ↓
数据层(Arduino 采集)  → 脉冲计数、模数转换、中值滤波
    ↓
计算层(曼宁公式)      → 由水位推算过水断面与流速、流量
    ↓
判定层(阈值判定)      → 临界流速、d·v 乘积、水位涨率
    ↓
预警层(声光/远程)     → LED 分级显示、蜂鸣器、无线发送

数据流说明:

  1. 超声波传感器(HC-SR04)周期性地测量水面到传感器的距离,换算为当前水深 h(t);
  2. Arduino 对连续 N 次测量做中值滤波,获得平滑水深值;
  3. 将水深代入预置的断面几何参数与曼宁公式,算出瞬时流速 v 和流量 Q;
  4. 比较 v、d·v(水深×流速)、dh/dt 与预设阈值,判定危险等级;
  5. 驱动对应颜色的 LED 与蜂鸣器模式,同时通过串口/无线模块发送数据报文。

系统亦可选配雨量计(板式或翻斗式)作为上游预警的提前量输入。

3. 曼宁公式推导

3.1 明渠均匀流基本假设

天然溪流可近似为明渠恒定均匀流,其成立需满足以下假设:

此时不必求解 Saint-Venant 方程组,可直接用阻力公式计算平均流速。

3.2 从 Chézy 到 Manning

法国工程师 Chézy(1769)最先给出均匀流流速公式:

v = C · √(R · S)

其中 C 为 Chézy 系数(量纲 L^(1/2)/T)、R 为水力半径、S 为底坡(无量纲)。

爱尔兰工程师 Manning(1891)根据大量河流与渠道实测数据,发现 C 并不恒定,而与 R^(1/6) 近似成正比。他提出经验公式:

v = (1/n) · R^(2/3) · S^(1/2)

这就是曼宁公式,其中:

符号 名称 单位 说明
v 断面平均流速 m/s
n 糙率(Manning's n) s/m^(1/3) 经验值,表征河床粗糙度
R 水力半径 m R = A / P
A 过水断面面积 横截面中水流占据的面积
P 湿周 m 断面中水体与河床接触的周长
S 底坡(能坡) m/m(无量纲) 对于均匀流 S = 河床比降

n 是纯经验参数,无严格物理推导。Chow(1959)编纂了大量天然河道的 n 值查表(见第 7 节)。

3.3 梯形断面几何推导

天然溪流断面通常不规则,工程上常概化为梯形(对称边坡 m:1,即水平:垂直):

        水面 ~~~~~~~~~~~~~
          ______________
         /              \
        /                \    ← 边坡 m:1
       /                  \
  ____/____________________\____ 河床
  |←—— b(底宽)——→|

设底宽为 b(m),水深为 h(m),边坡系数为 m(水平 / 垂直),则:

过水断面面积 A:

A = (b + m · h) · h

湿周 P(梯形两腰加底边):

P = b + 2h · √(1 + m²)

水力半径 R:

R = A / P = (b + m·h)·h / [b + 2h·√(1 + m²)]

3.4 流量公式

将 R 代入曼宁公式,乘以面积得流量:

Q = v · A = (1/n) · A · R^(2/3) · S^(1/2)

3.5 完整数值算例

给定参数:

计算三种水深下的水力要素:

h (m) A (m²) P (m) R (m) R^(2/3) v (m/s) Q (m³/s)
0.50 1.875 4.80 0.390 0.534 1.53 2.86
1.00 4.500 6.61 0.681 0.774 2.21 9.95
1.50 7.875 8.41 0.937 0.957 2.74 21.5

数值验算示例(h = 0.50 m):

量纲校验:v 的量纲为 [1/n]·[L^(2/3)]·[1] = (1 / T·L^(-1/3)) · L^(2/3) = L/T = m/s ✓;Q = m/s × m² = m³/s ✓。

⚠️ 值得注意的是,在底坡 S = 1% 的陡溪中,即使水深仅 0.5 m,流速已达 1.53 m/s —— 远超成人站立临界流速(见第 5 节),危险程度不容小觑。

4. 传感器选型与原理

4.1 主控

选择 Arduino Uno R3 或 Arduino Nano(ATmega328P,5V/16MHz),理由:

4.2 YF-S201 霍尔水流量传感器

YF-S201 内部结构为磁性叶轮 + 霍尔效应传感器:水流推动叶轮旋转,每转一圈霍尔元件产生一个脉冲。常见标定关系:

流量 Q_L (L/min) = 脉冲频率 f (Hz) / 7.5

即每升水约产生 450 个脉冲(7.5 Hz 对应 1 L/min)。量程 1–30 L/min,耐压 ≤ 1.75 MPa,适用于 DN15(1/2 英寸)管径。

接线:红线 VCC(5–24V)、黑线 GND、黄线信号(集电极开路,需 10kΩ 上拉至 VCC)。

4.3 关键工程设计问题:管流传感器如何测溪流?

诚实说明:YF-S201 设计用于封闭管道满管流,不能直接放入天然溪流测量 —— 溪流断面远大于传感器管径,且非满管流会导致叶轮裸露或进气,测量完全失效。

对此,本文给出两种工程解法,推荐方案 A:

方案 A(推荐):水位-流量关系法

在溪流断面正上方架设 HC-SR04 超声波测距模块,测量传感器到水面的距离,进而反算水深 h:

h = H_total − D_measured

其中 H_total 为传感器安装高度至河床底的已知距离(安装时标定),D_measured 为超声波实测距离。获得 h 后,代入曼宁公式 Q(h) 直接换算流量与流速。

HC-SR04 参数:测量范围 2–400 cm,精度 ±3 mm,Trig/Echo 触发模式,5V 供电。

优势:非接触测量,无需改造河道,不受漂浮物缠绕影响。

方案 B:流速测点标定法

将流速传感器(可用螺旋桨流速仪或改良的管道流速探头)固定在断面主流区某深度,实测点流速 v_meas。由于曼宁公式给出的是断面平均流速,可用实测值反算/率定糙率 n:

n = R^(2/3) · S^(1/2) / v_meas

在糙率 n 标定完成后,即可用水位 h → R(h) → 曼宁公式 → v 推算全场流速。

缺点:单点流速不能代表全断面平均流速,需乘以经验修正系数(约 0.8–0.9),且传感器浸入水中易被杂物缠绕。

4.4 可选传感器

传感器 用途 说明
翻斗式雨量计 上游降雨预警 每个翻斗 ≈ 0.2–0.5 mm 降雨,提前量关键
DS18B20 温度探头 水温监测 游泳舒适度参考(15℃ 以下有失温风险)
大气压力传感器 (BMP280) 辅助气象 气压骤降可辅助判断风暴来临

5. 危险判定阈值推导

5.1 人体流水稳定性力学分析

人站立于流水中,受到水流的拖曳力(drag force):

F_D = 0.5 · ρ · C_D · A_p · v²

其中:

人体抵抗水流的摩擦力来自足底与河床:

F_f = μ · W'

其中 μ ≈ 0.5–0.7(橡胶/赤足与岩石间静摩擦系数,取 0.6),W' 为水中有效重量(扣除浮力)。成人平均体重约 700 N,水中约 90% 体积没入时浮力约 630 N,故 W' ≈ 70 N。

则 F_f ≈ 0.6 × 70 = 42 N。

临界条件 F_D = F_f:

0.5 × 1000 × 1.0 × A_p × v_c² = 42

结论:成人可稳定站立的流速上限随水深增大而降低,工程上常取 0.5–0.6 m/s 为行走困难阈值,1.0–1.2 m/s 为无法站立/被冲倒阈值

5.2 水深-流速乘积标准

白水救援(Whitewater Rescue)与水安全工程中常用 d·v 乘积(depth × velocity product)作为综合危险指标:

d·v (m²/s) 危险等级 说明
< 0.2 安全 成人可稳定涉水
0.2–0.4 注意 儿童危险,成人行走困难
> 0.4 危险 成人无法站稳,禁止涉水

5.3 由 v = 0.5 m/s 反解临界水深与临界流量

沿用第 3.5 节的断面参数(b = 3.0 m, m = 1.5, S = 0.01, n = 0.035),求解 v(h) = 0.5 m/s 对应的 h_c:

用迭代法(试算):

临界水深 h_c ≈ 0.078 m,临界流量 Q_c = v × A ≈ 0.504 × 0.243 ≈ 0.12 m³/s。

物理意义:在该宽浅(b=3m)、大底坡(S=1%)的溪流中,只要水深超过约 8 cm,流速即超过成人安全站立阈值。这解释了为何"看着水不深"的山溪实际极为危险——流速早已在不经意间致命。

同理,d·v = 0.4 m²/s 对应的临界水深约 h ≈ 0.33 m(v ≈ 1.21 m/s),即水深超过小腿时已进入红区。

5.4 预警分级

等级 触发条件 响应
🔵 蓝色(关注) v > 0.3 m/s 或降雨开始 蓝色 LED 常亮,提醒游泳者注意
🟡 黄色(警告) v > 0.5 m/s 或 d·v > 0.4 m²/s 黄色 LED 闪烁 + 蜂鸣器间歇鸣响(1 Hz)
🔴 红色(立即撤离) v > 1.0 m/s 或 dh/dt > 0.3 m/h 或雨强 > 30 mm/h 红色 LED 高频闪烁 + 蜂鸣器长鸣;远程推送报警

其中 dh/dt(水位上涨速率)和雨强是比流速更灵敏的山洪前兆。单独依赖本站水位/流速会有滞后(见第 8 节)。

6. Arduino 实现

6.1 引脚接线表

Arduino 引脚 连接设备 说明
D2 (INT0) YF-S201 信号线(黄) 外部中断,脉冲计数
D3 HC-SR04 Trig 超声波触发
D4 HC-SR04 Echo 超声波回波
D5 蓝色 LED(经 220Ω) 关注指示
D6 黄色 LED(经 220Ω) 警告指示
D7 红色 LED(经 220Ω) 危险指示
D8 有源蜂鸣器 报警
D9 可选:雨量计输入 翻斗脉冲计数
A0 可选:DS18B20(OneWire) 水温
TX/RX 可选:ESP8266 / LoRa 模块 远程通信
5V / GND 各传感器 VCC / GND 公共供电

6.2 核心代码

// ====== 溪流山洪预警系统 ======
// 基于 HC-SR04 超声波水位 + 曼宁公式 + 分级报警

#include <NewPing.h>   // 超声波库(需安装)

// ---------- 引脚定义 ----------
#define TRIG_PIN    3
#define ECHO_PIN    4
#define LED_BLUE    5
#define LED_YELLOW  6
#define LED_RED     7
#define BUZZER      8

// ---------- 断面参数(安装时实测标定)----------
const float B      = 3.0;    // 底宽 (m)
const float M      = 1.5;    // 边坡系数
const float N_MAN  = 0.035;  // 曼宁糙率
const float S_SLOPE = 0.01;  // 底坡
const float H_TOTAL = 2.50;  // 传感器距河床总高 (m),安装时激光测距标定

// ---------- 预警阈值 ----------
const float V_BLUE   = 0.3;  // m/s
const float V_YELLOW = 0.5;  // m/s
const float V_RED    = 1.0;  // m/s
const float DV_CRIT  = 0.4;  // m²/s,成人危险 d·v 乘积
const float DH_RATE  = 0.3;  // m/h,水位上涨速率

// ---------- 采样参数 ----------
const int   SAMPLE_COUNT = 10;    // 中值滤波样本数
const float SAMPLE_NORMAL = 60000; // 正常采样间隔 60s (ms)
const float SAMPLE_FAST   = 5000;  // 加速采样间隔 5s (ms)

NewPing sonar(TRIG_PIN, ECHO_PIN, 400); // 最大距离 400 cm
float prevH = 0.0;
unsigned long prevTime = 0;

// ---------- 梯形断面水力计算 ----------
float calcArea(float h) {
  return (B + M * h) * h;
}

float calcWettedPerimeter(float h) {
  return B + 2.0 * h * sqrt(1.0 + M * M);
}

float calcHydraulicRadius(float h) {
  if (h <= 0.001) return 0.0;
  float a = calcArea(h);
  float p = calcWettedPerimeter(h);
  return a / p;
}

// 曼宁公式:v = (1/n) * R^(2/3) * S^(1/2)
float calcVelocity(float h) {
  if (h <= 0.001) return 0.0;
  float r = calcHydraulicRadius(h);
  return (1.0 / N_MAN) * pow(r, 2.0/3.0) * sqrt(S_SLOPE);
}

float calcDischarge(float h) {
  float v = calcVelocity(h);
  float a = calcArea(h);
  return v * a;
}

// ---------- 中值滤波(冒泡排序取中位)----------
float medianFilter(float *arr, int n) {
  float tmp[n];
  for (int i = 0; i < n; i++) tmp[i] = arr[i];
  for (int i = 0; i < n-1; i++)
    for (int j = i+1; j < n; j++)
      if (tmp[i] > tmp[j]) { float t = tmp[i]; tmp[i] = tmp[j]; tmp[j] = t; }
  return tmp[n/2];
}

// ---------- 读取超声波水深 ----------
float readDepth() {
  float samples[SAMPLE_COUNT];
  for (int i = 0; i < SAMPLE_COUNT; i++) {
    float d_cm = sonar.ping_cm();  // 距离水面 (cm)
    if (d_cm == 0) d_cm = H_TOTAL * 100; // 超量程当作河床
    samples[i] = (H_TOTAL * 100.0 - d_cm) / 100.0; // 水深 (m),限制 ≥0
    if (samples[i] < 0) samples[i] = 0;
    delay(30);
  }
  return medianFilter(samples, SAMPLE_COUNT);
}

// ---------- 预警判定与驱动 ----------
void evaluateAlarm(float h, float v) {
  float dv = h * v;  // d·v 乘积

  // 红色:立即撤离
  if (v > V_RED || dv > DV_CRIT) {
    digitalWrite(LED_BLUE,   LOW);
    digitalWrite(LED_YELLOW, LOW);
    digitalWrite(LED_RED,   HIGH);
    tone(BUZZER, 1000);  // 长鸣
    return;
  }

  // 黄色:警告
  if (v > V_YELLOW) {
    digitalWrite(LED_BLUE,  LOW);
    digitalWrite(LED_YELLOW, HIGH);
    digitalWrite(LED_RED,   LOW);
    tone(BUZZER, 800);
    delay(200);
    noTone(BUZZER);
    delay(800);
    return;
  }

  // 蓝色:关注
  if (v > V_BLUE) {
    digitalWrite(LED_BLUE,  HIGH);
    digitalWrite(LED_YELLOW, LOW);
    digitalWrite(LED_RED,   LOW);
    noTone(BUZZER);
    return;
  }

  // 安全
  digitalWrite(LED_BLUE,  LOW);
  digitalWrite(LED_YELLOW, LOW);
  digitalWrite(LED_RED,   LOW);
  noTone(BUZZER);
}

// ---------- 主程序 ----------
void setup() {
  Serial.begin(9600);
  pinMode(LED_BLUE,   OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  pinMode(LED_RED,    OUTPUT);
  pinMode(BUZZER,     OUTPUT);

  Serial.println("=== 溪流山洪预警系统启动 ===");
  Serial.println("h(m)\tv(m/s)\tQ(m3/s)\tdv(m2/s)\tdh/dt(m/h)\tLevel");

  prevH = readDepth();
  prevTime = millis();
}

void loop() {
  unsigned long now  = millis();
  float dt_hours    = (now - prevTime) / 3600000.0; // ms → h

  float h = readDepth();
  float v = calcVelocity(h);
  float q = calcDischarge(h);
  float dhdt = (dt_hours > 0.001) ? (h - prevH) / dt_hours : 0.0;
  float dv = h * v;

  evaluateAlarm(h, v);

  // 串口输出(可接 LoRa/WiFi 模块转发)
  String level = "SAFE";
  if (v > V_RED || dv > DV_CRIT) level = "RED";
  else if (v > V_YELLOW) level = "YELLOW";
  else if (v > V_BLUE) level = "BLUE";

  Serial.print(h, 3); Serial.print("\t");
  Serial.print(v, 2); Serial.print("\t");
  Serial.print(q, 3); Serial.print("\t");
  Serial.print(dv, 3); Serial.print("\t");
  Serial.print(dhdt, 2); Serial.print("\t");
  Serial.println(level);

  prevH = h;
  prevTime = now;

  // 自适应采样:水位上涨或已有预警时加速
  float interval = (dhdt > 0.1 || level != "SAFE") ? SAMPLE_FAST : SAMPLE_NORMAL;
  delay(interval);
}

6.3 采样策略

工况 采样间隔 理由
正常(v < 阈值、dh/dt 平缓) 60 秒 节省功耗,正常水位变化缓慢
预警状态(黄色/红色) 5 秒 快速追踪变化,及时升级
降雨触发(雨量计脉冲 > 阈值) 5 秒 山洪可能性增大,需密集监测

7. 校准、安装与维护

7.1 现场测量

部署前需完成三项实地勘测:

(1)断面测量

在监测断面位置,用皮尺/激光测距仪测量 b(底宽),在两侧河岸打桩记录左右边坡。天然断面可能非标准梯形,取 3–5 个特征水深点的 A-P 对建立分段函数。

(2)底坡 S 测量

在沿河 50–100 m 范围内,用水准仪或手持 GPS 测量上下游两点水面高程差 Δz,底坡 S = Δz / ΔL。山区溪流典型 S 在 0.005–0.05 之间。

(3)糙率 n 查表

参照 Chow(1959)《Open-Channel Hydraulics》第 5 章中的天然河道 n 值(节选):

河道状况 n 值范围
清洁、顺直、满水、无深潭或浅滩 0.025 – 0.033
同上,但有杂草与石块 0.030 – 0.040
清洁、蜿蜒、有浅潭与浅滩 0.033 – 0.045
多石河段、有水草 0.035 – 0.050
底部多砾石、大石块 0.040 – 0.070
杂草丛生、深潭 0.050 – 0.080
山区溪流、砾石/卵石/少量大石 0.030 – 0.050
山区溪流、大石与卵石 0.040 – 0.070

选择最接近现场描述的 n 值中位数作为初始值。

7.2 率定方法

多次实测对反算 n:

  1. 在断面选择水流平稳时段,用浮标法或手持流速仪实测表面流速 v_surface;
  2. 断面平均流速 v_obs ≈ 0.85 × v_surface(天然河道经验系数);
  3. 同步记录水深 h_obs,计算 R_obs = A(h_obs) / P(h_obs);
  4. 反算:n_cal = R_obs^(2/3) · S^(1/2) / v_obs;
  5. 至少在不同水位(低水、中水、高水)各测 3 次,取均值。
// 率定辅助代码片段
void calibrateN() {
  Serial.println("=== 率定模式 ===");
  Serial.println("输入实测水深(m)和流速(m/s),例如: 0.50,0.85");
  // 在串口监视器输入 "0.50,0.85" 计算 n
}

7.3 维护要点

项目 周期 操作
超声波探头清洁 每周 清除蜘蛛网、灰尘、露水凝结
供电检查 每周 太阳能板除尘、电池电压 ≥ 11.5V
断面复核 每季度或暴雨后 河床冲刷可能改变断面形状,重新测量 b、m
率定复核 每半年 重新用流速仪标定 n,确认曼宁曲线未漂移
防雷接地 安装时 金属杆架设避雷针、设备加 TVS 管
冬季防冻 入冬前 气温 < 0℃ 地区回收电子设备或做保温

8. 局限性与安全声明

8.1 系统局限

8.2 安全声明

⚠️ 本系统是一个辅助决策工具,不是安全证书。山洪预警的黄金法则是上游预警:只有在上游设置雨量计 + 水位计(联动无线通信),才能为下游游泳者提供足够长(15-30 分钟以上)的撤离窗口。本系统若仅依赖本站水位,滞后效应可能使预警发出时危险已到来。

本系统不可替代以下措施:

部署建议:将本系统作为多级预警体系的底层终端之一,与上游雨量-水位遥测站联动,构成完整的山洪预警链。

9. 参考文献

  1. Manning, R. (1891). On the flow of water in open channels and pipes. Transactions of the Institution of Civil Engineers of Ireland, 20, 161–207.
  2. Chow, V. T. (1959). Open-Channel Hydraulics. McGraw-Hill, New York. (第 5 章:糙率 n 值表;第 7 章:均匀流)
  3. Chézy, A. (1769). 关于渠道流速公式的原始报告,收录于 Clemens, H. & Herschel, C. (1897).
  4. Henderson, F. M. (1966). Open Channel Flow. Macmillan, New York.
  5. Rantz, S. E. et al. (1982). Measurement and Computation of Streamflow: Volume 1. Measurement of Stage and Discharge. USGS Water-Supply Paper 2175.
  6. Rescate, S. (2014). Whitewater Rescue Manual: Techniques for River Rescue. International Rescue Instructors Alliance. (有关 d·v 乘积的人身稳定性准则)
  7. Jonkman, S. N. & Penning-Rowsell, E. (2008). Human Instability in Flood Flows. Journal of the American Water Resources Association, 44(5), 1208–1218.
  8. Texas Electronics Inc. (2020). YF-S201 Hall Effect Water Flow Sensor Datasheet.
  9. Cytron Technologies (2019). HC-SR04 Ultrasonic Ranging Module User's Manual.
  10. 中国水利部水文局. (2015). 山洪灾害监测预警系统技术规范(SL 675-2014). 中国水利水电出版社.