Fun Cameras

Wildlife observation with self-tinkered camera units

Posted by Falk Mielke on 11th Jun 2021

Introduction

Thanks to the ambitious plans of a fellow PhD student and our lab technician Jan, I recently had fun setting up wildlife cameras!

The basic idea is to build autonomous camera stations from SOC Computers (in this case Raspberry Pi zero with a PiCamera) which are battery powered. Enclose them in a weather-sealed plastic box, hang them in the woods, start recording, and return later to grab your videos.

Several technical achievements enabled this project, which I will briefly document below.

Table of Contents

  1. Introduction
  2. (1) Python Sockets for network control
  3. (2) Streaming with gstreamer or raspivid
  4. (3) WiFi Hotspot setup
  5. Further Remarks

To present this to our bosses, we made a spontaneous advertisement video (4 min).

And, of course, the code is available: https://gitlab.com/falkm/funcameracaptain

This would integrate well with soldered controls, such as buttons and switches. And with camera calibration, one can cheaply get 3D data from the field.

(1) Python Sockets for network control

One or multiple processors on one or multiple computers may run processes in parallel. The problem is that these two processes are not always independent, they require information from each other. This is where sockets are useful. Sockets are not the only and not always the best method of process interaction, but they are commonly used in networking, i.e. when the parallel procedures are executed on different computers connected by a network. And they are basic python.

I cannot add much beyond what is found in the python documentation. Their implementation is straight forward. I call them “ear” here, although they technically are ear and mouth.

Here is how to define a socket:

import socket as SOCK
ear = SOCK.socket(SOCK.AF_INET, SOCK.SOCK_DGRAM)
ear.bind(self_address)

My communication paradigm is that the captain sends commands to its pirates, then waits for a response, and kills the pirate if it doesn’t respond.

Firstly, the message is initiated. In the case of the cameras, messages are short string codes associated with certain control procedures.

message = 'ping'.encode('utf-8') # message needs to be in pirate language (encoding).

try:
    ear.sendto(message, pirate_addr)
except OSError as ose:
    print('the network is disconnected.')

It might be that the ping is never returned, which is problematic. So we set a timeout (see here and here ).

# wait for confirmation from the pirates.
ear.settimeout(1.)
try:
    data, addr = ear.recvfrom(1024)
    pirate_ping = data.decode('utf-8')
except SOCK.timeout as to:
    return ':('

# de-activate timeout (starting streams takes longer)
ear.settimeout(None)

Finally, when all is done, the socket should be explicitly disconnected.

ear.close()

(2) Streaming with gstreamer or raspivid

I much appreciate the power of linux terminal commands. GStreamer is a perfect example for it.

GStreamer commands will easily get complex, due to “pipelines” (blocks of video operations that modify the stream). This lovely little command will stream a video test image to a mov file.

gst-launch-1.0 -e -v videotestsrc ! width=640,height=480,framerate=5/1 ! tune=zerolatency quantizer=30 speed-preset=fast ! qtmux ! filesink location=testing/test_pirate.mov sync=false -e

Luckily I succeeded in searching my way through the web and in finding general and specific reference pipelines. After a while, one familiarizes with the standard building blocks (source, encoding, muxing, sink) and learns to control the command.

The reward is an almost infinitely versatile video conversion tool, which can easily be integrated into other program blocks. GStreamer is also extraordinarily resource-efficient, thereby enabling quite high quality recordings on the limited hardware.

The tool is versatile in terms of supported formats for audio and video. For example, it takes few modifications to stream audio via network - for example to direct music to a dedicated hifi/multimedia player via network.

I can just encourage anyone to not be petrified by the seemingly incomprehensive commands, and the regular occurrence of bugs when changing them. Be brave: there’s a lot of help out there!

(3) WiFi Hotspot setup

Imagine you have several camera stations distributed in the field. Then you want to have a routine of walking the captains round, collecting bounty, and rebooting one or the other disobedient pirate. This should happen without physical interaction (though the battery is a limit).

Hence, WiFi control is required. Unfortunately we do not run around with a WiFi router. Or, do we? Isn’t a router just another little compouter which distributes your home network traffic? Indeed!

So let’s turn our pirate cameras into access points!

There are many guides for this out there. They vary with make, operating system, software versions.

Here’s a plain list of what worked in my case:

### network configuration
https://thepi.io/how-to-use-your-raspberry-pi-as-a-wireless-access-point/
https://linuxnatives.net/2014/create-wireless-access-point-hostapd
https://www.cyberciti.biz/faq/debian-ubuntu-linux-setting-wireless-access-point/
https://www.cyberciti.biz/faq/howto-ubuntu-debian-squeeze-dhcp-server-setup-tutorial/
https://raspberrypi.stackexchange.com/questions/88214/setting-up-a-raspberry-pi-as-an-access-point-the-easy-way/88234#88234

## install hostapd and dnsmasq
sudo apt-get install hostapd dnsmasq

## turn off services
sudo systemctl stop hostapd
sudo systemctl stop dnsmasq

## add lines to
sudo vim /etc/dhcpcd.conf

interface wlan0
static ip_address=192.168.1.1/24
static domain_name_servers=8.8.8.8 8.8.4.4
# denyinterfaces eth0
# denyinterfaces wlan0

## configure interfaces
sudo vim /etc/network/interfaces

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

allow-hotplug wlan0
#auto wlan0
iface wlan0 inet static
      # hostapd /etc/hostapd/hostapd.conf
      address 192.168.1.1
      netmask 255.255.255.0

## wpa_supplicant
sudo vim /etc/wpa_supplicant/wpa_supplicant.conf

country=BE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

## dnsmasq config
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
sudo vim /etc/dnsmasq.conf

interface=wlan0
  dhcp-range=192.168.1.11,192.168.1.200,255.255.255.0,24h

## configure hostapd
sudo vim /etc/hostapd/hostapd.conf

interface=wlan0
driver=nl80211
country_code=BE
hw_mode=g
channel=6
ieee80211n=1
# wmm_enabled=0
wmm_enabled=1
ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP
ssid=pirate_ap
wpa_passphrase=...

## add to system conf
sudo vim /etc/default/hostapd

DAEMON_CONF="/etc/hostapd/hostapd.conf"

# DHCPD config
sudo vim /etc/dhcp/dhcpd.conf

ddns-update-style none;
option domain-name "funmorph.cam";

option domain-name-servers 192.168.1.2, 192.168.1.3;
default-lease-time 86400;
max-lease-time 604800;
authoritative;

subnet 192.168.1.0 netmask 255.255.255.0 {
        ## dhcp start  and end IP range ##
        range 192.168.1.10 192.168.1.200;
        option subnet-mask 255.255.255.0;     ## subnet
        option broadcast-address 192.168.1.255; ## broadcast
        option routers 192.168.1.254; ## router IP
}

## enable services
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl enable dnsmasq
sudo systemctl restart dhcpcd

## check that all services are loaded
systemctl status dhcpcd
systemctl daemon-reload
systemctl restart dhcpcd

## reboot

Further Remarks

Of corse I did not invent any of this myself. There are professional providers of tinkering wildlife cameras out there, such as mynaturewatch. We started using our own software because their cameras use motion detection to just film if there is something moving in front of the camera. That feature is great for long term observations. Our task, however, involved constant recording for a fixed time to store a given experimental paradigm in a controlled manner. The mynaturewatch cameras are a great starter; and I am glad we were able to replicate something like this.

Another huge benefit is the headless linux system which runs on the pi’s. GStreamer was one example of a powerful tool directly available in the command line. Another one is cron, which enables periodic execution of programs. For example, one could very easily program a pirate to capture an image once every minute.

I’ve mentioned the options of soldering buttons and 3D calibration above.

Just be creative, and enjoy tinkering!


  1. Introduction
  2. (1) Python Sockets for network control
  3. (2) Streaming with gstreamer or raspivid
  4. (3) WiFi Hotspot setup
  5. Further Remarks

Note that I switched to emacs org mode for generating my notes, so apologies for errors.