🔔 ESP32で実現!高性能DIYガラス破壊センサーの作成ガイド:ピエゾ素子と信号処理の極意

【DIY】ホームセーフティ実践

はじめに:なぜピエゾ素子とESP32なのか?

自宅やガレージ、大切な工作物を守るためのセキュリティシステムは、市販品もありますが、自分の手で作ることに大きな価値があります。特にガラス破壊を検知するセンサーは、誤作動が少なく、コスト効率が良いことが求められます。

本記事で核となるのは、圧電サウンダー(ピエゾ素子)とESP32です。

  • 圧電素子(ピエゾ): ガラスが割れる瞬間に発生する微細で鋭い高周波振動を、正確に電気信号(電圧)に変換する能力に優れています。安価で設置が容易なため、ガラス破壊センサーのセンサー部として最適です。
  • ESP32: 高速な A/Dコンバータ(ADC) と強力な処理能力を持つため、微弱なアナログ信号を高速でサンプリングし、複雑なデジタル処理(ノイズとの識別)を行うのに理想的です。Wi-Fi/Bluetooth機能は、将来的にスマートフォン通知などへの拡張を容易にします。

この記事では、ピエゾ素子の微弱な信号をESP32が正確に捉え、他のノイズと区別してアラーム(ブザー)を鳴らすまでの ハードウェア(回路)ソフトウェア(プログラム) のすべてを、詳細な回路図とコードで解説します。


ステップ1:システムの全体設計と必要な部品

自作ガラス破壊センサーのシステムは、大きく以下の3つのブロックで構成されます。

  1. センサー部: 圧電サウンダー。
  2. 信号処理部 (アナログ): オペアンプとRCフィルタ回路。
  3. 制御・出力部 (デジタル): ESP32とブザー。

1. 必要な部品リスト

部品名数量役割備考
ESP32 Dev Board1制御・AD変換・ブザー駆動
圧電サウンダー/素子1振動 → 電圧変換小型で感度の高いものが望ましい
オペアンプ1信号増幅とフィルタリングLM358 または TL072推奨(単電源動作)
電解コンデンサ1DCバイアス結合用 (C1)1μF∼10μF
セラミックコンデンサ2フィルタ用 (C_HPF, C_LPF)0.1μF∼0.01μF
抵抗5-6バイアス、ゲイン調整、フィルタリング用1kΩ および 10kΩ 系統
ブザー/圧電スピーカー1アラーム出力アクティブブザー(電源接続で鳴動)が簡単
トランジスタ1ブザー駆動用NPN型(例:2SC1815)


ステップ2:信号処理回路の極意(ノイズフィルタと増幅)

圧電素子の最大の課題は、その出力信号が非常に微弱(mVレベル)であり、かつノイズが大量に含まれていることです。ESP32のADCに直接入力しても、ノイズに埋もれてしまい、ガラス破壊と風の揺れを区別できません。

そこで、オペアンプを使用したアクティブ・バンドパスフィルタ付き非反転増幅器を構築します。

1. 回路の設計思想

ガラス破壊時に発生する振動・音響信号は、通常数kHzの高周波成分を多く含みます。一方、風、車の通過、通常のドアの開閉による振動は数十Hz〜数百Hzの低周波成分が主です。

  • 目的: 不要な低周波ノイズをカットし、高周波の破壊信号を特異的に増幅する。

2. 圧電素子信号処理回路図

この回路は、単一の電源(ESP32の3.3Vまたは5V)で動作するように設計されています。

3. 各部の詳細解説と定数の目安

A. バイアス回路と入力結合

  • 抵抗 RA​,RB​(例: 10kΩ):
    • オペアンプの非反転入力(+端子)を電源電圧の半分(3.3V電源の場合1.65V)に固定するDCバイアスを生成します。ESP32のADCが負の電圧を読み取れないため、信号を0V∼3.3Vの範囲に持ち上げるために必須です。
  • コンデンサ C1(例: 1μF):
    • 圧電素子の出力はAC信号ですが、バイアス電圧にそのまま入力すると、電源電圧と素子のDCオフセットが干渉します。C1は素子のDC成分をカットし、AC信号のみをバイアス基準(1.65V)に入力します。

B. 非反転増幅器とゲイン設定

  • 増幅率(ゲイン G): G=1+RGain​RF​​
    • 圧電素子の信号の最大振幅(例:数mV〜数十mV)を、ESP32のADCの最大電圧(3.3V)を超えないレベル(例:ピークtoピークで3V程度)に調整します。
    • 例:素子の最大出力が10mV、目標ゲインが100倍なら、RF​=99kΩ、RGain​=1kΩ と設定します。

C. ノイズフィルタリングの組み込み

フィルタ機能は、増幅回路の帰還ループにコンデンサを追加することで実現します。

  1. ハイパスフィルタ(HPF)機能(低周波ノイズの除去)
    • RGain​ に並列なコンデンサ CHPF​(例: 0.1μF) を追加します。
    • 低い周波数では CHPF​ が高抵抗となるため、増幅率 G は高くなりません。高い周波数になるほど CHPF​ のインピーダンスが下がり、G が上昇します。
    • これにより、低周波ノイズの増幅を抑制し、ガラス破壊特有の高周波成分のみを強調して増幅できます。
    • 遮断周波数 fc​ (Hz): fc​=2π⋅RGain​⋅CHPF​1​
  2. ローパスフィルタ(LPF)機能(高周波ノイズの除去)
    • RF​ に並列なコンデンサ CLPF​(例: 0.01μF) を追加します。
    • オペアンプのノイズやESP32のクロックノイズなど、非常に高い周波数(数10kHz以上)のノイズを除去し、信号を滑らかにします。

ステップ3:ESP32での信号の受け取りと判定ロジック

ハードウェアで増幅・フィルタリングされた信号は、ESP32のADCピンに入力されます。ソフトウェアの役割は、 「現在のノイズレベル」「瞬間的なピーク」 を比較し、閾値を超えた場合にのみアラームを作動させることです。

1. ブザー駆動回路

ブザーはESP32のGPIOピンから直接駆動すると電流不足になる可能性があるため、NPNトランジスタを使ったスイッチング回路を推奨します。

  • 接続:
    • ESP32のGPIO 2 → トランジスタのベース (B)(間に1kΩ程度の抵抗を入れる)
    • ブザー → トランジスタのコレクタ (C)電源 (3.3V/5V)
    • トランジスタのエミッタ (E)GND

2. デジタル処理のロジック

  1. ベースラインの確立: センサーに何も入力されていない状態での平均的なADC値を「ベースライン」として把握します(通常、バイアス電圧であるADC値の中間値付近になります)。
  2. 高速サンプリング: loop()関数内で可能な限り高速にADC値を読み取ります。
  3. 差分の計算: 読み取った値とベースラインの絶対差分を計算します。
  4. ピーク値監視: 短い時間窓(例:2ミリ秒)内で、この差分の 最大値(ピーク) を検出します。
  5. 破壊判定: このピーク値が事前に設定した 「破壊閾値」 を大幅に超えた場合に、ガラス破壊と判定し、ブザーを鳴らします。

ステップ4:ESP32 プログラム(ブザー鳴動版)

以下のプログラムは、前述のロジックに基づき、センサー値を読み取り、閾値を超えた場合にブザーを鳴らすシンプルなコードです。

C++

// ----------------------------------------------------
// ESP32 ガラス破壊センサー - ブザー駆動プログラム
// ----------------------------------------------------

// センサーとブザーのピン設定
const int SENSOR_ADC_PIN = 34; // センサー信号入力(ADC1のピン)
const int ALARM_BUZZER_PIN = 2; // ブザー駆動ピン(トランジスタのベースへ)

// ----------------------------------------------------
// ガラス破壊検知パラメーター (環境に合わせて調整必須)
// ----------------------------------------------------
// 破壊と判断するADC値の最小変化量(0-4095)。
// この値が小さいほど感度が上がり、誤作動しやすくなる。
const int ADC_THRESHOLD = 600; 
                               
// ピーク値を監視する時間窓 (ms)。ガラス破壊は瞬間的なため、短く設定。
const int READ_WINDOW_MS = 2; 

// 一度アラームが鳴った後の待機時間(チャタリング防止)
const int DEBOUNCE_TIME_MS = 5000; 

// 実行時に動的に更新される変数
volatile int baselineADC = 0; // センサーの静止時の基準値

// ----------------------------------------------------
// ブザー鳴動関数
// ----------------------------------------------------
void activateBuzzer(bool state) {
  // HIGHでトランジスタON -> ブザー鳴動
  digitalWrite(ALARM_BUZZER_PIN, state ? HIGH : LOW); 
}

// ----------------------------------------------------
// 初期設定
// ----------------------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(ALARM_BUZZER_PIN, OUTPUT);
  activateBuzzer(false); // 初期はブザーOFF

  // ----------------------------------------------------
  // センサーの初期ベースライン取得とADC設定
  // ----------------------------------------------------
  
  // ESP32のADCはデフォルトで12bit(0-4095)
  // 起動時のノイズレベルをベースラインとする
  long tempBaseline = 0;
  for (int i = 0; i < 200; i++) {
    tempBaseline += analogRead(SENSOR_ADC_PIN);
    delay(5);
  }
  baselineADC = tempBaseline / 200;
  
  Serial.print("Initial Sensor Baseline (ADC): ");
  Serial.println(baselineADC);
  Serial.print("Detection Threshold (Absolute Diff): ");
  Serial.println(ADC_THRESHOLD);
  Serial.println("System Armed. Monitoring started...");
}

// ----------------------------------------------------
// メインループ
// ----------------------------------------------------
void loop() {
  static unsigned long lastAlarmTime = 0;
  
  // アラーム鳴動中は検知ロジックをスキップ
  if (millis() - lastAlarmTime < DEBOUNCE_TIME_MS) {
    delay(50);
    return;
  }

  // 高速サンプリングのための時間窓設定
  unsigned long startTime = millis();
  int currentPeakDifference = 0;

  // 短い時間窓内で最大のADC値とベースラインとの差分を検出
  while (millis() - startTime < READ_WINDOW_MS) {
    int sensorValue = analogRead(SENSOR_ADC_PIN);
    
    // バイアス電圧からの最大差分(振幅)を検出する
    int diff = abs(sensorValue - baselineADC);
    
    if (diff > currentPeakDifference) {
      currentPeakDifference = diff;
    }
    // ADCの読み取り速度を上げるために delay(0) や yield() は使用しない
  }

  // 破壊判定ロジック
  if (currentPeakDifference > ADC_THRESHOLD) {
    Serial.println("==========================================");
    Serial.print(">>> 💥 GLASS BREAK DETECTED! Peak Diff: ");
    Serial.println(currentPeakDifference);
    Serial.println("==========================================");
    
    // ブザー作動
    activateBuzzer(true);
    lastAlarmTime = millis();
    
    // アラームが鳴っている間にベースラインを大きく更新しないようにする
    
    // --- アラーム鳴動時間 ---
    delay(3000); // 3秒間ブザーを鳴らす
    
    // ブザー停止
    activateBuzzer(false);
    
    // 再び静かになった後、新しいベースラインを測定し直す
    long tempBaseline = 0;
    for (int i = 0; i < 50; i++) {
        tempBaseline += analogRead(SENSOR_ADC_PIN);
        delay(10);
    }
    baselineADC = tempBaseline / 50;
    Serial.print("Baseline updated to: ");
    Serial.println(baselineADC);
  }
  
  // 通常のループ処理速度を調整
  delay(10); 
}

ステップ5:調整と設置のヒント

自作センサーの性能は、主にアナログ回路の定数ソフトウェアの閾値に依存します。

1. 閾値(ADC_THRESHOLD)の調整方法

この値は、誤作動を防ぎ、必要な振動だけを捉えるための最も重要なパラメーターです。

  1. 通常ノイズの測定: センサーを窓枠に貼り付け、普段の生活音や風による揺れがある状態で、Serial.println(currentPeakDifference); を使って通常時の最大ピーク差分を測定します。
  2. 破壊模擬テスト: 指でガラスを軽く叩く、またはガラスの端を硬いもので叩くなど、破壊に近い振動を与え、その際のピーク差分を測定します。
  3. 閾値設定:
    • ADC_THRESHOLD = (破壊模擬テストのピーク値) と (通常ノイズの最大ピーク値) の中間よりやや上に設定します。
    • 例:通常ノイズの最大が200、破壊模擬テストのピークが1200の場合、閾値は600〜800程度に設定すると良いでしょう。

2. 回路定数の微調整

もし、増幅回路の出力がノイズばかりでベースライン付近で揺れすぎている場合、フィルタの定数を見直します。

  • 低周波ノイズが強い場合: $C_{HPF}$の値を小さくし、遮断周波数 fc​ を高くしてください(例: 0.1μF→0.047μF)。これにより、低周波ノイズがさらに減衰し、高周波の信号が際立ちます。
  • 信号が弱すぎる場合: RF​ の値を大きくするか、RGain​ の値を小さくし、ゲイン G を上げてください。ただし、ADCの最大値(4095)を超えないように注意が必要です。

3. 設置場所

  • ガラス直貼り: ピエゾ素子を窓ガラスの隅に両面テープや接着剤で密着させて貼り付けます。振動を最も効率よく拾えます。
  • 窓枠への設置: 窓枠(サッシ)の振動を拾う形での設置も有効です。

まとめ:自作センサーの可能性と拡張

ESP32と圧電サウンダーを使ったガラス破壊センサーの自作は、単なる工作以上の技術的な理解を深めます。特に、アナログ信号をデジタルシステムで扱う際のノイズフィルタリングと増幅の重要性を実体験できます。

このシステムは、非常に安価で高性能なセキュリティの核となります。さらに、ESP32の持つ強力な機能を使えば、以下のような拡張も可能です。

  • Wi-Fi通知: アラーム作動時に、ESP32を自宅のWi-Fiに接続し、LINEMQTTを通じてスマートフォンに通知を送る。
  • SDカードロギング: 破壊イベントが発生した時刻とセンサーのピーク値をSDカードに記録し、後で確認できるようにする。

市販のセンサーでは得られない柔軟性と学習機会が、このDIYプロジェクトには詰まっています。ぜひ、この記事を参考に、あなただけの高性能なガラス破壊センサーを完成させてください!

タイトルとURLをコピーしました