Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 7503

Camera board • Re: Complete Guide: Raspberry Pi Zero 2 W USB Webcam Setup

$
0
0
## Step 1: Fresh OS Installation

1. **Download Raspberry Pi OS Lite** from the official website

Doesn't need to be lite. This will work with the Desktop images too.

Imager does the download for you so this is not necessary.
2. **Flash to microSD** using Raspberry Pi Imager
3. **Enable SSH** by creating empty file named `ssh` in boot partition
4. **Configure WiFi** by creating `wpa_supplicant.conf` in boot partition:
```
country=US
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
ssid="YourWiFiName"
psk="YourWiFiPassword"
}
```

That's not going to work on Bookworm as it uses Network Manager not wpa_supplicant and that mechanism is no longer supported. Set it via Imager instead.

And not everyone needs a country of US. Despite what its President thinks there are 194 other countries most of which have different rules and regulations.
5. **Boot the Pi** and connect via SSH: `ssh pi@raspberrypi.local`

Not going to work. There will be no configured user account. The Pi will be running the first boot wizzard on the local console asking you to configure one.
## Step 2: Configure USB Gadget Mode

### Edit Boot Configuration

```bash
# Edit config.txt
sudo nano /boot/config.txt

# Add these lines:
start_x=1
dtoverlay=imx708

# Change camera_auto_detect to 0:
camera_auto_detect=0

Nope. Not needed.
# Add at the end:
dtoverlay=dwc2,dr_mode=peripheral
```

,dr_mode=peripheral is not required on any zero series Pi. It's the hardware default. [edit]TO clarify, unless the ID pin in the uUSB data connector is pulled low both the driver and hardware default to peripheral mode.[/edit]
### Edit Command Line Parameters

```bash
# Edit cmdline.txt
sudo nano /boot/cmdline.txt

# Add modules-load=dwc2 to the end of the single line
# Example result:
# console=serial0,115200 console=tty1 root=PARTUUID=xxx rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=US modules-load=dwc2
```

Not required. Enabling the overlay automatically gets the dwc2 module loaded.
### Enable Required Modules

```bash
# Add USB gadget modules
echo 'dwc2' | sudo tee -a /etc/modules
echo 'libcomposite' | sudo tee -a /etc/modules
```

### Reboot and Verify

```bash
sudo reboot

# After reboot, verify gadget mode:
lsusb # Should be empty (no USB devices)
lsmod | grep -E "(dwc2|libcomposite)" # Should show modules loaded
```

## Step 3: Install Dependencies

```bash
# Update system
sudo apt update
sudo apt upgrade -y

# Install build tools and dependencies
sudo apt install -y git cmake build-essential pkg-config
sudo apt install -y libcamera-dev libcamera-apps libevent-dev
sudo apt install -y libjpeg-dev libjpeg62-turbo-dev
sudo apt install -y meson ninja-build
sudo apt install -y v4l-utils
```

## Step 4: Download and Build UVC Gadget

```bash
# Clone the official UVC gadget repository
cd /home/pi
git clone https://gitlab.freedesktop.org/camera/uvc-gadget.git
cd uvc-gadget

# Checkout the stable commit
git checkout 04c18aa

# Build with meson
meson build
ninja -C build

# Install the binary and library
sudo cp build/src/uvc-gadget /usr/bin/
sudo chmod +x /usr/bin/uvc-gadget
sudo ninja -C build install
sudo ldconfig

# Verify installation
/usr/bin/uvc-gadget -h
# Should show -c option for libcamera support
```

## Step 5: Create USB Gadget Configuration Script

Create the configuration script:

```bash
nano /home/pi/.rpi-uvc-gadget.sh
```

Why are you hiding it? Why not put it where is belongs: $HOME/bin or /usr/local/bin?
Add this content:

```bash
#!/bin/bash

# Variables we need to make things easier later on.

CONFIGFS="/sys/kernel/config"
GADGET="$CONFIGFS/usb_gadget"
VID="0x0525"
PID="0xa4a2"
SERIAL="0123456789"
MANUF=$(hostname)
PRODUCT="UVC Gadget"
BOARD=$(strings /proc/device-tree/model)
UDC=`ls /sys/class/udc` # will identify the 'first' UDC

# Later on, this function is used to tell the usb subsystem that we want
# to support a particular format, framesize and frameintervals
create_frame() {
# Example usage:
# create_frame <function name> <width> <height> <format> <name> <intervals>

FUNCTION=$1
WIDTH=$2
HEIGHT=$3
FORMAT=$4
NAME=$5

wdir=functions/$FUNCTION/streaming/$FORMAT/$NAME/${HEIGHT}p

mkdir -p $wdir
echo $WIDTH > $wdir/wWidth
echo $HEIGHT > $wdir/wHeight
echo $(( $WIDTH * $HEIGHT * 2 )) > $wdir/dwMaxVideoFrameBufferSize
cat <<EOF > $wdir/dwFrameInterval
$6
EOF
}

# This function sets up the UVC gadget function in configfs and binds us
# to the UVC gadget driver.
create_uvc() {
CONFIG=$1
FUNCTION=$2

echo " Creating UVC gadget functionality : $FUNCTION"
mkdir functions/$FUNCTION

create_frame $FUNCTION 640 480 uncompressed u "333333
416667
500000
666666
1000000
1333333
2000000
"
create_frame $FUNCTION 1280 720 uncompressed u "1000000
1333333
2000000
"
create_frame $FUNCTION 1920 1080 uncompressed u "2000000"
create_frame $FUNCTION 640 480 mjpeg m "333333
416667
500000
666666
1000000
1333333
2000000
"
create_frame $FUNCTION 1280 720 mjpeg m "333333
416667
500000
666666
1000000
1333333
2000000
"
create_frame $FUNCTION 1920 1080 mjpeg m "333333
416667
500000
666666
1000000
1333333
2000000
"

mkdir functions/$FUNCTION/streaming/header/h
cd functions/$FUNCTION/streaming/header/h
ln -s ../../uncompressed/u
ln -s ../../mjpeg/m
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../class/ss
ln -s ../../header/h
cd ../../../control
mkdir header/h
ln -s header/h class/fs
ln -s header/h class/ss
cd ../../../

# This configures the USB endpoint to allow 3x 1024 byte packets per
# microframe, which gives us the maximum speed for USB 2.0. Other
# valid values are 1024 and 2048, but these will result in a lower
# supportable framerate.
echo 2048 > functions/$FUNCTION/streaming_maxpacket

ln -s functions/$FUNCTION configs/c.1
}

# This loads the module responsible for allowing USB Gadgets to be
# configured through configfs, without which we can't connect to the
# UVC gadget kernel driver
echo "Loading composite module"
modprobe libcomposite

# This section configures the gadget through configfs. We need to
# create a bunch of files and directories that describe the USB
# device we want to pretend to be.

if [ ! -d $GADGET/g1 ]; then
echo "Detecting platform:"
echo " board : $BOARD"
echo " udc : $UDC"

echo "Creating the USB gadget"

echo "Creating gadget directory g1"
mkdir -p $GADGET/g1

cd $GADGET/g1
if [ $? -ne 0 ]; then
echo "Error creating usb gadget in configfs"
exit 1;
else
echo "OK"
fi

echo "Setting Vendor and Product ID's"
echo $VID > idVendor
echo $PID > idProduct
echo "OK"

echo "Setting English strings"
mkdir -p strings/0x409
echo $SERIAL > strings/0x409/serialnumber
echo $MANUF > strings/0x409/manufacturer
echo $PRODUCT > strings/0x409/product
echo "OK"

echo "Creating Config"
mkdir configs/c.1
mkdir configs/c.1/strings/0x409

echo "Creating functions..."

create_uvc configs/c.1 uvc.0

echo "OK"

echo "Binding USB Device Controller"
echo $UDC > UDC
echo "OK"
fi

# Run uvc-gadget. The -c flag sets libcamera as a source, arg 0 selects
# the first available camera on the system. All cameras will be listed,
# you can re-run with -c n to select camera n or -c ID to select via
# the camera ID.
uvc-gadget -c 0 uvc.0
```

Make it executable:

```bash
chmod +x /home/pi/.rpi-uvc-gadget.sh
```

## Step 6: Test Manual Operation

```bash
# Run the configuration script
sudo /home/pi/.rpi-uvc-gadget.sh
```

You should see output showing:
- Platform detection
- USB gadget creation
- Camera detection with libcamera
- "Using camera imx708"
- Control requests from the host

## Step 7: Test with Host Computer

1. **Connect the Pi** to your computer using micro USB cable (data port, not power)
2. **Check Device Manager** (Windows) or System Information (Mac) - should show "UVC Gadget"
3. **Test with applications**:
- Windows Camera app
- OBS Studio
- VLC Media Player
- Web browser camera tests

## Step 8: Set Up Auto-Start

### Method 1: Using rc.local (Recommended)

```bash
sudo nano /etc/rc.local
```

Add before `exit 0`:

```bash
/home/pi/.rpi-uvc-gadget.sh &
```

Not recommended. /etc/rc.local is deprecated and no longer exists on a default RPiOS installation though it will be run if you create it and it has an appropriate shebang and the correct permissions.
### Method 2: Using systemd service

Create the systemd service:

```bash
sudo nano /etc/systemd/system/uvc-webcam.service
```

Add this content:

```ini
[Unit]
Description=UVC Webcam Setup
After=basic.target
Before=multi-user.target

[Service]
Type=simple
ExecStartPre=/bin/bash -c 'pkill -f libcamera || true'
ExecStartPre=/bin/bash -c 'pkill -f camera || true'
ExecStart=/home/pi/.rpi-uvc-gadget.sh
Restart=no
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
```

Enable the service:

```bash
# Reload systemd and enable service
sudo systemctl daemon-reload
sudo systemctl enable uvc-webcam.service
```

## Step 9: Final Testing

1. **Reboot the Pi**: `sudo reboot`
2. **Wait 30-45 seconds** for full boot and service startup
3. **Connect to computer** - should automatically work as plug-and-play webcam

This implies the Pi will have its own PSU as well as power from the USB host. Not a good idea as the higher voltage one will feed power to the lower voltage one. All 5V pins on a zero series Pi are directly connected.
4. **Test in multiple applications** to verify functionality

## Troubleshooting

### Camera Not Detected
```bash
# Check if camera is connected
libcamera-hello --list-cameras
# Should show: 0 : imx708 [4608x2592]

# Verify video devices exist
ls -la /dev/video*
```

### Service Not Starting
```bash
# Check if script is running
ps aux | grep uvc-gadget

# Check for errors
sudo journalctl -xe | grep -i uvc

# Run manually to see errors
sudo /home/pi/.rpi-uvc-gadget.sh
```

### UVC Gadget Binary Issues
```bash
# Check if binary has libcamera support
/usr/bin/uvc-gadget -h
# Should show -c option

# Check library dependencies
ldd /usr/bin/uvc-gadget
# Should show libuvcgadget.so.0
```

### Video Format Issues
```bash
# Check camera capabilities
v4l2-ctl --device=/dev/video0 --list-formats-ext
```

### Windows Compatibility
- Try different applications (OBS, VLC, browser tests)
- Check Device Manager for proper driver installation
- Ensure using data-capable USB cable

## Important Configuration Notes

The `/boot/config.txt` must include:
- `start_x=1` - Enables camera support
- `camera_auto_detect=0` - Disables auto-detection
- `dtoverlay=imx708` - Loads IMX708 driver for Pi Camera 3
- `dtoverlay=dwc2,dr_mode=peripheral` - Enables USB gadget mode

The script supports both:
- **Uncompressed formats** (YUYV) - Better compatibility
- **MJPEG formats** - Lower bandwidth usage

## Result

You now have a **plug-and-play USB webcam** that:
- ✅ Starts automatically on boot
- ✅ Works with Windows, Mac, and Linux
- ✅ Supports multiple resolutions (480p, 720p, 1080p)
- ✅ Requires no software installation on host computers
- ✅ Features auto-focus with Pi Camera 3
- ✅ Uses libcamera for optimal performance

Simply power on the Pi, wait ~30 seconds, then connect via USB to any computer for instant webcam functionality!

A couple of general points:
  • Markdown is not supported. You need to replace it with bbcode and/or appropriate tags.
  • It's not complete. What about other cameras? No mention of other methods to start at boot (hint: [shameless self promotion]Running A Program At Start Up A Beginner's Guide[/shameless self promotion]
  • The functionality is not limited to a zero2w. A, A+, 3A+, zero, zeroW[H], 4B, 400, 5, 500 and all CM series can also act as USB devices with minor variations (A series need to be forced into peripheral mode, 4B and later via the USB C port, CM series varies by carrier board).
  • Should work with any supported camera module if you stop loading a specific overlay and allow the firmware to do its job.

Statistics: Posted by thagrol — Fri Jul 04, 2025 2:05 pm



Viewing all articles
Browse latest Browse all 7503

Trending Articles