본문 바로가기

아두이노우노 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");
}

 

 

실행 예시입니다. 

 

 

 

반응형

캐어랩 고객 지원

취업, 창업의 막막함, 외주 관리, 제품 부재!

당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약, 아이디어는 있지만 구현할 기술이 없는 막막함.

우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.

이제 고민을 멈추고, 캐어랩을 만나세요!

코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.

제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!

귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.

지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.

카카오 채널 추가하기

카톡 채팅방에서 무엇이든 물어보세요

귀사가 성공하기까지의 긴 고난의 시간을 캐어랩과 함께 하세요.

캐어랩 온라인 채널 바로가기

캐어랩