这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【e起DIY】低功耗蓝牙温湿度计-成果贴

共1条 1/1 1 跳转至

【e起DIY】低功耗蓝牙温湿度计-成果贴

菜鸟
2026-06-29 14:47:12   被打赏 40 分(兑奖)     打赏

经过前面开箱、环境搭建和驱动调试的几轮折腾,这个基于 FRDM-MCXW71 + DHT11 的蓝牙温湿度计终于跑通了全部流程。这篇成果贴重点分享最终效果,特别是手机端如何通过小程序读取温湿度数据——这也是整个项目最有成就感的一环。

硬件端:一块 FRDM-MCXW71 板子连着 DHT11 传感器,上电后自动采集环境温湿度,通过 BLE 广播出去

手机端:打开配套的微信小程序(或 nRF Connect 等通用 BLE 工具),扫描连接名为 Zephyr TH Sensor 的设备,就能实时看到温湿度数据

数据更新:每 2 秒推送一次,温度显示格式如 26.7°C,湿度如 55.4%RH

整个过程不需要配网、不需要云端、不需要账号登录——开箱即连,连上即看

image.png

在手机端我采用读取 BLE 数据,nRF Connect 这类工具可以直接扫描、连接、订阅特征值,看到原始数据。优点是上手快,缺点是界面偏技术向,不适合日常使用。

以下是关键参数配置

设备树修改

需要在设备树中定义蓝牙 HCI 接口,如下所示:

&hci {
    status = "okay";
};
&nbu {
    status = "okay";
};

蓝牙初始化

/* 初始化 BLE */
    err = bt_enable(NULL);
    if (err) {
        LOG_ERR("Failed to enable BLE: %d", err);
        return;
    }
    LOG_INF("BLE enabled");
    /* 初始化 EHS 服务 */
    err = ble_ehs_service_init();
    if (err) {
        LOG_ERR("Failed to init EHS service: %d", err);
        return;
    }
    /* 开始广播 */
    err = ble_ehs_start_advertising();
    if (err) {
        LOG_ERR("Failed to start advertising: %d", err);
        return;
    }

广播数据设置

image.png

数据同步机制

同步机制说明

  • 互斥锁保护:使用 k_mutex 保护共享数据结构,防止并发访问冲突

  • 有效性标志:valid 字段标识数据是否有效,消费者需检查此标志

  • 时间戳:timestamp 记录数据采集时间,便于消费者判断数据新鲜度

  • 非阻塞读取:sensor_data_get() 使用 k_mutex_lock(K_NO_WAIT) 避免阻塞

微信小程序

实际上在调试过程中使用了 nRF Connect 手机APP,扫描、连接 FRDM-MCXW71 广播,查看传感器数据。

之后再开发微信小程序,遇到一些问题,例如数据不缺、数据丢失的问题,好在最后解决了。

用于通过蓝牙BLE连接 NXP MCXW71 开发板上的 DHT11空气质量传感器,实现实时数据监测和历史曲线展示。

BLE 设备搜索与连接

// 关键代码: BLE 连接流程
connectBLE() {
  // 1. 先清理旧状态(避免第二次连接失败)
  this.resetBLEState();
  // 2. 延迟 500ms 让 BLE 栈完全清理
  setTimeout(() => {
    // 3. 打开蓝牙适配器
    wx.openBluetoothAdapter({
      success: () => {
        // 4. 开始搜索设备
        this.startDiscovery();
      }
    });
  }, 500);
}
// 设备匹配逻辑
wx.onBluetoothDeviceFound((res) => {
  res.devices.forEach(device => {
    const name = device.name || device.localName || '';
    // 匹配设备名称关键词
    if (name.includes('BLE') || name.includes('HT') || 
        name.includes('Meter') || name.includes('SEN66')) {
      // 停止搜索并连接
      wx.stopBluetoothDevicesDiscovery();
      this.connectToDevice(device.deviceId);
    }
  });
});

MTU 协商与数据接收

// MTU 协商 - 关键! 确保能接收完整数据包
wx.setBLEMTU({
  deviceId,
  mtu: 247,  // 协商到 247 字节
  success: (res) => {
    console.log('MTU 协商成功:', res.mtu);
    // MTU 协商完成后发现服务
    setTimeout(() => {
      this.discoverServices();
    }, 500);
  }
});
// 启用数据通知
wx.notifyBLECharacteristicValueChange({
  deviceId: this.data.deviceId,
  serviceId: this.data.serviceId,
  characteristicId: characteristicId,
  state: true
});
// 数据监听
wx.onBLECharacteristicValueChange((res) => {
  this.handleSensorData(res.value);
});

传感器数据解析

// 解析 22 字节传感器数据包
handleSensorData(buffer) {
  const dataView = new DataView(buffer);
  // 数据包结构 (小端序)
  const pm1_0      = dataView.getUint16(0, true);   // 偏移 0
  const pm2_5      = dataView.getUint16(2, true);   // 偏移 2
  const pm4_0      = dataView.getUint16(4, true);   // 偏移 4
  const pm10       = dataView.getUint16(6, true);   // 偏移 6
  const rawHumi    = dataView.getInt16(8, true);    // 偏移 8
  const rawTemp    = dataView.getInt16(10, true);   // 偏移 10
  const voc_index  = dataView.getInt16(12, true);   // 偏移 12
  const nox_index  = dataView.getInt16(14, true);   // 偏移 14
  const co2        = dataView.getUint16(16, true);  // 偏移 16
  const timestamp  = dataView.getUint32(18, true);  // 偏移 18
  // 数据转换
  const data = {
    pm1_0: (pm1_0 / 10.0).toFixed(1),
    pm2_5: (pm2_5 / 10.0).toFixed(1),
    humidity: Math.max(0, Math.min(100, rawHumi / 100.0)).toFixed(1),
    temperature: Math.max(-10, Math.min(80, rawTemp / 200.0)).toFixed(1),
    voc_index: (voc_index / 10.0).toFixed(1),
    nox_index: (nox_index / 10.0).toFixed(1),
    co2: Math.min(40000, co2)
  };
  // 更新全局数据
  app.globalData.currentData = data;
  // 添加到历史记录
  app.addHistoryRecord({...data, timestamp: Date.now()});
}

使用这套系统的完整流程:

第一步:烧录固件。 用 ninja flash 将编译好的 zephyr.bin 烧录到开发板。

第二步:打开网页。 在 Chrome/Edge 中打开 ble-monitor.html,点击"搜索蓝牙设备",在弹出的设备列表中选择 MCXW72-BLE。

第三步:等待连接。 网页显示"已连接"后,等待约 5 秒,首次数据就会出现在页面上。之后每 5 秒更新一次。

第四步:查看原始数据。 页面底部的黑色区域会显示每次接收到的原始数据,方便排查问题。

        如果连接成功但页面不更新,打开浏览器开发者工具(F12)→ Console,查看是否有 updateData called 日付。如果没有,说明 parseData 解析失败,页面上会显示 [PARSE FAILED]。

八、关键配置参数

参数说明
广播名称MCXW72-BLE手机蓝牙扫描时看到的名字
NUS Service UUID6e400001-b5a3-f393-e0a9-e50e24dcca9e蓝牙服务唯一标识
NUS TX UUID6e400003-b5a3-f393-e0a9-e50e24dcca9e设备发送数据给手机
NUS RX UUID6e400002-b5a3-f393-e0a9-e50e24dcca9e手机发送数据给设备
CCCD UUID2902控制通知功能的 Descriptor
发送间隔5 秒k_sleep(K_SECONDS(5))控制
I2C 地址0x44SHT40 固定地址


至此,从开箱到成果,整个 FRDM-MCXW71 + DHT11 蓝牙温湿度计项目基本收官。核心收获不只是让一个传感器“连上了手机”,更是完整走通了 Zephyr Sensor 框架 → BLE GATT 服务 → 手机小程序 这条物联网原型开发的经典链路。后续如果还有时间,可以继续在低功耗优化、数据记录和图表展示方面做点有意思的扩展。










共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]