All posts by Simon

CatCam, version 5

CatCam v5 in situ with a light sprinkling of soap powder.

As mentioned in other posts we have cats. Originally, just the one stray cat who moved in. Then over time, others have drifted into the house, and stayed, and yet others have come and gone, including the odd fox. At a certain point I decided it was probably best to start trying to find out who was actually coming and going, I think it was just after the fox incident which surprised my wife and caused me some consternation as well (a story for another time but for Christmas reasons I was very, very drunk at the time). So I developed a CatCam to put near to where the catflap was in the back porch, or outhouse or whatever you would call the extra bit that Victorians added to the back of their houses in lieu of utility rooms and where they stuck their back doors. As people will note when pictures start appearing in this post the catflap actually doesn’t have a flap which was broken off during a cat fight some years ago and never replaced due to one of our cats treating it as a wall when the flap was closed which rather defeated the purpose of having it. Anyway, the CatCam itself went through a number of iterations over the years but originally started out around about 2015 or 2016… I think. Anyway, the iterations were:

  • CatCam v1 : was a Raspberry Pi 2 B with standard Rasp Pi camera and a USB WiFi dongle. It’s connectivity was terrible and lead to me getting WiFi repeater stations throughout the house. No idea what the Victorians put in their bricks they used for their internal walls but it obviously contained a lot of iron. The software in this iteration took still pictures and was triggered via a Passive Infra Red (PIR) detector. Because of the wide angle of the PIR it tended to take several images and a lot of them were empty of animals. A subsidiary version had black electrical tape wrapped round part of the sensor to cut down it’s field of vision which improved sensitivity but still wasn’t great due to the problem mentioned in the next iteration.
  • CatCam v2 : was a Raspberry Pi 2 B with standard Rasp Pi camera and a USB WiFi dongle. The software took still pictures and was still triggered via a Passive Infra Red (PIR) detector. This like the last version used the software deployed with Raspbian of the raspistill application which tended to take between 2 and 3 seconds to activate and take the pictures, completely missing the cat actually entering or leaving the catflap.
  • CatCam v3 : was a Raspberry Pi 2 B with Rasp Pi camera and a USB WiFi dongle. The software took video pictures and was triggered via a Passive Infra Red (PIR) detector. This version used the USER1 signal to fire off the video signal but still used the in build version of the raspivid application which meant that the video images were huge as the application just waited and was triggered each time a cat appeared.
  • CatCam v4 : was a Raspberry Pi Zero W with Infra red Rasp Pi camera with night infra red lights. The software took video pictures and was still triggered via a Passive Infra Red (PIR) detector. This version used the USER1 signal to fire off the video signal but still used the in build version of the raspivid application which meant that the video images were still huge as the application just waited and was triggered each time a cat appeared. It was a bit unstable presumably due to the Zero as that was the only difference from prior versions.

In all of these cases I had a Java application wrapping the trigger code which captured the image and sent it up to my central server to be stored. This avoided large image files building up on the local machine and causing crashes due to space constraints on the local SD card. This was not particularly reliable when it came to the video selection as the files produced were huge and could not be captured in memory, so there was some programming jiggery pokery to stream them down and store them locally on the SD card and then upload them later at a specified time. This was becoming too complex to manage accurately and consistently without errors so I needed to look at a better way to do this.

I had come across OpenCV which is a fantastic package for Computer Vision which can be configured to handle a lot of different situations as well as different programming languages but again this seemed a little heavy duty for my purposes. I then found a package called Motion which is entirely configured by a straightforward properties file. This looked like more what I was looking for, but I suspected that I would need more processing power than provided by just a Rasp Pi Zero W. I decided it would be best to move up to a Rasp Pi A+ which had just been introduced at this time and had the same central chipset as the Rasp Pi 3 B+ but not the same set of peripherals. These were not so much my concern as I just needed the camera connection, the Wifi and the processing power. The A+ model also had the more powerful wifi connection that the Rasp Pi 3 B+ model.

It turned out that I needed to compile and build the Motion package on the Rasp Pi but this turned out not to be too difficult. I just needed to follow the steps in the link which mentioned Raspbian.

If these steps in the link are confusing to follow, then I boiled it down to these steps below on the Rasp Pi, but remember that these steps are less likely to be updated if libraries or OS’s change over time:

sudo apt-get install autoconf automake build-essential pkgconf libtool libzip-dev libjpeg-dev git libavformat-dev libavcodec-dev libavutil-dev libswscale-dev libavdevice-dev libwebp-dev gettext libmicrohttpd-dev
cd ~
git clone https://github.com/Motion-Project/motion.git
cd motion
autoreconf -fiv
./configure
make
sudo make install

The configuration setup part was a bit more tricky.

The default configuration for the app is in a file which you need to rename to motion.conf which is straightforward and there is documentation as to what parameters are in local documentation distributed with the software at /usr/local/share/doc/motion/motion_guide.html. However, I would go looking for online documentation either at the site wiki at https://motion-project.github.io/motion_config.html#configfiles and there are a LOT of configuration items which can be changed. I thought I would take it easy and change as few as I needed:

  • # File to write logs messages into. If not defined stderr and syslog is used.
    log_file /home/pi/capture/logfile/logfile.log
  • # Level of log messages [1..9] (EMG, ALR, CRT, ERR, WRN, NTC, INF, DBG, ALL).
    log_level 8
  • # Target directory for pictures, snapshots and movies
    target_dir /home/pi/capture/video
  • # Name of mmal camera (e.g. vc.ril.camera for pi camera).
    mmalcam_name vc.ril.camera
  • # Camera control parameters (see raspivid/raspistill tool documentation)
    mmalcam_control_params --exposure sports
  • # Image width in pixels.
    width 640
  • # Image height in pixels.
    height 480
  • # Maximum number of frames to be captured per second.
    framerate 30
  • # Text to be overlayed in the lower left corner of images
    text_left CatCam1 - %o
  • # Turns the text showing changed pixels on/off.
    text_changes on
  • # The number of pre-captured (buffered) pictures from before motion.
    pre_capture 60
  • # Number of frames to capture after motion is no longer detected.
    post_capture 60
  • # Create movies of motion events.
    movie_output on
  • # Maximum length of movie in seconds.
    movie_max_time 300
  • # Container/Codec to used for the movie. See motion_guide.html
    movie_codec mpeg4
  • # File name(without extension) for movies relative to target directory
    movie_filename %Y-%m-%d-%H-%M-%S_%v
  • # The port number for the live stream.
    stream_port 8096

So this seems like quite a lot of parameters to change but they are generally small changes to allow for straight forward control of the video. for instance, I have limited the size of the video to 640 by 480 and no longer than 5 minutes duration which means that it is unlikely that one video file will fill the SD card.

There are thirty frames per second so I have put in a pre capture buffer of 60 frames which means that 2 seconds of the constant video stream will be captured to the file before the action starts and another 2 seconds at the end of the action so that the video file doesn’t start and end too abruptly when a cat appears. You have to switch the movie output on so that you get files produced and you should set them to mpeg4 so that it records standard .avi files that most PC’s will play. Then give the video files specific names so that you can tie down the time and date precisely and repeat some of this information in the corners of the screen so you can see what is going on when you are watching the video. I have also switched on the pixel change rate which I want to use in the future to adjust the sensitivity of what is picked up, as the camera tends to pick up small night insects flying past the lens at 3:00am, which is a bit annoying, but that’s because the trigger level is only 2500 pixels changing between images.

Note that it is possible to pass parameters via the mmalcam_control_params to the underlying camera driver which in this case is the default Rasp Pi camera driver which is used in the raspivid application. So I have also passed the --exposure sports option to speed up the capture.

Finally I switch on the post for live streaming the output which means that on the local network (or the network that the camera is setup on) I can use a web browser to link the IP address and that port of the camera and see the current image of the camera when it is active.

All the rest of the settings are either not set or left at the default settings for Motion.

So with all this setup I had another problem. If this was running all the time then as well as picking up the cats entering and leaving it would also pick up me and the wife entering and leaving the back porch or entering and leaving the back door. As I was really only interested in the night or late evening to early morning hours, I needed a timing solution. Which of course was Cron.

Cron is a huge discussion subject on its own right so to simplify this I am going to provide a few links to the Raspbian version, link in a thread where someone starting at this gets some guidance from people who have done it before, mention the crontab file which controls when things start and stop and show you what the contents of my crontab file are below:

# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command

# Startup the catwatcher at 10:00pm
0 22 * * * /home/pi/capture/start.sh >> /home/pi/capture/cronlog.txt

# Stop the catwatcher at 7:00am
0 7 * * * /home/pi/capture/stop.sh >> /home/pi/capture/cronlog.txt

# transfer all the video from the preceeding night to the central server
0 8 * * * /home/pi/capture/transfer.sh >> /home/pi/capture/cronlog.txt

So what do we have here. I kept all the original comments that are added by default when you start editing the crontab file because as an old software developer that’s the way I was taught; never throw away any documentation which may prove useful sometime in the future. As you will note this included the format of the cron commands which are run. That’s the m h dom mon dow command a the bottom of the comments.

I also comment each of my entries I have added because I know that I will possibly forget what some of the commands do or were originally for (unless you name the scripts sensibly, but as you will find out developing in Unix/Linux/Raspian, silly command names are a defacto standard in the Operating System). This may sound stupid, but as you are not likely to look in this file for months at a time (If all goes well) then forgetfulness is always a possibility.

So first command is to start up the Motion camera software at 10:00 pm at night and feed any output from that command to a file called cronlog. Now this may seem either obvious or counter intuitive depending on where you stand but remember that that cron runs these commands unattended and all output, including error messages will be send off into infinity unless redirected somewhere sensible and believe me you will want to know when something has gone wrong as there is nothing more puzzelling than trying to debug cron problems.

Second command is to stop the Motion software at 7:00 am in the morning and final command is to transfer all of the captured video files up to the central server at 8:00 am and clear the files off ready for the next nights crop of interesting antics from the cats.

But what’s in the scripts, I hear you cry? Well you did ask for it.

The start script looks like this:

#!/bin/sh
cd /home/pi/capture
echo "start motion" `date`
echo `pwd`
/usr/local/bin/motion &

It really is that simple! Writing shell scripts is again a bit beyond this blog post so I will constrain myself to a link or two. (Note that the first link in the last sentence is not Raspian specific but bash shell scripting is common across a lot of Unix type OS’es).

The stop script is slightly more complex:

#!/bin/sh
PROCESS_ID=`ps -ef | grep "motion" | grep -v "grep" | awk '{print $2}'`
echo "Stop motion on pid " $PROCESS_ID " at " `date`
kill -9 $PROCESS_ID

This script uses a bit of awk to get the process id of the running motion program and then passes that to the OS kill command to stop it. The awk scripting language again is a bit beyond this blog but something I picked up on my professional travels and am happy for people to steal once they have worked out what it does. 🙂

Finally we have the most interesting script to transfer the video files up to the server. I know I keep calling it a server and I really should produce a future blog post about what it is (It was originally an old converted PC, one of my desktop PC’s, it’s a slightly better unit now). This looks like this:

#!/bin/bash
echo "transfer files" `date`
echo `pwd`
rsync --remove-source-files -a /home/pi/capture/video/*.avi simon@192.168.1.50:/home/simon/catwatch/video

The magic line in this script is the rsync command which copies all the avi video files produced up to the directory for the simon user on the machine/PC/server at the IP address specified.

A few interesting things to note from all of this. First is that the server has a fixed IP address on my local network. This is not difficult to do with Raspbian or other Unix type OS’s (in the servers case it’s using Ubuntu). It also means that the communication between the CatCam and the server is using ssh which again is not difficult to do if you follow the instructions and provides you with secure communications across your local network.

So, what does it look like when working? This first example is just a straightforward example of a cat leaving the house and taking his time about it, but he is fairly elderly:

My older cat leaving the house at 4:00 am

This next example is a complete mess-up when you forget the CatCam is recording and it’s a nice late summer evening and you left the garden chains on the back lawn. Note for example the night lights and camera change colours as the trousers I am wearing are in fact black.

Simon forgetting the CatCam is recording everything he is doing.

A default view of a cat coming in:

Socks coming back into the house after out adventuring.

And these last three are antics that the cats get up to with Theo finally breaking the 4th wall in the final video.

This is not my cat! In fact we had never seen it before and we have never seen it since! This is a good example of the night vision of the camera as this is 2:00 am in May and in total darkness.
Cat chase. The first cat in is not ours but one of the neighbours cats from two doors up, but obviously treats this as his ‘safe’ place in the area. He overnights here from time to time. The second cat we have seen a few times and is obviously nervous about being in our house. He has come back in a few times since then getting bolder each time.
Theo happily breaking the 4th wall. Less like a cat and more like a little bear.

A few last points. From the picture at the top of this post you can see that the Rasp Pi A+ is in a standard Rasp I A+ case (for some reason you buy the cases and tops separately). I haven’t fitted a heat sink, but I probably should as the Pi is on 24/7 even though the camera and the Motion application are not running all the time. The case is held onto the shelving unit using velcro squares which can support up to 25kg so this is not going to trouble them. The camera is held onto the case using the same velcro cut to size and there is a 2mm thick cardboard spacer with velcro on both sides which allows me to adjust the angle and position of the camera as I see fit. It also allows me to move the camera elsewhere if needs be. Note that one thing I didn’t mention in the settings is that I rotate the camera 180 degrees because the way that it is setup the camera is in fact upside down with respect to the picture produced. This is easy to do in the Motion settings.

Thank you for reading this far and if you have any comments of have found any broken links please add comments.