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?

Raspberry Pi で「人感・傾き・光」を同時監視し、AWS IoT Core に MQTT 送信する仕組みを構築した話(gpiozero 版)

Posted at

前書き

会社の技術研究の一環として、IoT機器で取得したデータをAWSに送信することを勉強しました。
以下、AIを使用して作成したまとめです。

本文

Raspberry Pi を使って、

  • ✅ 人感センサー(PIR)
  • ✅ 傾きセンサー
  • ✅ 光センサー(MCP3008)

の3つを同時に監視し、イベントが発生したら AWS IoT Core に MQTT 送信する仕組みを構築しました。

当初は RPi.GPIO を使っていましたが、Raspberry Pi OS Bookworm ではイベント検知が不安定で、
最終的に gpiozero に統一することで安定動作を実現しました。

この記事では、
センサー接続 → Python 実装 → MQTT → AWS 連携 → 運用
までをまとめます。


✅ 使用したハードウェア

  • Raspberry Pi 3 Model B Rev 1.2
  • PIR 人感センサー(GPIO17)
  • 傾きセンサー(GPIO16)
  • MCP3008(光センサー用 ADC)
  • CdS 光センサー
  • ジャンパー線
  • AWS IoT Core(MQTT)

✅ 全体アーキテクチャ

┌──────────────┐
│  PIR(GPIO17) │───┐
└──────────────┘   │
┌──────────────┐   │
│ 傾き(GPIO16) │───┼→ Python(gpiozero) → MQTT → AWS IoT Core
└──────────────┘   │
┌──────────────┐   │
│ 光(MCP3008) │───┘
└──────────────┘

✅ gpiozero を採用した理由

❌ RPi.GPIO の問題点(Bookworm)

  • add_event_detect() が失敗する
  • MCP3008(gpiozero)と競合しやすい
  • 割り込みが不安定

✅ gpiozero のメリット

  • センサーを「オブジェクト」として扱える
  • イベント検知が安定
  • MCP3008 も統一的に扱える
  • コードが短くて読みやすい

✅ Raspberry Pi の配線(重要)

ここでは、PIR・傾き・光(MCP3008) の3つを同時に接続するための配線をまとめます。


✅ Raspberry Pi の GPIO ピン配置(BCM)

(左) 3.3V  (右) 5V
(左) GPIO2 (右) 5V
(左) GPIO3 (右) GND
(左) GPIO4 (右) GPIO14
(左) GND   (右) GPIO15
(左) GPIO17 ← PIR
(右) GPIO18
(左) GPIO27 (右) GND
(左) GPIO22 (右) GPIO23
(左) 3.3V  (右) GPIO24
(左) GPIO10 (右) GND
(左) GPIO9  (右) GPIO25
(左) GPIO11 (右) GPIO8
(左) GND   (右) GPIO7
(左) GPIO5 (右) GPIO6 ← MCP3008 CLK
(左) GPIO13 ← MCP3008 MISO
(右) GPIO19 ← MCP3008 MOSI
(左) GPIO26 ← MCP3008 CS

✅ 1. PIR 人感センサー(GPIO17)

配線

PIR Raspberry Pi
VCC 5V
OUT GPIO17
GND GND

備考

  • 出力は HIGH/LOW のデジタル信号
  • gpiozero の MotionSensor が自動で安定化処理してくれる

✅ 2. 傾きセンサー(GPIO16)

配線

傾きセンサー Raspberry Pi
片側 GPIO16
片側 GND

備考

  • 機械式スイッチなのでチャタリングが発生するが、gpiozero が吸収
  • Button(16, pull_up=True) で内部プルアップを使用

✅ 3. 光センサー(MCP3008 + CdS)

MCP3008 配線(bitbang SPI)

MCP3008 Raspberry Pi
VDD 3.3V
VREF 3.3V
AGND GND
DGND GND
CLK GPIO6
DOUT (MISO) GPIO13
DIN (MOSI) GPIO19
CS GPIO26

CdS 光センサー配線

3.3V ── CdS ── MCP3008 CH0 ── 10kΩ ── GND

備考

  • MCP3008 は 0〜3.3V を 0.0〜1.0 の値に変換
  • gpiozero の MCP3008(channel=0) で簡単に扱える

✅ Python 実装(MQTT + gpiozero + ログ)

ポイント:

  • gpiozero のイベントハンドラで PIR / 傾きを監視
  • 光センサーは定期ポーリング
  • MQTT は AWS IoT Core に TLS で接続
  • ログは RotatingFileHandler でローテーション

✅ 完成コード(フル実装)

import time
import json
import ssl
import logging
from logging.handlers import RotatingFileHandler
from gpiozero import MotionSensor, Button, MCP3008
import paho.mqtt.client as mqtt

# ============================
# ログ設定
# ============================
log_formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
log_handler = RotatingFileHandler("sensor_mqtt.log", maxBytes=1_000_000, backupCount=3)
log_handler.setFormatter(log_formatter)

logger = logging.getLogger("sensor_mqtt")
logger.setLevel(logging.INFO)
logger.addHandler(log_handler)

logger.info("===== Program started =====")

# ============================
# AWS IoT Core 設定
# ============================
ENDPOINT = "XXX"
PORT = 8883
CLIENT_ID = "raspi_sensors"
TOPIC = "sensor/events"

CA_PATH = "XXX"
CERT_PATH = "XXX"
KEY_PATH = "XXX"

# ============================
# センサー設定(gpiozero)
# ============================
pir = MotionSensor(17)             # 人感センサー
tilt = Button(16, pull_up=True)    # 傾きセンサー
light_sensor = MCP3008(channel=0, clock_pin=6, mosi_pin=19, miso_pin=13, select_pin=26)

LIGHT_THRESHOLD = 0.2

# ============================
# MQTT 初期化
# ============================
def on_connect(client, userdata, flags, rc):
    logger.info(f"MQTT connected: {rc}")

def on_disconnect(client, userdata, rc):
    logger.warning(f"MQTT disconnected: {rc}")

client = mqtt.Client(client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_disconnect = on_disconnect

client.tls_set(
    ca_certs=CA_PATH,
    certfile=CERT_PATH,
    keyfile=KEY_PATH,
    tls_version=ssl.PROTOCOL_TLSv1_2
)

client.connect(ENDPOINT, PORT, keepalive=60)
client.loop_start()

# ============================
# イベント送信関数
# ============================
def send_event(event_name, value=None):
    payload = {
        "device": "raspberrypi",
        "event": event_name,
        "timestamp": int(time.time())
    }
    if value is not None:
        payload["value"] = value

    client.publish(TOPIC, json.dumps(payload), qos=1)
    logger.info(f"MQTT sent: {payload}")

# ============================
# イベントハンドラ
# ============================
pir.when_motion = lambda: send_event("motion_detected")
tilt.when_pressed = lambda: send_event("tilt_detected")

logger.info("Sensors ready. Waiting for events...")

# ============================
# メインループ(光センサー)
# ============================
last_light_sent = 0
light_interval = 5

try:
    while True:
        now = time.time()

        if now - last_light_sent > light_interval:
            value = light_sensor.value
            logger.info(f"Light value: {value:.3f}")
            if value < LIGHT_THRESHOLD:
                send_event("low_light", value=value)
            last_light_sent = now

        time.sleep(0.1)

except KeyboardInterrupt:
    client.loop_stop()
    logger.info("Program stopped")

✅ AWS IoT Core 側の設定

  1. デバイス証明書を作成
  2. ポリシーで iot:Publish を許可
  3. エンドポイントを Python に設定
  4. テストコンソールでメッセージを確認

✅ 動作ログ例

[INFO] Sensors ready. Waiting for events...
[INFO] Light value: 0.996
[INFO] MQTT sent: {'event': 'motion_detected', ...}
[WARNING] MQTT disconnected: 7
[INFO] MQTT connected: 0

✅ ハマりどころ

✅ RPi.GPIO のイベント検知が動かない

→ Bookworm では不安定
→ gpiozero に切り替えると解決

✅ MCP3008 と RPi.GPIO が競合

→ gpiozero で統一すると安定

✅ MQTT が切断される

loop_start() で自動再接続
→ QoS1 の ACK タイミングで切断されることがあるが正常範囲


✅ まとめ

  • gpiozero を使うと複数センサーの同時監視が安定
  • AWS IoT Core との MQTT 連携も簡単
  • ログを残すことで運用性が向上
  • Bookworm では RPi.GPIO より gpiozero が圧倒的に安定

以上です。
この記事が、同じように複数センサーを扱いたい人の助けになれば嬉しいです!

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?