「Bluetoothでデータを飛ばすデバイスって、自分でも作れるの?」

そう思ったことがある方、いるんじゃないでしょうか。実はESP32とArduino IDEを使えば、BLE(Bluetooth Low Energy)対応のIoTデバイスが意外とサクッと作れちゃいます。

今回はDHT22温湿度センサーで取得したデータをBLEで飛ばす仕組みを、ゼロから一緒に作っていきましょう!シリアル通信やWi-Fi通信とはひと味違う、無線BLE通信の世界を体験してみてください。

📌 この記事の対象読者

  • Arduino IDEでの開発経験がある方(初〜中級者)
  • ESP32を使ってみたいけどBLEは未経験な方
  • Wi-Fiを使わずにBluetoothでデータを送りたい方

BLEって何?Wi-Fiと何が違うの?

ESP32 bluetooth sensor
ESP32 bluetooth sensor / Photo by Bmonster Lab via Pexels

まずざっくり整理しておきましょう。

BLE(Bluetooth Low Energy)は、名前のとおり「省電力なBluetooth」です。スマートウォッチや体温計、IoTセンサーによく使われています。Wi-Fiと比べると通信距離は短め(〜10m程度)ですが、消費電力が極めて少ないのが大きな特徴です。

イメージとしてはこんな感じです。

  • 📡 Wi-Fi:インターネットにつながる・遠くまで飛ぶ・消費電力大
  • 🔵 BLE:近距離で端末と直接やりとり・消費電力が超小さい・IoT向き

ESP32はWi-FiとBLEの両方を内蔵しているすごいマイコンボードです。今回はそのBLE機能をフル活用します。

用意するもの

必要な部品はシンプルです。

  • ESP32開発ボード(ESP32-DevKitCなど)
  • DHT22温湿度センサー(DHT11でも代用可)
  • 10kΩ抵抗(プルアップ用)
  • ✅ ブレッドボード・ジャンパワイヤ
  • ✅ USBケーブル(データ転送対応のもの)
  • ✅ Arduino IDE(ESP32ボードパッケージ導入済み)

Arduino IDEへのESP32ボードパッケージの追加がまだの方は、ボードマネージャで https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json を追加してからインストールしてください。

配線図

DHT22とESP32の接続はとてもシンプルです。

  • DHT22のVCC → ESP32の3.3V
  • DHT22のGND → ESP32のGND
  • DHT22のDATA → ESP32のGPIO4(10kΩ抵抗でVCCにプルアップ)

DHT22のDATAピンとVCCの間に10kΩ抵抗を挟むのを忘れずに。これがないと通信が不安定になります。

ライブラリのインストール

Arduino IDEのライブラリマネージャから以下をインストールしてください。

  • DHT sensor library(Adafruit製)
  • Adafruit Unified Sensor(依存ライブラリ)

BLE関連のライブラリはESP32ボードパッケージに最初から同梱されています。追加インストール不要なのが嬉しいですね。

BLEの基本的な仕組みを先に理解しよう

コードを書く前に、BLEの用語を少しだけ押さえておきましょう。ここがわかると、コードの構造がグッとクリアになります。

  • 🏠 サービス(Service):機能のグループ。「温湿度計サービス」のようなくくり
  • 📋 キャラクタリスティック(Characteristic):実際のデータの入れ物。温度用・湿度用とそれぞれ作る
  • 🔑 UUID:サービスやキャラクタリスティックを識別するIDのこと

つまり「サービスの中にキャラクタリスティックが入っている」という入れ子構造です。スマホのBLEスキャナアプリで見ると、この構造がそのまま見えます。

ESP32 BLE温湿度センサーのコード

では実際にコードを書いていきましょう!ポイントは以下のとおりです。

  • 温度・湿度をそれぞれ別のキャラクタリスティックで送る
  • 5秒おきにセンサーを読み取ってBLEの値を更新する
  • notify機能を使い、接続中のスマホに自動で新しい値を通知する
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <DHT.h>

// --- ピン設定 ---
#define DHTPIN 4        // DHT22のDATAピンをGPIO4に接続
#define DHTTYPE DHT22   // DHT22を使用(DHT11の場合はDHT11に変更)

// --- BLE UUID(自分で自由に決めてOK。他デバイスと重ならない値を使う)---
#define SERVICE_UUID        "12345678-1234-1234-1234-1234567890ab"
#define TEMP_CHAR_UUID      "12345678-1234-1234-1234-1234567890ac"  // 温度用
#define HUMID_CHAR_UUID     "12345678-1234-1234-1234-1234567890ad" // 湿度用

DHT dht(DHTPIN, DHTTYPE);

BLEServer* pServer = nullptr;
BLECharacteristic* pTempCharacteristic = nullptr;
BLECharacteristic* pHumidCharacteristic = nullptr;

bool deviceConnected = false;

// --- 接続・切断イベントを検知するコールバック ---
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("クライアントが接続しました!");
  }
  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("クライアントが切断しました。アドバタイズ再開...");
    pServer->startAdvertising(); // 切断後も自動で再スキャン可能にする
  }
};

void setup() {
  Serial.begin(115200);
  dht.begin();

  // BLEデバイスの初期化(デバイス名を設定)
  BLEDevice::init("ESP32-TempHumid-BLE");

  // BLEサーバーを作成してコールバックをセット
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // サービスを作成
  BLEService* pService = pServer->createService(SERVICE_UUID);

  // 温度用キャラクタリスティックを作成(読み取り+通知対応)
  pTempCharacteristic = pService->createCharacteristic(
    TEMP_CHAR_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
  );
  pTempCharacteristic->addDescriptor(new BLE2902()); // NOTIFY有効化に必要

  // 湿度用キャラクタリスティックを作成
  pHumidCharacteristic = pService->createCharacteristic(
    HUMID_CHAR_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
  );
  pHumidCharacteristic->addDescriptor(new BLE2902());

  // サービスを開始
  pService->start();

  // アドバタイズ開始(スマホからスキャンできるようにする)
  BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->start();

  Serial.println("BLEアドバタイズ開始!スマホからスキャンしてみてください。");
}

void loop() {
  delay(5000); // 5秒待機

  float temp = dht.readTemperature();  // 温度(℃)を取得
  float humid = dht.readHumidity();    // 湿度(%)を取得

  // センサー読み取りエラーチェック
  if (isnan(temp) || isnan(humid)) {
    Serial.println("センサーの読み取りに失敗しました。配線を確認してください。");
    return;
  }

  Serial.printf("温度: %.1f℃  湿度: %.1f%%\n", temp, humid);

  // 値を文字列に変換してキャラクタリスティックにセット
  String tempStr = String(temp, 1);   // 例: "24.5"
  String humidStr = String(humid, 1); // 例: "58.3"

  pTempCharacteristic->setValue(tempStr.c_str());
  pHumidCharacteristic->setValue(humidStr.c_str());

  // 接続中のクライアントに通知(notify)を送る
  if (deviceConnected) {
    pTempCharacteristic->notify();
    pHumidCharacteristic->notify();
    Serial.println("BLEでデータを送信しました!");
  }
}

コードのポイントをまとめるとこんな感じです。

  • 🔵 BLEDevice::init() でデバイス名を設定 → スマホのスキャン時にこの名前が見える
  • 🔵 PROPERTY_READ | PROPERTY_NOTIFY でスマホから読み取り&自動通知の両方に対応
  • 🔵 BLE2902 ディスクリプタを追加しないとNOTIFYが動かないので要注意!
  • 🔵 切断時に startAdvertising() を再実行することで、スマホから何度でも再接続できる

スマホで受信してみよう


コードをESP32に書き込んだら、スマホでBLEスキャンアプリを起動してみましょう。

おすすめのアプリはこちらです。

  • 📱 nRF Connect for Mobile(iOS / Android どちらも対応・無料)
  • 📱 BLE Scanner(Android向け・シンプルで使いやすい)

アプリを起動してスキャンすると、「ESP32-TempHumid-BLE」という名前のデバイスが見つかるはずです。接続するとサービスとキャラクタリスティックが表示され、温度・湿度の値が読み取れます。

NOTIFYを有効にすれば、5秒おきに自動で新しいデータがスマホに届きます。これがBLEの醍醐味ですね 😊

シリアルモニタの確認もしておこう

Arduino IDEのシリアルモニタ(ボーレート115200)を開くと、動作ログが流れてきます。スマホとの接続・切断も確認できるので、デバッグにも役立ちます。

BLEアドバタイズ開始!スマホからスキャンしてみてください。
クライアントが接続しました!
温度: 24.5℃  湿度: 58.3%
BLEでデータを送信しました!
温度: 24.6℃  湿度: 58.1%
BLEでデータを送信しました!

こんなログが流れてきたら成功です 🎉

うまく動かないときのチェックポイント


詰まりやすいポイントをまとめておきます。

  • スマホにデバイスが表示されない → ボードの選択が「ESP32 Dev Module」になっているか確認。書き込み後にリセットボタンを押してみる
  • センサーが「NaN」を返す → 配線とプルアップ抵抗を確認。DHT22はVCCに3.3Vを使うこと
  • NOTIFYが来ないBLE2902 ディスクリプタが追加されているか確認
  • 再接続できないonDisconnect 内で startAdvertising() を呼んでいるか確認

まとめ

今回はESP32とDHT22を使って、BLE対応の温湿度センサーデバイスをArduino IDEでゼロから作る方法を解説しました。

ポイントをおさらいすると、

  • 🔵 BLEは「サービス → キャラクタリスティック」という入れ子構造でデータを管理する
  • 🔵 PROPERTY_NOTIFY を使うと、スマホに自動でデータを送れる
  • 🔵 切断後も startAdvertising() で再接続を受け付けられる

Wi-Fiなしでスマホにデータを飛ばせるって、なんかワクワクしますよね。バッテリー駆動の小型センサーノードを作るときにも BLE は大活躍します。

まずは今回のコードをそのまま動かしてみて、動いたらUUIDを変えたり、センサーを追加したりして自分だけのBLEデバイスにカスタマイズしてみてください!ぜひ試してみてくださいね 🚀

📡 Arduinoをもっと深く学ぼう!

Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。

Arduinoロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。