注釈

こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiast Community on Facebookへようこそ!他の愛好家と一緒に、Raspberry Pi、Arduino、ESP32の世界により深く入り込みましょう。

参加する理由

  • 専門家サポート: 購入後の問題や技術的な課題を、コミュニティと私たちのチームの助けを借りて解決します。

  • 学習と共有: ヒントやチュートリアルを交換して、スキルを向上させましょう。

  • 限定プレビュー: 新製品の発表や先行プレビューに早期アクセスできます。

  • 特別割引: 最新製品を特別割引でお楽しみいただけます。

  • 季節限定キャンペーンとプレゼント: プレゼント企画やホリデーキャンペーンに参加しましょう。

👉 一緒に発見し、創造する準備はできましたか? [こちら] をクリックして、今すぐ参加しましょう!

4.6 カウント装置

はじめに

このプロジェクトでは、PIR モーションセンサーと 4 桁 7 セグメントディスプレイを使用して、人の通過数をカウントするシステムを作成します。PIR センサーが動きを検出するたびに、表示されるカウント値が 1 ずつ増加します。このプロジェクトは、廊下や入口の通行量を監視する用途に適しており、GPIO プログラミングと表示制御を実践的に学ぶことができます。


必要なもの

このプロジェクトに必要なコンポーネントは以下のとおりです。

COMPONENT INTRODUCTION

PURCHASE LINK

ブレッドボード

購入

ジャンパーワイヤー

購入

抵抗器

購入

PIRモーションセンサーモジュール

購入

4桁7セグメントディスプレイ

-

74HC595

購入

Fusion HAT+

-

Raspberry Pi

-


回路図

以下はこのプロジェクトの回路図です。

../_images/4.1.4_sch.png

配線図

以下の配線図に従って、各コンポーネントを正しく接続してください。

../_images/4.1.4_bb.png

注釈

最適な感度と検出距離を得るために、PIR モジュール上の 2 つの可変抵抗を調整してください。最良の結果を得るには、両方を反時計回りいっぱいまで回してください。

../_images/PIR_TTE.png

サンプルの実行

このチュートリアルで使用するすべてのサンプルコードは ai-lab-kit ディレクトリに含まれています。 以下の手順に従ってサンプルを実行してください。

cd ~/ai-lab-kit/python/
sudo python3 4.6_CountingDevice.py

この Python スクリプトは、PIR モーションセンサーと 74HC595 シフトレジスタで駆動する 7 セグメントディスプレイを組み合わせたものです。このスクリプトは次のように動作します。

  1. 動きの検出: GPIO22 に接続された PIR モーションセンサーが動きを検出します。動きを 1 回検出するごとにカウンターが 1 増加します。

  2. 数字の表示:

    • 現在のカウント値が 4 桁の 7 セグメントディスプレイに表示されます。

    • 動きが検出されるたびに表示が更新され、数値が増加します。

  3. 継続的な監視: スクリプトは動きを継続的に監視し、表示をリアルタイムで更新します。

  4. 安全な終了: Ctrl+C を押すと、すべてのピンがオフになり、スクリプトは安全に終了します。


コード

以下は、このプロジェクトで使用する Python スクリプトです。

#!/usr/bin/env python3
from fusion_hat.pin import Pin, Mode, Pull

# Initialize PIR motion sensor on GPIO 22 (input with pull-down)
pir = Pin(22, mode=Mode.IN, pull=Pull.DOWN)

# Define GPIO pins for the 74HC595 shift register
SDI = Pin(17, mode=Mode.OUT)   # Serial Data Input
RCLK = Pin(4, mode=Mode.OUT)   # Register Clock (latch)
SRCLK = Pin(27, mode=Mode.OUT) # Shift Register Clock

# Define GPIO pins used to select one of the 4 digits on the 7-segment display
placePin = [Pin(pin, mode=Mode.OUT) for pin in (23, 24, 25, 12)]

# Segment code table for digits 0–9 (common-cathode 7-segment display)
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)

# Counter to display the number of detections
counter = 0

def clearDisplay():
   """Clear the 7-segment display by shifting out 'all off' bits."""
   for _ in range(8):
      SDI.high()     # Send a high bit
      SRCLK.high()   # Clock it in
      SRCLK.low()
   RCLK.high()        # Latch output
   RCLK.low()

def hc595_shift(data):
   """Shift a full byte of data into the 74HC595 to control the segments."""
   for i in range(8):
      SDI.value(0x80 & (data << i))  # Output next bit of the data
      SRCLK.high()                   # Pulse shift clock
      SRCLK.low()
   RCLK.high()                        # Latch data to display
   RCLK.low()

def pickDigit(digit):
   """Enable one specific digit (0–3) on the multiplexed display."""
   for pin in placePin:
      pin.low()                      # Disable all digits
   placePin[digit].high()             # Activate the selected digit

def display():
   """Display the current 4-digit counter value on the 7-segment display."""
   global counter

   # Display ones place
   clearDisplay()
   pickDigit(3)
   hc595_shift(number[counter % 10])

   # Display tens place
   clearDisplay()
   pickDigit(2)
   hc595_shift(number[counter % 100 // 10])

   # Display hundreds place
   clearDisplay()
   pickDigit(1)
   hc595_shift(number[counter % 1000 // 100])

   # Display thousands place
   clearDisplay()
   pickDigit(0)
   hc595_shift(number[counter % 10000 // 1000])

def loop():
   """Main loop: continuously update display and detect PIR motion transitions."""
   global counter
   currentState = 0
   lastState = 0

   while True:
      display()                                      # Refresh 7-segment display
      currentState = 1 if pir.value() == 1 else 0    # Read PIR output

      # Detect rising edge: motion detected now, but not in last cycle
      if currentState == 1 and lastState == 0:
            counter += 1                               # Increase the count

      lastState = currentState                        # Save state for next loop

try:
   loop()                                             # Start main loop
except KeyboardInterrupt:
   # Clean up GPIO pins when exiting
   SDI.low()
   SRCLK.low()
   RCLK.low()
   pass

コードの解説

  1. 動きの検出:

    PIR センサーが動きを検出すると、その信号によってカウンターが増加します。

  2. 表示の更新:

    hc595_shift 関数と pickDigit 関数が連携して 7 セグメントディスプレイを制御し、カウンター値をリアルタイムで更新します。

  3. メインループ:

    loop 関数は PIR センサーを継続的に監視し、動きが検出されると表示を更新します。

  4. 割り込み処理:

    スクリプトは中断時にすべての GPIO ピンを安全にオフにし、予期しない動作を防ぎます。


トラブルシューティング

  1. ディスプレイが動作しない:

    • 原因: 7 セグメントディスプレイまたはシフトレジスタの配線が正しくありません。

    • 対処方法:

      • GPIO ピンとシフトレジスタの SDI、SRCLK、RCLK ピンの接続を確認してください。

      • すべての placePin の接続が対応する桁ピンと一致していることを確認してください。

  2. モーションセンサーが反応しない:

    • 原因: PIR センサーの配線ミス、または周囲環境による干渉。

    • 対処方法:

      • PIR センサーが GPIO22、電源、GND に正しく接続されていることを確認してください。

      • 必要に応じて、PIR センサー上の感度および遅延時間調整用の可変抵抗を調整してください。

  3. カウンターが増加しない:

    • 原因: モーションセンサーの状態変化が正しく検出されていません。

    • 対処方法:

      • pir.value() の値が正しく更新されているか確認してください。

      • loop() 関数にデバッグ用の print を追加して、状態遷移を確認してください。

  4. 表示がちらつく:

    • 原因: 表示更新のタイミングが適切でない、または遅延が不足しています。

    • 対処方法: display() 関数に小さな待機時間を追加して表示を安定させてください。

      import time
      time.sleep(0.01)
      

拡張アイデア

  1. 双方向カウンター: もう 1 つ PIR センサーを追加して反対方向の動きを検出し、カウンターを減算できるようにします。

    pir2 = Pin(16, Pin.IN, pull= Pin.PULL_DOWN)
    if pir2.value()==1:
       counter -= 1
    
  2. しきい値アラート: カウンターがあらかじめ設定した値を超えたときに、LED やブザーなどで警告を出します。

    from fusion_hat import Buzzer
    buzzer = Buzzer(Pin(22))
    if counter > 50:
          buzzer.on()
    else:
          buzzer.off()
    
  3. データログ記録: カウンター値とタイムスタンプをファイルへ保存して分析できます。

    with open("motion_log.txt", "a") as log_file:
          log_file.write(f"{time.time():.3f}, Counter: {counter}\n")
    
  4. タイマーによるリセット: 一定時間動きがない場合にカウンターをリセットします。

    last_motion_time = time.time()
    if time.time() - last_motion_time > 300:  # 5 minutes
          counter = 0
    
  5. イベント連動の動作: カウンターが特定の値に達したときに、家電の制御など特定の動作を実行します。


まとめ

このプロジェクトでは、PIR センサーと 7 セグメントディスプレイを使用した動き検出と表示制御の基本を学びます。より高度な IoT やデータ可視化プロジェクトへ発展させるための、実践的な基礎となります。