【物联网】BLE Fundamentals 核心概念总结-广告-读写特征-LED控制-传感器通知-上下游通信过程

发布于:2025-08-31 ⋅ 阅读:(27) ⋅ 点赞:(0)

BLE 开发完整指南与应用

一、BLE 核心概念总结

1. 角色定义

  • Peripheral(外设):Arduino Nano 33 IoT,作为数据提供者
  • Central(中心设备):树莓派/手机,作为数据消费者

2. 通信模式

  • Advertising(广告):设备广播自身存在
  • Connection(连接):建立稳定通信链路
  • GATT 通信:通过服务/特征进行数据交换

3. 数据操作类型

  • Read:中心设备读取数据
  • Write:中心设备写入命令
  • Notify:外设主动推送数据

二、核心库函数详解

1. BLE 初始化

#include <ArduinoBLE.h>  // 引入BLE库

if (!BLE.begin()) {      // 初始化BLE模块
    Serial.println("Failed to initialize BLE!");
    while (true);        // 初始化失败则停止
}

2. 设备配置

// 设置设备标识(重要:使用唯一名称)
BLE.setDeviceName("Arduino_Sensor_xx");    // 内部设备名
BLE.setLocalName("Arduino_Sensor_xx");     // 广播显示名
BLE.setConnectable(true);                   // 允许连接(默认为true)

3. 服务与特征创建

// 定义UUID(必须唯一)
#define SERVICE_UUID        "12345678-1234-1234-1234-123456789abc"
#define SENSOR_CHAR_UUID    "87654321-4321-4321-4321-cba987654321"
#define COMMAND_CHAR_UUID   "11111111-2222-3333-4444-555555555555"

// 创建服务
BLEService sensorService(SERVICE_UUID);

// 创建特征(不同权限组合)
BLEStringCharacteristic sensorCharacteristic(
    SENSOR_CHAR_UUID,
    BLERead | BLENotify,  // 可读+通知
    100                   // 最大数据长度
);

BLEStringCharacteristic commandCharacteristic(
    COMMAND_CHAR_UUID, 
    BLEWrite,            // 只写
    20                   // 命令通常较短
);

4. 服务组装与广播

// 添加特征到服务
sensorService.addCharacteristic(sensorCharacteristic);
sensorService.addCharacteristic(commandCharacteristic);

// 添加服务到BLE栈
BLE.addService(sensorService);

// 设置广告服务并开始广播
BLE.setAdvertisedService(sensorService);
BLE.advertise();

5. 事件处理循环

void loop() {
    BLE.poll();  // 必须定期调用,处理BLE事件
    
    // 检查特征写入
    if (commandCharacteristic.written()) {
        String command = commandCharacteristic.value();
        processCommand(command);  // 处理接收到的命令
    }
    
    // 定期发送传感器数据
    static unsigned long lastSend = 0;
    if (millis() - lastSend > 5000) {  // 每5秒发送一次
        sendSensorData();
        lastSend = millis();
    }
}

三、四个示例代码的详细注释与应用

1. BLE_advertise.ino - 基础广告示例

// 作用:仅广播设备存在,不接受连接
// 应用:测试设备可见性,调试广播设置

#include <ArduinoBLE.h>

void setup() {
    Serial.begin(9600);
    
    if (!BLE.begin()) {
        Serial.println("Failed to initialize BLE!");
        while (true);
    }

    BLE.setDeviceName("YourName");      // 设置设备名
    BLE.setLocalName("YourName");       // 设置广播名
    BLE.setConnectable(false);          // 禁止连接,纯广播模式
    
    BLE.advertise();                    // 开始广播
    Serial.println("BLE advertising started...");
}

void loop() {
    BLE.poll();  // 维持BLE栈运行
    // 纯广播模式,无其他操作
}

2. BLE_read-write.ino - 读写特征示例

// 作用:提供可读写的文本特征
// 应用:调试基本的BLE通信,测试命令传输

#include <ArduinoBLE.h>

#define SERVICE_UUID        "19B10000-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC_UUID "19B10001-E8F2-537E-4F6C-D104768A1214"

BLEService customService(SERVICE_UUID);                
BLECharacteristic rwCharacteristic(
    CHARACTERISTIC_UUID,
    BLERead | BLEWrite,  // 读写权限
    20                   // 最大20字节
);

void setup() {
    Serial.begin(9600);
    
    if (!BLE.begin()) {
        Serial.println("Failed to initialize BLE!");
        while (true);
    }

    BLE.setDeviceName("YourName");
    BLE.setLocalName("YourName");
    
    BLE.setAdvertisedService(customService);
    customService.addCharacteristic(rwCharacteristic);
    BLE.addService(customService);
    
    rwCharacteristic.writeValue("Hello World");  // 设置初始值
    
    BLE.advertise();
    Serial.println("BLE advertising with read/write characteristic started...");
}

void loop() {
    BLE.poll();
    
    if (rwCharacteristic.written()) {
        String newValue = String((const char*)rwCharacteristic.value());
        Serial.print("Characteristic written: ");
        Serial.println(newValue);
        // 在这里可以添加命令处理逻辑
    }
    delay(100);
}

3. BLE_LED-ctrl.ino - LED控制示例

// 作用:通过BLE控制LED
// 应用:学习如何通过BLE控制执行器

#include <ArduinoBLE.h>

#define SERVICE_UUID    "19B20000-E8F2-537E-4F6C-D104768A1214"
#define LED_CHAR_UUID   "19B20001-E8F2-537E-4F6C-D104768A1214"

BLEService ledService(SERVICE_UUID);
BLECharacteristic ledCharacteristic(
    LED_CHAR_UUID,
    BLEWrite | BLERead,  // 读写权限
    1                    // 1字节数据(0或1)
);

void setup() {
    Serial.begin(9600);
    
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);  // 初始关闭LED
    
    if (!BLE.begin()) {
        Serial.println("Failed to initialize BLE!");
        while (true);
    }

    BLE.setDeviceName("YourName");
    BLE.setLocalName("YourName");
    BLE.setAdvertisedService(ledService);
    
    ledService.addCharacteristic(ledCharacteristic);
    BLE.addService(ledService);
    
    uint8_t off = 0;
    ledCharacteristic.writeValue(off);  // 设置初始值为0
    
    BLE.advertise();
    Serial.println("BLE LED Control service started");
}

void loop() {
    BLE.poll();
    
    if (ledCharacteristic.written()) {
        uint8_t value = ledCharacteristic.value()[0];  // 读取第一个字节
        if (value == 1) {
            digitalWrite(LED_BUILTIN, HIGH);
            Serial.println("LED ON");
        } else {
            digitalWrite(LED_BUILTIN, LOW);
            Serial.println("LED OFF");
        }
    }
}

4. BLE_sensor-notify.ino - 传感器通知示例

// 作用:实时推送传感器数据
// 应用:学习如何实现实时数据流

#include <ArduinoBLE.h>
#include <Arduino_LSM6DS3.h>  // IMU传感器库

BLEService imuService("19B10000-E8F2-537E-4F6C-D104768A1214");
BLECharacteristic imuDataCharacteristic(
    "19B10001-E8F2-537E-4F6C-D104768A1214", 
    BLERead | BLENotify,  // 可读+通知权限
    32                    // 足够存储传感器数据
);

void setup() {
    Serial.begin(9600);
    
    if (!IMU.begin()) {  // 初始化IMU传感器
        Serial.println("Failed to initialize IMU!");
        while (1);
    }
    
    if (!BLE.begin()) {
        Serial.println("Starting BLE failed!");
        while (1);
    }

    BLE.setLocalName("YourName");
    BLE.setAdvertisedService(imuService);
    
    imuService.addCharacteristic(imuDataCharacteristic);
    BLE.addService(imuService);
    
    imuDataCharacteristic.setValue("0.00,0.00,0.00");  // 初始值
    
    BLE.advertise();
    Serial.println("BLE advertising with sensor notify characteristic started...");
}

void loop() {
    BLEDevice central = BLE.central();  // 检查中心设备连接
    
    if (central) {
        Serial.print("Connected to central: ");
        Serial.println(central.address());
        
        while (central.connected()) {  // 保持连接时持续发送数据
            float x, y, z;
            if (IMU.accelerationAvailable()) {
                IMU.readAcceleration(x, y, z);
                
                // 格式化传感器数据
                String imuString = String(x, 2) + "," + String(y, 2) + "," + String(z, 2);
                Serial.println("Sending: " + imuString);
                
                // 更新特征值(会自动通知订阅的客户端)
                imuDataCharacteristic.setValue(imuString.c_str());
            }
            delay(100); // 10Hz更新频率
        }
        
        Serial.print("Disconnected from central: ");
        Serial.println(central.address());
    }
}

四、具体应用方案

1. 上游通信(传感器数据 → BLE → MQTT)

// Arduino端 - 传感器数据特征
BLEStringCharacteristic dhtCharacteristic(
    DHT_CHAR_UUID,
    BLERead | BLENotify,  // 可读+通知
    100
);

// 定期更新传感器数据
void updateDHTData() {
    float temp = dht.readTemperature();
    float humidity = dht.readHumidity();
    
    String jsonData = "{\"temp\":" + String(temp) + 
                     ",\"humidity\":" + String(humidity) + "}";
    
    dhtCharacteristic.writeValue(jsonData);  // 自动通知订阅者
}

2. 下游通信(MQTT → BLE → 执行器控制)

// Arduino端 - 命令特征
BLEStringCharacteristic commandCharacteristic(
    COMMAND_CHAR_UUID,
    BLEWrite,  // 只写权限
    20
);

// 处理接收到的命令
void loop() {
    BLE.poll();
    
    if (commandCharacteristic.written()) {
        String command = commandCharacteristic.value();
        
        if (command == "LED_ON") {
            digitalWrite(LED_PIN, HIGH);
            Serial.println("LED turned ON via BLE");
        } 
        else if (command == "LED_OFF") {
            digitalWrite(LED_PIN, LOW);
            Serial.println("LED turned OFF via BLE");
        }
        else if (command == "BUZZER_BEEP") {
            playTone(1000, 200);
            Serial.println("Buzzer activated via BLE");
        }
    }
}

3. 完整的代码结构

#include <ArduinoBLE.h>
#include <DHT.h>

// UUID定义
#define SERVICE_UUID        "你的服务UUID"
#define DHT_CHAR_UUID       "你的传感器特征UUID"  
#define CMD_CHAR_UUID       "你的命令特征UUID"

// 引脚定义
#define DHT_PIN 2
#define LED_PIN LED_BUILTIN
#define BUZZER_PIN 5

DHT dht(DHT_PIN, DHT11);
BLEService sensorService(SERVICE_UUID);
BLEStringCharacteristic dhtCharacteristic(DHT_CHAR_UUID, BLERead | BLENotify, 100);
BLEStringCharacteristic cmdCharacteristic(CMD_CHAR_UUID, BLEWrite, 20);

void setup() {
    // 初始化串口、传感器、引脚
    // 初始化BLE并配置服务特征
    // 开始广播
}

void loop() {
    BLE.poll();
    
    // 处理命令
    if (cmdCharacteristic.written()) {
        processCommand(cmdCharacteristic.value());
    }
    
    // 定期发送传感器数据
    static unsigned long lastSend = 0;
    if (millis() - lastSend > 5000) {
        sendSensorData();
        lastSend = millis();
    }
}

void processCommand(String command) {
    // 处理各种控制命令
}

void sendSensorData() {
    // 读取并发送传感器数据
}

五、调试与测试建议

1. 使用 nRF Connect 应用测试

  • 扫描确认设备可见性
  • 连接后查看服务特征结构
  • 测试读写操作
  • 订阅通知观察实时数据

2. 串口调试输出

Serial.println("BLE connected!");  // 连接事件
Serial.print("Received: ");        // 数据接收
Serial.println(receivedData);
Serial.print("Sending: ");         // 数据发送  
Serial.println(sensorData);

3. 分阶段测试

  1. 先测试BLE基础通信
  2. 再测试传感器数据读取
  3. 然后测试执行器控制
  4. 最后集成完整功能

这个完整的指南应该能帮助你在成功实现BLE通信功能。


网站公告

今日签到

点亮在社区的每一天
去签到