作成の背景
前職で介護士として勤務していた際、現場で使用していた離床センサーなどの組み込み機器に課題を感じ、自ら開発に携わりたいと考えるようになりました。
その後、会社の研修でマイコン講座を受講し、基礎的な開発スキルを習得したことをきっかけに、実践的なアウトプットとして離床センサーの開発に取り組みました。
環境
PC:Windows11
マイコン:ESP32-DevKitC
センサー:HC-SR04 超音波距離センサー
開発環境:Arduino IDE 2.3.6
使用言語:C++, Arduino
通知アプリ:IFTTT 4.97.0
事前準備
1. 部品の購入
Amazonにて以下の機材を購入する。
・ESP32
https://www.amazon.co.jp/dp/B0C9TGJRPH?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
・測定センサモジュール
https://www.amazon.co.jp/dp/B0CPVDX544?ref=ppx_yo2ov_dt_b_fed_asin_title
・抵抗 セット
https://www.amazon.co.jp/dp/B0D58FXVBL?ref=ppx_yo2ov_dt_b_fed_asin_title
・ブレッドボードジャンパーワイヤー
https://www.amazon.co.jp/dp/B0FCFJ6JFD?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
・ブレッドボード
https://www.amazon.co.jp/dp/B0C3TNP1RG?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
2. Arduino IDE、ESP32ボードの設定(PC)
2_1.以下のサイトを参考にしてArduino IDEをインストール
https://www.indoorcorgielec.com/resources/arduinoide%E8%A8%AD%E5%AE%9A/arduino-ide%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%A8%E8%A8%AD%E5%AE%9A/

※Arduino IDE バージョン:2.3.6
2_2.Arduino IDEから「File」->「Preferences」を開き、「Additional boards manager URLs」に以下のURLを入力する。
URL:https://dl.espressif.com/dl/package_esp32_index.json

2_3.「Tools」->「Board」->「Boards Manager」を開く。

2_4.「esp32」と検索し、表示された「esp32 by Espressif Systems」をインストールする。

2-5.ESP32をUSBケーブルでPCに接続する。
2_6.「Tools」->「Board」->「esp32」->「ESP32-WROOM-DA Module」を選択する。

2_7.「Tools」->「Ports」->「COM3」を選択する。

3. IFTTTアプリのインストール(スマホ)
3_1.App Storeから「IFTTT」と検索し、IFTTTアプリをダウンロードする。

3_2.IFTTTアプリを開き任意の方法でログインする。
3_4.「If This」を押下した後に「Webhooks」と検索し、「Webhooks」を選択する。


3_5.「Receive a web request」を選択し、「接続する」を押下する。


3_7.「Then That」を押下した後に「Notifications」と検索し、「Notifications」を選択する。


3_8.「Send a notification from the IFTTT app」を選択し、「アクションを作成する」を押下する。


3_10.「私のアブレット」から作成したイベントを選択し、「Documentation」を押下する。

3_11.「Your key is:」の下に表示されるWebhookキーをメモする。
配線
以下の回路図を参考に配線を行う。
# Bed-Exit Sensor 回路図(ESP32 + HC-SR04)
ESP32 (DevKit)
┌───────────────────────────────────────┐
│ 3V3 (3.3V) │
│ VIN / 5V (USB 5V) → HC-SR04 VCC │
│ GND ↔ HC-SR04 GND │
│ GPIO5 (TRIG) → HC-SR04 TRIG │
│ GPIO18 (ECHO) ← HC-SR04 ECHO via divider │
└───────────────────────────────────────┘
電圧分割回路(ECHO信号保護)
HC-SR04 ECHO ── 10kΩ ──●── 20kΩ ── GND(ESP32共通)
│
└── GPIO18(ESP32)
出力電圧 ≒ 3.3V(5V入力時)
補足:
- TRIGピン: ESP32 から 10µs の HIGH パルスを出力
- ECHOピン: センサーからの反射時間をパルス幅で返す(分圧を通して安全に入力)
- VCC: 5V 推奨(ESP32 の VIN または USB 5V)
- GND: 共通化必須
実装
1.Arduino IDEから「Tools」->「Board」->「esp32」->「ESP32-WROOM-DA Module」を開き、新規スケッチからテキストエディタに以下のコードを実装する。
// インクルード設定
#include <WiFi.h>
#include <esp_http_client.h>
// ネットワーク設定
const char* ssid = "WiFiのSSID名"; // 自身の設定を入力する
const char* password = "SSIDのパスワード"; // 自身の設定を入力する
// IFTTT設定
const char* IFTTT_EVENT = "3_7にて作成したイベント名"; // 自身の設定を入力する
const char* IFTTT_KEY = "3_12にて取得したWebhookキー"; // 自身の設定を入力する
// ピン設定
const int PIN_TRIG = 5;
const int PIN_ECHO = 18;
// パラメータ設定
const float DISTANCE_CM = 100.0; // 離床の距離の設定
const unsigned long STABLE_MS = 2000; // 継続時間の設定
const unsigned long SUPPRESS_MS = 60000; // 通知後のサプレッション設定
// 変数設定
unsigned long belowStrat = 0; // 離床検出開始時間
unsigned long lastNotifyTime = 0; // 最終通知時間
bool isOnBed = true; // ベッド上にいるかどうかの状態(true = ベッド上、false = ベッド外)
// 距離を取得する
float measureDistanceCm() {
// 測定開始信号を出す
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
// pulseIn関数で距離を算出する
unsigned long duration = pulseIn(PIN_ECHO, HIGH,38000UL);
// 距離が離れている場合はタイムアウトする
if (duration == 0) {
return 999.0;
}
// 測定した時間を距離(cm)に変換する
float distance = (duration * 0.0343) / 2.0;
// 距離を返す
return distance;
}
// IFTTT通知を行う
bool sendIFTTT(const char* event, const char* key, String value1 = "") {
// HTTP通信できない場合処理を中断する
if (WiFi.status() != WL_CONNECTED) return false;
// HTTPClientクラスのインスタンスを生成する
HTTPClient http;
// エンドポイントURLの組み立て、接続を初期化する
String url = String("https://maker.ifttt.com/trigger/") + event + "/with/key/" + key;
http.begin(url);
// HTTPヘッダを追加する
http.addHeader("Content-Type", "application/json");
// JSON本文を作成する
String payload = "{\"value1\":\"" + value1 + "\"}";
// HTTP POSTを実行し、リソースを解放する
int code = http.POST(payload);
http.end();
// 成功判定を返す
return (code >= 200 && code < 300);
}
// 通信の初期化を行う
void setup() {
// シリアル通信を初期化する
Serial.begin(115200);
delay(100);
// ピンの設定を行う
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
// WiFi接続を行う
Serial.printf("Connection to WiFi '%s' ...\n", ssid);
WiFi.begin(ssid, password);
// WiFi接続の待機処理を行う
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
delay(500);
Serial.print(".");
}
Serial.println();
// 接続成功した場合、接続状態とIPアドレスを表示する
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi conneted.");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
// 接続失敗した場合、エラーメッセージを表示する
} else {
Serial.println("WiFi connect failed (will retry later).");
}
}
// 距離を5回測定し、中央値を扱う
void loop() {
// 距離を5回測定する
const int SAMPLES = 5;
float vals[SAMPLES];
for (int i = 0; i < SAMPLES; i++) {
vals[i] = measureDistanceCm();
delay(60);
}
// 中央値を算出し、表示する
for (int i = 0; i < SAMPLES - 1; i++) {
for (int j = i + 1; j < SAMPLES; j++) {
if (vals[j] < vals[i]) {
float t = vals[i];
vals[i] = vals[j];
vals[j] = t;
}
}
}
float distance = vals[SAMPLES / 2];
Serial.printf("Distance: %.1f cm\n", distance);
// サプレッション中の通知連打を防止する
unsigned long now = mills();
if (now - lastNotifyTime < SUPPRESS_MS) {
// DISTANCE_CMより近い場合、通知はしないが状態の更新は行う
if (distance < DISTANCE_CM) {
isOnBed = true;
}
delay(200);
return;
}
// DISTANCE_CMより離れているか判定を行う
if (distance >= DISTANCE_CM) {
// はじめて離床を検出した場合は現在時刻でbelowStartを初期化する
if (belowStart == 0) {
belowStart = now;
}
// STABLE_MS以上離れている場合、離床を確定する
if (now - belowStart >= STABLE_MS) {
// ベッド上にいた状態から離れた場合、離床を通知する
if(isOnBed) {
Serial.println("離床検出:sending notification...");
// スマホに距離を送信する
bool ok = sendIFTTT(IFTTT_EVENT, IFTTT_KEY, String("Distance=") + String(distane, 1));
// 送信成功した場合、成功メッセージを表示する
if (ok) {
Serial.println("IFTTT sent.");
// 送信失敗した場合、失敗メッセージを表示し0.5秒待ってリトライする
} else {
Serial.println("IFTTT sendfailed.");
delay(500);
ok = sendIFTTT(IFTTT_EVENT, IFTTT_KEY, String("Retry Distance=") + String(distance, 1));
if (ok) {
Serial.println("IFTTT retry ok.");
}
}
// 状態を更新する
lastNotifyTime = now;
isOnBed = false;
}
belowStart = 0;
}
// STABLE_MSより近い場合、belowStartをリセットしisOnBedをtrueに戻す
} else {
belowStart = 0;
isOnBed = true;
}
delay(250);
}
3.USBケーブルでESP32をPCに接続する。
5.「Tools」->「Serial Monitor」を開き、115200ボーレートに設定する。

テスト
前提条件
- 上記の事前準備・配線・実装を完了していること
- ESP32 が正しく Wi-Fi に接続されていること
- IFTTT の Webhook キーとイベント名がコード内と一致していること
- センサーがベッド付近の適切な位置に固定されていること
- スマートフォンで IFTTT アプリの通知が有効になっていること
操作手順1
センサーの検知範囲内に人がいる状態で動作を開始する。
期待値1
操作手順2
その後、センサーが人を検知できない位置まで離れる。
期待値2
今後の展望
本離床センサーでは、離床検知の基本動作とIFTTT通知までを実現しました。
今後は「NTCR」要件をさらに満たし、より実用的かつ信頼性の高いシステムへ発展させていくことを目指します。
N(Navigation / 精度):
センサーの検知範囲と精度を向上させる。
たとえば、超音波センサーに加えて赤外線センサーや複数点測定を組み合わせ、誤検知を低減する。
T(Timing / リアルタイム性):
離床検知の反応時間を短縮し、ハードリアルタイム処理を意識した設計に改善する。
割り込み処理(interrupt)やFreeRTOSタスク制御を活用して遅延を最小化する。
C(Cost / 消費資源):
消費電力とメモリ使用量を最適化する。
Deep Sleepモードや軽量データ処理アルゴリズムを導入し、バッテリー駆動でも安定動作を目指す。
R(Reliability / 信頼性):
高信頼性が求められる医療・介護用途(特定管理医療機器)を意識し、
冗長化・フェイルセーフ設計や異常検知ロジックの導入を検討する。












