0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

離床センサーの作り方

Posted at

作成の背景

前職で介護士として勤務していた際、現場で使用していた離床センサーなどの組み込み機器に課題を感じ、自ら開発に携わりたいと考えるようになりました。
その後、会社の研修でマイコン講座を受講し、基礎的な開発スキルを習得したことをきっかけに、実践的なアウトプットとして離床センサーの開発に取り組みました。

環境

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/
{60F2C922-44FD-41E0-B999-B566C376D56A}.png
※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
{993308AC-C4FF-4368-B25F-373CF3F845E2}.png

2_3.「Tools」->「Board」->「Boards Manager」を開く。
{1B3C92ED-FE03-456D-B95D-73386483A523}.png

2_4.「esp32」と検索し、表示された「esp32 by Espressif Systems」をインストールする。
{9E7D86A2-D24A-4609-8878-4BA03CC35871}.png

2-5.ESP32をUSBケーブルでPCに接続する。

2_6.「Tools」->「Board」->「esp32」->「ESP32-WROOM-DA Module」を選択する。
{845F8696-D0CD-47E3-B9CC-7A6414505BBE}.png

2_7.「Tools」->「Ports」->「COM3」を選択する。
{FE0F75B4-F6CE-4999-8D60-6657EB625698}.png

3. IFTTTアプリのインストール(スマホ)

3_1.App Storeから「IFTTT」と検索し、IFTTTアプリをダウンロードする。
1.png

3_2.IFTTTアプリを開き任意の方法でログインする。

3_3.下のタブから「作成する」を押下する。
13.png

3_4.「If This」を押下した後に「Webhooks」と検索し、「Webhooks」を選択する。
14.png
12.png

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

3_6.イベント名を入力し、「トリガーの作成」を押下する。
10.png

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

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

3_9.「続ける」を押下した後に「終了する」を押下する。
6.png
IMG_5.png

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

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: 共通化必須

拝殿.jpeg

実装

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);
}

image.png

2.「Ctr + S」で名前をつけて保存する。
image.png

3.USBケーブルでESP32をPCに接続する。

4.左上のUploadボタン(→ボタン)を押下する
image.png
image.png

5.「Tools」->「Serial Monitor」を開き、115200ボーレートに設定する。
image.png

テスト

前提条件
  1. 上記の事前準備・配線・実装を完了していること
  2. ESP32 が正しく Wi-Fi に接続されていること
  3. IFTTT の Webhook キーとイベント名がコード内と一致していること
  4. センサーがベッド付近の適切な位置に固定されていること
  5. スマートフォンで IFTTT アプリの通知が有効になっていること
操作手順1

センサーの検知範囲内に人がいる状態で動作を開始する。

期待値1

Arduinoで人との距離を測定できること。
image.png

操作手順2

その後、センサーが人を検知できない位置まで離れる。

期待値2
  • エディタ上で「IFTTT sent.」と表示されること。
    スクリーンショット 2025-11-15 145128.png
  • 同時にスマートフォンに IFTTT 通知が届くこと。
    前.jpeg
    後.png

今後の展望

本離床センサーでは、離床検知の基本動作とIFTTT通知までを実現しました。
今後は「NTCR」要件をさらに満たし、より実用的かつ信頼性の高いシステムへ発展させていくことを目指します。

N(Navigation / 精度):

センサーの検知範囲と精度を向上させる。
たとえば、超音波センサーに加えて赤外線センサーや複数点測定を組み合わせ、誤検知を低減する。

T(Timing / リアルタイム性):

離床検知の反応時間を短縮し、ハードリアルタイム処理を意識した設計に改善する。
割り込み処理(interrupt)やFreeRTOSタスク制御を活用して遅延を最小化する。

C(Cost / 消費資源):

消費電力とメモリ使用量を最適化する。
Deep Sleepモードや軽量データ処理アルゴリズムを導入し、バッテリー駆動でも安定動作を目指す。

R(Reliability / 信頼性):

高信頼性が求められる医療・介護用途(特定管理医療機器)を意識し、
冗長化・フェイルセーフ設計や異常検知ロジックの導入を検討する。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?