← Portfolio
Picammory

Picammory Mark II

The garden's camera based on Raspberry Pi — with motion detection.

Open-source hardware · Raspberry Pi · GPL-2.0

Introduction

The Picammory camera in the garden

This project builds a waterproof, high-definition camera. The camera:

  1. Takes an hourly full-definition picture of the garden
    • to create high-speed movies of the garden over the years,
    • to see how the garden changes under different watering settings;
  2. Detects and records intrusions in a noisy environment (trees, leaves, wind, sun…)
    • for security,
    • for watching the squirrels.
The finished camera

Picammory has the following capabilities:

  • Captures one full-size image every hour
  • A mix of Python 3 and C for fast image processing — 100 ms capture, 26 ms processing
  • Records continuous HD video in memory, keeping ~10 s before the trigger event
  • Uploads movies to an FTP server
  • Automatic start at boot, and auto-restart after a crash (restartd)
  • Automatic h.264 → mp4 conversion for easy viewing on Mac/PC
  • Bonjour to advertise services, and AFP file sharing with the Mac

A 5-stage motion-detection algorithm

  1. A moving average of the previous images (with low memory usage)
  2. The difference between that moving average and the current image
  3. A moving-average mask to automatically remove noisy pixels
  4. Surface detection to convert adjacent pixels into surfaces (a very efficient algorithm)
  5. Surface processing to detect motion

Hardware build

Overview of the camera build
An overview of the process to build the camera.

Camera body

The body is an aluminium housing with good waterproofing and an excellent two-axis orientation system. The inside is very roomy — a platform on a rail secures the circuit board.

Inside the camera housing
Roomy inside, with a rail platform for the board.

Component platform

The Raspberry Pi and all future components sit on a platform cut from a 0.080″ styrene sheet, so the Pi is easy to insert and remove. From a 12×12″ sheet I cut a 3.5″ (90 mm) band.

The cut styrene band

I bend one end to a 90° angle — this forms the front that covers the body's window. Bending is easy once the styrene is warmed with a heat tool (a Portasol 75 W).

Bending the styrene with a heat tool

Camera mount

The square camera hole

A square hole is drilled in the middle of the platform to hold the camera — roughed out with a Dremel and a 194 high-speed cutter, then trued up with a precision blade (an X-ACTO).

Raspberry Pi attach

The Pi centred on the platform

The Pi is centred on the platform, at a comfortable distance for the camera cable. I drill four holes with a No 43 drill and tap a 4-40 NC female thread. To avoid a misplaced hole, test-fit the Pi after each drilling.

Nylon hex standoffs

Screw in the four nylon hex standoffs (#4-40, 1/4″).

The Pi on the standoffs

Put the Pi on the standoffs, secure with four screws, and check that everything fits.

Cutting the standoff screws flush

Cut off the small part of the standoff screws poking through the styrene, or they will stop the sheet from sitting flat on the camera platform. (Alternatively, invert the order — make the Pi attach and the camera platform together, and drill the standoff holes through both.) The Pi is set; remove it and keep it safe until the final integration.

Component platform on the rail

The component platform on the camera rail

The component platform is fixed on top of the camera's rail platform. The camera's existing 8 holes are hard to use — they're in direct contact with the rail, with no room for a nut or screw head — and because a fair bit of force is needed to unclip the platform from the rail, I add nuts here.

Aligning the two platforms

The camera platform sits under the component platform, centered in width but aligned to one end to limit traction when it's unclipped from the camera. The plan: drill six holes, tap a female thread, plus four nuts at the end.

Normally it's a bad idea to assemble several pieces with female threads — it's hard to make it right and tight through all layers; better to leave the holes un-threaded and use nuts. But here the plastic is malleable and I tap all the pieces at once, so it's fine, and more threads give a better coupling. Using a No 43 drill and a 4-40 NC tap: drill the left (border) hole first, tap it, and bolt it to hold position; do the same for the opposite diagonal hole; now that everything is held together, safely drill the four remaining holes.

Waterproof Ethernet connector

The first version was weak on waterproofing where the network cable entered; the second uses a waterproof RJ45 coupler.

The RJ45 coupler and the body hole

The body's existing hole is 18.9 mm and the coupler is 25 mm — a bigger hole is needed. The box is 1.2 mm aluminium, so a Dremel with the 194 cutter handles it easily.

The hole must be shifted

The rail blocks a symmetrical expansion, so the hole must be shifted. Before removing any metal, draw the part to remove carefully — here, black is the metal to cut and red the limit not to pass.

The coupler is made to join two Ethernet cables and waterproof both sides; since one side sits inside the already-waterproof box, I remove that side's seal for a lower profile.

The finished waterproof connector
An external network connector through a female-to-female RJ45 coupler — waterproof outside, low-profile inside.

Power over Ethernet

Standard Power over Ethernet is complex and expensive; a non-standard “passive” PoE is friendlier. 10Base-T and 100Base-T need only 4 of the 8 wires — the other 4 are free.

RJ45 pinWire colourWire Diagram100Base-T1000Base-T
1White/GreenTransmit+BI_DA+
2GreenTransmit−BI_DA−
3White/OrangeReceive+BI_DB+
4BlueUnusedBI_DC+
5White/BlueUnusedBI_DC−
6OrangeReceive−BI_DB−
7White/BrownUnusedBI_DD+
8BrownUnusedBI_DD−

The passive PoE injector uses the 4 remaining wires to provide power, grouping them by two:

WireConnected toProvides
4 (Blue) +5 (White/Blue) DC + (12 V)
8 (Brown) +7 (White/Brown) 0 V

The Pi needs 5 V, but 5 V can't be carried over a long distance (voltage drop) — usually 24 V or 48 V is used. Since the camera isn't far and the Cat6 is 23 AWG, I opt for 12 V DC; the DC/DC converter in the camera takes 5–23 V in and outputs 5 V.

Passive PoE injector

Passive PoE injector on the router side

On the router side, connect the passive PoE injector/splitter between the router and the cable to the camera, and connect a 12 V DC supply to its DC connector.

Passive PoE splitter

The same cable can extract the power, but the off-the-shelf splitter is bulky and doesn't provide the micro-USB the Pi needs — too complex for the camera side. Instead I make a compact custom splitter.

Stripping the Cat6 cable

Start with a 1-foot Ethernet cable and remove a band of the outer sheath near one end.

Joining the power pairs

Cut the Blue and White/Blue and solder them together; cut the Brown and White/Brown and solder them together.

Soldering to the DC/DC converter

Take the DC/DC converter, slip a small heat-shrink onto each power cable and a bigger one over both. Solder the Blue to the converter's Red , and the Brown to the Black .

Shrinking the tubing

Cover both power wires and shrink; do the same with the bigger tubing over the pair. Small tubings also go on the four remaining cut wires.

Covering all exposed wires

Finally, a big tubing covers all exposed wires.

Micro-USB male pinout

On the other side of the converter, cut off the supplied connector and replace it with a micro-USB.

Soldering the micro-USB

Solder the red and black wires to pins 1 and 5. Pins 1, 3 and 5 sit very close together — to avoid bridging pin 3, just cut it off the connector.

Gluing the micro-USB pin

Add a little hot glue on the micro-USB pin and cap it with heat-shrink.

The finished compact power cable
The final cable — compact and simple.
The cable in place
The Ethernet cable in place. (Later, a cable tie attaches the converter to the cable.)

Camera sensor

Finally, the little square hole takes the camera. Unlike the first version, the space between the sensor and the Pi lets the camera sit in its standard orientation.

The Pi camera in the mount

Final result

A very simple, clean build with plenty of room for future expansion. (The RGB LED and temperature/humidity sensor from the first version were dropped — they weren't very useful.)

Parts & cost

TypeReferenceQtyPrice
CPURaspberry Pi Model B+1$28.48
SensorRaspberry Pi 5 MP Camera Board Module1$25.00
Camera bodyWeatherproof aluminium CCTV housing (M57)1$24.99
EthernetAEAC waterproof RJ45 coupler, F–F, 25 mm1$14.99
Power supplyDC 12 V 2 A1$13.00
SD cardTranscend 16 GB1$7.85
DC/DC converterUBEC, 5–23 V in → 5 V 3 A out1$4.76
Power partHuacam HCP05 passive PoE injector/splitter1$3.45
BoardStyrene sheet, white, 12×12″, 0.08″1$2.75
EthernetCat6 patch cable, 1 ft1$2.00
ScrewNylon 6/6 machine screw, pan head, #4-40, 1/4″10$0.51
ScrewNylon hex standoff, male-female, #4-40, 1/4″4$0.44
ConnectorMicro-USB Type A male, 5-pin1$0.39
ScrewNylon 6/6 hex nut, #4-404$0.23
MiscHeat-shrink tubing1$0.10
Total$128.94

Software installation & setup

A step-by-step installation.

Setting up the Raspberry Pi

Download and install Raspbian per raspberrypi.org/downloads. (At the time of writing I used the raw Raspbian image, release 2015-02-16.) With the micro-SD card in a USB reader, run something like:

diskutil list
diskutil unmountDisk /dev/<disk# from diskutil>
sudo dd if=path_of_your_image.img of=/dev/<disk# from diskutil> bs=1m

⚠︎ Giving a wrong device to /dev/<disk#> can wipe your computer — be extremely careful with dd. Then wait a long time, and insert the card into the Pi.

Raspbian initial settings

Connect to the new Pi and start the configuration:

$ ssh pi@<ip address>
  password: raspberry
$ sudo raspi-config

Modify the following:

  • 1 — Expand Filesystem
  • 2 — Change User Password
  • 4 — Internationalisation Options
    • I1 Change Locale — remove en_GB.UTF-8, add en_US.UTF-8, set it as default
    • I2 Change Timezone — e.g. US · Pacific
  • 5 — Enable Camera
  • Advanced Options → A2 Hostname → PiCammoryGarden
  • Finish → Reboot now → Yes

Only step 5 is required; 1 and 2 are strongly suggested. If raspi-config doesn't offer to reboot, do it manually with sudo shutdown -r now. After rebooting, check the date/timezone with date.

Update Raspbian

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rpi-update

A reboot activates the new firmware.

Install Netatalk & Bonjour

Netatalk is an open-source AFP file server. With it (and Bonjour), Picammory shows up in the macOS Finder and you can copy files over AFP; advertising SSH is just a nice touch.

$ sudo apt-get install netatalk

Register AFP (file sharing with the Mac):

$ sudo nano /etc/avahi/services/afpd.service

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
    <name replace-wildcards="yes">%h</name>
    <service>
        <type>_afpovertcp._tcp</type>
        <port>548</port>
    </service>
</service-group>

Register SSH (remote shell):

$ sudo nano /etc/avahi/services/ssh.service

<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
    <name replace-wildcards="yes">%h</name>
    <service>
        <type>_ssh._tcp</type>
        <port>22</port>
    </service>
</service-group>

Restart the Avahi mDNS daemon:

$ sudo /etc/init.d/avahi-daemon restart

The Pi should now be visible in the Finder as PiCammoryGarden; connect with the pi account. Optionally, test Bonjour:

$ sudo apt-get install avahi-utils
$ avahi-browse -a | grep PiCammoryGarden
+  eth0 IPv4 PiCammoryGarden   Remote Disk Management  local
+  eth0 IPv4 PiCammoryGarden   SSH Remote Terminal     local
+  eth0 IPv4 PiCammoryGarden   Apple File Sharing      local
+  eth0 IPv4 PiCammoryGarden   Workstation             local

Install PiCamera, PIL & GPAC

PiCamera is a pure-Python interface to the camera module (Python 3.2+); PIL/Pillow is the imaging library; GPAC is the multimedia framework used for the h.264 → mp4 conversion.

$ sudo apt-get install python3-picamera
$ sudo apt-get install python3-pip
$ sudo pip-3.2 install Pillow
$ sudo apt-get install gpac

Install Picammory

Clone the sources — last released version, or the development branch:

$ git clone https://github.com/pmermoz/picammory.git ~/picammory
# or, for the development version:
$ git clone https://github.com/pmermoz/picammory.git -b develop ~/picammory

Build the C code (optional — Picammory rebuilds it at startup):

$ cd ~/picammory; python3 setup.py build_ext --inplace; cd ..

Create the log folder:

$ sudo mkdir /var/log/picammory
$ sudo chown pi /var/log/picammory

Edit the configuration file:

$ cp ~/picammory/picammory.ini_template ~/picammory/picammory.ini
$ nano ~/picammory/picammory.ini
SectionNameDescription
[camera]nameName for your camera — prefixes the generated filenames
[smtp]Picammory mails you system status and detection events
usernameYour email account username
passwordYour email account password
usetls · serverYES for TLS; server & port (e.g. smtp.mailserver.com:587)
[email]recipientAddress(es) for the alerts
senderIdentifies the program (e.g. GardenCam <cam@domain.com>)
[ftp]usernameFTP username — Picammory uploads videos/pictures here
passwordFTP password
serverFTP server address

Automatic start at boot

$ sudo cp ~/picammory/etc/init.d/picammory /etc/init.d/
$ sudo chmod 755 /etc/init.d/picammory
$ sudo update-rc.d picammory defaults

Automatic restart

restartd is a daemon that watches processes and restarts one if it dies (it can take up to ~20 s).

$ sudo apt-get install restartd
$ sudo nano /etc/restartd.conf

picammory ".*picammorydaemon.py*" "service picammory restart"

Finally, reboot

$ sudo shutdown -r now