Raspberry Pi 2 Timelapse Output to Video

I’ve done some nifty timelapses in the past. This time, I wanted to make them a little more convenient to view and maintain. I had recently gained access to a nice view, so I thought now was a good time to put something together.

The skinny of the project is:

  • A Raspberry Pi 2 with the old V1 camera board, 64GB MicroSD Card
  • Apache2 web server
  • Small script to take all the pics
  • Another small script to convert the pics to mp4 movie, and do some clean up

Here’s what my setup looks like. That’s just a phone windshield mount. I also am using this camera case from Amazon.


Script to take the pictures

This script runs every minute. You pass it in a parameter to tell it how often to take the pictures. I know the -t (time to take pictures) and -tl (timelapse mode) parameters exist, but I learned of them after making my script, so I just decided to keep it this way:


# This script takes a variable amount of pictures over 1 minute. The script takes in a parameter
# to indicate how many times per minute to take a pic. The output
# is saved to a directory, ~/camera/time_lapse_images, and a copy is written to the root
# of the web server so you can see a “current view”.

# Loop for a minute, taking a pic every specified amount of seconds
for x in $(seq 1 60)

mod=$(( $x % $1 ))

if [[ $mod -eq 0 ]]; then

# We need to name the files sequentially to combine them to mp4 video later. This little loop
# determines what to name the file so they’re sequential.
if [[ -e /home/pi/camera/time_lapse_images/$name.jpg ]] ; then
while [[ -e /home/pi/camera/time_lapse_images/$name-$i.jpg ]] ; do
let i++

#Record the still and copy the current view over to the web server root
sudo raspistill -o /home/pi/camera/time_lapse_images/$name.jpg -w 1280 -h 720
sudo cp /home/pi/camera/time_lapse_images/$name.jpg /var/www/still.jpg -f

Script to make the video and clean up the old files

This script runs every night at midnight. I’m using¬†ffmpeg version 0.8.17-6:0.8.17-1+rpi1:

# move the previous days images to the processing folder
mv /home/pi/camera/time_lapse_images/*.jpg /home/pi/camera/time_lapse_images/timelapse_processing/ -f

# make the movie
ffmpeg -i /home/pi/camera/time_lapse_images/timelapse_processing/still-%d.jpg /home/pi/camera/time_lapse_images/timelapse_processing/video.mp4

# archive the previous day’s movie
now=$(date +”%m_%d_%Y” -d “2 days ago”)
sudo mv /var/www/video.mp4 /var/www/video-archive/timelapse_$now.mp4

# mv the movie to /var/www/
sudo mv /home/pi/camera/time_lapse_images/timelapse_processing/video.mp4 /var/www/ -f

# delete the processed images
rm /home/pi/camera/time_lapse_images/timelapse_processing/*.jpg -f

Super-simple webpage for viewing the current view and timelapses

My webpage to serve the image and timelapse video is really simple. I am using a little bit of JavaScript to update the current view image without refreshing the whole page:




<h1>Raspberry Pi Cam</h1>

<!– <meta http-equiv=”refresh” content=”120″ > –>

<h2>Current view – Refreshes every 10 seconds</h2>

<!– Refreshes the still image every 10 seconds –>

function refreshIt() {
if (!document.images) return;
document.images[‘still.jpg’].src = ‘still.jpg?’ + Math.random();
setTimeout(‘refreshIt()’,10000); // refresh every 10 secs


<body onLoad=” setTimeout(‘refreshIt()’,5000)”>

<img src=”still.jpg” style=”width:1280;height:720px” name=”still.jpg”;>


<h2>Timelapse recording of previous day</h2>
<video width=”1280″ height=”720″ controls>
<source src=”video.mp4″ type=”video/mp4″>
<source src=”video.ogg” type=”video/ogg”>


<a href=”video-archive/”>Archived Timelapse Videos</a>




And here’s some fruit of the labor! Pardon the reflection and dirty window ūüė¶

Generating Random Network Traffic with IPerf

When you setup a nice bandwidth monitoring application, it is generally acceptable to just set it and forget it; the data you get is usually taken at face value. I started to wonder how I could test the accuracy of the data given by a bandwidth monitoring application. I could use an Ethernet test set, like a JDSU T-berd to pump accurate amounts of traffic through an interface then match that up with what the graph sees, but I have to manually adjust the traffic if I want to test if the graph is accurately representing the peaks and troughs that come along with typical data use.

So I finally got around to coding up a little bash script to fire off iperf to generate random amounts of traffic over a given time. For those unfamiliar with iperf, it¬†is an easy to use, client/server application you can use to generate all types of network traffic. It’s trivial to setup two end devices to transfer data from one to the other, but this method suffers the same problem as the Ethernet test set scenario, in that you must manually adjust the traffic between tests.

So the following script generates random bits of UDP traffic from iperf from the client side over a given amount and outputs a CSV you can use to match up against your graph. It takes in two parameters: server hostname/ip and the time length of the test. Its a pretty simple script, so you can adjust it to your liking, such as the bandwidth limits and the output file.


# Usage: ./random_iperf_traffic.sh &amp;lt;hostname/IP&amp;gt; &amp;lt;time length&amp;gt;
# Outputs to filename &quot;random_traffic_iperf_date_time&amp;gt;

#Read in the command line params: time and target



# Get the current date for the filename
fileDate=`date +%m_%d_%y_%T`
touch random_traffic_iperf_&quot;$fileDate&quot;.csv

# Now I need to run the iperf loop. The trick here is to stay within the time limit.
# For now, I'm going to take the target time ($time), and divide it in half before the loop. I'll start with a random
# length of time within that time contraint divided by 4, then work up to the $totalTime from there. This way, I ensure we'll have
# at least some random traffic generated.

splitTime=$(( totalTime / 4 ))

# Get a random time between the new time
time=`shuf -i 1-$splitTime -n 1`

while [ $totalTime -ne 0 ]

# nerfing this var due to the Pi limits of about 40Mbps
targetBandwidth=`shuf -i 1-40 -n 1`

# Output the current time and bandwidth target
echo `date +%D_%T`,&quot;$targetBandwidth&quot;Mbps &amp;gt;&amp;gt; random_traffic_iperf_&quot;$fileDate&quot;.csv 

echo Running iperf3 in client mode towards host $host at target bandwidth of &quot;$targetBandwidth&quot;Mbps for $time seconds.  

iperf3 -c $host -t $time -u -b &quot;$targetBandwidth&quot;m

totalTime=$((totalTime - time))

time=`shuf -i 1-$totalTime -n 1`


Quickest VNC Server Setup on Raspian to View the Actual Desktop

Scenario: You need to use a Raspberry Pi hooked to a TV to view a network monitor or something.

Easily setup x11vnc to be your vnc server:

I found this thread featured a working fix:


install and set password
– sudo apt-get install x11vnc
– x11vnc -storepasswd

create autostart entry

– cd .config
– mkdir autostart
– cd autostart
– nano x11vnc.desktop
– paste following text:

[Desktop Entry]
Exec=x11vnc -forever -usepw -display :0 -ultrafilexfer

– save and exit (Ctrl-X, Y, <Enter>)

This start x11vnc when lxde starts.

Then remove the pesky screensaver with:

Found here: http://raspberrypi.stackexchange.com/questions/2059/disable-screen-blanking-in-x-windows-on-raspbian

Edit /etc/xdg/lxsession/LXDE-pi/autostart and add these three lines

@xset s off
@xset -dpms
@xset s noblank

Log out, log in, verify it’s working with

xset -q

Then just use your VNC client of choice to connect to the ip with :5900 on the end.

RingMon: An application to monitor Cisco REP and Ciena RAPs Ring Topologies

Service providers often build their layer 2 Ethernet networks in ring typologies. By connecting devices in the shape of a ring, all devices can still communicate with the rest of the network in case there is a single break in the ring.

Two breaks, however, results in a device being isolated from the rest of the network, usually resulting in an outage.


To connect switches in a ring topology without causing a loop, protocols like Cisco REP and G.8032 (the open standard) exist to assign a blocking port (just like STP). In the event of a break, the blocking port switches to forwarding traffic. Once the ring heals, the blocking port will return to prevent a loop.

When these rings break, administrators usually configure them to send SNMP traps to a listener that is being monitored by NOC personnel or something similar. But if these traps are missed, or no stateful alerting mechanism is in place to notify personnel of the break, broken rings can go unnoticed.

Enter RingMon. RingMon is designed to keep track of the current status of rings in a network. You just open it up, add the IP addresses of switches with rings you want to track, and it will show you the current state. It sure beats logging into all the switches and manually checking the status.


I wrote this application in VB.NET for my solo Senior project at the University of South Alabama. The code is up on github if you would like to have a look.

To download and use the application, here is a link to the .exe and SNMP code library used (library must be in same directory as the .exe).


Cisco ASR 920 CDP Config

Getting CDP to work on an ASR 920 trunk link is strange. I found that just enabling CDP globally with “cdp run” isn’t enough. And further, enabling “l2protocol peer cdp” on the trunk service instance is also not the ticket. Using “Show cdp traffic”, I could see that I was sending version 2 CDP frames, but not receiving them. I dug deep and took a packet¬†dump of the CDP¬†frames¬†going between an ASR 920 and ME3400 over a dot1q trunk link. I found the ME3400 CDP frames¬†come tagged via VLAN 1 (the native vlan), but the ASR 920 frames¬†are untagged.


With some help from a dude on the Cisco forums, we determined that we needed to implement a workaround on the ASR 920 to allow it to interpret the native VLAN¬†frames it was getting. The following config tells the ASR 920 to accept VLAN 1 frames on the trunk link, thus processing the CDP frames. I confirmed after implementing I was able to see the neighbor via CDP, and confirmed the receipt of CDP packets with “show cdp traffic”.

Note the first service instance basically designates VLAN 1 as native, while the second handles the trunk config.

interface GigabitEthernet0/0/4
no ip address
load-interval 30
media-type auto-select
negotiation auto
cdp enable
service instance 1 ethernet
encapsulation untagged
l2protocol peer cdp
bridge-domain 1
service instance trunk 2 ethernet
encapsulation dot1q 99,3001-3002
rewrite ingress tag pop 1 symmetric
bridge-domain from-encapsulation

My Cisco Forums post

Backpacking in the Sipsey Wilderness

I recently went on a trip with the USA Outdoor Adventures group to the Sipsey Wilderness in northwest Alabama. The adventure would take us through approximately a roughly 8 mile loop, passing the state’s largest tree and some of the prettiest waterfalls. Unfortunately, the weather was uncooperative the first night, causing us to cut our two day trip a day short. Worse, other than the leader, I was the only camper with experience. The journey, however, ended up being completely worth the soggy¬†hike.


Randolph Trailhead Sign

The Sipsey Wilderness is located about an hour northwest of Birmingham, close to Double Springs. We first drove close to 6 hours¬†via Interstate to the Randolph trailhead to begin our hike. We left around noon-thirty and hit the trail closer to 6:15, putting us at a bit of a disadvantage given we only had about an hour or so left of good daylight. After a small hike up trail 201, a wrong turn, and a few slips in the mud, we setup camp around 7:20 PM on the west side of a¬†creek near the intersection of 201 and 209. By this time it was already dark and drizzling. I regret not offering assistance to the first time campers with properly securing¬†their rain flys, as it would turn out to be a dangerous mistake. Most everyone wouldn’t sleep much, dealing with 2-3 inches of water in their tents.

My tent is awesome; it’s a Mountainsmith Morrison 2. The Morrison 2 is known to be an easy to setup, watertight tent. It’s a two person tent, but at only 4 pounds¬†packed, it doubles as a luxurious one person tent. I don’t know how much rain we got, but it started to trickle at 7 PM and didn’t stop until 8 AM the next morning. It stormed hard at 3 AM, complete with thunder and lightning. All in all, the vent seams in my rain fly leaked a little, dripping a total of about 2 table spoons near my head and knees.


Morning camp after the storm

The campers were not pleased¬†the morning after the rain. I didn’t want to potentially upset anyone by taking pictures of the water in the tents, but believe me it was bad, and quite dangerous. The temperatures that night dipped in to the 50’s. You don’t need me to explain that being soaking wet in 50 degree weather is a bad idea.¬†The trip leader broke the news to¬†me that the group had decided they wanted to leave that day, but not before seeing the waterfalls and Big Tree. I totally understood and made sure to offer help whoever I could with their gear.

I ended up carrying another camper’s soaked, 2 person North Face tent to help lighten their load. The tent’s extra weight didn’t phase me much, but having to deal with the tent flapping around in my Teton Explorer’s top loops was a bit annoying. To get to the falls, we needed to cross the creek¬†and get on trail 209. Trail 209 would lead us to the 204/204b trails and eventually the Bee Branch falls. We first had to negotiate crossing the¬†creek.

The water, although stronger in current thanks to the rain, was only knee deep and an easy cross with camp shoes on. We then trekked hard east, winding north and south before crossing another creek to intersect the southern end of trail 204. We headed north on 204 at a slow, arduous pace thanks mostly to the numerous fallen trees that had yet to be bifurcated for passage.

One of the two Bee Branch falls that were flowing

One of the two Bee Branch falls that were flowing

We arrived at the falls after a pretty hard ascent up trail 204. There were at least 20 or so downed trees all no smaller than 15 inches in diameter that were either head or waist level, or lying on the ground. This, along with the soggy, muddy conditions, made the climb more difficult. Add on top of that the lack of wind and high humidity. We finally could hear the rushing falls in the near distance and were greeted by the Big Tree. We were all elated to reach the tree and dunk our heads in the falls.

The Big Tree hug

The Big Tree hug

After exploring the falls and taking a nice long lunch, we attempted to find the 204B route that would loop us around to 209. We scouted for nearly a half hour and could not find it. We decided to double back the way we came back to 209. We ended up passing the sign for the southern end of the 204B route, which at least proves that it’s there somewhere. Shortly after, we approached two hikers in the distance; a father and a son. We exchanged our headings and prepared each other for what was ahead. After explaining we would be taking trail 209 to 202, the duo let us know the water level of the creek we would need to cross was chest deep. I suggested we may need to go back, as we know the previous crossing was only knee deep. The group easily persuaded me we should go for it, and I was glad we pushed on.


We all handled the crossing, but were immediately greeted with a pretty grueling 100 foot climb over about a quarter mile. After about a mile or so ascent, things flattened and widened considerably all the way back to the parking lot. There is also a small, practically ancient cemetery on the way that is a nice spot to stop for a break.

This trail is pretty and also a legit hike. My only beef with the trail is the lack of blazes. There were only handful of orange markings painted on trees, and only on trail 204. There were some signs at intersections, but that was pretty much it. All in all, Sipsey is a well beaten trail, with numerous camp sites and obviously stunning water falls. The Big Tree is a state treasure that only those willing to put in the effort to see it will enjoy. I highly suggest making it out to this trail, preferably on dryer occasions.