Takuo6712のアイコン画像
Takuo6712 2025年01月31日作成 © MIT
製作品 製作品 閲覧数 89
Takuo6712 2025年01月31日作成 © MIT 製作品 製作品 閲覧数 89

SPRESENSEとHome Assistantを使用したスマートガスセンサーの開発

SPRESENSEとHome Assistantを使用したスマートガスセンサーの開発

概要

元々スマートホームが好きで自作のスマートリモコンやドアの開閉センサーをHome Assistant上で動作できるようにしていました。
そこで今回はSPRESENSEにガスセンサーを取り付け,オープンソースでお馴染みのHome Assistant OS上で部屋の環境がわかるようにしました!
自作スマートリモコンスマートリモコンのコントロールボード

必要部品

  • SPRESENSE本体
  • BME680
  • BLE1507
  • Raspberry Pi5(Home Assistant OS用)
  • ESP32(ESPHome用)

Home Assistantとは

Home Assistant OS以下(HAOS)は、スマートホームのデバイスを一元管理・自動化するためのオープンソースプラットフォーム「Home Assistant」を専用のオペレーティングシステム(OS)として提供するものです。Raspberry Piや眠っているデスクトップPCなどにインストールすることで、Home Assistantの全機能を簡単に利用できます。
主な特徴:
・オールインワンパッケージ: Home Assistant OSには、OS自体、Home Assistant本体、アドオン管理機能などがすべて含まれており、追加の設定なしで利用を開始できます。
・簡単なセットアップ: 専用のハードウェアにインストールすることで、初めてのユーザーでも直感的にセットアップが可能です。
・アドオン機能: Node-REDやMosquitto(MQTTブローカー)などのアドオンをGUI上で簡単に追加・管理できます。

Home AssistantでBLEを使用する方法

残念ながらHAOSではデフォルトでBLEに対応していません。そのためESPHomeという追加アドオンを用いてESPとBLEデバイス間で通信を行います。
設定→アドオン→「ESPHome」で検索します。ヒットしたものをインストールすれば自動的に使えるようになります。よく使用する人はサイドバーに表示も有効にすると楽になります。
キャプションを入力できます

デバイスの追加方法

ESPHomeを開いてNEW DEVICEをクリックし任意の名前を付けて保存することでデバイスを追加できます。
そうして出力されたYAMLファイルをいじりながら好きなようにカスタマイズすることが可能です。
以下にBLEを使用する際のYAMLファイルを乗せときます。
自分はこれでドアの開閉状況を検知しています。

sensor: - platform: ble_client type: characteristic id: door_sensor name: "Door Sensor" ble_client_id: door_ble_client service_uuid: "123F" # ドアサービスUUID(16進数を文字列で指定) characteristic_uuid: "234F" # ドアキャラクタリスティックUUID notify: true icon: "mdi:door" - platform: ble_client type: characteristic id: battery_level name: "Battery Level" ble_client_id: door_ble_client service_uuid: "180F" # バッテリーサービスUUID characteristic_uuid: "2A19" # バッテリーレベルキャラクタリスティックUUID notify: true unit_of_measurement: "%" accuracy_decimals: 0 icon: "mdi:battery" binary_sensor: - platform: template name: "Door Status" lambda: |- if (id(door_sensor).state == 1) { return true; // ドアが閉まっている } else { return false; // ドアが開いている } device_class: door ble_client: - mac_address: "CE:A5:FD:BA:41:58" # BLEデバイスのMACアドレスを指定 id: door_ble_client

ドアセンサーコントロールボード

SPRENSENSE側の処理

  1. ガスセンサーの動作確認
    Adafruit_BME680ライブラリーを用いて動作確認します。
    https://github.com/adafruit/Adafruit_BME680/tree/master
    基本的にはライブラリーのexampleを参考に書いただけです。

BME680テストプログラム

#include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME680.h> #define BME680_I2C_ADDR 0x77 Adafruit_BME680 bme; void setup() { Serial.begin(115200); while (!Serial); // シリアル通信が開くまで待機 Serial.println("BME680 センサーの初期化中..."); if (!bme.begin(BME680_I2C_ADDR)) { Serial.println("BME680の初期化に失敗しました。接続を確認してください!"); while (1); } // センサーの設定 bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_2X); bme.setPressureOversampling(BME680_OS_4X); bme.setIIRFilterSize(BME680_FILTER_SIZE_3); bme.setGasHeater(320, 150); } void loop() { Serial.println("データ取得中..."); // 測定リクエスト if (!bme.performReading()) { Serial.println("センサーデータの取得に失敗しました!"); return; } // データ表示 Serial.print("温度: "); Serial.print(bme.temperature); Serial.println(" °C"); Serial.print("湿度: "); Serial.print(bme.humidity); Serial.println(" %"); Serial.print("気圧: "); Serial.print(bme.pressure / 100.0); Serial.println(" hPa"); Serial.print("ガス抵抗値: "); Serial.print(bme.gas_resistance / 1000.0); Serial.println(" kΩ"); Serial.println("------------------------------------"); delay(2000); }
  1. 実行結果
    BME680実行結果

  2. BLEデバイスの動作確認
    こちらはTomonobuHayakawa様が出してるBLE用exampleを使用して動作確認します。今回はESP32がセントラルのためSPRESENSE側はペリフェラルになります。
    https://github.com/TomonobuHayakawa/BLE1507_Arduino

SPRESENSE側のコード

#include <Wire.h> #include "Adafruit_BME680.h" #include "BLE1507.h" #define UUID_SERVICE 0xFFF0 #define UUID_CHAR 0xFFF1 static BT_ADDR addr = {{0x19, 0x84, 0x06, 0x14, 0xAB, 0xCD}}; static char ble_name[BT_NAME_LEN] = "SPRESENSE-GAS-INT"; Adafruit_BME680 bme; BLE1507 *ble; void setup() { Wire.begin(); if (!bme.begin(0x77)) { // センサ初期化失敗時の処理 while (true) { sleep(1); } } // BME680設定 (必要に応じて) bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_4X); bme.setPressureOversampling(BME680_OS_4X); bme.setIIRFilterSize(BME680_FILTER_SIZE_3); bme.setGasHeater(320, 150); // BLE初期化 ble = BLE1507::getInstance(); ble->begin(ble_name, addr, UUID_SERVICE, UUID_CHAR); } void loop() { // BME680計測 if (!bme.performReading()) { sleep(1); return; } // ガス抵抗[Ω] → kΩ float gas_kohm = bme.gas_resistance / 1000.0f; // 例: kΩを 0.1kΩ刻みにスケーリング (10.2kΩ → 102) // 16ビット(0~65535)に収める uint16_t gas_scaled = (uint16_t)(gas_kohm * 10.0f + 0.5f); // BLE1507は「writeNotify(uint8_t* data, uint32_t size)」のみ // 2バイトの整数を送る ble->writeNotify((uint8_t*)&gas_scaled, 2); printf("Gas=%.1f kΩ => scaled=%u\n", gas_kohm, gas_scaled); sleep(1); }

YAML

sensor: - platform: ble_client type: characteristic id: door_sensor name: "Door Sensor" ble_client_id: door_ble_client service_uuid: "123F" # ドアサービスUUID characteristic_uuid: "234F" # ドアキャラクタリスティックUUID notify: true icon: "mdi:door" - platform: ble_client type: characteristic id: battery_level name: "Battery Level" ble_client_id: door_ble_client service_uuid: "180F" # バッテリーサービスUUID characteristic_uuid: "2A19" # バッテリーレベルキャラクタリスティックUUID notify: true unit_of_measurement: "%" accuracy_decimals: 0 icon: "mdi:battery" # ガス抵抗 (kΩ) を受け取る - platform: ble_client type: characteristic id: gas_level ble_client_id: spresense_ble_client service_uuid: "FFF0" characteristic_uuid: "FFF1" notify: true name: "Gas Value" unit_of_measurement: "kΩ" accuracy_decimals: 2 binary_sensor: - platform: template name: "Door Status" lambda: |- if (id(door_sensor).state == 1) { return true; // ドアが閉まっている } else { return false; // ドアが開いている } device_class: door ble_client: - mac_address: "CE:A5:FD:BA:41:58" # ドアセンサのMACアドレス id: door_ble_client - mac_address: "CD:AB:14:06:84:19" # SPRESENSEのMACアドレス(例) id: spresense_ble_client

実行結果

キャプションを入力できます

ログインしてコメントを投稿する