2015-04-08

Not too long ago, I purchased a programmable remote for my DSLR camera so that I could take long exposures as well as multiple exposures in order to create time lapse videos. While the timer does a great job, I still needed a way to convert a series of images into a video.

Fortunately, ffmpeg does a great job of converting a pile of images into a video file, and I most certainly have ffmpeg installed on my laptop. Now all I need is a bit of code to:

  1. search for some files
  2. copy and rename the files
  3. always skip step 3 :)
  4. use ffmpeg to convert the files to a video

When the script runs, it looks for a directory named 'images' and recursively looks for files in that directory (my camera tends to make multiple directories of files). Then the files are copied into a temp folder and given a 6 digit name: 000001, 000002, 000003, etc. Finally, ffmpeg converts those 6 digit named files into a video.

Enter The Ruby

#!/usr/bin/env ruby
require 'fileutils'
require 'date'

#where will we look for files?
LOCAL_DIR File.expand_pathFile.dirname(__FILE__) )
TEMP_DIR File.join(LOCAL_DIR"temp")
IMAGES_DIR File.join(LOCAL_DIR"images")
#if the temp dir exists, delete it and its contents
if Dir.exists? TEMP_DIR
    FileUtils.rm_rf TEMP_DIR
end

#make the temp dir
FileUtils.mkdir TEMP_DIR

#keep track of how many files we have
@file_count 0

def copy_files(location)
  files = []
  dirs = []
  Dir.foreach(locationdo |name|
    #ignore . and ..
    if name!='.' and name!='..'
      #what is the path of the item?
      path File.join(location,name)
      #recurse if path is a directory
      if Dir.exists? path
        dirs << path
      else
        files << path
      end
    end
  end
  #sort the directories by name and recurse
  dirs dirs.sort()
  dirs.each do |d|
    puts "DIRECTORY: #{d}"
    copy_files(d)
  end
  #sort the files by name and recurse
  files files.sort()
  files.each do |d|
    new_name @file_count.to_s
    #increment the file_count
    @file_count+=1
    ## pad the new file name with 0
    (6-new_name.length()).times do
      new_name "0"+new_name
    end
    #determine where the new file is going
    new_file File.join(TEMP_DIRnew_name)
    #what is the command to copy the file?
    copy_command "cp #{d} #{new_file}"
    puts copy_command
    #run the command
    `#{copy_command}`
  end
end

#recursively get a list of all files in the current directory
copy_files(IMAGES_DIR)

#what day is it?
ymd Date.today.strftime("%Y%m%d")

#what video command should we run?
cmd "ffmpeg -y -f image2 -i temp/%06d -b:v 50000k  #{ymd}_timelapse.avi"
#run the command
`#{cmd}`

By default, the ffmpeg command will create a video at 10 frames/second.

My first time lapse was during Sunset on the Equinox

Sadly, I didn't adjust the camera properly when capturing the April 4th Lunar Eclipse. However, considering I set everything up 7 hours before the eclipse, I think I did a fairly sweet job of determining where to point the camera. :)

Now quit reading, slow down, and speed up.

Comments
2015-04-22 Alison Chaiken:
'gst-launch multifilesrc location="somematchingstring"' would work as well.
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
1 plus 2
Answer:
required
2015-03-15

The Magic starts at 3:30AM... because at 3:30AM every day, a cron task runs on the chicken coop computer to determine when the coop door should open and close later that day. For most of my weather needs I had been using the http://wunderground.com API, but for some reason, they don't offer access to twilight data through the API and I didn't want to write a webpage scraper to harvest the data from their website.

Fortunately for me, hamweather.com has a wonderful API accessible weather service with great documentation, all at a very reasonable price (free, if making less than 750 API calls per day).

For this piece of the project, I decided to use civil twilight as the opening and closing times. Then it was just a matter of reading the hamweather API documentation for sun and moon data and then hacking together some code. Since the majority of the code is written in Python, I opted to use python for this script.

Enter the Python

#!/usr/bin/env python2
import urllib
import json
import os.path
import subprocess
import time

client_id "MY_CLIENT_ID"
client_secret "MY_CLIENT_SECRET"
url="http://api.aerisapi.com/sunmoon/MY_CLOSEST_TOWN?client_id=%s&client_secret=%s" % (client_idclient_secret)

print url

script_dir os.path.dirnameos.path.realpath(__file__) )
data_file os.path.join(script_dir'sunmoon.json')
open_script os.path.join(script_dir,"open_door.sh")
close_script os.path.join(script_dir,"close_door.sh")

try:
  #read the data from the url and write it to a file
  response urllib.urlopen(url)
  data response.read()
  open(data_file"w")
  f.write(data)
  f.close()
except:
  #something failed, open the old data file
  open(data_file,'r')
  data f.read()

#load the json into an object
json_object json.loads(data)

#get the twilight from the json object
twilight json_object['response'][0]['sun']['twilight']

#get the twilight start and end
civilbegin twilight['civilBegin']
civilend twilight['civilEnd']

#format the start and end times in Hour:Minute format
twilight_start time.strftime("%H:%M"time.localtime(civilbegin))
twilight_end time.strftime("%H:%M",time.localtime(civilend))

#create commands based on the times
open_cmd =  "at -f "+open_script +' '+twilight_start
close_cmd =  "at -f "+close_script +' 'twilight_end

#run the commands as a subprocess
subprocess.call(open_cmdshell=True)
subprocess.call(close_cmdshell=True)

During the event loop of my door controller, a file is checked to see if the door should open or close, and the door behaves accordingly. This twilight fetching script will determine when to open and close the door, and submits a command to at, which then handles the timing for running the open or close script.

The chickens will be going into their new home next weekend, and the close time will probably need to be adjusted, but that just means I need to hang out in the hammock at sunset/twilight and see if all the chickens go in the coop before the door closes.

Now quit reading, and go make something that can only be tested by relaxing in a hammock at sunset. :)

Comments
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
7 plus 8
Answer:
required
  • Tags:
  • Python
2015-03-08

Last Autumn, I began the process of building a chicken coop and chicken run for about 4 chickens. One of the biggest concerns for me was making sure that the door to the coop is secure at night. There are plenty of expensive automatic coop doors available online, but I was more intent on building my own door because ... uh... well.... I like to build things.

Enough jibber jabber, let's get to it!

The Door

Mounting the motor

For opening and closing the door, I am using a 12 volt automobile antenna. My original plan was to make the door open vertically, but after a few tests, I opted for a horizontal sliding door design.

In the vertical orientation, is was common for the door weight to make the gears jump in the motor and then the door would come crashing down. I want a door, not a guillotine!.

Push/Pull Mount for the antenna

Much like the mounting brackets for the motor itself, the antenna is connected to the door using plumber's tape. Yea, it looks rather janky, but it is solid and it works.

Opened and Closed

On the top left and right of the sliding door, are magnetic switches that are used to register when the door is finished opening or closing.

A bar of soap was rubbed in the channels where the door will slide, in order to make for a smooth operation.

There is a gap in the door track (visible in the bottom left). As the chickens go in and out of the coop, the track will accumulate straw and droppings that may cause problems with closing the door all the way. By leaving a gap in the track, accumulated gunk will get pushed out of the way when the door closes.

Making A Case For The Controller

The coop door is controlled by a BeagleBone Black running Debian Linux.

Gather some supplies

  • a ceiling lamp for the recycling center
  • some j-b weld
  • a beaglebone black
  • a DPDT 12 v relay
  • a 2 channel relay controllable via IO pins on the BeagleBone.
  • some of those stand-off thingies I like so much

TAKE IT APART!

Sadly, this is the only part of this build where I get to take something apart.

All of the electronic internals were removed from the lamp.

Weld things in place

The relays and beaglebone black were mounted to stand-offs and then j-b welded in place.

The hole in the bottom of the lamp base will be used for routing wires and cables.

Route some wires.

There are 5 wires coming from the coop door that need to be routed into the shed where the controller will be mounted. One wire for each of the magnetic switches, the common ground for the switches, and two wires for the motor.

Mount it!

Here is the 'lamp' with the cover in place. Originally, I had hoped that I could use a USB WiFi adapter for the BeagleBone to access the network but the distance was too great. Instead, I configured a spare router running DD-WRT to act as a repeater bridge and the BeagleBone was networked to the repeater.

A 12v 6a power adapter was wired to the relays in order to send 12 volts of power to the antenna.

Platform and ramp

After the door was finished, a platform and ramp to the chicken run was added to the coop.

Now it is time to get some birdies! bok bok bok!

Why did I use GNU Linux when I could have used a microcontroller with a light sensor to control the door?

I used Linux as the basis for my door because I wanted to use skills and tools that I already know, and I like having choice when it comes to programming languages used in my projects... and the light sensor doors are all fine and dandy until those sneaky no-good raccoons get their hands on a flashlight!

Now quit reading, and go make something.

See also: http://www.jezra.net/blog/The_magic_starts_at_330AM_a_coop_story to see how the coop gets open and close times from the interwebs

Comments
2015-03-20 Alison Chaiken:
I like the repurposing of the lamp: appropriate size, appropriate price, hopefully not scary in appearance to chickens.
2015-03-20 Peter van der Linden:
Where can I get some of that plumber's tape? It seems way better than the pathetic duct tape I have been using to date!
Name:
not required
Email:
not required (will not be displayed)
Website:
not required (will link your name to your site)
Comment:
required
Please do not post HTML code or bbcode unless you want it to show up as code in your post. (or if you are a blog spammer, in which case, you probably aren't reading this anyway).
Prove you are human by solving a math problem! I'm sorry, but due to an increase of blog spam, I've had to implement a CAPTCHA.
Problem:
0 plus 3
Answer:
required
subscribe
 
2015
2014
2013
2012
2011
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008