4、常用传感器详解(下):HC-SR04超声波测距模块、BMP280气压传感器、MQ系列气体传感器,实战接线与测试。

好,咱们接着聊传感器。上一节我们把温湿度、光照和红外给搞定了,这一节咱们来啃几个硬骨头——超声波测距、气压测量,还有气体检测。这几个传感器在实际项目中出镜率极高,我个人的经验是,搞懂它们,你的物联网项目基本就能覆盖80%的物理量采集场景了。

4.1 HC-SR04 超声波测距模块

先说说这个测距模块。HC-SR04,说白了就是个声呐。它发出超声波,碰到障碍物弹回来,通过计算时间差来算距离。原理不复杂,但坑不少。

核心原理: 发射端发出8个40kHz的脉冲,接收端等待回波。从发射到接收的时间差t,乘以声速340m/s,再除以2,就是距离。

公式:距离 = t × 340 / 2 (单位:米)

4.1.1 引脚与接线

这个模块有4个引脚,我列个表,你照着接就行,别搞反了。

引脚功能接ESP32/Arduino
VCC电源正极5V
GND电源负极GND
Trig触发引脚GPIO 5(示例)
Echo回波引脚GPIO 18(示例)

注意: Echo引脚输出的是5V电平!如果你用的是3.3V的ESP32或STM32,必须加一个分压电阻(比如1kΩ和2kΩ分压),否则会烧引脚。我曾经有一次偷懒没加分压,结果烧了一个ESP32的GPIO口,血的教训。

4.1.2 实战代码与测试

我习惯用NewPing库,它把时序处理封装好了,省心。下面这段代码,你直接烧录进去,打开串口监视器就能看到距离数据。

#include <NewPing.h>

#define TRIG_PIN 5
#define ECHO_PIN 18
#define MAX_DISTANCE 400 // 最大测量距离(厘米)

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {
  Serial.begin(115200);
  Serial.println("HC-SR04 超声波测距测试开始");
}

void loop() {
  delay(500);
  unsigned int distance = sonar.ping_cm(); // 获取距离,单位厘米
  if (distance == 0) {
    Serial.println("超出测量范围或未检测到物体");
  } else {
    Serial.print("距离: ");
    Serial.print(distance);
    Serial.println(" cm");
  }
}

跑起来之后,你拿个纸板在传感器前面晃一晃,看看数值变化。嗯,这里要注意,如果距离小于2cm,数据会不准,这是模块的物理限制。

避坑指南: 我曾经在项目里用这个模块做液位检测,发现数据老是跳变。后来排查发现,超声波打到水面会产生漫反射,导致回波不稳定。解决办法是加一个导波管,让声波定向传播。你想想看,如果直接对着水面测,误差能到好几厘米。

4.2 BMP280 气压传感器

接下来是BMP280。这个传感器挺有意思,它能测气压和温度,精度还不错。我常用它来做海拔高度估算——气压越低,海拔越高。说白了,就是利用大气压随高度变化的规律。

4.2.1 通信方式与接线

BMP280支持I2C和SPI两种通信方式。我一般用I2C,因为接线简单,只需要两根线。默认I2C地址是0x76,如果你把SDO引脚接VCC,地址会变成0x77。

引脚功能接ESP32(I2C)
VCC电源正极3.3V
GND电源负极GND
SDA数据线GPIO 21
SCL时钟线GPIO 22

注意: BMP280的VCC只能接3.3V!接5V会直接烧掉。我见过有人把模块插到5V面包板上,瞬间冒烟。别问我怎么知道的。

4.2.2 实战代码与测试

用Adafruit的BMP280库,几行代码就能读出数据。我习惯先初始化,然后循环读取。

#include <Wire.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp; // 使用I2C接口

void setup() {
  Serial.begin(115200);
  if (!bmp.begin(0x76)) { // 检查设备地址
    Serial.println("BMP280 未找到,请检查接线!");
    while (1);
  }
  Serial.println("BMP280 初始化成功");
}

void loop() {
  delay(1000);
  float temperature = bmp.readTemperature();
  float pressure = bmp.readPressure() / 100.0F; // 转换为hPa
  float altitude = bmp.readAltitude(1013.25); // 海平面标准气压1013.25hPa

  Serial.print("温度: ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("气压: ");
  Serial.print(pressure);
  Serial.println(" hPa");

  Serial.print("估算海拔: ");
  Serial.print(altitude);
  Serial.println(" m");
}

跑起来后,你用手捏一下传感器(别太用力),气压值会微微变化。为什么会这样?因为手温加热了传感器内部空气,导致局部气压升高。嗯,这个细节在精密测量时要注意。

个人经验: 用BMP280估算海拔时,一定要校准海平面气压。不同地区、不同天气,海平面气压都不一样。我一般在项目里加一个GPS模块,用GPS获取真实海拔,然后反推出当前的海平面气压,这样后续测量才准。

4.3 MQ系列气体传感器

最后说说MQ系列。这个系列传感器种类很多,MQ-2测可燃气体,MQ-7测一氧化碳,MQ-135测空气质量。它们的原理都一样——气敏材料遇到特定气体,电阻值会变化。说白了,就是通过电阻变化来反推气体浓度。

4.3.1 模块类型与选型

我列个表,你根据需求选型。别买错了,MQ-2和MQ-7虽然长得一样,但检测对象完全不同。

型号检测气体典型应用
MQ-2液化气、丙烷、氢气厨房燃气泄漏报警
MQ-7一氧化碳车库、锅炉房CO检测
MQ-135氨气、苯、烟雾空气质量监测

4.3.2 接线与注意事项

MQ模块通常有4个引脚:VCC、GND、DO(数字输出)、AO(模拟输出)。我建议你直接用AO引脚接ADC,这样能读到气体浓度的模拟量,数据更丰富。

引脚功能接ESP32
VCC电源正极5V(注意!)
GND电源负极GND
AO模拟输出GPIO 34(ADC)
DO数字输出可接GPIO,用于阈值报警

重要警告: MQ模块的加热丝需要5V供电!如果接3.3V,传感器无法正常工作,读数会一直偏低。另外,新模块第一次通电需要预热24小时以上,这叫“老化”,目的是让气敏材料稳定。我当年第一次用MQ-2,没预热就直接测,数据飘得跟心电图似的。

4.3.3 实战代码与测试

下面这段代码,用MQ-135测空气质量。我读取模拟值,然后映射到0-100的百分比,方便理解。

#define MQ_PIN 34 // 模拟输入引脚

void setup() {
  Serial.begin(115200);
  Serial.println("MQ-135 空气质量传感器测试");
  Serial.println("请预热5分钟后查看数据");
}

void loop() {
  delay(2000);
  int sensorValue = analogRead(MQ_PIN);
  // 将ADC值(0-4095)映射到0-100
  float percentage = map(sensorValue, 0, 4095, 0, 100);
  
  Serial.print("ADC原始值: ");
  Serial.print(sensorValue);
  Serial.print("  空气质量指数: ");
  Serial.print(percentage);
  Serial.println(" %");
  
  if (percentage > 70) {
    Serial.println("警告:空气质量较差!");
  }
}

测试时,你对着传感器吹一口气,数值会立刻飙升。为什么会这样?因为呼出的二氧化碳和水分会影响气敏材料。嗯,这个特性可以用来做简易的呼吸检测,但精度就别指望了。

避坑指南: MQ系列传感器功耗很大,加热电流能到150mA以上。如果你用电池供电,记得加一个MOS管开关,只在需要测量时才给传感器供电。我曾经在野外监测项目里没注意功耗,结果电池半天就耗光了。

4.4 小结

这一节我们搞定了三个传感器:HC-SR04测距离、BMP280测气压、MQ系列测气体。每个传感器都有自己的脾气——超声波怕漫反射、BMP280怕5V、MQ系列怕冷启动。你只要记住这些坑,实际用起来就顺了。

下一节,咱们开始讲传感器数据怎么通过WiFi和MQTT协议上传到云端。到时候,这些传感器采集的数据就能真正“上网”了。

课后练习: 把这三个传感器同时接到一块ESP32上,每5秒采集一次数据,通过串口打印出来。试试看,能不能让超声波测距和气压数据联动——比如,当距离小于10cm时,记录当前的气压值。