โปรเจกต์ Bluetooth Weather Station
เรียนรู้พื้นฐานของ Bluetooth โดยการ Polling ค่า Temperature, Humidity และ Barometer จาก Arduino Nano 33 Sense ผ่าน Raspberry Pi
เรียนรู้พื้นฐานของ Bluetooth โดยการ Polling ค่า Temperature, Humidity และ Barometer จาก Arduino Nano 33 Sense ผ่าน Raspberry Pi
ฉันต้องการมีความเข้าใจเกี่ยวกับระบบ home automation ให้มากขึ้น — ซึ่งมันมีอะไรที่มากกว่าแค่การซื้อผลิตภัณฑ์มาตัวหนึ่งแล้วเชื่อมต่อมันเข้ากับ Hub เพื่อสั่งเปิดปิดไฟจากโทรศัพท์ได้อย่างน่าอัศจรรย์ ฉันอยากรู้ว่าเกิดอะไรขึ้นภายใต้เลเยอร์ของหน้าจอเมนูที่สวยงามและบริการแบบ Cloud-based เหล่านั้น
โดย Arduino Nano 33 Sense และ Raspberry Pi เป็นคู่ที่สมบูรณ์แบบในการสำรวจพื้นฐานของอุปกรณ์ Bluetooth Low Energy (BLE) และวิธีการรวบรวมข้อมูลจากอุปกรณ์เหล่านั้น โดย Hardware ที่จำเป็นทั้งหมดถูกติดตั้งมาให้พร้อมแล้วทั้งใน Arduino และ Pi ทำให้ง่ายต่อการเริ่มต้น
ในส่วนของ Software จะประกอบไปด้วย Arduino Sketch และโปรแกรม Python พื้นฐานบางส่วน
นี่คือบทเรียนแบบง่ายๆ และอาจจะยังไม่ค่อยมีประโยชน์ในฐานะผลิตภัณฑ์สำเร็จรูปเท่าใดนัก เป้าหมายหลักคือการเรียนรู้พื้นฐานและใช้ความรู้นี้เป็นอิฐก้อนแรกสำหรับการสร้างสิ่งที่ยิ่งใหญ่และดีกว่าต่อไป
ฉันได้ทำลิงก์ไปยัง Sketch ที่ฉันสร้างขึ้นชื่อว่า BluetoothWeather.ino ในมุมของ Bluetooth แล้ว มันค่อนข้างเรียบง่าย แต่แน่นอนว่ามันซับซ้อนกว่า Sketch พื้นฐานอย่างการสั่งให้ LED กระพริบเล็กน้อย
สำหรับตอนนี้ ฉันจะสมมติว่าคุณพอใจที่จะใช้วิธี Copy และ Paste ไปก่อน แล้วฉันจะลงรายละเอียดในภายหลัง
เมื่อ Sketch ถูก Flash ลงใน Nano 33 BLE Sense แล้ว มันจะรอการเชื่อมต่อแบบ Bluetooth Low Energy และรายงานค่าอุณหภูมิ (temperature), ความชื้น (humidity) และความดันบรรยากาศ (barometric pressure) ไปยังอุปกรณ์ใดก็ตามที่มาเชื่อมต่อ
แอป nRF Connect ของ Nordic Semiconductor สามารถใช้เพื่อตรวจสอบว่า Sketch ทำงานได้ถูกต้องหรือไม่ เพียงแค่สแกนหาอุปกรณ์แล้วเชื่อมต่อกับตัวที่ชื่อว่า Nano33BLE
Raspberry Pi 3 เป็นรุ่นแรกที่มี Bluetooth Adapter ติดตั้งมาในตัว ในบทเรียนนี้ ฉันเลือกใช้ Raspberry Pi 3 B+ พร้อมกับติดตั้ง Raspbian OS Lite (เวอร์ชัน Lite คือรุ่นที่มีเฉพาะ Command-line interface และไม่มี GUI)
มีแหล่งข้อมูลมากมายที่สอนวิธีดาวน์โหลดและ Flash SD Card สำหรับ Raspberry Pi OS ดังนั้นเราจะไม่ครอบคลุมในส่วนนี้ อย่างไรก็ตาม ฉันแนะนำให้ลองหาวิธีเปิดใช้งาน SSH หากคุณวางแผนที่จะรัน Pi โดยไม่มีคีย์บอร์ดและหน้าจอ ซึ่ง Tom's Hardware มีบทความดีๆ ที่อธิบายขั้นตอนนี้ไว้
นอกเหนือจากนั้น ทุกอย่างเป็นส่วนหนึ่งของ OS พื้นฐานอยู่แล้ว ดังนั้น มาเปิดเครื่อง Raspberry Pi และเริ่มต้นกันเลย
Raspberry Pi OS มีพื้นฐานมาจาก Debian Linux ซึ่งมาพร้อมกับเครื่องมือ Bluetooth แบบ Command-line ที่เรียกว่า bluetoothctl นี่คือสิ่งที่เราจะใช้ในการทดสอบการเชื่อมต่อกับ Arduino Nano และรวบรวมข้อมูลจาก Sensors ต่างๆ หากทุกอย่างทำงานได้ถูกต้อง เราจะขยับไปใช้ตัวอย่างที่ก้าวหน้ากว่าเดิมด้วย Python
เพียงแค่รันคำสั่ง sudo bluetoothctl ที่ Command prompt
การสแกนหาอุปกรณ์
ก่อนที่เราจะเชื่อมต่อกับ Arduino เราต้องหาอุปกรณ์ให้เจอก่อน ซึ่งทำได้ด้วยคำสั่ง scan on
เมื่อพบอุปกรณ์แล้ว เราจะใช้คำสั่ง scan off เพื่อบอกให้ bluetoothctl หยุดการค้นหา
นี่คือตัวอย่างการเริ่มใช้งาน bluetoothctl และการค้นหา Nano
$ sudo bluetoothctl
[bluetooth]# scan on
[CHG] Device FB:A7:C6:D4:64:C4 Name: Nano33BLE
[CHG] Device FB:A7:C6:D4:64:C4 Alias: Nano33BLE
[bluetooth]# scan off
สังเกตตัวเลขฐานสิบหกหกคู่ที่แสดงพร้อมกับชื่อ Nano33BLE นี่คือ Bluetooth hardware address ของ Arduino ซึ่งจะเป็นค่าเฉพาะตัวและไม่เคยเปลี่ยนแปลง ชื่อ Nano33BLE สามารถเปลี่ยนได้ใน Arduino Sketch แต่ hardware address จะยังคงเดิม
ให้คัดลอก hardware address ที่แสดงบน Raspberry Pi ของคุณเก็บไว้ในที่ที่หาง่าย เพราะต้องนำไปใช้อีกครั้ง ที่จริงแล้ว เมื่อคุณทราบ address แล้ว การสแกนก็ไม่จำเป็นอีกต่อไป
อุปกรณ์ Bluetooth Low Energy มีพฤติกรรมแตกต่างจากอุปกรณ์ Bluetooth แบบเดิมอย่างคีย์บอร์ดหรือหูฟัง ไม่จำเป็นต้องมีการทำ Pairing ก่อนเชื่อมต่อกับอุปกรณ์ BLE คุณเพียงแค่สั่งเชื่อมต่อได้เลย
ใน bluetoothctl จะใช้คำสั่ง connect
[bluetooth]# connect FB:A7:C6:D4:64:C4
[CHG] Device FB:A7:C6:D4:64:C4 Connected: yes
Connection successful
[NEW] Primary Service
/org/bluez/hci0/dev_FB_A7_C6_D4_64_C4/service0006
00001801-0000-1000-8000-00805f9b34fb
Generic Attribute Profile
...
[NEW] Primary Service
/org/bluez/hci0/dev_FB_A7_C6_D4_64_C4/service000a
0000181a-0000-1000-8000-00805f9b34fb
Environmental Sensing
...
[NEW] Characteristic
/org/bluez/hci0/dev_FB_A7_C6_D4_64_C4/service000a/char000f
00002a6e-0000-1000-8000-00805f9b34fb
Temperature
...
เมื่อเชื่อมต่อสำเร็จ บริการ (Services) ที่ถูกประกาศไว้จะถูกส่งออกมา ผลลัพธ์ที่แสดงด้านบนถูกตัดทอนเพื่อให้ดูง่ายขึ้น สังเกตว่า Characteristic ของ Temperature จะแสดงขึ้นมาพร้อมกับ Service ของ Environmental Sensing (ค่าความดันและความชื้นถูกละไว้ในตัวอย่างด้านบน แต่จะแสดงให้เห็นเมื่อคุณรันคำสั่งจริง)
โค้ดใน Arduino Sketch ส่วนที่รับผิดชอบในการส่งผลลัพธ์ที่แสดงบน Raspberry Pi คือ:
BLEService environmentalSensingService("181A");
BLEShortCharacteristic temperatureCharacteristic("2A6E", BLERead);
BLE.setAdvertisedService(environmentalSensingService);
environmentalSensingService.addCharacteristic(temperatureCharacteristic);
BLE.addService(environmentalSensingService);
BLE.setConnectable(true);
BLE.advertise();
ตอนนี้ Raspberry Pi ได้รายการของ Services และ Characteristics มาแล้ว การอ่านค่าเหล่านั้นทำได้ง่ายมากโดยใช้เมนูย่อย gatt ของ bluetoothctl (GATT เป็นคำศัพท์เฉพาะทาง Bluetooth ย่อมาจาก Generic ATTribute)
เข้าสู่เมนูย่อย GATT ด้วยคำสั่ง menu gatt
ในนี้จะมีชุดคำสั่งใหม่ให้ใช้ สองคำสั่งที่น่าสนใจคือ list-attributes และ select-attribute
คำสั่ง list-attributes ใช้เพื่อแสดงข้อมูลเกี่ยวกับ Services และ Characteristics ที่เราเห็นตอนเริ่มเชื่อมต่อกับ Nano ตราบใดที่เรามีรายการนั้นอยู่แล้ว คำสั่งนี้ก็ไม่สำคัญมากนัก
คำสั่ง select-attribute ช่วยให้เราโฟกัสไปที่ Characteristic ใดอันหนึ่งที่ Nano ให้บริการ ในตัวอย่างด้านล่าง เป็นการใช้คำสั่งเพื่อเลือก Temperature characteristic จาก Environmental Sensing service
[Arduino]# menu gatt
select-attribute 00002a6e-0000-1000-8000-00805f9b34fb
[Arduino:/service000a/char000f]#
สังเกตว่ามีการระบุ Characteristic โดยใช้ Universally Unique ID (UUID) ของมัน ซึ่งคล้ายกับการที่เราอ้างอิง Arduino ด้วย hardware address ฐานสิบหกแทนที่จะใช้ชื่อ UUID จะใช้งานได้เสมอและไม่เปลี่ยนแปลง
เมื่อเราเลือก UUID สำหรับ Temperature characteristic แล้ว ก็แค่ใช้คำสั่ง read เพื่อรับค่าอุณหภูมิ
[Arduino:/service000a/char000f]# read
Attempting to read /org/bluez/hci0/dev_FB_A7_C6_D4_64_C4/service000a/char000f
[CHG] Attribute /org/bluez/hci0/dev_FB_A7_C6_D4_64_C4/service000a/char000f Value:
4c 08 L.
4c 08 L.
ค่าที่ส่งกลับมาจากคำสั่ง read ดูไม่เหมือนค่าอุณหภูมิที่คุณจะได้รับหากอ่าน Characteristic เดียวกันนี้ด้วยแอป nRF Connect บนมือถือ มันดูไม่เหมือนอุณหภูมิเลยด้วยซ้ำ
แต่ข้อมูลมันอยู่ในนั้นแหละ แค่ต้องออกแรงนิดหน่อยเพื่อให้มนุษย์อ่านเข้าใจ
เอกสาร Bluetooth GATT definition for temperature อธิบายวิธีตีความค่าที่ส่งกลับมา หัวใจสำคัญคือมันเป็น signed integer ขนาด 16 บิต ที่แสดงค่าอุณหภูมิเซลเซียสโดยมีความละเอียดทศนิยม 2 ตำแหน่ง
การดู signed integer ขนาด 16 บิตนั้นไม่ยาก ค่าที่แสดงคือ 4c 08 โดยเรียงลำดับจากค่าที่มีนัยสำคัญน้อยที่สุดขึ้นก่อน (Little Endian) ซึ่งเป็นเรื่องปกติในการแสดงตัวเลขในระดับ Low-level ของคอมพิวเตอร์ เพียงแค่สลับคู่เลขฐานสิบหกใหม่ ตัวเลขจริงๆ ก็คือ 0x084C
เมื่อแปลงจากเลขฐานสิบหกเป็นฐานสิบ เราจะได้ค่า 2124
ซึ่งดูจะร้อนเกินไปหน่อย แต่เรายังทำไม่เสร็จ อีกส่วนที่สำคัญของนิยาม GATT สำหรับอุณหภูมิคือมันมีความละเอียดทศนิยม 2 ตำแหน่ง แล้วเลขจำนวนเต็ม (integer) จะมีทศนิยมได้อย่างไร? จริงๆ แล้วมันไม่มีหรอก แต่มีการกำหนดไว้ว่าตำแหน่งทศนิยมจะอยู่ที่ 2 ตำแหน่งสุดท้ายเสมอ
เมื่อนำตัวเลข 2124 มาใส่ทศนิยม 2 ตำแหน่ง จะได้ผลลัพธ์เป็น 21.24 ซึ่งเป็นอุณหภูมิเซลเซียสที่สมเหตุสมผลสำหรับวันหนึ่งในช่วงปลายเดือนกันยายน
ในการแปลงค่าในโปรแกรมคอมพิวเตอร์ เราจะหารด้วย 100 ส่วนค่าอื่นๆ เช่น ความดันบรรยากาศ จะมีความละเอียดทศนิยม 1 ตำแหน่ง ซึ่งเราจะหารด้วย 10 ตัวอย่างของเรื่องนี้สามารถดูได้ใน Arduino Sketch ที่มีการแปลงค่า floating-point จาก Sensor เป็น integer แบบ fixed-point เพื่อส่งผ่าน Bluetooth
// อัปเดต Bluetooth characteristics ด้วยค่าใหม่
pressureCharacteristic.writeValue((uint32_t) round(p * 10000));
temperatureCharacteristic.writeValue((int16_t) round(t * 100));
humidityCharacteristic.writeValue((uint16_t) round (h * 100));
สังเกตว่าค่า floating-point อย่าง t และ h ถูกคูณด้วย 100 เพื่อรักษามูลค่าทศนิยม 2 ตำแหน่งในรูปแบบ integer ส่วนความดัน p มีความละเอียด 1 ตำแหน่ง ซึ่งเราน่าจะเห็นการคูณด้วย 10 แต่เอกสาร GATT ยังระบุว่าความดันต้องอยู่ในหน่วย Pascal (Pa) ในขณะที่ Arduino ให้ค่าเป็น kiloPascals (kPa) ดังนั้นเราจึงคูณด้วย 1000 เพื่อแปลงเป็น Pascal และคูณอีก 10 เพื่อให้ได้ทศนิยม 1 ตำแหน่ง (10 x 1000 จึงเท่ากับ 10000)
เห็นได้ชัดว่า bluetoothctl ไม่ใช่วิธีที่เหมาะที่สุดในการรับข้อมูลจาก Arduino Sensors แต่มันเป็นจุดเริ่มต้นที่ดีในการทำความเข้าใจการทำงานของ Bluetooth Low Energy ขั้นตอนต่อไปคือการทำให้มันใช้งานได้ง่ายขึ้น
ภาษาโปรแกรมหลายภาษามาพร้อมกับ Bluetooth libraries เราได้พิสูจน์แล้วว่า Raspberry Pi สามารถเชื่อมต่อและรวบรวมค่าลักษณะทางสิ่งแวดล้อมจาก Nano ได้สำเร็จ ในส่วนนี้ เราจะใช้ภาษา Python และ Library ที่ชื่อว่า Bleak เพื่อดึงค่า GATT characteristics จาก Arduino Nano
Raspbian OS Lite ไม่ได้รวมทุกอย่างที่เราต้องการไว้ ดังนั้นต้องติดตั้งบาง Package เพิ่มด้วยเครื่องมือ apt
sudo apt install python3-pip
sudo pip3 install bleak
เมื่อติดตั้ง PIP3 และ Bleak เสร็จแล้ว เราก็พร้อมลุย
Library Bleak มี โค้ดตัวอย่าง ที่เป็นจุดเริ่มต้นที่ดีสำหรับการอ่านค่าจาก Nano ตัวอย่างแรกบนหน้าหลักของเขาแสดงวิธีค้นหาอุปกรณ์ (Discover) ซึ่งคล้ายกับคำสั่ง scan on ใน bluetoothctl
เช่นเดียวกับ bluetoothctl โปรแกรม Python จำเป็นต้องรันด้วยสิทธิ์ root เพื่อเข้าถึงอุปกรณ์ Bluetooth ของ Raspberry Pi หลังจากรอสักครู่ มันจะแสดงรายการอุปกรณ์รวมถึง Arduino Nano 33 BLE Sense ในระบบของฉันแสดงผลแบบนี้:
$ sudo python3 ./discover.py
FB:A7:C6:D4:64:C4: Nano33BLE
สามารถคัดลอก address ไปใช้ในตัวอย่างถัดไปบนหน้าหลักของ Bleak Library ได้เลย เพียงแค่เปลี่ยนบรรทัดที่เขียนว่า: address = "24:71:89:cc:09:05" ด้วย address ที่ได้จากสคริปต์ discover
การรันสคริปต์สำหรับอ่าน Model Number ที่คัดลอกมาจากหน้า Bleak โดยตรงจะล้มเหลว นั่นเป็นเพราะมันมองหา Characteristic (2A24) ที่ไม่ได้ถูกกำหนดไว้ใน Arduino Sketch เราต้องแก้ไขโค้ด Python จาก MODEL_NBR_UUID = "00002a24-0000-1000-8000-00805f9b34fb" เป็น MODEL_NBR_UUID = "00002a00-0000-1000-8000-00805f9b34fb"
มันเป็นการเปลี่ยนแปลงเล็กน้อยมาก เพียงแค่เปลี่ยนตัวเลขสองตัวในชุดแรกของ UUID จาก 2a24 เป็น 2a00 ส่วนที่เหลือคงไว้เหมือนเดิม เมื่อทำเช่นนี้ สคริปต์ Python จะทำงานได้โดยไม่มีข้อผิดพลาด
$ sudo python3 ./read_model.py
Model Number: Arduino
การเปลี่ยน UUID เพียงเล็กน้อยนี้คือสิ่งที่คุณต้องทำเพื่ออ่าน GATT characteristic ใดๆ ที่ต้องการ งานที่เหลือมีเพียงการตรวจสอบให้แน่ใจว่าฟังก์ชัน print() แสดงประเภทของ Variable ที่ถูกต้อง
ในการอ่านค่าความชื้น (humidity) จาก Nano ต้องเปลี่ยนโค้ดเพียง 2 บรรทัด คือ UUID และคำสั่ง print() โดย UUID จะกลายเป็น:
00002a6f-0000-1000-8000-00805f9b34fb
และคำสั่ง print() จะกลายเป็น:
print("Humidity: {0}%".format(int.from_bytes(humidity, byteorder='little', signed=False) / 100))
การปรับแต่งเล็กๆ น้อยๆ ในโค้ดตัวอย่างของ Bleak นี้คือทั้งหมดที่ใช้ในการอ่าน GATT characteristic ใดๆ โปรแกรม Python สำหรับการอ่านค่าลักษณะทางสิ่งแวดล้อมทั้งหมดจาก Arduino Nano ถูกรวมไว้ในส่วน Code แล้ว
ด้วย Bleak Library และความรู้การเขียนสคริปต์ Python เล็กน้อย Raspberry Pi สามารถตั้งค่าให้อ่านค่าเป็นระยะและแสดงผลบนหน้าจอหรือหน้าเว็บได้ มันยังสามารถไปไกลถึงการวิเคราะห์แนวโน้มเพื่อพยากรณ์อากาศที่กำลังจะมาถึงได้ด้วย
Arduino Sketch สามารถปรับปรุงให้บังคับตัดการเชื่อมต่อกับ Client หลังจากผ่านไประยะเวลาหนึ่ง โดยธรรมชาติของ Bluetooth Low Energy ถูกออกแบบมาเพื่อการทำงานแบบ เชื่อมต่อ-อ่าน/เขียน-ตัดการเชื่อมต่อ หาก Client ใดเชื่อมต่อค้างไว้นานเกินไป จะเป็นการบล็อกไม่ให้ Client อื่นเข้ามาอ่านค่าได้
ถึงจุดนี้ หวังว่าคุณจะมีความมั่นใจและทักษะเพียงพอที่จะรับงานทั้งสองอย่างนี้ไปสร้างสถานีตรวจอากาศ Bluetooth Low Energy ที่สมบูรณ์แบบของคุณเอง
ตามที่สัญญาไว้ นี่คือข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับส่วนที่เกี่ยวข้องกับ Bluetooth ใน Arduino Sketch ฉันได้แบ่งออกเป็นส่วนของ Variables, Setup และ Loop
Variables
การประกาศวัตถุ (Objects) สำหรับ Service และ Characteristic จะต้องทำเป็นอันดับแรกเพื่อให้พวกมันเป็น Global
BLEService environmentalSensingService("181A");
BLEUnsignedIntCharacteristic pressureCharacteristic("2A6D", BLERead);
BLEShortCharacteristic temperatureCharacteristic("2A6E", BLERead);
BLEUnsignedIntCharacteristic humidityCharacteristic("2A6F", BLERead);
ค่าเลขฐานสิบหกสี่หลักในเครื่องหมายอัญประกาศคือ GATT UUIDs ที่ใช้โดย Object constructor โดย UUID แบบสั้น 16 บิตเหล่านี้ถูกกำหนดไว้ล่วงหน้าในมาตรฐาน Bluetooth Low Energy GATT คุณไม่สามารถนำไปใช้เพื่อวัตถุประสงค์อื่นนอกเหนือจากที่กำหนดไว้ได้
181A คือ Environmental Sensing service ส่วน UUID อื่นๆ อ้างถึง Characteristics ฉันไม่พบกฎที่ระบุว่า Characteristic บางอย่างต้องอยู่กับ Service บางอย่างเท่านั้น แต่ส่วนใหญ่จะจับคู่กันอย่างสมเหตุสมผลอยู่แล้ว อุณหภูมิ ความชื้น และความดัน จึงเหมาะอย่างยิ่งสำหรับ Environmental Sensing service ที่เกี่ยวกับสภาพอากาศ
อย่างไรก็ตาม ยังมี Battery service ด้วย แล้ว Battery service จะใช้อุณหภูมิได้ไหม? วงจรชาร์จแบตเตอรี่จำนวนมากมีการตรวจสอบอุณหภูมิเพื่อตรวจจับสภาวะที่ไม่ปลอดภัย ดังนั้นมันจึงดูสมเหตุสมผล แต่ฉันยังไม่เคยลองดู
ส่วน BLERead เป็นการระบุว่า Characteristics เหล่านี้สามารถอ่านได้ แต่เขียนทับไม่ได้ ซึ่งเหมาะสมสำหรับข้อมูลสภาพอากาศ คุณไม่ได้เป็นคนกำหนดความดันบรรยากาศ แต่คุณเป็นคนอ่านมัน นอกจากนี้ยังมีค่าที่เขียนได้ (writable) และ flag สำหรับ notify ซึ่ง notify คือวิธีส่งค่าที่อัปเดตไปยัง Client โดยตรง เพื่อลดภาระของ Client ในการคอยส่งคำสั่งมาถาม (polling)
อีกแง่มุมที่สำคัญของการประกาศ Objects เหล่านี้คือการเลือกประเภท Variable ที่เหมาะสม
สังเกตว่าอุณหภูมิเป็น short integer ในขณะที่ความชื้นเป็น unsigned integer ซึ่งสมเหตุสมผลเพราะอุณหภูมิเซลเซียสมีได้ทั้งค่าบวกและลบ แต่ความชื้นสัมพัทธ์จะมีค่าระหว่าง 0 ถึง 100 เปอร์เซ็นต์เสมอ
การกำหนดประเภท Variable ต้องตรงตามที่ระบุในนิยามของ Bluetooth GATT เป๊ะๆ คุณไม่สามารถกำหนดให้อุณหภูมิเป็น floating point characteristic ได้ (ในทางเทคนิคคุณอาจทำได้ แต่ค่าที่ได้จะใช้งานไม่ได้) คุณต้องทำตามนิยาม GATT สำหรับ Characteristics เหล่านั้น
Setup
หลังจากตัดโค้ดส่วนการ Debug และการสั่งงาน LED แสดงสถานะออกไปแล้ว การตั้งค่า Bluetooth จะประกอบไปด้วย:
การตั้งชื่อและ Service
BLE.setLocalName("Nano33BLE");
BLE.setAdvertisedService(environmentalSensingService);
ชื่อ Nano33BLE จะเป็นอะไรก็ได้ตามที่คุณต้องการ หากคุณมีสองตัว ตัวหนึ่งอยู่ในบ้านและอีกตัวอยู่นอกบ้าน คุณก็สามารถตั้งชื่อให้แตกต่างกันได้
การเพิ่ม Characteristics เข้าไปยัง Service
environmentalSensingService.addCharacteristic(pressureCharacteristic);
environmentalSensingService.addCharacteristic(temperatureCharacteristic);
environmentalSensingService.addCharacteristic(humidityCharacteristic);
โค้ดสามบรรทัดนี้เป็นการเชื่อมโยง Characteristics เข้ากับ Service หากคุณใช้แอป nRF connect บนมือถือ คุณจะเห็นค่าเหล่านี้แสดงเป็นลำดับชั้นอยู่ภายใต้ Service ที่เกี่ยวข้อง
ส่วนสุดท้ายคือการทำให้แน่ใจว่า Client สามารถเชื่อมต่อได้และมีการประกาศ Service ที่เรามีอยู่
BLE.setConnectable(true);
BLE.advertise();
อย่าลืมบรรทัดเหล่านี้ ไม่อย่างนั้นคุณอาจจะสงสัยว่าทำไมมันถึงใช้งานไม่ได้
Loop
ใน Loop หลัก เรามี:
if (central) {
while (central.connected()) {
pressureCharacteristic.writeValue((uint32_t) round(p * 10000));
temperatureCharacteristic.writeValue((int16_t) round(t * 100));
humidityCharacteristic.writeValue((uint16_t) round(h * 100));
delay(1000);
}
}
Central คืออีกชื่อหนึ่งของอุปกรณ์ฝั่ง Client ที่เข้ามาเชื่อมต่อกับ Nano ซึ่ง Central อาจจะเป็น Raspberry Pi หรือแอป nRF Connect ก็ได้
ตรรกะตรงนี้คือเมื่อมี Client เชื่อมต่อเข้ามา ให้วนลูปอัปเดตค่าสำหรับ Characteristics ต่อไปตราบเท่าที่ Client นั้นยังคงเชื่อมต่ออยู่ วิธีนี้ช่วยให้ Client ได้ข้อมูลที่สดใหม่อยู่เสมอโดยไม่ต้องตัดการเชื่อมต่อแล้วต่อใหม่ ส่วนการหน่วงเวลา (delay) มีไว้เพื่อให้ค่ามีความนิ่งขึ้นเล็กน้อย (ค่าจะไม่เปลี่ยนเร็วกว่าวินาทีละครั้ง)
ปัญหาเดียวของ Loop นี้คือ Client อาจจะถือการเชื่อมต่อไว้ตลอดกาล ไม่ว่าจะโดยตั้งใจหรือเพียงแค่ลืมตัดการเชื่อมต่อ ซึ่งจะทำให้การเชื่อมต่อถูกจองไว้และป้องกันไม่ให้ Client อื่นเข้ามาอ่านค่า Characteristics ได้ (หมายเหตุ: นี่เป็นข้อจำกัดของตัว Sketch ส่วนชิป nRF52840 ใน Nano นั้นจริงๆ แล้วสามารถรองรับ การเชื่อมต่อจาก Client พร้อมกันได้ถึง 4 เครื่อง)
การเพิ่มตัวนับ (Counter) เพื่อคอยตรวจสอบว่า Client เชื่อมต่อนานเท่าใดแล้ว และสั่งบังคับตัดการเชื่อมต่อ (Disconnect) เมื่อถึงเกณฑ์ที่กำหนด น่าจะเป็นการปรับปรุงส่วนเสริมที่ดีมาก
สนับสนุนเพื่อรับ Source Code หรือแอปพลิเคชันสำหรับโปรเจกต์นี้