지난번 포스팅에서 기압 센서 LPS22HB로 기압과 온도를 측정하여 그래픽 디스플레이에 표시했습니다.
본 문서의 전체 리스트를 링크로 연결하였습니다. 참고하세요.
UNO R4 WiFi BLE ⑥ BME280의 BLE 주변기기와 연결되는 센트럴
UNO R4 WiFi BLE ⑤ BME280의 BLE peripheral
UNO R4 WiFi BLE ④ 기압 센서 BME280을 연결
UNO R4 WiFi BLE ③ LPS22의 BLE 주변기기와 연결되는 센트럴
UNO R4 WiFi BLE ② LPS22의 BLE 주변기기
UNO R4 WiFi BLE ① 기압 센서 LPS22 연결
이번에는 측정한 두 데이터를 BLE(Bluetooth Low Energy)로 전송하는 BLE 페리페럴(peripheral)을 만들겠습니다. 수신하는 쪽을 BLE 센트럴(central)이라고 합니다.
ArduinoBLE 라이브러리를 이용하여 스케치를 작성합니다. 작성 시점에는 1.3.6이 최신 버전입니다.
사용 환경
Arduino UNO R4 WiFi
Arduino IDE 2.2.1
Windows10 22H2
BLE의 각종 정의
BLE가 주변장치와 중앙장치 간에 BLE가 연결되면 GATT 통신이 이루어지며, GATT는 Generic attribute profile의 약자이다.
GATT 통신 안에는 여러 Service(서비스)가 포함되어 있습니다. 여기서는 LPS22라는 이름의 하나의 서비스만 존재합니다.
서비스 안에는 여러 개의 Characteristic(특성)이 포함되어 있습니다. 여기서는 온도와 기압 두 가지입니다.
Characteristic에는 설명; Descriptor(설명자)를 붙일 수 있습니다. 없을 수도 있습니다.
여러 기기들 사이에서 그 서비스나 특성 등이 겹치지 않도록 고유한 UUID로 식별합니다.
BLERead는 중앙에서 Characteristic의 값을 읽어들이고, BLENotify는 주변기기에서 Characteristic의 값을 알려주는 처리 내용입니다.
#define LPS22_SERVICE_UUID "F000AA30-0451-4000-B000-000000000000" // BLE Service
BLEService Sensor_LPS22_Service(LPS22_SERVICE_UUID);
#define LPS22_Temp_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000" // BLE Characteristic
#define LPS22_Press_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic LPS22_Temp(LPS22_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic LPS22_Press(LPS22_Press_Characteristic_UUID, BLERead | BLENotify);
#define LPS22_Temp_Descriptor_UUID "2901" // BLE Descriptor
#define LPS22_Press_Descriptor_UUID "2901"
BLEDescriptor LPS22_Temp_Descriptor(LPS22_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor LPS22_Press_Descriptor(LPS22_Press_Descriptor_UUID, "Pressure: hPa");
BLEFloatCharacteristic은 ArduinoBLE 라이브러리에서 실수 Characteristic이라는 것을 지정하고 있으며, IEEE-754 형식(단정밀도 부동소수점 수, Arduino의 실수가 메모리에 유지되는 형식)입니다. 이 외에도 BLECharCharacteristic, BLEUnsignedCharCharacteristic 등이 있습니다.
Descriptor의 2901은 사용자가 읽을 수 있는 Characteristic의 설명 문자열(UTF-8)을 지정한다.
setup-BLE
최초 초기화합니다.
BLE.begin();
localname을 지정합니다.
#define localNAME "LPS22_float"
BLE.setLocalName(localNAME);
service, characteristic, descriptor를 BLE에 추가한다.
BLE.setAdvertisedService(Sensor_LPS22_Service); // add the service UUID
Sensor_LPS22_Service.addCharacteristic(LPS22_Temp); // add characteristic
Sensor_LPS22_Service.addCharacteristic(LPS22_Press);
LPS22_Temp.addDescriptor(LPS22_Temp_Descriptor); // add descriptor
LPS22_Press.addDescriptor(LPS22_Press_Descriptor);
BLE.addService(Sensor_LPS22_Service); // Add service
Characteristic에 초기값을 입력합니다.
LPS22_Temp.writeValue(oldValue); // 이 특성의 초기값을 설정합니다.
LPS22_Press.writeValue(oldValue);
준비가 완료되었으니, 중앙에서 연결 대기 = 광고를 시작합니다.
BLE.advertise(); // start advertising
Serial.println("Bluetooth device active, waiting for connections...");
루프 BLE
중앙과의 연결을 기다립니다.
// wait for a BLE central
BLEDevice central = BLE.central(); // wait for a BLE central
연결되면 메시지를 출력한다.
// 센트럴이 주변장비와 연결되어 있는 경우:
if (central) {
delay(100);
Serial.print("Connected to central: ");
// print the central's BT address:
Serial.println(central.address());
연결되어 있는 동안 updateValue();로 데이터를 전송한다.
while (central.connected()) {
updateValue();
delay(1000);
}
연결이 끊어지면 메시지를 출력합니다.
// when the central disconnects
Serial.print("Disconnected from central: ");
Serial.println(central.address());
updateValue() {} 함수 내에서 기압과 온도를 전송한다.
LPS22_Temp.writeValue(tempC);
LPS22_Press.writeValue(press);
전체 스케치
#include <ArduinoBLE.h>
#define LPS22_SERVICE_UUID "F000AA30-0451-4000-B000-000000000000" // BLE Service
BLEService Sensor_LPS22_Service(LPS22_SERVICE_UUID);
#define LPS22_Temp_Characteristic_UUID "F000AA31-0451-4000-B000-000000000000" // BLE Characteristic
#define LPS22_Press_Characteristic_UUID "F000AA32-0451-4000-B000-000000000000"
BLEFloatCharacteristic LPS22_Temp(LPS22_Temp_Characteristic_UUID, BLERead | BLENotify);
BLEFloatCharacteristic LPS22_Press(LPS22_Press_Characteristic_UUID, BLERead | BLENotify);
#define LPS22_Temp_Descriptor_UUID "2901" // BLE Descriptor
#define LPS22_Press_Descriptor_UUID "2901"
BLEDescriptor LPS22_Temp_Descriptor(LPS22_Temp_Descriptor_UUID, "Temperature: `C IEEE-754 format");
BLEDescriptor LPS22_Press_Descriptor(LPS22_Press_Descriptor_UUID, "Pressure: hPa");
#include <Wire.h>
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_SSD1306.h>
Adafruit_LPS22 lps;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
#define localNAME "LPS22_float"
float oldValue = 0; // last value
void setup(void) {
Serial.begin(115200);
while (!Serial) delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit LPS22 + ssd1306 + BLE");
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// Try to initialize!
if (!lps.begin_I2C()) {
Serial.println("Failed to find LPS22 chip");
while (1) { delay(10); }
}
Serial.println("LPS22 Found!");
lps.setDataRate(LPS22_RATE_10_HZ);
Serial.print("Data rate set to: ");
switch (lps.getDataRate()) {
case LPS22_RATE_ONE_SHOT: Serial.println("One Shot / Power Down"); break;
case LPS22_RATE_1_HZ: Serial.println("1 Hz"); break;
case LPS22_RATE_10_HZ: Serial.println("10 Hz"); break;
case LPS22_RATE_25_HZ: Serial.println("25 Hz"); break;
case LPS22_RATE_50_HZ: Serial.println("50 Hz"); break;
case LPS22_RATE_75_HZ: Serial.println("75 Hz"); break;
}
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for (;;)
; // Don't proceed, loop forever
}
display.display();
delay(500); // Pause for 2 seconds
display.setTextSize(1);
display.setTextColor(WHITE);
display.setRotation(0);
display.clearDisplay();
BLE.setLocalName(localNAME);
BLE.setAdvertisedService(Sensor_LPS22_Service); // add the service UUID
Sensor_LPS22_Service.addCharacteristic(LPS22_Temp); // add characteristic
Sensor_LPS22_Service.addCharacteristic(LPS22_Press);
LPS22_Temp.addDescriptor(LPS22_Temp_Descriptor); // add descriptor
LPS22_Press.addDescriptor(LPS22_Press_Descriptor);
BLE.addService(Sensor_LPS22_Service); // Add service
LPS22_Temp.writeValue(oldValue); // set initial value for this characteristic
LPS22_Press.writeValue(oldValue);
BLE.advertise(); // start advertising
Serial.println("Bluetooth device active, waiting for connections...");
}
void loop() {
// wait for a BLE central
BLEDevice central = BLE.central();
// if a central is connected to the peripheral:
if (central) {
delay(100);
Serial.print("Connected to central: ");
// print the central's BT address:
Serial.println(central.address());
while (central.connected()) {
updateValue();
delay(1000);
}
// when the central disconnects
Serial.print("Disconnected from central: ");
Serial.println(central.address());
}
}
void updateValue() {
display.clearDisplay();
display.setCursor(0, 0);
sensors_event_t temp;
sensors_event_t pressure;
lps.getEvent(&pressure, &temp);// get pressure
float tempC = temp.temperature;
float press = pressure.pressure;
Serial.print("Temperature: ");Serial.print(tempC);Serial.println(" degrees C");
Serial.print("Pressure: ");Serial.print(press);Serial.println(" hPa");
Serial.println("");
display.println("Temperature: - `C");
display.print(tempC, 2);
display.println("");
display.println("");
display.println("Pressure: - hPa");
display.print(press, 1);
display.display();
// if value has changed
if (tempC != oldValue) {
// update characteristic
LPS22_Temp.writeValue(tempC);
LPS22_Press.writeValue(press);
oldValue = tempC; // save the level for next comparison
}
}
동작 확인 온세미컨덕터의 BLE인 RSL10 Bluetooth Low Energy Explorer의 중앙 기능을 사용하여 PC에서 정보를 확인한다.
localname을 검색하여 LPS22_float를 찾았으니 Connect를 클릭하고 Discover Services를 클릭하여 Services의 내용을 표시한 화면이다.
Notification을 체크하면 항상 최신 데이터가 전송됩니다.
보내주신 실수치를 이 사이트를 통해 변환하여 정확한 값인지 확인했습니다.
'아두이노우노 R4' 카테고리의 다른 글
아두이노 나노, PM2008 미세먼지 SSD1306 Oled Display (1) | 2024.07.29 |
---|---|
i2c 충돌나면 풀업저항 다는 게 제일 먼저 할 일 (1) | 2024.07.28 |
DS1302 아두이노 RTC 모듈 사용법 (2) | 2024.07.12 |
아두이노 0.96인치 OLED 디스플레이(SSD1306) 실습 (0) | 2024.07.04 |
UNO R4 WiFi BLE ① 기압 센서 LPS22 연결 (1) | 2024.06.17 |
Arduino Mega의 PWM 주파수를 변경하는 방법 (0) | 2024.05.23 |
UNO R4 Mechanical Size (1) | 2024.05.22 |
아두이노 UNO R4 WiFi 최강 가이드 (0) | 2024.05.22 |
더욱 좋은 정보를 제공하겠습니다.~ ^^