ESP32でBLEデバイスを自作する方法!ArduinoIDEで作るBluetooth温湿度センサー入門ガイド
「Bluetoothでデータを飛ばすデバイスって、自分でも作れるの?」
そう思ったことがある方、いるんじゃないでしょうか。実はESP32とArduino IDEを使えば、BLE(Bluetooth Low Energy)対応のIoTデバイスが意外とサクッと作れちゃいます。
今回はDHT22温湿度センサーで取得したデータをBLEで飛ばす仕組みを、ゼロから一緒に作っていきましょう!シリアル通信やWi-Fi通信とはひと味違う、無線BLE通信の世界を体験してみてください。
📌 この記事の対象読者
- Arduino IDEでの開発経験がある方(初〜中級者)
- ESP32を使ってみたいけどBLEは未経験な方
- Wi-Fiを使わずにBluetoothでデータを送りたい方
BLEって何?Wi-Fiと何が違うの?

まずざっくり整理しておきましょう。
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コースや電子部品もまとめています。
📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。





