portfolio/PetWatch System

PetWatch - Automated Pet Detection & Deterrent System

Distributed embedded system using BeagleBone Black, Raspberry Pi Pico 2W, and YOLOv5 AI to detect and deter pets from restricted areas with automated water spray.

BeagleBoneRaspberry PiYOLOv5PythonCYoctoOpenCV

Demo Media

Overview

PetWatch is a distributed embedded system designed to protect designated areas from pet/wild animal intrusions using computer vision and automated deterrents. The system uses a three-tier architecture: BeagleBone Black for motion detection and camera capture, Raspberry Pi Pico 2W for network forwarding and deterrent control, and a detection server running YOLOv5 for accurate pet identification with a larger model.

When motion is detected, the BeagleBone captures a frame and transmits it via UART protocol to the Pico 2W. The Pico forwards the image to the detection server over WiFi, which uses YOLOv5 to identify if the motion was caused by a pet (cat, dog, or other animals). Upon positive detection, the system triggers a water pump and buzzer alarm to deter the pet, while sending an email notification with an annotated image showing the detection.

Project Goal: Create a reliable, automated system that can distinguish between pets and humans, triggering deterrents only when pets enter restricted areas. The system needed to be modular, resilient to network failures, and capable of real-time processing with minimal false positives.

Key Features

  • AI-Powered Pet Detection - YOLOv5l model (classes 15-17, 21)
  • Motion-Triggered Capture - OpenCV MOG2 background subtraction for efficient detection
  • Reliable UART Protocol - frame protocol with CRC-16 validation
  • Automated Water Deterrent - Latching relay control with pulse patterns
  • Email Notifications - SMTP integration with annotated detection images
  • Custom Yocto Linux - Example of embedded Linux for BeagleBone Black
  • WiFi Resilience - Automatic reconnection with exponential backoff
  • Real-time Processing - Capture rate with dynamic motion thresholds
  • Modular Architecture - Independent components for high availability

System Architecture

Three-Tier Architecture

The system uses a distributed architecture with clear separation of concerns:

BeagleBone Black - Motion Detection Layer

  • Runs custom Yocto Linux (kirkstone branch)
  • Captures video at 640x480 resolution (I used an old HP Webcam HD-3300)
  • OpenCV MOG2 background subtraction
  • Dynamic motion threshold adjustment
  • UART transmission at 460800 baud (higher baud rate causes issues)

Raspberry Pi Pico 2W - Network Bridge

  • CYW43 WiFi connectivity
  • Frame receiver with ring buffer
  • HTTP POST forwarding to server
  • Water pump relay control (GP12)
  • PWM buzzer at 2kHz (GP14)
  • Automatic WiFi reconnection

Server - AI Processing

  • YOLOv5l model (large variant)
  • Confidence threshold: 0.25
  • IOU threshold: 0.45
  • Target classes: Cat(15), Dog(16), Sheep(17), Bear(21)
  • Email notifications via SMTP
  • Bounding box annotation

Communication Flow

  • 1. Motion detected - Capture frame
  • 2. Frame - UART - Pico 2W
  • 3. Pico - HTTP POST - Server
  • 4. Server analyzes with YOLOv5
  • 5. If pet detected - "ALARM" response
  • 6. Pico triggers water pump + buzzer

Technical Implementation

AI Pet Detection

The server uses YOLOv5 large model for high accuracy pet detection:
Python
# Load YOLOv5 model
model = torch.hub.load('ultralytics/yolov5', 'yolov5l', pretrained=True)
model.conf = 0.25  # Confidence threshold
model.iou = 0.45   # IoU threshold for NMS

# Target pet classes from COCO dataset
target_classes = [15, 16, 17, 21]  # Cat, Dog, Sheep, Bear
class_names = {15: 'Cat', 16: 'Dog', 17: 'Sheep', 21: 'Bear'}

# Process detection
results = model(image)
detections = results.pandas().xyxy[0]
pet_detections = detections[detections['class'].isin(target_classes)]

if len(pet_detections) > 0:
    # Draw bounding boxes and send alarm
    annotated_image = draw_detection_boxes(image, pet_detections)
    send_alarm_notification(annotated_image)
    return "ALARM"

Alarm & Deterrent System

The Pico 2W controls a latching relay module for water pump and PWM buzzer for audio alerts.
C
/** 
 * @brief Alarm timing
*/
#define ALARM_DURATION_MS      5000   // Total alarm duration
#define PUMP_TOGGLE_COUNT      3      // Number of pump activations  
#define PUMP_TOGGLE_DELAY_MS   1500   // Delay between toggles
#define RELAY_PULSE_MS         100    // Pulse duration for latching relay

Custom Yocto Linux Build

The BeagleBone Black runs a custom Yocto Linux distribution (kirkstone) with the meta-petwatch layer:

petwatch-image.bb
SUMMARY = "PetWatch System Image"
DESCRIPTION = "Minimal Linux image with PetWatch application"

inherit core-image

# Core packages
IMAGE_FEATURES += "ssh-server-openssh"

IMAGE_INSTALL:append = " \
    kernel-modules \
    kernel-devicetree \
    config-pin \
    systemd-serialgetty \
    openssh \
    python3 \
    python3-modules \
    python3-opencv \
    python3-pyserial \
    python3-numpy \
    v4l-utils \
    usbutils \
    petwatch \
    "

# Camera, UART and USB support
IMAGE_INSTALL:append = " \
    kernel-module-uvcvideo \
    kernel-module-usb-storage \
    "

Layer Configuration

  • Base: Poky
  • Machine: BeagleBone Black (Sitara AM335x)
  • Dependencies: meta-openembedded, meta-arm, meta-ti
  • Custom Recipes: petwatch app, config-pin utility, UART overlay
  • Kernel Patches: Enable UART1 on P9_24/P9_26 pins

Hardware Components

BeagleBone Black Connections

  • USB Port - any UVC-compatible camera
  • P9_24 (UART1_TX) - Pico GP5 (RX)
  • P9_26 (UART1_RX) - Pico GP4 (TX)
  • GND - Common ground
  • Power - Mini USB or 5V/2A barrel jack. (I used mini USB connected to powerbank)

Raspberry Pi Pico 2W Pinout

  • GP4 (UART1_TX) - BBB P9_26
  • GP5 (UART1_RX) - BBB P9_24
  • GP12 - Relay connected to water pump
  • GP14 - Buzzer module (PWM)
  • VSYS - 5V power input for buzzer module

Peripherals

  • Camera: Any USB UVC webcam
  • Relay: Latching relay module (12V)
  • Water Pump: 12V submersible pump
  • Buzzer: Passive buzzer module
  • Power: Powerbank to power both BBB and Pico 2W

Server Requirements

  • OS: Linux
  • Python: 3.8+
  • GPU: Optional (CUDA support)
  • Network: Static IP

Software Stack

BeagleBone Black

  • Yocto Linux - kirkstone LTS
  • Python - Application runtime
  • OpenCV - Computer vision
  • systemd - Service management
  • pySerial - UART communication

Raspberry Pi Pico 2W

  • Pico SDK - Development framework (if you are using VS Code like me just use the dedicated Pico extension)
  • CYW43 Driver - WiFi support
  • lwIP - TCP/IP stack
  • CMake - Build system

Detection Server

  • PyTorch - Deep learning framework
  • YOLOv5 - Object detection
  • Pillow - Image processing
  • NumPy/Pandas - Data handling
  • smtplib - Email notifications

System Configuration

config.h
// Network configuration
#define WIFI_SSID               "SomeSSID"
#define WIFI_PASSWORD           "SomePassword" 
#define PC_SERVER_IP            "192.168.1.1xx"
#define PC_SERVER_PORT          7702

// BBB communication
#define BBB_UART_ID             uart1
#define BBB_UART_BAUD           460800
#define BBB_UART_TX_PIN         4
#define BBB_UART_RX_PIN         5

// Hardware pins
#define PUMP_RELAY_PIN          12
#define BUZZER_PIN              14

// Frame protocol
#define MAX_IMAGE_SIZE          (100 * 1024)  // 100KB max
#define IMAGE_TIMEOUT_MS        15000
#define FRAME_TIMEOUT_MS        5000

// Alarm configuration  
#define ALARM_DURATION_MS       5000
#define PUMP_TOGGLE_COUNT       3
#define PUMP_TOGGLE_DELAY_MS    1500
#define BUZZER_BEEP_COUNT       10
#define BUZZER_BEEP_DELAY_MS    250
watch.py
#!/usr/bin/env python3

# Camera configuration
CAM_ID = 0  # /dev/video0
camera_resolution = (640, 480)
camera_fps = 10

# UART configuration
TTY_DEV = "/dev/ttyS1"
BAUDRATE = 460800

# Motion detection thresholds
bg_history = 300          # Frames for background model
var_threshold = 20        # Variance threshold
motion_threshold = 300    # Minimum motion area
motion_cooldown = 1.5     # Seconds between captures

# JPEG compression
jpeg_quality_low = 70     # For high motion
jpeg_quality_high = 85    # For moderate motion
server.py
# Email configuration
notification_emails = ["receiver@example.com"]
smtp_server = "smtp.gmail.com"
smtp_port = 587
email_user = "sender@gmail.com"
email_password = "app_specific_password"

# YOLOv5 detection settings
model_variant = 'yolov5l'
confidence_threshold = 0.25
iou_threshold = 0.45
target_classes = [15, 16, 17, 21]

# Server configuration
server_port = 7702
server_address = '0.0.0.0'

Challenges & Solutions

  • Challenge: Reliable high-speed UART communication between BBB and Pico
    Solution: Implemented frame protocol with CRC-16 validation and interrupt driven ring buffer
  • Challenge: WiFi disconnections causing system failures
    Solution: Added automatic reconnection with exponential backoff and state preservation
  • Challenge: Low trigger relay module requiring specific pulse patterns
    Solution: Implemented pulse generation with Hi-Z state management to avoid interference
  • Challenge: Building minimal yet functional Yocto image
    Solution: Created custom meta-petwatch layer with only essential packages