基于 ESP32-WROOM-32 实践 EddystoneTLM_Beacon 遥测(广播电压、温度、运行时间) – PlatformIO

最近更新于 2026-07-26 23:02

测试环境

  • ESP32-WROOM-32
  • PlatformIO IDE 3.3.4
  • PlatformIO Core 6.1.19
  • pioarduino platform-espressif32 55.03.311(Arduino Release v3.3.11 based on ESP-IDF v5.5.5)

platformio.ini

[env:esp32dev]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.311/platform-espressif32.zip
board = esp32dev
framework = arduino
monitor_speed = 115200

实践

源码参考来源:https://github.com/espressif/arduino-esp32/blob/3.3.11/libraries/BLE/examples/EddystoneTLM_Beacon/EddystoneTLM_Beacon.ino

EddystoneTLM_Beacon 是谷歌设计的,用于广播设备的电压、温度和运行时间。一般是运维人员查看设备健康状态的情境下会使用。

下面的案例会广播电压和温度,温度部分我对参考案例做了修改,会读取真实的芯片传感器温度,而不是随机数。

/*
   ESP32-WROOM-32 Eddystone-TLM 遥测信标(使用真实片上温度)

   数据说明:
   - 温度:提取 ESP32 内部晶圆结温,并转换装载到 TLM 8.8 定点数格式中
   - 电池:模拟电池电压(如硬件连接了 VBAT 分压 ADC,可替换为真实采样值)
*/

#include "sys/time.h"
#include <Arduino.h>

#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "BLEAdvertising.h"
#include "BLEEddystoneTLM.h"
#include "esp_sleep.h"

// 1. C 语言外部声明:引用 ESP32-WROOM-32 底层片上温度传感器接口
#ifdef __cplusplus
extern "C"
{
#endif
    uint8_t temprature_sens_read();
#ifdef __cplusplus
}
#endif

#define GPIO_DEEP_SLEEP_DURATION 2 // 唤醒后广播 10 秒,休眠 2 秒
#define BEACON_POWER ESP_PWR_LVL_N12

RTC_DATA_ATTR static time_t last;        // RTC 慢速内存:保存上一次唤醒的 Unix 时间戳
RTC_DATA_ATTR static uint32_t bootcount; // RTC 慢速内存:保存设备唤醒总次数

BLEAdvertising *pAdvertising;
struct timeval nowTimeStruct;

/**
 * @brief 读取真实芯片温度并构建 Eddystone-TLM 遥测广播帧
 */
void setBeacon()
{
    BLEEddystoneTLM EddystoneTLM;

    // -------------------------------------------------------------
    // 读取 ESP32 芯片内部传感器
    // -------------------------------------------------------------
    uint8_t raw_temp = temprature_sens_read();     // 获取原始 ADC 采样值
    float chip_temp_c = (raw_temp - 32.0f) / 1.8f; // 华氏度转换为摄氏度 (°C)

    // 将摄氏度设置到 TLM 类中,底层会自动编码为 Eddystone 要求的 8.8 定点数
    EddystoneTLM.setTemp(chip_temp_c);

    // 模拟设定系统电压(单位:mV,如 3300mV = 3.3V)
    // 后续若有硬件分压电路接入 ADC,可在此替换为真实的电池读取数值
    EddystoneTLM.setVolt((uint16_t)random(3200, 3300));

    // 串口调试输出
    Serial.printf("TSENS Raw Value : %u\n", raw_temp);
    Serial.printf("Real Chip Temp  : %.2f °C\n", EddystoneTLM.getTemp());
    Serial.printf("TLM 8.8 Format  : 0x%04X\n", EddystoneTLM.getRawTemp());
    Serial.printf("Battery Voltage : %u mV\n", EddystoneTLM.getVolt());

    // -------------------------------------------------------------
    // 打包广播数据包
    // -------------------------------------------------------------
    BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
    BLEAdvertisementData oScanResponseData = BLEAdvertisementData();

    // 将 TLM 负载装载至 Service Data 中,挂载 Google 专用的 0xFEAA 16位短 UUID
    oScanResponseData.setServiceData(
        BLEUUID((uint16_t)0xFEAA),
        String(EddystoneTLM.getData().c_str(), EddystoneTLM.getData().length()));

    oAdvertisementData.setName("ESP32 TLM Beacon");

    pAdvertising->setAdvertisementData(oAdvertisementData);
    pAdvertising->setScanResponseData(oScanResponseData);
}

void setup()
{
    Serial.begin(115200);
    gettimeofday(&nowTimeStruct, NULL);

    Serial.printf("\n=========================================\n");
    Serial.printf("Starting ESP32 TLM Beacon (BootCount: %" PRIu32 ")\n", bootcount++);
    Serial.printf("Time since last boot: %" PRIu32 "s\n", (uint32_t)(nowTimeStruct.tv_sec - last));
    Serial.printf("=========================================\n");

    last = nowTimeStruct.tv_sec;

    // 初始化 BLE 引擎与设置硬件发射功率
    BLEDevice::init("TLMBeacon");
    BLEDevice::setPower(BEACON_POWER);

    pAdvertising = BLEDevice::getAdvertising();

    // 装载遥测数据
    setBeacon();

    // 开启广播并维持 10 秒
    pAdvertising->start();
    Serial.println("Advertising TLM data for 10s...");
    delay(10000);

    // 停止广播并进入 Deep Sleep
    pAdvertising->stop();
    Serial.println("Entering Deep Sleep...");
    esp_deep_sleep(1000000LL * GPIO_DEEP_SLEEP_DURATION);
}

void loop()
{
    // Deep Sleep 唤醒后芯片直接复位重走 setup(),不会执行 loop
}
字段名称 字节大小 说明与格式
Frame Type (类型) 1 字节 固定为 0x20,用于标识该广播包为 TLM 遥测帧。
VERSION (版本) 1 字节 固定为 0x00(当前协议版本)。
VBATT (电池电压) 2 字节 无符号 16 位整数,单位为毫伏(mV)。
TEMP (温度) 2 字节 带符号的 8.8 定点数格式。
ADV_CNT (广播计数器) 4 字节 自设备上电或重启以来,已发送的广播帧总数。
SEC_CNT (运行时间) 4 字节 自设备上电或重启以来的运行时间,精度为 0.1 秒(每过 1 秒该值加 10)。

file

基于 ESP32-WROOM-32 实践 EddystoneTLM_Beacon 遥测(广播电压、温度、运行时间) – PlatformIO
Scroll to top
打开目录