このページの目次

一般的な周辺回路

素子とプロトコルを学んだ後、最終的には動作する回路を組み立てる必要があります。以下はプロジェクトで最も頻繁に登場する周辺モジュールです。


ボタンとデバウンス

問題

機械式スイッチを押したときのオン/オフはクリーンではありません:
  V
  │ ┌─┐  ┌──┐
  │ │ │  │  │      ← 接点のバウンス (bounce)
  │ │ └──┘  └──────
  └──────────────── t
      ↑          ↑
    押下        安定

バウンス時間: 典型値 5〜20ms
デバウンスしない → 1回の押下で数十回のトリガーが発生する

ハードウェアデバウンス (RC)

Vcc
 │
 Rpullup (10k)
 │
 ├────── GPIO
 │
 ├── R1 (1k) ──┬── スイッチ ── GND
               │
              C1 (0.1μF)
               │
              GND

RC時定数 τ = R1×C1 = 100μs (短すぎる)
τ ≈ バウンス時間 ≈ 10ms が必要
→ R1=10k, C1=1μF → τ=10ms

欠点: 追加の素子が必要だが、信頼性が高い
利点: CPUリソースを消費せず、割り込みウェイクアップのシナリオに適している

ソフトウェアデバウンス (一般的)

// 最もシンプルで効果的な方法
if (digitalRead(BUTTON) == LOW) {
    delay(20);  // 20ms待機 (またはタイマーを使用し、delayは避ける)
    if (digitalRead(BUTTON) == LOW) {
        // 押下が確認できた
        handle_press();
    }
}

// より良い方法: 状態マシン + タイマー、ブロックしない
// 前回の状態変化時刻を記録し、間隔が20ms以上の場合のみ有効とする

MOSFETを用いた負荷スイッチ

なぜ直接GPIOで駆動せずMOSFETを使うのか

GPIOの最大電流: 典型値 8〜20mA
必要な駆動: LEDストリップ (1A), リレー (100mA), モーター (>1A)
→ GPIOでMOSFETを制御し、MOSFETが負荷を駆動する

ローサイドスイッチ (N-MOSFET, 負荷がDrainとVccの間):
  Vcc ── 負荷 ──┬── Drain
                 │
  GPIO ── Rg ──── Gate
                 │
                Source ── GND

  利点: シンプル、N-MOSFETのRds(on)が低い
  欠点: 負荷がGNDに接続されない (一部のシナリオでは不可)

ハイサイドスイッチ (P-MOSFET, 負荷がDrainとGNDの間):
         Source ── Vcc
           │
  GPIO ──┬─ Rg ── Gate
         │
        NPN/ NMOS (レベルシフト、GPIO 3.3VではP-MOSを完全にオフにできないため)
         │
        GND

         Drain ── 負荷 ── GND

  利点: 負荷の一端がGNDに接続される (安全)
  欠点: レベルシフトが必要、P-MOSのRds(on)が高い

ゲート保護 (必須!)

            Rg (100Ω〜1k)
  GPIO ───┤├─────── Gate
                   │
                   Rgs (10k〜100k)
                   │
                  GND

Rg: ゲートの充放電電流を制限し、振動を抑制
Rgs: GPIOが未初期化/リセット中にGateをGNDに確保 (MOSFETをオフ状態に!)
     Rgsがない → 電源投入直後にGateが浮遊 → MOSFETが誤ってオンになる可能性あり

高電圧/誘導性負荷: Gate対GNDにTVSダイオードまたはツェナーダイオードを追加
  (ドレインのスパイクがCgdを介してゲートに結合し、ゲート酸化膜を破壊するのを防ぐ)

オプトカプラ (光カプラ) による絶縁

オプトカプラが必要な場合

- 高電圧と低電圧の間 (商用電源 220V ↔ MCU 3.3V)
- 長距離信号伝送 (グランドポテンシャル差が大きい)
- グランドループノイズの除去が必要
- 産業現場 (サージ/雷撃)

オプトカプラが不要なシナリオ:
  - 同一基板内の異なる電圧ドメイン → レベルシフトICを使用
  - 同一基板内のI2C/SPI → 絶縁は不要 (産業用途を除く)

基本回路

MCU側 (3.3V)            制御側 (12V/24V)
    │                       │
  GPIO                      R (電流制限)
    │                       │
    R (LED電流制限)       ┌──┴──┐
    │                    │オプト│
   ┌┴┐                   │カプラ│
   │LED (内部)           │出力側│
   └┬┘                   └──┬──┘
    │                       │
   GND                     GND (制御側)

典型: PC817 (安価、低速), 6N137 (高速、10Mbps)

LED側: If = 5〜20mA, R = (3.3V-1.2V)/If
出力側: 負荷に応じて電流制限を計算

リレー駆動

フライホイールダイオード — 絶対に省略不可!

               Vcc
                │
              ┌─┴─┐   ▸├ (フライホイールダイオード)
              │リレー│   │
              └─┬─┘   │
                │     │
              ┌─┴─┐   │
              │MOSFET│  │
              └─┬─┘   │
                │     │
               GND────┘

遮断瞬間: コイル電流は急変できない → 逆起電力が発生 (L×dI/dt)
          100Vを超える可能性あり! → フライホイールダイオードがない → MOSFETが破壊

ダイオードの向き: 逆並列 (カソードをVcc、アノードをMOSFETのDrainに接続)
  通常時は逆バイアスで導通しない
  MOSFETが遮断されたときに電流ループを提供

ダイオードの選定: 1N4148 (小リレー), 1N4007 (大リレー)
         フラストリカバリまたはショットキー (EMI低減)

完全な回路

              Vcc (5V/12V/24V)
               │
              ┌┴┐
              │▸├ (フライホイール)
              └┬┘
               │
              ┌┴┐
              │リレー│
              └┬┘
               │
             Drain
  GPIO ──Rg─── Gate  N-MOSFET
               │     (Rds(on)が低く、Vds > Vcc×2のものを選ぶ)
             Source
               │
              GND

リレーコイル電流: I = Vcc/R_coil
  例: 5Vリレー 70Ω → 71mA

MOSFETの選定:
  Vds > Vcc × 1.5
  Id > I_coil × 1.5
  Vgs(th) < GPIOのハイレベル (3.3Vシステムでは2.5V以下を選ぶ)
  推奨: AO3400 (30V/5.8A, Vth<1V, 安価で使いやすい)

LED駆動

方式回路用途
電流制限抵抗R = (Vcc-Vf)/I_LEDインジケータ用LED
定電流ICCAT4101, BCR401など高出力/照明用
PWM + MOSGPIO PWM → MOS → LEDディミング
定電流LEDドライバーWS2812B/SK6812などアドレス指定可能RGB

定電流 vs 電流制限抵抗

電流制限抵抗:
  I_LED = (Vcc - Vf) / R
  Vccの変動 → 電流の変動
  Vfの温度ドリフト → 電流のドリフト
  高出力時、抵抗の発熱が激しい

定電流源:
  電流が一定で、Vcc/Vfの変化に影響されない
  LEDを直列接続することも可能 (電圧は加算され、電流は一定)
  効率が高い

ウォッチドッグ (Watchdog)

必要性

組み込みデバイスが3ヶ月稼働 → ハングアップ → ユーザーは電源を抜くしかない
原因: メモリリーク、ポインタの暴走、EMI干渉、稀なバグ

ウォッチドッグ = 独立タイマー
  ファームウェア正常: タイマーを定期的に「餌やり」(リセット)
  ファームウェアハング: 餌やりしない → タイムアウト → ハードウェアリセット

使用上の注意点

❌ メインループ内で餌やり (サブ関数内でハングしていても、ループ自体は回っているため)
✅ 独立したモニタリングタスクで餌やり
   または: 複数のタスクがすべてサインインした場合のみ餌やり

❌ delay/sleep使用中に餌やりを忘れる
✅ 長時間の待機を複数の短時間待機 + 餌やりに分割

❌ ウォッチドッグのタイムアウトを非常に短く設定 (通常動作中に餌やりが間に合わない場合がある)
✅ タイムアウトは最長タスク実行時間の2倍以上

独立ウォッチドッグ (IWDG): 独立したクロックソース、システムクロックが停止してもリセット可能
ウィンドウウォッチドッグ (WWDG): 特定の時間窓内でのみ餌やり可能 (より厳格)

キーワード: デバウンス, MOSFETスイッチ, オプトカプラ, フライホイールダイオード, リレー, LED駆動, ウォッチドッグ, GPIO