ESP32 + Android 实现地震预警:从硬件选型到实操部署
用 ESP32 搭建地震预警系统,核心不在于能不能检测到震动,而在于如何解决“误报”与“延迟”这两个技术死穴。很多初学者直接用数字触发,结果风吹草动就报警,这种方案在实际场景中毫无意义。要实现一个相对可靠的 IoT 预警链路,必须走「传感器采集 → 阈值滤波 → MQTT 异步推送 → Android 端实时响应」这条路。
- MPU6050 GND → ESP32 GND
- MPU6050 SCL → ESP32 GPIO 22
- MPU6050 SDA → ESP32 GPIO 21
不能直接读取原始加速度值,因为 MPU6050 存在零点漂移。需要计算三轴合成加速度的矢量和 $\sqrt{x^2+y^2+z^2}$,并与重力加速度 $g$ 做差值,得到实际的震动强度。
为了保证 Android 端能秒级收到通知,建议放弃 HTTP 轮询,直接用 MQTT 协议。部署一个轻量级的 Mosquitto Broker,ESP32 作为 Publisher,Android App 作为 Subscriber。
Android 端需要一个后台 Service 维持 MQTT 连接。为了防止系统杀掉进程导致预警失效,必须申请
下一篇
分享一个能让视频动起来的AI黑科技 →
一、 硬件链路与关键参数
这套方案的硬件成本极低,但对采样率有要求。我实测发现,如果采样间隔超过 100ms,很容易漏掉地震波的 P 波(纵波)特征。
- 控制器: ESP32-WROOM-32(必须选带 Wi-Fi 的版本,用于数据上报)
- 传感器: MPU6050(三轴加速度计 + 三轴陀螺仪)。注意:必须通过 I2C 接口连接,且建议在 VCC 和 GND 之间并联一个 10uF 的电容来滤除电源噪声。
- 逻辑连接:
- 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
程
