Skip to main content
Patrick’s Preoccupations
  • Contact
  • Notes
  • Projects
    • Hedgehog Camera
      • Webcam unreliability

Hedgehog Camera contents

  • Hedgehog Camera
    • IR illuminator
    • Powering the router
    • Installing OpenWRT
    • Video capture
    • USB flash drive power
    • PIR motion detector
    • Webcam unreliability
    • Better automation
    • USB flash drive failure
    • Footage

Working around webcam reliability issues

By Patrick Wigmore, May 2020, published: 16 July 2023, updated July 2023

After running the Hedgehog Home Hub for some time, I came to realise: There did seem to be an issue with the webcam crashing, and it did seem to require the camera to be power-cycled in order to recover from it

I don’t know whether my webcam was defective, or whether it was simply not designed to be left plugged in for more than a few hours at a time, or whether I damaged it by not giving it a very good power supply. Whichever way, I wasn’t going to buy a new one, so finding a way to power cycle the existing camera looked like the only option.

The buck regulator supplying the USB voltage does actually have an enable terminal on it. So I decided to take an output from the red broadband LED to control this enable, so that when the LED comes on, the 5V power is cut, resetting all the USB devices when the LED goes out.

Showing the connection to the red broadband LED to get a signal to enable and disable the 5V regulator. A shrink-wrapped resistor is in-line with the signal.
Connection to the red broadband LED.

Then, I modified my hhcam-record script so that if v4l2-ctl exits with an error, or if the camera’s device file is not present, the LED flashes once, briefly, before trying again, to power-cycle the camera.

In fact, it’s a bit more complicated than that. The flash drive needs to be unmounted and re-mounted at the appropriate points. I later discovered that, if there is still a v4l2-ctl process running, it needs to be terminated so that the flash drive can be unmounted cleanly.

I ended up splitting the functionality up into a couple of scripts;

  • hhcam-power to abstract away the detail of turning the LED on or off
  • hhcam-usbreset to kill remaining v4l2-ctl processes, unmount the flash drive and cycle the USB power

/sbin/hhcam-power:

#!/bin/sh

# Script to set USB power state on the modified BT Home Hub.
# This script has no niceties like checking whether it's a good idea
# to turn the power on or off. It's just a raw on/off control.

if [[ "$1" == "on" ]]; then
    /bin/echo "0" > /sys/class/leds/bthomehubv5a\:red\:broadband/brightness
    
elif [[ "$1" == "off" ]]; then
    /bin/echo "255" > /sys/class/leds/bthomehubv5a\:red\:broadband/brightness
    
elif [[ "$1" == "" || "$1" == "status" ]]; then
    usb_power_state=$(cat /sys/class/leds/bthomehubv5a\:red\:broadband/brightness)
    if [[ $usb_power_state -eq 0 ]]; then
        echo "on"
    else
        echo "off"
    fi
    
else
    echo "Usage: $0 [on|off|status]"
    echo "Set USB power state to \"on\" or \"off\", or show current state."
    echo "Current state is shown if action is not specified."
fi

/sbin/hhcam-usbreset:

#!/bin/sh

# Script to reset all the USB devices on the Hedgehog Home Hub.
# Intended to be used when the webcam hardware crashes.

# First, we need to unmount the flash drive

# If there are any lingering v4l2-ctl processes, those need terminating
# because they might prevent the filesystem from unmounting cleanly
if [[ "$(pgrep v4l2-ctl | wc -l)" -ne 0 ]]; then
    killall -q -s TERM v4l2-ctl

    # We need to hurry, because the longer we wait the bigger the gap
    # in our recordings will end up being, so only give it a second.
    sleep 1
    if [[ "$(pgrep v4l2-ctl | wc -l)" -ne 0 ]]; then
        killall -q -s KILL v4l2-ctl
    fi
fi

# Now we should be safe to unmount the flash drive
# If it wasn't successful, force the unmount
/bin/umount /mnt/hhusb || /bin/umount -f /mnt/hhusb

# Now, power-cycle the USB devices.

/sbin/hhcam-power off
sleep 1
/sbin/hhcam-power on

# Hotplug will re-mount flash drive automatically, as configured in uci
# (To see mount config, run 'uci show fstab'.)

Auto mounting the USB flash drive

To re-mount the flash drive, I configured OpenWRT to mount the flash drive when it was plugged in.

I installed the package block-mount. The OpenWRT Wiki seemed to imply that the block-mount package had been removed in favour of ubox, but what it actually meant was that the original block-mount package had been replaced by a new one that drew its functionality from ubox, so you still had to install block-mount in order to use the functionality.

opkg install block-mount

I could view the current uci config for fstab:

uci show fstab

This gave me:

fstab.@global[0]=global
fstab.@global[0].anon_swap='0'
fstab.@global[0].anon_mount='0'
fstab.@global[0].auto_swap='1'
fstab.@global[0].auto_mount='1'
fstab.@global[0].delay_root='5'
fstab.@global[0].check_fs='0'

Block detect provides a sample configuration on the standard output, which can be piped into uci to set a new config.

block detect | uci import fstab

uci can then be made to show the config

uci show fstab

This gave me:

fstab.@global[0]=global
fstab.@global[0].anon_swap='0'
fstab.@global[0].anon_mount='0'
fstab.@global[0].auto_swap='1'
fstab.@global[0].auto_mount='1'
fstab.@global[0].delay_root='5'
fstab.@global[0].check_fs='0'
fstab.@mount[0]=mount
fstab.@mount[0].target='/mnt/sda1'
fstab.@mount[0].uuid='8DC7-2C15'
fstab.@mount[0].enabled='0'

Which was not quite what I wanted, so I changed it a little.

uci set fstab.@mount[0].target='/mnt/hhusb'
uci set fstab.@mount[0].enabled='1'

I later realised it would be worth adding:

uci set fstab.@mount[0].options='noatime,errors=continue'

Then the settings can be committed

uci commit

Then, block mount mounts the drive, and it is also mounted on hotplug events.

© 2017-2023 Patrick Wigmore