Note

Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.

Why Join?

  • Expert Support: Solve post-sale issues and technical challenges with help from our community and team.

  • Learn & Share: Exchange tips and tutorials to enhance your skills.

  • Exclusive Previews: Get early access to new product announcements and sneak peeks.

  • Special Discounts: Enjoy exclusive discounts on our newest products.

  • Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.

👉 Ready to explore and create with us? Click [here] and join today!

4.6 Counting Device

Introduction

In this project, you will build a people-counting system using a PIR motion sensor and a 4-digit 7-segment display. The system increments the count displayed whenever the PIR sensor detects motion. This project is ideal for monitoring foot traffic in a hallway or entrance, and it provides hands-on experience with GPIO programming and display control.


What You’ll Need

The following components are required for this project:

COMPONENT INTRODUCTION

PURCHASE LINK

Breadboard

BUY

Jumper Wires

BUY

Resistor

BUY

PIR Motion Sensor Module

BUY

4-Digit 7-Segment Display

-

74HC595

BUY

Fusion HAT+

-

Raspberry Pi

-


Circuit Diagram

Below is the circuit diagram for the project:

../_images/4.1.4_sch.png

Wiring Diagram

Follow the wiring diagram to connect the components correctly:

../_images/4.1.4_bb.png

Note

Adjust the two potentiometers on the PIR module for optimal sensitivity and detection distance. Turn both counterclockwise to their maximum setting for best results.

../_images/PIR_TTE.png

Running the Example

All example code used in this tutorial is available in the ai-lab-kit directory. Follow these steps to run the example:

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

This Python script integrates a PIR motion sensor and a 7-segment display driven by a 74HC595 shift register. The script performs the following:

  1. Motion Detection: A PIR motion sensor connected to GPIO 26 detects motion. Each motion detection increments a counter.

  2. Number Display:

    • The current counter value is displayed on a 4-digit 7-segment display.

    • The display updates dynamically as motion is detected, incrementing the value.

  3. Continuous Monitoring: The script continuously monitors for motion and updates the display in real-time.

  4. Graceful Exit: On Ctrl+C, all pins are turned off, ensuring a clean shutdown of the script.


Code

Below is the Python script used in this project:

#!/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

Understanding the Code

  1. Motion Detection:

    The PIR sensor detects motion and sends a signal to increment the counter.

  2. Display Update:

    The hc595_shift and pickDigit functions work together to control the 7-segment display and update the counter in real time.

  3. Main Loop:

    The loop function continuously checks the PIR sensor and updates the display when motion is detected.

  4. Interrupt Handling:

    The script ensures all GPIO pins are safely turned off when interrupted, preventing unexpected behavior.


Troubleshooting

  1. Display Not Working:

    • Cause: Incorrect wiring of the 7-segment display or shift register.

    • Solution:

      • Verify connections between the GPIO pins and the SDI, SRCLK, and RCLK pins of the shift register.

      • Ensure all placePin connections match the corresponding digit pins.

  2. Motion Sensor Not Triggering:

    • Cause: PIR sensor wiring or environmental interference.

    • Solution:

      • Check the PIR sensor connections to GPIO 26, power, and ground.

      • Adjust the sensitivity and delay potentiometers on the PIR sensor if available.

  3. Counter Does Not Increment:

    • Cause: Motion sensor state changes not detected.

    • Solution:

      • Ensure the pir.value() value updates correctly.

      • Add debugging prints to confirm state transitions in the loop() function.

  4. Flickering Display:

    • Cause: Insufficient delay or improper timing in the display update.

    • Solution: Add a small delay in the display() function to stabilize the display:

      import time
      time.sleep(0.01)
      

Extendable Ideas

  1. Bidirectional Counter: Add another PIR sensor to detect motion in opposite directions and decrement the counter:

    pir2 = Pin(16, Pin.IN, pull= Pin.PULL_DOWN)
    if pir2.value()==1:
       counter -= 1
    
  2. Threshold-Based Alerts: Trigger an alert (e.g., LED or buzzer) when the counter exceeds a predefined value:

    from fusion_hat import Buzzer
    buzzer = Buzzer(Pin(22))
    if counter > 50:
          buzzer.on()
    else:
          buzzer.off()
    
  3. Data Logging: Log the counter value and timestamps to a file for analysis:

    with open("motion_log.txt", "a") as log_file:
          log_file.write(f"{time.time():.3f}, Counter: {counter}\n")
    
  4. Timer-Based Reset: Reset the counter after a specific period of inactivity:

    last_motion_time = time.time()
    if time.time() - last_motion_time > 300:  # 5 minutes
          counter = 0
    
  5. Event-Based Triggers: Trigger specific actions (e.g., controlling appliances) when the counter reaches specific values.


Conclusion

This project introduces the basics of motion detection and display control using a PIR sensor and 7-segment display. It provides a practical foundation for more advanced IoT and data visualization projects.