Skip to content

Progress Log: WiFi接続機能の実装検討

Task Description

ESP32-WROOM-32Eに内蔵されているWiFi機能を有効化し、以下の機能実装を検討するための事前評価:

  • WiFi接続機能:スマートフォンやPC等のブラウザから接続可能な設定
  • ブラウザUI:ステータス確認、スレッショルド設定など最小限の管理機能
  • ノイズ対策:WiFi有効時の電磁ノイズ発生可能性と対策方法

Current Architecture Analysis

既存の通信メカニズム

現在のkurikintonsは以下の通信手段を実装済み:

  • Serial Protocol (UART):115200 baud固定、コマンド/レスポンス形式
  • Binary protocol (ENABLE_TEXT_PROTOCOL=0):3バイトDACコマンド形式
  • Text protocol (ENABLE_TEXT_PROTOCOL=1):人間が読める形式(開発用)
  • SPI DAC Control:スレッショルド設定用(3チャネル独立)

モジュール構成

src/
├── serial_protocol.cpp      # UART通信(バイナリ/テキスト)
├── text_command_handler.cpp # テキストコマンド処理(10項目FIFO)
├── sensor_formatter.cpp      # センサデータ出力フォーマット(SSV/TSV/CSV/JSONL)
├── cosmic_detector.cpp       # 検出エンジン
├── bme280_sensor.cpp         # BME280環境センサ(I2C 0x76)
├── adc_sensor.cpp            # ADC(GPIO32)
├── spi_control.cpp           # SPI DAC制御
└── runtime_config.cpp        # 設定管理

現状: WiFi機能は未実装。新規モジュルとして実装が必要。

WiFi機能の実装検討

1. WiFi接続機能の設計

デバイスのWiFi能力

  • SoC: ESP32-WROOM-32E(802.11 b/g/n対応)
  • アンテナ: 内蔵アンテナまたはU.FL対応
  • 必要なライブラリ: Arduino FreeRTOS SDK内の WiFi.h(標準装備)

WiFiアクセスポイント(AP)モード vs ステーション(STA)モード

APモード(初期実装推奨):

  • デバイスが親機として動作
  • スマホから直接接続(設定が簡単)
  • メモリ効率: 良好
  • 実装複雑度: 低い
  • 実現方法: SSID "OSECHI-xxxx" でBroadcast、DHCPサーバはデバイス側で提供

STAモード(将来拡張向け):

  • 既存WiFiネットワークに接続
  • ネットワーク統合が可能
  • メモリ効率: より効率的
  • 実装複雑度: 中程度

初期実装案:

  • APモード採用
  • IPアドレス: 192.168.4.1(標準)
  • ポート: 80(HTTP)
  • HTTPサーバ組み込み

実装パターン(概要)

// Wi-Fi AP初期化
WiFi.mode(WIFI_AP);
WiFi.softAP("OSECHI-1234", "password");  // SSID, パスワード
WiFi.softAPIP();  // 通常は192.168.4.1

// HTTPサーバ起動
server.on("/", handleRoot);
server.on("/api/status", handleStatus);
server.on("/api/threshold", HTTP_POST, handleThreshold);
server.begin();

2. ブラウザUI設計

フラッシュメモリ制約への対応

現在の使用状況:

  • 使用率: 22.6%(約925KB/4MB)
  • WiFi + HTTPサーバライブラリ追加: 推定150-200KB必要
  • 残り容量: 約2.75MB(充分な余裕あり)

UI実装戦略の比較

パターンA(推奨初期):外部CDN + 最小HTML

  • HTMLファイルはデバイスに保存(5-10KB)
  • CSS/JavaScriptは外部CDN(jsDelivr等)参照
  • 利点: 最小メモリ使用、動的更新容易
  • 欠点: インターネット接続必須

パターンB:JSON API + JavaScriptベースUI

  • API: RESTful JSON形式(データのみ)
  • フロントエンド: PC/スマホのブラウザで実装
  • 利点: デバイス側軽量、柔軟性高い
  • 欠点: デバイス側制御複雑

パターンC:完全埋め込みHTML

  • HTML/CSS/JavaScriptをFLASH内に収納
  • 利点: 完全自己完結(インターネット不要)
  • 欠点: フラッシュ圧迫(gzip圧縮必須)

最小限UI仕様(パターンA推奨)

<!DOCTYPE html>
<html>
<head>
  <title>OSECHI Control</title>
  <meta name="viewport" content="width=device-width">
  <style>body{font-family:sans-serif;max-width:400px;margin:20px auto;}</style>
</head>
<body>
  <h1>OSECHI Status</h1>
  <div id="status"></div>

  <h2>Threshold Settings</h2>
  <form id="thresholdForm">
    <label>Channel 1: <input type="range" min="0" max="4095" name="ch1"></label><br>
    <label>Channel 2: <input type="range" min="0" max="4095" name="ch2"></label><br>
    <label>Channel 3: <input type="range" min="0" max="4095" name="ch3"></label><br>
    <button type="submit">Set</button>
  </form>

  <script>
    fetch('/api/status')
      .then(r => r.json())
      .then(data => {
        document.getElementById('status').innerHTML =
          `Version: ${data.version}<br>Poll Count: ${data.poll_count}`;
      });
  </script>
</body>
</html>

必要なAPIエンドポイント

  • GET / → HTMLファイル(インラインまたはLittleFS)
  • GET /api/status → JSON: {version, poll_count, threshold_ch1/2/3}
  • POST /api/threshold → JSON: {ch, value} → "OK" or error
  • GET /api/sensor-data → JSON: {signal1, signal2, signal3, adc, temp, ...}

3. WiFi有効時のノイズ対策

ノイズ発生の可能性とリスク

RF干渉

  • スペクトラム競合(Bluetooth/Zygee等と共用)
  • 対策: ESD/EMIフィルタ、シールド

グラウンド戻り路

  • スイッチングノイズ結合
  • 対策: レイアウト工夫、ビア配置最適化

電源ノイズ

  • VCC変動がADC/GPIO読み値に影響
  • 対策: レギュレータ増強、デカップリングコンデンサ

クロックノイズ

  • 80/160MHz CPUクロック由来
  • 対策: スペクトラム拡散(SSCG)有効化

パッケージ放射

  • チップ自体からの放射
  • 対策: ケース内シールド

ハードウェア対策(優先度順)

優先度: 高 - 電源管理

  • 検出回路とWiFi用の電源ラインを物理的に分離
  • BME280用と検出用の別レギュレータ使用を検討
  • デカップリングコンデンサ(0.1µF)を各電源ノードに密配置

優先度: 高 - グラウンド設計

  • 多層PCB設計時に専用グラウンドプレーン配置
  • コンテルプレーン:デジタル、アナロググラウンドの分離スター結線
  • ビア密度増加(検出ノード周辺)

優先度: 中 - シールド・EMI対策

  • ESP32周辺をFaraday cage(銅テープ/メッシュ)で囲む
  • 検出入力:10µH チョークコイル + 10nF CSVを直列
  • SPI/I2Cラインのツイストペア配線

ソフトウェア対応(優先度: 中)

  • WiFi動作中のCPU負荷平準化(FreeRTOSタスク設定)
  • ADC読み値のデジタルフィルタリング強化(移動平均)
  • 検出ロジックの動的キャリブレーション(背景ノイズレベル追跡)

ノイズ影響の定量評価方法

// 検出イベント時のノイズフロア自動学習
struct noise_stats {
  uint16_t baseline1, baseline2, baseline3;  // 背景レベル
  uint16_t threshold1, threshold2, threshold3;  // 検出閾値
  uint8_t noise_std_dev;  // 標準偏差(信号の安定性指標)
};

// WiFi ON/OFF時の比較測定ロジック:
// 1. WiFi OFF: 100サンプル取得 → 背景統計計算
// 2. WiFi ON: 同じ条件で100サンプル → 比較分析
// → Δ値がしきい値超過 → カウンター増加

4. 実装段階案

Phase 1: WiFi+HTTPサーバ基盤(1-2週間)

  • WiFi AP初期化
  • HTTPサーバ立ち上げ
  • 静的HTML配信
  • /api/status エンドポイント実装
  • メモリ確認: Flash/RAM使用率再測定

Phase 2: ステータス・スレッショルド管理API(1週間)

  • /api/sensor-data 実装
  • /api/threshold POST処理
  • JSON フォーマッター検証
  • エラーハンドリング

Phase 3: ノイズ評価とキャリブレーション(2-3週間)

  • ノイズ統計ロジック実装
  • WiFi ON/OFF比較測定
  • デジタルフィルタ強化
  • 実機検証(ハードウェア評価)

Phase 4: UI 洗練・ドキュメント(1週間)

  • レスポンシブデザイン
  • セキュリティ強化(WPA2-PSK例)
  • ユーザー向けドキュメント作成

Learnings

コードベース構造から学んだこと

モジュール化の重要性

  • 既存の serial_protocol.h/cpp, text_command_handler.cpp パターンをWiFi実装でも踏襲すべき
  • 提案: wifi_manager.h/cpp + web_server.h/cpp の分割設計

リソース制約への配慮

  • 現在22.6% Flash使用(925KB/4MB)
  • WiFi ライブラリ追加で約150-200KB必要
  • 残り2.75MBで対応可能(十分な余裕あり)

ビルド構成の柔軟性

  • platformio.ini 既存のフラグシステム(OUTPUT_FORMAT, ENABLE_BME280等)を参考に
  • 提案: ENABLE_WIFI=1/0 フラグでコンパイル時選択可能に

テキストコマンド拡張の可能性

  • 既存の text_command_handler.cpp に WiFi 関連コマンド追加可能
  • WIFI_STATUS, WIFI_ENABLE など
  • STA/APモード切り替え、認証情報設定も実装可能

技術的な課題

FLASHメモリ制約

  • 現在から+200KB追加で76% → 圧縮/外部参照必須

ノイズ対策の検証

  • 実機ハードウェアなしの理論予測では不完全
  • 試作機での実測確認が必須

WiFi電源管理

  • デフォルトのWiFi.mode()は常時接続が前提
  • スリープモード併用で消費電力抑制可能

Next Steps

検討・分析

  • FLASHメモリ使用量詳細分析(WiFiライブラリのサイズ測定)
  • パターンA(外部CDN) vs パターンC(埋め込みHTML)のプロトタイプ比較
  • 現行PCBの電源配置図確認
  • グラウンドプレーン設計状況確認
  • RF干渉テスト計画立案

初期実装(WiFi基盤)

  • wifi_manager.h/cpp モジュール作成
  • HTTPサーバ初期化テスト
  • リソース使用量の再測定

ノイズ対策の実装戦略

  • デジタルフィルターの強化(カルマンフィルター or 移動平均の最適化)
  • 背景ノイズレベルの自動追跡アルゴリズム設計
  • テスト用: WiFi ON/OFF切り替えロジックの実装

5. 実装計画(パターンC採用)

屋外での使用を想定し、パターンC(完全埋め込みHTML) を採用します。 インターネット接続なしでスマートフォン単体から設定・確認できる自己完結型の実装です。

5.1 ビルド構成の追加

platformio.iniにWiFi対応ビルド環境を追加します:

; WiFi対応ビルド環境
[env:esp32dev-wifi]
build_type = release
build_flags =
    ${env.build_flags}
    -O2
    -DDEBUG_DETECTION_MODE=0
    -DENABLE_TEXT_PROTOCOL=0
    -DENABLE_WIFI=1
    -DOUTPUT_FORMAT=0
    -DENABLE_BME280=1

ビルドコマンド:

  • pio run -e esp32dev-wifi - WiFi対応ファームウェア生成
  • pio run -e esp32dev-release - 従来の非WiFi版(既存互換性維持)

5.2 モジュール構成

新規追加モジュール:

  • wifi_manager.h/cpp - WiFi AP初期化、HTTPサーバー管理
  • wifi_init() - WiFi APとHTTPサーバの起動
  • wifi_handle_client() - HTTPリクエスト処理
  • APIエンドポイント登録

  • web_ui.h - 埋め込みHTMLコンテンツ管理

  • HTML/CSS/JavaScript の定義
  • gzip圧縮対応

命名規則統一: 既存コードベースに合わせてadc_read()bme280_init()などmodule_function()パターンで統一。WiFi関数はwifi_prefixのみ使用(wifi_server_ではなくwifi_

5.3 config.h への追加

// ============================================================================
// WiFi Configuration (v1.8.0+)
// ============================================================================
// Controls whether WiFi AP mode and embedded web UI are compiled into firmware.
// - ENABLE_WIFI=1: WiFi AP mode enabled, embedded HTML UI compiled in
// - ENABLE_WIFI=0: WiFi disabled (default, reduces firmware size by ~150-200KB)
// Default: 0 (disabled, production)
// Override via platformio.ini build_flags: -DENABLE_WIFI=1

#ifndef ENABLE_WIFI
#define ENABLE_WIFI 0              // 0=disabled (default), 1=enabled
#endif

#ifndef WIFI_SSID_PREFIX
#define WIFI_SSID_PREFIX "OSECHI"  // WiFi SSID prefix
#endif

#ifndef WIFI_PASSWORD
#define WIFI_PASSWORD "osechi1234" // WiFi パスワード(デフォルト)
#endif

#ifndef WIFI_AP_IP
#define WIFI_AP_IP "192.168.4.1"   // WiFi AP IPアドレス
#endif

5.4 HTTPサーバAPIエンドポイント

静的コンテンツ:

  • GET / → 埋め込みHTML(gzip圧縮)

ステータスAPI:

  • GET /api/status → JSON応答
{
  "version": "1.8.0",
  "poll_count": 100,
  "threshold_ch1": 2048,
  "threshold_ch2": 2048,
  "threshold_ch3": 2048,
  "wifi_enabled": true
}

ステータス&センサデータAPI:

  • GET /api/sensor-data → JSON応答(最新データ)
{
  "signal1": 45,
  "signal2": 38,
  "signal3": 42,
  "adc": 2048,
  "temp": 25.3,
  "pressure": 1013.25,
  "humidity": 55.2,
  "uptime_ms": 3600000
}

スレッショルド設定API:

  • POST /api/threshold → リクエストボディ形式
{
  "ch": 1,
  "value": 2500
}

応答: {"status":"ok"} または {"error":"invalid_channel"}

5.5 埋め込みHTMLコンテンツ設計

最小限のHTML + インラインCSS/JavaScriptを使用(圧縮時~15-20KB)。

主要機能:

  • ステータス表示(バージョン、ポーリング数)
  • チャネル1-3のスレッショルド調整(スライダーUI)
  • リアルタイムセンサー値表示(自動更新1秒ごと)
  • 検出イベント数・統計表示(オプション)

UI実装戦略:

  • 単一ページアプリケーション(SPA)化
  • Fetch APIでサーバーと非同期通信
  • モバイル対応(viewportメタタグ)
  • 最小限CSS(インライン)

HTML概要構成:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>OSECHI Control Panel</title>
  <style>
    /* インラインCSS */
  </style>
</head>
<body>
  <header>
    <h1>OSECHI Control</h1>
    <div id="status">...</div>
  </header>

  <section>
    <h2>Threshold Control</h2>
    <div id="thresholds">
      <!-- チャネル1-3スライダー -->
    </div>
  </section>

  <section>
    <h2>Sensor Data</h2>
    <div id="sensorData">
      <!-- リアルタイムセンサ値 -->
    </div>
  </section>

  <script>
    // JavaScriptロジック
  </script>
</body>
</html>

5.6 gzip圧縮戦略

HTMLファイルをgzipで圧縮し、ビルド時にC++ソースコード内に埋め込みます。

プロセス:

# 1. HTMLファイル作成
echo "..." > web_ui.html

# 2. gzip圧縮
gzip -k web_ui.html  # web_ui.html.gz 生成

# 3. バイナリ化
xxd -i web_ui.html.gz > web_ui_gz.h  # C++配列に変換

# 4. C++コードに包含
// web_ui.cpp
#include "web_ui_gz.h"
const uint8_t UI_DATA[] = web_ui_html_gz;
const size_t UI_SIZE = web_ui_html_gz_len;

圧縮効果:

  • 非圧縮: 約20-25KB
  • 圧縮後: 約6-8KB(60-70%削減)
  • HTTPヘッダーでContent-Encoding: gzipを設定し、ブラウザーが自動展開

5.7 実装ロードマップ

Stage 1: 基盤構築(初期1-2週間)

  • config.hにENABLE_WIFIフラグ追加
  • platformio.inに esp32dev-wifiビルド環境追加
  • wifi_manager.h/cpp骨組み作成
  • HTTPサーバー初期化テスト(APIなし)
  • メモリ使用量確認(Target: 70%以下)

Stage 2: API実装(1週間)

  • /api/statusエンドポイント実装
  • /api/sensor-dataエンドポイント実装
  • /api/thresholdPOST処理実装
  • JSONフォーマッター検証
  • エラーハンドリング追加

Stage 3: UI実装(1-2週間)

  • HTML/CSS/JavaScript設計
  • gzip圧縮パイプライン構築
  • web_ui.hに埋め込みHTMLデータ配置
  • ブラウザーUIテスト(スマートフォン確認)
  • UIドキュメント作成

Stage 4: 統合テスト・最適化(1週間)

  • WiFi+検出ロジック連携確認
  • メモリプロファイリング(Flash/RAM)
  • ノイズ影響評価(簡易版)
  • ドキュメント完成(ユーザー向け)
  • コミット+リリース準備

5.8 開発環境とテスト方法

ビルド・アップロード:

# WiFi対応版のビルド
task build -- -e esp32dev-wifi

# または
pio run -e esp32dev-wifi -t upload

# シリアルモニターで確認
task monitor

ブラウザーアクセス:

  1. デバイス起動 → WiFi AP「OSECHI-xxxx」がブロードキャスト
  2. スマートフォンでSSID選択 → パスワード「osechi1234」入力
  3. ブラウザーでhttp://192.168.4.1/にアクセス
  4. UIが表示 → スレッショルド調整・センサー値確認可能

5.9 フラッシュメモリ予算

現在: 925KB/4MB(22.6%)

追加コンポーネント:

  • WiFiライブラリ: 約120KB
  • HTTPサーバーライブラリ: 約30KB
  • 埋め込みHTML(圧縮): 約8KB
  • wifi_server.cpp: 約10KB

合計追加: 約168KB 新使用率: (925+168)/4096 = 26.8%

余裕: 73.2%✓(十分)

5.10 セキュリティ考慮事項

パターンC(ローカルネットワーク内)では以下対応で十分:

  • HTTPSは不要(ローカルネットワーク内のみ通信)
  • 固定パスワード「osechi1234」でシンプル運用
  • CSRF対策: JSONPOSTでRefererチェック(後期対応)

今後の拡張候補:

  • WiFiパスワード設定変更コマンド
  • STAモード対応(既存ネットワーク接続)
  • HTTPS化(Let's Encrypt+自動更新、将来版)

5.11 テスト計画

単体テスト:

  • WiFi AP起動確認(電波到達距離)
  • APIエンドポイント応答確認(curl/Postman)
  • JSON形式検証

統合テスト:

  • ブラウザUI動作確認(iOS/Android)
  • スレッショルド設定の即座反映
  • 検出イベント時のセンサデータ更新

負荷テスト:

  • 複数デバイス同時接続(3台程度)
  • 高頻度リクエスト(1秒毎API呼び出し)
  • メモリリーク確認(1時間連続運用)