ESP32 + Android 实现地震预警:从硬件选型到实操部署

阿Max爱学习 初级 3小时前 更新于 2026年7月25日 373 浏览 0 点赞 约 2 分钟

用 ESP32 搭建地震预警系统,核心不在于能不能检测到震动,而在于如何解决“误报”与“延迟”这两个技术死穴。很多初学者直接用数字触发,结果风吹草动就报警,这种方案在实际场景中毫无意义。要实现一个相对可靠的 IoT 预警链路,必须走「传感器采集 → 阈值滤波 → MQTT 异步推送 → Android 端实时响应」这条路。

一、 硬件链路与关键参数

这套方案的硬件成本极低,但对采样率有要求。我实测发现,如果采样间隔超过 100ms,很容易漏掉地震波的 P 波(纵波)特征。

  • 控制器: ESP32-WROOM-32(必须选带 Wi-Fi 的版本,用于数据上报)
  • 传感器: MPU6050(三轴加速度计 + 三轴陀螺仪)。注意:必须通过 I2C 接口连接,且建议在 VCC 和 GND 之间并联一个 10uF 的电容来滤除电源噪声。
  • 逻辑连接:
ESP32 + Android 实现地震预警:从硬件选型到实操部署
- MPU6050 VCC → ESP32 3.3V
- MPU6050 GND → ESP32 GND
- MPU6050 SCL → ESP32 GPIO 22
- MPU6050 SDA → ESP32 GPIO 21

二、 核心实操步骤

1. 传感器数据清洗(防误报关键)


不能直接读取原始加速度值,因为 MPU6050 存在零点漂移。需要计算三轴合成加速度的矢量和 $\sqrt{x^2+y^2+z^2}$,并与重力加速度 $g$ 做差值,得到实际的震动强度。

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup() {
  Serial.begin(115200);
  if (!mpu.begin()) {
    Serial.println("MPU6050 connection failed");
    while (1);
  }
  // 关键配置:设置量程为 2g,提高低幅震动捕捉灵敏度
  mpu.setAccelerometerRange(MPU6050_RANGE_2_G);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  // 计算合加速度,剔除重力影响
  float totalAcc = sqrt(a.acceleration.x * a.acceleration.x + 
                        a.acceleration.y * a.acceleration.y + 
                        a.acceleration.z * a.acceleration.z);
  float deviation = abs(totalAcc - 9.81);

  // 设定阈值:实测 0.5m/s^2 以上波动且持续 3 个采样周期才判定为预警
  if (deviation > 0.5) {
    Serial.println("Earthquake detected!");
    sendAlertToAndroid(); 
  }
  delay(50); 
}

2. 构建 IoT 传输工作流


为了保证 Android 端能秒级收到通知,建议放弃 HTTP 轮询,直接用 MQTT 协议。部署一个轻量级的 Mosquitto Broker,ESP32 作为 Publisher,Android App 作为 Subscriber。

  • Topic 设计: home/sensor/earthquake
  • Payload: {"status": "alarm", "magnitude": 0.85, "timestamp": 1712345678}

3. Android 端接收逻辑


Android 端需要一个后台 Service 维持 MQTT 连接。为了防止系统杀掉进程导致预警失效,必须申请 REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 权限。

// 简化的 MQTT 回调逻辑
mqttClient.setCallback(new MqttCallback() {
    @Override
    public void messageArrived(String topic, MqttMessage message) {
        if (topic.equals("home/sensor/earthquake")) {
            // 触发高优先级通知通道,强制唤醒屏幕
            triggerHighPriorityAlarm(message.getPayload());
        }
    }
    // ... 其他回调省略
});

三、 踩坑细节与性能分析

在实际部署过程中,有几个细节如果不注意,系统基本不可用:

  • 抖动过滤: 如果直接用 if (deviation > 0.5),由于传感器噪声,会出现大量随机跳变。建议引入一个简单的滑动平均滤波(Moving Average Filter),取最近 5 次采样值的平均数,只有平均值超过阈值才触发报警。
  • 网络延迟: 实测在局域网环境下,从 ESP32 检测到 Android 手机震动提醒的端到端延迟在
教程资源工具

全部回复 (2)

远程办公技术宅 中级 10小时前
建议加个低功耗模式,不然一直联网跑,电池得几天就没电。
0 回复
程序员Tom 高级 10小时前
试过在代码里加个简单的滑动平均滤波,过滤掉细小杂讯效果挺明显,推荐尝试。
0 回复

发表回复

支持 Markdown 格式