Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> ระบบ >> Mac

เชี่ยวชาญ Particle Bluetooth API: คู่มือทีละขั้นตอน

บทความต้นฉบับจาก www.jaredwolff.com

ผมพ่ายแพ้ - ใช้คืนเต็มพยายามทำ Bluetooth Low Energy Project ให้ทำงาน ไม่ได้ ระดม ไม่ว่า จะยอมแพ้

นั่นตอนแรกๆ ของ BLE ตอนนี้ง่ายขึ้นเยอะ Particle Mesh Bluetooth Library ไม่ใช่ข้อยกเว้น

บทความนี้สอนใช้ Particle Bluetooth API ตั้งค่า LED 3 สี ดูการเปลี่ยนแปลงบนอุปกรณ์ทุกตัวใน Mesh Network ใช้ Argon และ Xenon

พร้อมไหม? เริ่มเลย!

P.S. บทความยาว ต้องการ PDF ดาวน์โหลดได้จากลิงก์ต้นฉบับ

Stage 1: ตั้งค่า Bluetooth

  1. Download/Install Particle Workbench
  2. สร้าง Project ใหม่ ชื่อ ble_mesh
  3. เปิด /src/<project>.ino
  4. ตั้ง DeviceOS version > 1.3.0

เขียนโค้ด

ตั้งค่า Service พร้อม 3 Characteristics สำหรับความเข้มของ RGB LED

  1. ใน Setup() เปิด App Control LED: RGB.control(true);
  2. ตั้ง UUIDs ที่บนสุดไฟล์:
    const char* serviceUuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
    const char* red = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
    const char* green = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
    const char* blue = "6E400004-B5A3-F393-E0A9-E50E24DCCA9E";

    UUID = Unique Identifier แยก Service/Characteristics สร้างเองได้ด้วย uuidgen (macOS) หรือ Online GUID Generator

  3. ใน Setup() เริ่มต้น Service: BleUuid rgbService(serviceUuid);
  4. เริ่มต้น Characteristics ใน Setup():
    BleCharacteristic redCharacteristic("red", BleCharacteristicProperty::WRITE_WO_RSP, red, serviceUuid, onDataReceived, (void*)red);
    BleCharacteristic greenCharacteristic("green", BleCharacteristicProperty::WRITE_WO_RSP, green, serviceUuid, onDataReceived, (void*)green);
    BleCharacteristic blueCharacteristic("blue", BleCharacteristicProperty::WRITE_WO_RSP, blue, serviceUuid, onDataReceived, (void*)blue);

    ใช้ Property WRITE_WO_RSP (เขียนไม่ต้อง Response) Callback = onDataReceived Context = UUID String เพื่อแยกว่าตัวไหนถูกเขียน

  5. เพิ่ม Characteristics: BLE.addCharacteristic(...) ทั้ง 3 ตัว
  6. ตั้ง Callback Function (นอก Setup):

    static void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) { }
  7. ตั้ง Advertising ท้าย Setup():
    BleAdvertisingData advData;
    advData.appendServiceUUID(rgbService);
    BLE.advertise(&advData);

    สร้าง Adv Data เพิ่ม Service UUID เริ่ม Advertising -> Discoverable!

ทดสอบ Stage 1

  1. เพิ่ม SYSTEM_MODE(MANUAL); บนสุด ไปไม่ให้เชื่อม Mesh (กันกระพริบสีน้ำเงิน)
  2. Flash DeviceOS 1.3.0-rc.1 (ดาวน์โหลดจาก GitHub Assets)
  3. DFU Mode: กด Mode + คลิก Reset ถึงกระพริบเหลือง
  4. Flash System Part: particle flash --usb xenon-system-part1@1.3.0-rc.1.bin
  5. VS Code: Compile Application (Local) แก้ Error
  6. Flash Application (Local)
  7. โทรศัพท์: เปิด BLE App (nRF Connect หรือ LightBlue Explorer)
  8. หา Device "Xenon-<id>" กดเข้าไปดู Services/Characteristics
  9. ตรวจ Service UUID 6E400001-B5A3-F393-E0A9-E50E24DCCA9E และ Characteristics 3 ตัว

Stage 2: จัดการข้อมูล (Handling Data)

เขียนโค้ด

  1. Struct เก็บ State LED (บนสุดไฟล์):
    typedef struct { uint8_t red; uint8_t green; uint8_t blue; } led_level_t;
    static led_level_t m_led_level;
  2. ใน onDataReceived ตรวจ Error: รับแค่ 1 Byte (if(len != 1) return;)
  3. เช็ค Characteristic จาก Context:
    if( context == red ) m_led_level.red = data[0];
    else if( context == green ) m_led_level.green = data[0];
    else if( context == blue ) m_led_level.blue = data[0];
  4. ตั้งค่า RGB LED: RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);

ทดสอบ Stage 2

  1. DFU Mode, Flash Application (Local)
  2. เชื่อมต่อด้วย LightBlue Explorer
  3. กด Characteristic Red -> Write FF -> LED แดงสว่าง
  4. Write 00 -> LED แดงดับ
  5. ทำซ้ำ Green, Blue -> ควบคุม RGB ครบ 3 สีผ่าน BLE แล้ว!

Stage 3: แชร์ผ่าน Mesh Network

เขียนโค้ด

  1. ลบ/Comment SYSTEM_MODE(MANUAL);
  2. ตัวแปร Track Publish: static bool m_publish = false; (Init ใน Setup)
  3. ใน onDataReceived หลังตั้ง RGB: m_publish = true;
  4. ใน loop():
    if( m_publish ) {
      m_publish = false;
      Mesh.publish("red", String::format("%d", m_led_level.red));
      Mesh.publish("green", String::format("%d", m_led_level.green));
      Mesh.publish("blue", String::format("%d", m_led_level.blue));
    }
  5. Subscribe ใน Setup():
    Mesh.subscribe("red", meshHandler);
    Mesh.subscribe("green", meshHandler);
    Mesh.subscribe("blue", meshHandler);
  6. Mesh Handler (บนสุดไฟล์):
    static void meshHandler(const char *event, const char *data) {
      String eventString = String(event);
      String dataString = String(data);
      if( eventString.equals("red") ) m_led_level.red = dataString.toInt();
      else if( eventString.equals("green") ) m_led_level.green = dataString.toInt();
      else if( eventString.equals("blue") ) m_led_level.blue = dataString.toInt();
      else return;
      RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
    }

ทดสอบ Stage 3

  1. Particle App: Setup Argon ก่อน (กระพริบสีน้ำเงิน -> Pairing จด Admin Password Mesh)
  2. Flash Argon Firmware 1.3.0 แล้ว Flash Tinker App
  3. Argon Solid Cyan (Cloud Connected) -> Cloud Flash โค้ด (เลือก DeviceOS 1.3.0-rc1, Argon, Device Name)
  4. Setup Xenon เข้า Mesh Network ผ่าน Phone App
  5. Cloud Flash Xenon ด้วยโค้ดเดียวกัน
  6. LightBlue Explorer: เชื่อม Argon หรือ Xenon
  7. เปลี่ยนค่า Characteristic LED -> LED เปลี่ยนสีบนอุปกรณ์ทุกตัว!

โค้ดเต็ม (Final Code)

/* Project ble_mesh - BLE + Mesh Example - Jared Wolff */
const char* serviceUuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
const char* red = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
const char* green = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
const char* blue = "6E400004-B5A3-F393-E0A9-E50E24DCCA9E";

BleUuid rgbService(serviceUuid);

typedef struct { uint8_t red; uint8_t green; uint8_t blue; } led_level_t;
static led_level_t m_led_level;
static bool m_publish;

static void meshHandler(const char *event, const char *data) {
  String eventString = String(event);
  String dataString = String(data);
  if( eventString.equals("red") ) m_led_level.red = dataString.toInt();
  else if( eventString.equals("green") ) m_led_level.green = dataString.toInt();
  else if( eventString.equals("blue") ) m_led_level.blue = dataString.toInt();
  else return;
  RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
}

static void onDataReceived(const uint8_t* data, size_t len, const BlePeerDevice& peer, void* context) {
  if( len != 1 ) return;
  if( context == red ) m_led_level.red = data[0];
  else if( context == green ) m_led_level.green = data[0];
  else if( context == blue ) m_led_level.blue = data[0];
  RGB.color(m_led_level.red, m_led_level.green, m_led_level.blue);
  m_publish = true;
}

void setup() {
  RGB.control(true);
  m_led_level.red = m_led_level.green = m_led_level.blue = 0;
  m_publish = false;
  Mesh.subscribe("red", meshHandler);
  Mesh.subscribe("green", meshHandler);
  Mesh.subscribe("blue", meshHandler);
  BleCharacteristic redCharacteristic("red", BleCharacteristicProperty::WRITE_WO_RSP, red, serviceUuid, onDataReceived, (void*)red);
  BleCharacteristic greenCharacteristic("green", BleCharacteristicProperty::WRITE_WO_RSP, green, serviceUuid, onDataReceived, (void*)green);
  BleCharacteristic blueCharacteristic("blue", BleCharacteristicProperty::WRITE_WO_RSP, blue, serviceUuid, onDataReceived, (void*)blue);
  BLE.addCharacteristic(redCharacteristic);
  BLE.addCharacteristic(greenCharacteristic);
  BLE.addCharacteristic(blueCharacteristic);
  BleAdvertisingData advData;
  advData.appendServiceUUID(rgbService);
  BLE.advertise(&advData);
}

void loop() {
  if( m_publish ) {
    m_publish = false;
    Mesh.publish("red", String::format("%d", m_led_level.red));
    Mesh.publish("green", String::format("%d", m_led_level.green));
    Mesh.publish("blue", String::format("%d", m_led_level.blue));
  }
}

สรุป

บทช่วยสอนนี้สอนเพิ่ม Bluetooth ใน Particle Mesh Project ความเป็นไปได้ไม่มีที่สิ้นสุด - เพิ่ม User/Admin Apps เข้าไปใน Experience ได้

ติดตามเนื้อหาเพิ่มเติมในหนังสือ The Ultimate Guide to Particle Mesh สมัครรับข่าวสารได้ลิงก์ต้นฉบับ