본문 바로가기

아두이노우노 R4

UNO R4 WiFi BLE ② LPS22의 BLE 주변기기

반응형

 

지난번 포스팅에서 기압 센서 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을 체크하면 항상 최신 데이터가 전송됩니다. 

 

 

 

보내주신 실수치를 이 사이트를 통해 변환하여 정확한 값인지 확인했습니다. 

 

 

참고 사이트

 

Arduino UNO R4 WiFiでBLE ② LPS22のBLEペリフェラル | Arduinoクックブック

IoT spresense Arduino IDE LED Lチカ

www.denshi.club

 

 

 

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^