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 |
|---|---|
- |
|
- |
|
Raspberry Pi |
- |
Circuit Diagram
Below is the circuit diagram for the project:
Wiring Diagram
Follow the wiring diagram to connect the components correctly:
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.
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:
Motion Detection: A PIR motion sensor connected to GPIO 26 detects motion. Each motion detection increments a counter.
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.
Continuous Monitoring: The script continuously monitors for motion and updates the display in real-time.
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
Motion Detection:
The PIR sensor detects motion and sends a signal to increment the counter.
Display Update:
The
hc595_shiftandpickDigitfunctions work together to control the 7-segment display and update the counter in real time.Main Loop:
The
loopfunction continuously checks the PIR sensor and updates the display when motion is detected.Interrupt Handling:
The script ensures all GPIO pins are safely turned off when interrupted, preventing unexpected behavior.
Troubleshooting
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
placePinconnections match the corresponding digit pins.
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.
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.
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
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
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()
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")
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
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.