4、传感器选型与接口:加速度传感器(MPU6050)、门磁传感器、温湿度传感器(DHT22)、电平转换电路

好,咱们进入第四讲。这一讲我打算把整个系统里用到的几个关键传感器,一个一个拎出来说清楚。

选传感器这事儿,说白了就是「够用、稳定、好买」。我在项目里吃过不少亏,比如选了某个冷门型号,结果供货周期八周起步,项目差点黄了。所以这次我选的,都是市面上烂大街、资料多、不容易翻车的型号。

4.1 加速度传感器:MPU6050

电梯运行状态监测,加速度是核心数据。电梯启动、制动、匀速、颠簸、急停,全看加速度波形。

为什么选MPU6050?

  • 六轴数据:三轴加速度 + 三轴陀螺仪。电梯里其实陀螺仪用得少,但留着做姿态解算也不亏。
  • I2C接口:两根线搞定,省IO口。
  • 内置DMP:可以直接输出四元数,省得你自己算欧拉角。
  • 便宜:淘宝几块钱一片,坏了不心疼。

关键参数:

参数
加速度量程±2g / ±4g / ±8g / ±16g
陀螺仪量程±250 / ±500 / ±1000 / ±2000 °/s
ADC分辨率16位
通信接口I2C(地址0x68或0x69)
工作电压3.3V ~ 5V(但逻辑电平是3.3V)

接线方式:

MPU6050的VCC接3.3V,GND接地,SCL接主控的SCL引脚,SDA接SDA引脚。注意,AD0引脚接地时I2C地址是0x68,接VCC时是0x69。如果你像我一样,板子上挂了好几个I2C设备,记得检查地址冲突。

我的经验:MPU6050上电后默认是休眠状态,必须往电源管理寄存器(0x6B)写0x00才能唤醒。我第一次用的时候忘了这茬,读回来的数据全是0,查了半天才发现。

代码示例(初始化部分):

// MPU6050初始化
void MPU6050_Init(void) {
    I2C_WriteByte(MPU6050_ADDR, 0x6B, 0x00);  // 唤醒
    I2C_WriteByte(MPU6050_ADDR, 0x1C, 0x00);  // 加速度量程 ±2g
    I2C_WriteByte(MPU6050_ADDR, 0x1B, 0x00);  // 陀螺仪量程 ±250°/s
    I2C_WriteByte(MPU6050_ADDR, 0x1A, 0x03);  // 低通滤波 44Hz
}

这里我设了44Hz的低通滤波,为什么?电梯的振动频率一般不会超过几十赫兹,44Hz够用了,还能滤掉高频噪声。你想想看,如果滤波设得太高,数据毛刺多,后面算法处理起来就费劲。

4.2 门磁传感器

电梯门开关状态,这个信息太重要了。电梯能不能走,门没关好绝对不能动。门磁传感器就是干这个的。

选型要点:

  • 干簧管型:便宜、无源、寿命长。我推荐这种。
  • 霍尔型:需要供电,但抗干扰更好。
  • 机械微动开关:容易坏,不推荐。

我选的是干簧管门磁,就是那种一个磁铁加一个干簧管,门关上时磁铁靠近,干簧管导通;门打开时断开。简单粗暴,几乎不会坏。

接线方式:

干簧管一端接GND,另一端接主控的GPIO(内部上拉)。门关上时,GPIO读到低电平;门打开时,读到高电平。

注意:干簧管有常开和常闭两种,买的时候看清楚。我习惯用常开型,门关时导通。另外,磁铁和干簧管的安装距离别超过1cm,否则灵敏度不够。

代码示例(读取门状态):

uint8_t Door_GetState(void) {
    return HAL_GPIO_ReadPin(DOOR_GPIO_Port, DOOR_Pin);
    // 返回0:门关,返回1:门开
}

就这么简单。但实际项目中,我建议加个软件消抖。电梯门开关时会有机械抖动,直接读可能会误判。我曾经遇到过,门明明关好了,但抖动导致系统以为门没关,电梯不走,维保人员查了半天。

4.3 温湿度传感器:DHT22

电梯机房里的温湿度,对设备寿命有影响。温度太高,变频器容易过热保护;湿度太大,电路板容易结露短路。

为什么选DHT22而不是DHT11?

参数DHT11DHT22
温度精度±2°C±0.5°C
湿度精度±5%±2%
采样周期1秒2秒
价格便宜稍贵

我个人习惯用DHT22。虽然贵几块钱,但精度高出一大截。电梯机房温度变化不大,但湿度监测需要准一些,否则容易误报。

接线方式:

DHT22有四个引脚:VCC(3.3V~5V)、DATA、NC(空脚)、GND。DATA引脚需要接一个4.7kΩ上拉电阻到VCC。注意,DHT22是单总线协议,时序要求比较严格。

避坑指南:DHT22的采样周期是2秒,也就是说,你两次读取之间至少间隔2秒,否则数据会出错。我曾经在循环里每100ms读一次,结果读出来的数据全是乱的。后来查手册才发现这个坑。

代码示例(读取温湿度):

uint8_t DHT22_Read(float *temp, float *humi) {
    uint8_t data[5] = {0};
    // 主机发送起始信号
    DHT22_Pin_Low();
    delay_ms(18);
    DHT22_Pin_High();
    delay_us(30);
    // 等待响应
    if (DHT22_Pin_Read() == 0) {
        while (DHT22_Pin_Read() == 0);  // 等待拉高
        while (DHT22_Pin_Read() == 1);  // 等待拉低
        // 读取40位数据
        for (int i = 0; i < 40; i++) {
            while (DHT22_Pin_Read() == 0);
            delay_us(40);
            if (DHT22_Pin_Read() == 1) {
                data[i/8] |= (1 << (7 - (i % 8)));
            }
            while (DHT22_Pin_Read() == 1);
        }
        // 校验
        if ((data[0] + data[1] + data[2] + data[3]) == data[4]) {
            *humi = ((data[0] << 8) | data[1]) / 10.0;
            *temp = ((data[2] << 8) | data[3]) / 10.0;
            return 1;
        }
    }
    return 0;
}

这段代码看着长,其实核心就是单总线时序。注意那个40微秒的延时,太短或太长都会导致数据错位。我建议用逻辑分析仪抓一下波形,确认时序对不对。

4.4 电平转换电路

嗯,这里要重点说一下。很多传感器是5V供电,但主控(比如ESP32、STM32)是3.3V逻辑电平。直接连?烧IO口是小事,烧芯片就麻烦了。

为什么需要电平转换?

  • 3.3V主控的IO口耐压通常只有3.6V,5V信号直接灌进来会烧。
  • 5V传感器可能不识别3.3V的高电平,导致通信失败。

常用方案:

方案优点缺点
电阻分压便宜、简单只能单向、带载能力弱
MOS管双向转换双向、高速需要两个电阻
专用电平转换芯片稳定、多通道贵、占地方

我个人习惯用MOS管方案,一个2N7002加两个10kΩ电阻,成本几分钱,效果很好。电路图如下:

// 单向电平转换(5V -> 3.3V)
// 5V传感器TX ---[10k]--- 3.3V主控RX
//                      |
//                     GND

// 双向电平转换(I2C用)
// 5V侧 ---[10k上拉]---||---[10k上拉]--- 3.3V侧
//                     MOS管(2N7002)
//                     G极接3.3V
//                     S极接5V侧
//                     D极接3.3V侧

注意:I2C总线是开漏输出,必须用双向电平转换。单向分压电路用在I2C上会出问题。我刚开始做的时候不懂,用电阻分压接了MPU6050,结果通信时好时坏,查了三天才发现是电平不匹配。

实际接线建议:

  • MPU6050:3.3V供电,不需要电平转换。
  • DHT22:可以3.3V供电,但5V供电时DATA引脚需要电平转换。
  • 门磁传感器:干簧管是无源器件,直接接GPIO,不需要电平转换。

好了,这一讲的内容就是这些。传感器选型看似简单,但每个细节都可能影响系统稳定性。下一讲咱们开始讲通信方案,LoRa模块怎么配、怎么组网,到时候见。

本章小结:

  • MPU6050:六轴加速度+陀螺仪,I2C接口,注意唤醒和滤波设置。
  • 门磁传感器:干簧管型,简单可靠,注意消抖。
  • DHT22:高精度温湿度,单总线协议,注意采样周期。
  • 电平转换:MOS管方案性价比最高,I2C必须用双向转换。