본문 바로가기

아두이노우노 R4

UNO R4 WiFi BLE ⑥ BME280의 BLE 주변기기와 연결되는 센트럴

반응형

 

Arduino UNO R4 WiFi로 BLE ⑥ BME280의 BLE 주변기기와 연결되는 센트럴 

 

지난번에 Arduino UNO R4 WiFi에 기압센서 BME280을 연결하여 BLE 주변기기를 만들었는데요, PC에서 동작하는 온세미컨덕터의 BLE인 RSL10 Bluetooth Low Energy Explorer를 연결하여 기압과 온도 데이터를받았습니다.

 

이 마이크로컴퓨터 보드 Arduino UNO R4 WiFi를 PC의 USB에서 분리하고 전원을 연결하여 단독으로 작동하도록 합니다.그리고 RSL10 Bluetooth Low Energy Explorer로 연결할 수 있음을 확인했습니다.

 

 

본 문서의 전체 리스트를 링크로 연결하였습니다. 참고하세요.

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 연결 

 

 

● 두 번째 마이크로 컴퓨터 보드 Arduino UNO R4 WiFi 준비

 

또 다른 마이크로 컴퓨터 보드 Arduino UNO R4 WiFi를 준비하여 PC에 연결하고 BLE 센트럴의 스케치를 만듭니다.

 

● BLE의 각종 정의

 

BLE 주변기기란 localNAME으로 선택합니다.

 

#define localNAME "BME280_int"

 

연결이 완료되면 캐릭터스틱을 지정하여 읽어옵니다. 

 

 

#define BME280_Temp_Characteristic_UUID    "F000AA31-0452-4000-B000-000000000000"  // BLE  Characteristic
#define BME280_Press_Characteristic_UUID   "F000AA32-0452-4000-B000-000000000000"
#define BME280_Humidity_Characteristic_UUID   "F000AA33-0452-4000-B000-000000000000"

 

 

●setup - BLE

 

먼저 초기화합니다.

 

BLE.begin();

 

localNAME으로 찾습니다.

 

// start scanning for peripherals

BLE.scanForName(localNAME); 

 

 

●loop-BLE

 

주변기기를 찾으면 주소, localNAME, 서비스 UUID를 출력합니다. 

 

// check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

 

스캔을 중지합니다.

 

// stop scanning

BLE.stopScan();

 

읽기 함수를 실행합니다.

 

readData(peripheral);

 

읽기 함수에서는 먼저 connect를 수행합니다.

 

if (peripheral.connect()) {

 

다음으로 discover합니다.

 

if (peripheral.discoverAttributes()) {

 

온도와 기압, 습도의 UUID로 데이터를 가져옵니다. 

 

 // retrieve the characteristic
  BLECharacteristic Temperature_Characteristic = peripheral.characteristic(BME280_Temp_Characteristic_UUID);
  BLECharacteristic Pressure_Characteristic  = peripheral.characteristic(BME280_Press_Characteristic_UUID);
  BLECharacteristic Humidity_Characteristic  = peripheral.characteristic(BME280_Humidity_Characteristic_UUID);

 

온도 데이터를 2바이트씩 읽어오는데, 2바이트(상위)와 1바이트(하위)에 정수 데이터가 들어있으므로 16비트 데이터로 수정한다.

 

Temperature_Characteristic.readValue(buffer,2);

uint16_t temperature = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];

 

측정한 실수를 100배하여 정수로 보내왔으므로 100으로 나눕니다.

 

Serial.println(temperature / 100.0);

 

기압과 습도 데이터도 마찬가지로 읽어들여 실수로 변환하여 출력한다.기압과 습도는 10배입니다.

 

전체 스케치입니다. 

 

#include <ArduinoBLE.h>

#define localNAME "BME280_int"
#define BME280_Temp_Characteristic_UUID    "F000AA31-0452-4000-B000-000000000000"  // BLE  Characteristic
#define BME280_Press_Characteristic_UUID   "F000AA32-0452-4000-B000-000000000000"
#define BME280_Humidity_Characteristic_UUID   "F000AA33-0452-4000-B000-000000000000"

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10); 
  BLE.begin();
  Serial.println("\n start BLE peripherals - Temperature/Pressure/Humidity");
  // start scanning for peripherals
  BLE.scanForName(localNAME);
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != localNAME) {
      return;
    }
    // stop scanning
    BLE.stopScan();

    readData(peripheral);

    // peripheral disconnected, start scanning again
    BLE.scanForName(localNAME);
  }
}

void readData(BLEDevice peripheral) {
  byte buffer[2] ;
  // connect to the peripheral
  Serial.print("\nConnecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.print("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered\n");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }
  // retrieve the characteristic
  BLECharacteristic Temperature_Characteristic = peripheral.characteristic(BME280_Temp_Characteristic_UUID);
  BLECharacteristic Pressure_Characteristic  = peripheral.characteristic(BME280_Press_Characteristic_UUID);
  BLECharacteristic Humidity_Characteristic  = peripheral.characteristic(BME280_Humidity_Characteristic_UUID);

  if (!Temperature_Characteristic) {
    Serial.println("Peripheral does not have Temp characteristic!");
    peripheral.disconnect();
    return;
  } 

  Serial.println("---Found CHARACTERISTIC_UUID");
  while (peripheral.connected()) {
  if (Temperature_Characteristic.canRead()) {
      Serial.print("\ntemp = ");
      Temperature_Characteristic.readValue(buffer,2);
      uint16_t temperature = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println(temperature / 100.0); 

  }

  if (Pressure_Characteristic.canRead()) {
      Serial.print("Pressure = ");
      Pressure_Characteristic.readValue(buffer,2);
      uint16_t pressure = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println((pressure / 10.0),1);
  }

  if (Humidity_Characteristic.canRead()) {
      Serial.print("Humidity = ");
      Humidity_Characteristic.readValue(buffer,2);
      uint16_t humidity = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println((humidity / 10.0),1);
  }

  delay(1000);
  }
 
  Serial.println("Peripheral disconnected");
}

 

 실행 예시입니다. 

 

 

 

● 그래픽 디스플레이에 수신된 데이터 표시

 

LPS22 때처럼 마이크로보드의 LED 매트릭스에 텍스트를 표시하려고 했지만, 온도, 기압, 습도를 표시하기에는 너무 좁아서 스크롤을 하면 보기가 매우 어려웠다.

 

Arduino UNO R4 WiFi로 BLE ③ LPS22의 BLE 주변기기와 연결되는 센트럴

 

그래서 BLE 주변기기와 마찬가지로 OLED 그래픽 디스플레이를 사용했다.아마존에서 구입할 수 있는 I2C 연결 타입이다.이 마이컴 보드에는 Qwiic 전용 커넥터가 준비되어 있지만, OLED 그래픽 디스플레이는 인식하지 못했습니다.

 

Spresense에서 Lchica로 시작하는 (5) Wire 라이브러리 그래픽 디스플레이

 

스케치입니다.제조사를 알 수 없는 OLED 그래픽 디스플레이이지만, 드라이버는 Adafruit의 ssd1306용 드라이버를 사용했습니다.슬레이브 주소는 0x3c입니다. 

 

 

#include <ArduinoBLE.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

#define localNAME "BME280_int"
#define BME280_Temp_Characteristic_UUID    "F000AA31-0452-4000-B000-000000000000"  // BLE  Characteristic
#define BME280_Press_Characteristic_UUID   "F000AA32-0452-4000-B000-000000000000"
#define BME280_Humidity_Characteristic_UUID   "F000AA33-0452-4000-B000-000000000000"

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10); 

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // 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.begin();
  Serial.println("\n start BLE peripherals - Temperature/Pressure/Humidity + ssd1306");
  // start scanning for peripherals
  BLE.scanForName(localNAME);
}

void loop() {
  display.clearDisplay();
  display.setCursor(0, 0);

  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != localNAME) {
      return;
    }
    // stop scanning
    BLE.stopScan();

    readData(peripheral);

    // peripheral disconnected, start scanning again
    BLE.scanForName(localNAME);
  }
}

void readData(BLEDevice peripheral) {
uint16_t temperature;
uint16_t pressure;
uint16_t humidity;

  byte buffer[2] ;
  // connect to the peripheral
  Serial.print("\nConnecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.print("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered\n");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }
  // retrieve the characteristic
  BLECharacteristic Temperature_Characteristic = peripheral.characteristic(BME280_Temp_Characteristic_UUID);
  BLECharacteristic Pressure_Characteristic  = peripheral.characteristic(BME280_Press_Characteristic_UUID);
  BLECharacteristic Humidity_Characteristic  = peripheral.characteristic(BME280_Humidity_Characteristic_UUID);

  if (!Temperature_Characteristic) {
    Serial.println("Peripheral does not have Temp characteristic!");
    peripheral.disconnect();
    return;
  } 

  Serial.println("---Found CHARACTERISTIC_UUID");
  while (peripheral.connected()) {
  if (Temperature_Characteristic.canRead()) {
      Serial.print("\ntemp = ");
      Temperature_Characteristic.readValue(buffer,2);
      temperature = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println(temperature / 100.0); 

  }

  if (Pressure_Characteristic.canRead()) {
      Serial.print("Pressure = ");
      Pressure_Characteristic.readValue(buffer,2);
      pressure = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println((pressure / 10.0),1);
  }

  if (Humidity_Characteristic.canRead()) {
      Serial.print("Humidity = ");
      Humidity_Characteristic.readValue(buffer,2);
      humidity = (uint8_t)buffer[1]*256 + (uint8_t)buffer[0];
      Serial.println((humidity / 10.0),1);
  }

  display.clearDisplay();
  display.setCursor(0, 0);

  display.println("Temperature - `C");
  display.print(temperature / 100.0, 2);
  display.println("");

  display.println("");
  display.println("Pressure - hPa");
  display.print(pressure / 10.0, 1);
  display.println("");

  display.println("");
  display.println("Humidity - %");
  display.print(humidity / 10.0, 1);
  display.println("");

  display.display();

  delay(1000);
  }
 
  Serial.println("Peripheral disconnected");
}

 

 

실행 예시입니다. 

 

 

 

반응형

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