Wednesday, July 26, 2017

Filming Birds with a Raspberry Pi (Part One)

I had recently purchased a camera module for the Raspberry Pi, mainly just out of curiosity, and a desire to learn how to use it.  In the back of my mind I had been working on an idea to build a birdhouse and use a Pi to film the birds, but I was currently working on several other projects, so I was in no hurry to start a new one.  One evening I was working at my desk in my shop, and I heard some chirping outside the window.  I pulled back the curtain to find a Carolina Wren's nest with baby chicks inside chirping away.  How fortuitous.  Suddenly my project to film birds with the Pi moved to the front of the list.  With little knowledge of how to use the camera, I bent a piece of 12awg copper wire into a makeshift camera stand, hooked it up to the Pi, and set it in the window.  A quick Google search told me that I could enable the camera module using the raspi-config menu, and then operate the camera from the command line using the following commands for pictures and video respectively:

raspistill -o birdpic.jpg

The above command takes an 8 megapixel image and outputs it to a file named birdpic.jpg.

raspivid -o birdvid.h264 -t 10000

The above command takes a video and outputs it to a file named birdvid.h264.  The -t specifies the length of the video in miliseconds, so -t 10000 takes a 10 second video.

It worked.  I sat there for a little while amusing myself taking video of the birds every time they started chirping, because that usually meant that it was feeding time.  The video through the window was decent, and I managed to edit together a short video.





Obviously, this was far from an optimal set-up.  The video through the window was OK, but it could definitely be better, and the whole thing was dependent on me sitting there listening for the chirping and hitting a button.  It was time to take this to the next level.  I had some IR motion sensors lying around, and some leftover 1/2" plywood from a previous project, so I whipped up a quick little box with a hinged lid and a removable front panel with holes for the camera and motion detector.  I decided to store the video on a 16 GB usb thumb drive.  The other options would have been to save it
to the SD card, which would only wear out the card faster, or stream it via wifi to my server.  I decided against wifi in case I wanted to use this project for filming something else that was too far away from the house for wifi.  The USB drive turned out to be an adequate solution.  I made sure to leave plenty of room in the box, and air gaps at the top to deal with the heat produced by the Pi and the USB stick.  To mount the motion detector and camera on the front of the box I simply used electrical tape, since this was more of a prototype or proof-of-concept than anything else.  I was pleased with my little box, considering I made it on the fly in just a little
 over an hour.  The IR motion sensor I used was a HC-SR501, which runs off of 5V, but conveniently send a 3.3V signal when motion is detected, so I could hook it up directly to the Pi using only three pins without having to use a level-shifter.  With that, the hardware was complete.  Now all I needed was a little code to automate the whole process.  Back to Google.

It turns out, as to be expected, the Raspberry Pi Camera Python module is located in the Raspbian repositories, so it can be installed with a quick:

sudo apt-get install python-picamera

I don't want to get too in-depth on how to use this module, so I will just point you to Raspberrypi.org's documentation here.  The code is simple.  All I am going to do is to  monitor the GPIO pin that the motion sensor is connected to.  When motion is detected I am going to start recording.  After 10 seconds, I am going to check the motion sensor again.  If there is no motion, then the clip is over.  If there is still motion after 10 seconds then it will wait another 10 seconds and check again.  This results in a minimum size clip of 10 seconds, with no maximum size as long as motion continues.  To prevent video files from overwriting each other, each clip will contain a time-stamp in the file name.  I could have gone a little more advanced with the code, but I was in a hurry to get this up and running, so I kept it simple.  Here's the code if anyone would like to use it:

 #!/usr/bin/env python  
   
 import RPi.GPIO as GPIO  
 import picamera  
 import time  
   
 MOTION_PIN = 4  
 camera = picamera.PiCamera()  
   
 GPIO.setmode(GPIO.BCM)  
 GPIO.setup(MOTION_PIN, GPIO.IN)  
   
 def take_video():  
      timestamp = time.strftime("%y-%m-%d-%H-%M-%S")  
      print 'recording started' # for troubleshooting only  
      camera.start_recording('vid%s.h264' % timestamp)  
      camera.wait_recording(10)  
      while GPIO.input(MOTION_PIN):  
           camera.wait_recording(10)  
      camera.stop_recording()  
      print 'recording stopped' # for troubleshooting only  
   
 # Begining of Program  
   
 time.sleep(2)  
 while True:  
      print 'waiting for motion' # for troubleshooting only  
      GPIO.wait_for_edge(MOTION_PIN, GPIO.RISING)  
      print 'motion detected' # for troubleshooting only  
      take_video()  

As always, we need to make the file executable using sudo chmod +x /home/pi/motion-vid.py.  I want to have this script run on start-up, so we need to add this file to the /etc/rc.local file, but before we do that, we need to think about the USB flash drive that we are using to store the video.  When a USB drive is inserted into the Raspberry Pi, it is not automatically mounted as it is in many other operating systems, so we need to make sure that the Pi also mounts the USB drive on start-up.  To do this, we must first determine the name of the drive, and of the partition on the drive.  Typically the first USB drive you insert in the Pi will be sda, but in the interest of being thorough we will double check just to be sure using the command ls /dev/sd*.





As you can see above, it returned two values.  sda is the name of the drive itself, and sda1 is the name of the partition on the drive.  We want to mount the partition.  Next we need to look to see if we have a place to mount the drive.  Navigate to /mnt using cd /mnt, and see if you have directories there.  If not, create a directory named usb (the name is arbitrary) using the command sudo mkdir ./usb.  We can now mount the usb drive using sudo mount /dev/sda1 /mnt/usb.







So now that we know how to do it, let's tell the Pi to mount the USB on boot and run the camera script.  Open up the /etc/rc.local file using your text editor du jour (i.e. sudo vim /etc/rc.local)and add the following lines to the file:

# The following line mounts sda1 to /mnt/usb
sudo mount /dev/sda1 /mnt/usb

#The following lines runs the script that takes video based on a motion sensor
cd /mnt/usb
sudo /home/pi/motion-vid.py &

And that's it.  I put the box on the windowsill next to the birds nest and plugged it in.  The first day I got just under 400 video clips, which took up about 3.5 GB.  That means with a 16 GB USB drive I would only need to swap out the drive every four days or so.  At any time I could log into the Pi over wifi to make sure it was still working, and view any of the clips I chose.  And of course, I had to make another bird montage:



And now for the sad conclusion of this project.  After a little less than a week of watching the birds, and admittedly becoming a bit attached to the little guys, I was working in my shop when I heard a commotion at the window.  I figured the birds were getting active, so I logged into the Pi and pulled down the last video clip.  Horrified I watched as one of the neighbor's cats pounced onto the nest and pulled it, and the baby birds, off of the window ledge.  C'est la vie.  It is nature after all, and cats will be cats.  I can't be happy they keep away the mice and snakes, and then fault them for eating the birds.  It wasn't the smartest place for the Wrens to build a nest anyway, 2 feet off the ground.  At least I got to watch them for a while, and it gave me a good starting point for this project.

So what did I learn, and what's next.  Most importantly, next time I film baby birds they will be in a bird house where they will be better protected from predators.  My code could also use a little bit of improvement, and next time I will probably just stream the video to a server instead of using the USB drive for storage.  I am already working on a design for a bluebird house that will have an internal camera and an external camera, and will be able to conceal the electronics in a separate compartment from the birds.  The biggest hurdle to overcome with that project will be powering two Pi Zeros and two cameras, but I'm sure I can come up with something.  Until then, stay safe, and keep building.

Sunday, July 9, 2017

Watering the Garden with Raspberry Pi

If you've ever planted a garden or grass seed in the spring, you know that watering can be a time consuming task, and going out of town for a weekend can be disastrous for your new plants if the weather is hot and no one is around to water them.  More importantly, I just like to build things, so why not scratch that building itch and create an automated hose bib that can be scheduled to turn on and off using a Raspberry Pi?

My original approach to this project involved a watering system located near the garden, but I ran into several complications during the design phase.  The first issue arose trying to power the Pi as well as the electronic solenoid valve that would control the water flow.  Running wires across the back yard was not an ideal solution, and battery power was going to require frequent recharging.  I was also going to have to find a way to protect the electronics from the sun's UV rays as well as moisture, while at the same time allowing enough air-flow to let heat escape.  It occurred to me that locating all of the electronics inside the house and using them to control a hose bib on the side of the house solved both of these issues, and also added the flexibility to allow me to change the location of my automatic sprinklers or drip-watering-systems whenever necessary.

With this basic concept in mind, I broke the project into three segments: electronic hardware, plumbing hardware, and control software.  For the electronic hardware, I would need to be able to switch on and off a 12V fused power source that would supply an electric solenoid valve that would control the water.  This could easily be done by controlling a relay with a GPIO pin on the Pi.  For the plumbing hardware, I would need to tap into my water line and run it through the electric solenoid valve, and from there outside to a hose bib.  I would also need to be sure to include a check valve to prevent the back-flow of water from the outside, and there would need to be a way to drain any outdoor pipes to prevent freezing in the winter.  The control software would be the easiest.  All I needed was a short start-up script to set-up the GPIO pin, and then the timing of opening and closing the valve could be done with cron jobs.  With a plan in place it was time to get building.

Electronic Hardware

For this project I purchased a 12V / 3amp normally-closed brass solenoid valve to control the water flow.  You can buy a plastic one cheaper, but I had reservations about connecting a plastic water valve to my plumbing.  Basically all I needed to do was to connect a GPIO pin from the Pi to a relay that could then switch on/off the 12V power supply to the valve.  I went with a 4-channel relay module since I already had plans for future projects that would require additional relays.  I had a 12V / 30 amp power supply from previous projects on hand, which will provide more than enough current for this project, as well as anything I might need it for in the future.  The only thing left to plan was a fuse for the power to the valve.  For most people a simple in-line fuse holder would solve this problem, but I just so happened to have an old DC fuse panel lying around looking for a job to do, so I put it to use.  Here is the schematic for the final design:


In the above schematic I also drew in the relay board.  Obviously if you use the same relay board that I did, you don't need to build any of this, but I wanted to include it so that anyone using a different relay could adapt the circuit to their own needs.

Regarding the switches, I added the first switch to cut the 12V power so I don't have to pull the fuse every time I want to make adjustments to the set-up.  This particular switch has an LED that is powered via the same 12V that it switches, so I had to add a resistor to the ground leg on the switch to limit the current for the LED without limiting the current to the valve.  This was done by simply cutting the wire and adding the resistor in-line.  I also added a second switch to bypass the relay and open the valve without involving the Pi.  This is a standing "request" from my wife that anything I automate must still have a manual switch for operation.

One last, but very important note, when I finally had the whole set-up finished, I tested it out.  As soon as I sent power to the solenoid, my Pi emailed me that my smoke detector was alerting and gave me an audible alert that it was preparing to shut down.  What!?!?  These are all separate systems that should have nothing to do with each other except that the same Pi controls them all!  Well, since I had run my 12V lines along the same path as the jumpers for all of my GPIO pins, as soon as I switched the solenoid on, the electrical noise on the 12V lines interfered with the signals on the other GPIOs, causing a moment of havoc for the Pi. This could have been solved by rerouting my wires, or by trying to smooth things over with capacitors, but I happened to have some ferrite core noise suppression filters lying around, so I tried one out.  After testing several times, I can verify that this does in fact solve the problem.  With the noise filter there are no issues, without it the Pi goes a little nuts.  So keep this in mind when determining your cable management, or invest in some filters to solve the problem after the fact.

Plumbing Hardware


I hate plumbing, but it's a handy thing to know how to do.  I know just enough about it to make me dangerous, but that probably applies to a lot of things.  I won't go into too much detail here, because everyone's plumbing situation is going to be different, so there is no one-size-fits-all solution.  I am going to try to focus on the few components that will be universally required, and then just skip to the final result.  If you are not completely comfortable with altering the plumbing in your house, then you may want to look into another way to do this project.  Plumbers are expensive, so mistakes could be costly, not to mention messy.  You've been warned, so I accept no responsibility if you choose to proceed and accidentally flood your house.


Above is the basic set up for the plumbing piece.  Starting on the left, the first piece we need is a cut-off valve.  If my improvised plumbing leaks or brakes, or my Pi goes all Superman 3 on me, I need to have a way to cut off the water from it's source.  Next comes the solenoid valve that will be controlled by the Pi.  After that we need to use a check valve to prevent the water from the hose from draining back into my water pipes (this is probably required by code in most places).  Finally, I used a T-junction and another cut-off valve to allow for draining the outdoor pipes.  This valve will stay closed during normal operation, and will only be opened at the end of the season in order to drain the outdoor pipes so they don't freeze.  The outlet for this valve will lead to a sink basin in my shop so that I don't have to mess with sewer lines and traps.


So that is the basic design.  To the right is the fully installed product.  To tap into the waterline I opted to slice into one of my newer Pex waterlines, which is much easier than trying to mess with 70 year old galvanized water pipe.  For the line that continues outside I opted to use galvanized steel water pipe because I wanted something more rigid to support the solenoid valve, and because you can't run Pex outside.  If you do something similar and use steel pipe outside, be sure to paint it to keep it from rusting.


Control Software

With everything in place, all I needed to do was to write a couple of short scripts to control the solenoid valve.  This is the easy part.  Here are the two python scripts called water-on.py and water-off.py:

 #!/usr/bin/env python  
   
 # water-on.py  
   
 import RPi.GPIO as GPIO  
 from time import sleep  
   
 RELAY_PIN = 26  
   
 GPIO.setmode(GPIO.BCM)  
 GPIO.setup(RELAY_PIN, GPIO.OUT)  
   
 GPIO.output(RELAY_PIN, 0)  
 sleep(1200)  
 GPIO.output(RELAY_PIN, 1)  

 #!/usr/bin/env python  
   
 # water-off.py  
   
 import RPi.GPIO as GPIO  
   
 RELAY_PIN = 26  
   
 GPIO.setmode(GPIO.BCM)  
 GPIO.setup(RELAY_PIN, GPIO.OUT)  
 GPIO.output(RELAY_PIN, 1)  

For the water-on.py script I added in a 20 minute timer before automatically turning the water back off as a fail-safe.  As always, once the scripts are created using a text editor, they need to be made executable by using

chmod +x water-on.py
chmod +x water-off.py

I need to make sure that the GPIO pin that controls the relay isn't floating when the Pi reboots, so I need to run the water-off.py script on boot.  I am going to do this by adding the following line to the /etc/rc.local file:

sudo /home/pi/water/water-off.py

This time I am also going to make the file executable without having to specify the whole path to the file by copying it to the /usr/bin folder like so:

cp /home/pi/water/water-on.py /usr/bin/water-on
cp /home/pi/water/water-off.py /usr/bin/water-off

Notice I dropped the .py when I added the file to /usr/bin.  This is not necessary, but in Linux land file extensions are not required, and it saves me a little bit of typing.  So now the water can be turned on with a simple command.

water-on

But the point of this was not to be able to turn on the water by typing a command, we could do that more easily by flipping a switch.  The goal is to be able to schedule the water to turn on and off automatically.  For this we will use Linux's built in scheduling system called Cron.  To add a task to the cron table we use the following command:

crontab -e

 The first time you edit the cron table you will be prompted to pick a text editor.  I prefer vim, but it's purely a matter of personal taste.  When the file is opened for the first time there is nothing but lines of comments explaining how Cron works.  Since the directions are built into the cron table, I won't go into too much detail here.  To turn the sprinklers on for 20 minutes every morning at 6:00am you would add the following two lines to the end of the cron table:

00 6 * * * water-on &
20 6 * * * water-off

Remember that I added a fail-safe to the water-on script to have it shut off after 20 minutes, so the water-off isn't 100% necessary, but it seems like good practice.  If you wanted to run the sprinklers for more than 20 minutes you could either edit the sleep line of the water-on script, or just add another line to the cron table to turn the water back on after 20 minutes.

So that's it.  Now every morning my Pi will wake up at 6am sharp and take care of my watering for me.  Sure you can buy an off-the-shelf product that will do the same thing, but what's the fun in that?  If anyone needs any help adapting this walk-through to your own projects just let me know in the comments and I'll do my best to help.