ESP32-C3蓝牙实战:手把手教你构建一个动态更新的温湿度传感器GATT服务
ESP32-C3蓝牙实战构建动态更新的温湿度传感器GATT服务在物联网设备开发中蓝牙低功耗BLE技术因其低功耗和广泛兼容性成为传感器数据无线传输的首选方案。ESP32-C3作为一款集成了Wi-Fi和BLE 5.0的芯片特别适合用于构建小型环境监测设备。本文将带您从零开始实现一个能够通过手机APP实时查看温湿度数据的完整解决方案。1. 环境准备与基础配置1.1 硬件选型与连接我们需要以下硬件组件ESP32-C3开发板如ESP32-C3-DevKitM-1温湿度传感器如SHT30或DHT22杜邦线若干传感器连接方式SHT30引脚 | ESP32-C3引脚 VCC | 3.3V GND | GND SCL | GPIO8 SDA | GPIO7注意不同型号传感器引脚定义可能不同务必查阅对应数据手册1.2 开发环境搭建安装最新版ESP-IDF开发框架git clone --recursive https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh source export.sh创建项目模板cp -r examples/bluetooth/bluedroid/ble/gatt_server . cd gatt_server安装必要的Python依赖pip install adafruit-circuitpython-sht31d2. GATT服务设计与实现2.1 自定义服务UUID定义在gatt_server示例基础上我们需要定义自己的服务UUID和特征值// 自定义服务UUID #define GATT_SERVICE_UUID 0xAA30 #define GATT_CHAR_HUMIDITY_UUID 0xAA31 #define GATT_CHAR_TEMPERATURE_UUID 0xAA32 static uint16_t humidity_handle 0; static uint16_t temperature_handle 0;2.2 特征值属性配置在gatt_server_profile_tab数组中添加我们的温湿度特征// 湿度特征 [IDX_CHAR_HUMIDITY] { {ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)GATT_CHAR_HUMIDITY_UUID, ESP_GATT_PERM_READ, ESP_GATT_CHAR_PROP_BIT_READ, NULL, NULL} }, // 温度特征 [IDX_CHAR_TEMP] { {ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)GATT_CHAR_TEMPERATURE_UUID, ESP_GATT_PERM_READ, ESP_GATT_CHAR_PROP_BIT_READ, NULL, NULL} },3. 传感器数据采集与更新机制3.1 传感器初始化与数据读取创建sensor.c文件实现传感器驱动#include sht31.h void sht31_init() { i2c_config_t conf { .mode I2C_MODE_MASTER, .sda_io_num GPIO_NUM_7, .scl_io_num GPIO_NUM_8, .sda_pullup_en GPIO_PULLUP_ENABLE, .scl_pullup_en GPIO_PULLUP_ENABLE, .master.clk_speed 100000 }; i2c_param_config(I2C_NUM_0, conf); i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0); } void read_sht31(float *temp, float *humidity) { uint8_t cmd[2] {0x2C, 0x06}; uint8_t data[6]; i2c_cmd_handle_t handle i2c_cmd_link_create(); i2c_master_start(handle); i2c_master_write_byte(handle, (0x44 1) | I2C_MASTER_WRITE, true); i2c_master_write(handle, cmd, 2, true); i2c_master_start(handle); i2c_master_write_byte(handle, (0x44 1) | I2C_MASTER_READ, true); i2c_master_read(handle, data, 6, I2C_MASTER_LAST_NACK); i2c_master_stop(handle); i2c_master_cmd_begin(I2C_NUM_0, handle, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(handle); *temp -45 175 * (float)((data[0] 8) | data[1]) / 65535; *humidity 100 * (float)((data[3] 8) | data[4]) / 65535; }3.2 数据更新策略优化在gatt_server.c的主循环中添加数据更新逻辑void update_sensor_data() { float temp, humidity; read_sht31(temp, humidity); // 将浮点数转换为百分比的整数表示保留2位小数 uint16_t hum_val (uint16_t)(humidity * 100); uint16_t temp_val (uint16_t)(temp * 100); esp_ble_gatts_set_attr_value(humidity_handle, sizeof(hum_val), (uint8_t *)hum_val); esp_ble_gatts_set_attr_value(temperature_handle, sizeof(temp_val), (uint8_t *)temp_val); } void app_main() { // ...其他初始化代码... while(1) { update_sensor_data(); vTaskDelay(2000 / portTICK_PERIOD_MS); } }提示实际项目中应考虑添加数据变化阈值只有温湿度变化超过一定范围时才更新特征值以减少不必要的蓝牙通信4. 客户端交互与性能优化4.1 手机APP连接测试推荐使用以下BLE调试工具进行测试nRF ConnectiOS/AndroidLightBlueiOSBLE ScannerAndroid连接步骤扫描并找到名为ESP_GATTS_DEMO的设备连接后浏览服务列表找到我们自定义的服务UUID(AA30)订阅温湿度特征的通知如支持4.2 数据更新延迟问题解决BLE的READ操作是请求-响应模式客户端每次读取都会获取最新的特征值。但为了更实时地反映数据变化我们可以启用通知功能需修改特征属性// 修改特征属性为READ | NOTIFY ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY实现通知发送函数void send_notification(uint16_t handle, uint16_t value) { esp_ble_gatts_send_indicate(gatts_if, conn_id, handle, sizeof(value), (uint8_t *)value, false); }在数据变化时触发通知if(abs(hum_val - last_hum) HUMIDITY_THRESHOLD) { send_notification(humidity_handle, hum_val); last_hum hum_val; }4.3 功耗优化技巧对于电池供电的设备可采取以下措施降低数据更新频率如每30秒一次使用ESP32-C3的深度睡眠模式仅在数据变化超过阈值时唤醒和发送缩短广播间隔修改广播参数示例esp_ble_gap_config_adv_data(adv_data); esp_ble_adv_params_t adv_params { .adv_int_min 0x100, .adv_int_max 0x200, .adv_type ADV_TYPE_IND, .own_addr_type BLE_ADDR_TYPE_PUBLIC, .channel_map ADV_CHNL_ALL, .adv_filter_policy ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }; esp_ble_gap_start_advertising(adv_params);5. 项目扩展与进阶功能5.1 多传感器集成在现有基础上可以轻松扩展更多传感器#define GATT_CHAR_CO2_UUID 0xAA33 #define GATT_CHAR_PM25_UUID 0xAA34 // 在服务表中添加新特征 [IDX_CHAR_CO2] { {ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)GATT_CHAR_CO2_UUID, ESP_GATT_PERM_READ, ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY, NULL, NULL} },5.2 数据历史记录功能添加一个特征用于查询历史数据#define GATT_CHAR_HISTORY_UUID 0xAA35 typedef struct { uint32_t timestamp; uint16_t temp; uint16_t humidity; } sensor_record_t; // 在服务表中添加历史特征 [IDX_CHAR_HISTORY] { {ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)GATT_CHAR_HISTORY_UUID, ESP_GATT_PERM_READ, ESP_GATT_CHAR_PROP_BIT_READ, NULL, NULL} },5.3 OTA固件更新通过蓝牙实现固件更新添加一个专门的OTA服务实现数据分包传输机制添加校验和验证实现bootloader更新逻辑关键代码结构void ota_service_init() { // 初始化OTA特征 esp_ble_gatts_create_attr_tab(ota_gatt_db, gatts_if, ota_handle_count, 0); // 注册写回调 esp_ble_gatts_register_callback(ota_gatts_event_handler); }在实际部署中发现合理设置MTU大小可以显著提高OTA更新速度。通过协商更大的MTU如247字节可以减少传输所需的包数量。

相关新闻

最新新闻

日新闻

周新闻

月新闻