<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>The Roaming Drone</title>
	<atom:link href="http://roamingdrone.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://roamingdrone.wordpress.com</link>
	<description>Exploring, Software, Electronics, Photography, and Kayaking from the Gulf Coast</description>
	<lastBuildDate>Sun, 03 Jan 2010 22:42:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='roamingdrone.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>The Roaming Drone</title>
		<link>http://roamingdrone.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://roamingdrone.wordpress.com/osd.xml" title="The Roaming Drone" />
	<atom:link rel='hub' href='http://roamingdrone.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Timelapse Motion Control Axis</title>
		<link>http://roamingdrone.wordpress.com/2010/01/03/timelapse-motion-control-axis/</link>
		<comments>http://roamingdrone.wordpress.com/2010/01/03/timelapse-motion-control-axis/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 22:09:30 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[CNC]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robots]]></category>
		<category><![CDATA[Time-lapse Video]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[axis]]></category>
		<category><![CDATA[engine]]></category>
		<category><![CDATA[motor]]></category>
		<category><![CDATA[openmoco]]></category>
		<category><![CDATA[stepper]]></category>
		<category><![CDATA[timelapse]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=155</guid>
		<description><![CDATA[I&#8217;ve been working on the OpenMoco project lately, and have been playing around with some pan/tilt/etc axis designs.  This is the latest of my prototypes, CNC routed out of cast acrylic with worm gearing. The specs are: 120:1 Worm Gearing Anaheim stepper motor (1.8&#8242;) Minimum rotational degrees at 8x microstepping: 0.0019&#8242; Easydriver v4 stepper driver [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=155&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on the <a href="http://openmoco.org" target="_blank">OpenMoco project</a> lately, and have been playing around with some pan/tilt/etc axis designs.  This is the latest of my prototypes, CNC routed out of cast acrylic with worm gearing.</p>
<p>The specs are:</p>
<ul>
<li>120:1 Worm Gearing</li>
<li>Anaheim stepper motor (1.8&#8242;)</li>
<li>Minimum rotational degrees at 8x microstepping: 0.0019&#8242;</li>
<li>Easydriver v4 stepper driver</li>
<li>Max camera weight: 10lbs.</li>
</ul>
<p>Mounting is allowed is different configurations through the use of small plates and threaded inserts in three sides of the axis.  An additional plate allows a clamp to be mounted to the output shaft.  One small plate aso has a 3/8&#8243;-16 threaded insert for direct attachment to a tripod.  The motor axis is controlled by an Arduino running the <a href="http://openmoco.org/node/9" target="_blank">OpenMoco Timelapse Engine</a>, which is in turn controlled by a netbook using the <a href="http://openmoco.org/node/99" target="_blank">Slim</a> application.</p>
<p>Here&#8217;s a video of it in action, showing how the engine allows real-time changes in addition to scripted activities using keyframes and actions.</p>
<span style="text-align:center; display: block;"><a href="http://roamingdrone.wordpress.com/2010/01/03/timelapse-motion-control-axis/"><img src="http://img.youtube.com/vi/RfYpckCxGy0/2.jpg" alt="" /></a></span>
<p><span id="more-155"></span></p>
<p>And, here&#8217;s a video shot by the previous prototype, using the same engine, to shoot a macro video through a magnifying glass.  While the above video shows its ability to make large movements, this video shows its ability to make very fine-grained movements, covering less than 1/2&#8243; of the magnifying glass throughout the video.  The motion is controlled via pre-programmed keyframes while the engine is running, and the entire video is shot using a DSLR, without assistance.</p>
<span style="text-align:center; display: block;"><a href="http://roamingdrone.wordpress.com/2010/01/03/timelapse-motion-control-axis/"><img src="http://img.youtube.com/vi/TaluuFfFRGo/2.jpg" alt="" /></a></span>
<p>Taking a close-up look at the new axis:</p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5080.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5080.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5079.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5079.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5081.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5081.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5076.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5076.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5087.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5087.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5091.JPG" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5091.JPG" alt="" width="420" height="281" /></a></p>
<p>And here&#8217;s a very simple enclosure for the Arduino running the engine:</p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5085.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5085.jpg" alt="" width="420" height="281" /></a></p>
<p><a href="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5083.jpg" target="_blank"><img class="alignnone" src="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5083.jpg" alt="" width="420" height="281" /></a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/155/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/155/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/155/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=155&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2010/01/03/timelapse-motion-control-axis/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5080.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5079.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5081.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5076.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5087.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5091.JPG" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5085.jpg" medium="image" />

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/om-proto/2/IMGP5083.jpg" medium="image" />
	</item>
		<item>
		<title>A Detailed Guide on Implementing Arduino Intervalometers</title>
		<link>http://roamingdrone.wordpress.com/2009/08/04/arduino_intervalometer/</link>
		<comments>http://roamingdrone.wordpress.com/2009/08/04/arduino_intervalometer/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 15:37:15 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Time-lapse Video]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[blocking]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[canon]]></category>
		<category><![CDATA[interrupts]]></category>
		<category><![CDATA[intervalometer]]></category>
		<category><![CDATA[non-blocking]]></category>
		<category><![CDATA[pentax]]></category>
		<category><![CDATA[time-lapse]]></category>
		<category><![CDATA[timelapse]]></category>
		<category><![CDATA[timing]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=151</guid>
		<description><![CDATA[I&#8217;ve begun a series of tutorials on the basics of developing your own time-lapse electronics. To make sense of all of it, I&#8217;m working in a forward-manner: starting with the most basic elements, and providing tips and tricks that will be built upon in future tutorials. While I understand that most of the DIY builders [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=151&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve begun a series of tutorials on the basics of developing your own time-lapse electronics. To make sense of all of it, I&#8217;m working in a forward-manner: starting with the most basic elements, and providing tips and tricks that will be built upon in future tutorials.</p>
<p>While I understand that most of the DIY builders reading this post are long past the point of building just a simple intervalometer, for those just getting started, this should be highly informative. Unlike many other tutorials, I&#8217;m not just giving you some schematics and a block of code. Instead, my goal is to explain why things are done a certain way, and teaching foundations for better system design.</p>
<p>This tutorial covers building a simple test circuit that will allow you to validate your software and hardware without putting wear on your camera, the importance of protecting your equipment from mistakes, three different timing options: blocking, non-blocking, and non-blocking using simple interrupts, and finally controlling a Canon or Pentax camera. (Nikon, etc. I don&#8217;t have much info on &#8211; perhaps one of the Nikon-having contributors can expand in a later tutorial.)</p>
<p>The tutorial can be accessed here: <a href="http://openmoco.org/node/88">http://openmoco.org/node/88</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/151/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/151/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/151/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=151&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2009/08/04/arduino_intervalometer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>
	</item>
		<item>
		<title>OpenMoco: The Open-Source Photographic Motion Control System</title>
		<link>http://roamingdrone.wordpress.com/2009/04/17/openmoco-the-open-source-photographic-motion-control-system/</link>
		<comments>http://roamingdrone.wordpress.com/2009/04/17/openmoco-the-open-source-photographic-motion-control-system/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 16:08:52 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[CNC]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Time-lapse Video]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[article]]></category>
		<category><![CDATA[artistic license]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[circuit]]></category>
		<category><![CDATA[diy motion control]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[moco]]></category>
		<category><![CDATA[motor]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[openmoco]]></category>
		<category><![CDATA[robot]]></category>
		<category><![CDATA[sketch]]></category>
		<category><![CDATA[time-lapse]]></category>
		<category><![CDATA[timelapse]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=147</guid>
		<description><![CDATA[I&#8217;m happy to announce that I have released the first parts of the OpenMoco System, and set up a website for it. I&#8217;ve been working with Jay Burlage (milapse) on bringing this to market as a viable product. The first components are designed around a simple and inexpensive controller to build for time-lapse motion control [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=147&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m happy to announce that I have released the first parts of the OpenMoco System, and set up a website for it. I&#8217;ve been working with Jay Burlage (milapse) on bringing this to market as a viable product.</p>
<p>The first components are designed around a simple and inexpensive controller to build for time-lapse motion control (What I refer to as the &#8216;Engine&#8217;), including a fully-functional API for perl scripts running on a computer to configure and control the engine.</p>
<p>The OpenMoco system is designed around several key components:</p>
<ul>
<li><strong>OpenMoco Engine</strong>: A core body of code that runs on a stand-alone arduino providing direct control of motors and cameras.  The code and hardware combined make up an &#8216;engine&#8217;</li>
<li><strong>OpenMoco Interface</strong>: A body of code and/or a physical hardware component that provides an abstracted user interface, fulfilling a given use-case (easy timelapse, advanced timelapse, stop-motion, scripting APIs, etc.)</li>
<li><strong>OpenMoco Elements</strong>: The physical motor and bracket components that perform the motion and provide the final step in fulfilling the users&#8217; goals.  These components are CC licensed, and may be built or bought</li>
</ul>
<p>I&#8217;m working on prototyping the OpenMoco Elements hardware designs for fabrication using my wonderful K2 CNC machine, but in the mean-time I&#8217;ve already released a fully-functional Engine and Perl-Based API.</p>
<p>Here&#8217;s a very brief review of the engine features:</p>
<ul>
<li>Camera Intervalometer (1-65,535 seconds)</li>
<li>Focus pre-tap function (trigger focus line before firing)</li>
<li>3-axis stepper motor control (for pulse-driven [step/dir] stepper drivers)</li>
<li>Linear ramping of move execution speed (to prevent missed steps and jarring of camera during movement)</li>
<li>Linear ramping of motor movements in output video</li>
<li>Action Scripting (define actions to be taken at given keyframes)</li>
<li>Camera, Time, and Motor Movement Keyframing (trigger actions after # of shots, movements, or time)</li>
<li>An alt Input/Output for firing flash, triggering second camera, controlling program via external input, etc.</li>
<li>Two serial command interfaces for controlling via computer and/or another microcontroller (touch-screen UI, etc.)</li>
</ul>
<p>For an example of the simplicity of the design of the engine, even given all of the above capabilities, check out the circuit design:</p>
<p style="text-align:center;"><a href="http://openmoco.org/sites/default/files/openmoco-circuit.png" target="_blank"><img class="aligncenter" title="OpenMoco Engine Schematic" src="http://openmoco.org/sites/default/files/openmoco-circuit.png" alt="" width="495" height="225" /></a></p>
<p>The goal is also to make the OpenMoco website a haven for all kinds of information related to DIY photographic motion control.</p>
<p>Come on by and check it out: <a href="http://www.OpenMoco.org/" target="_blank"> www.OpenMoco.org</a></p>
<p>The engine documentation (incomplete as of this writing):<a href="http://openmoco.org/node/9" target="_blank"> Engine Documentation<br />
</a></p>
<p>Download the Engine and the Perl API:  <a href="http://openmoco.org/node/12" target="_blank">Software Downloads</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/147/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/147/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/147/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=147&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2009/04/17/openmoco-the-open-source-photographic-motion-control-system/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>

		<media:content url="http://openmoco.org/sites/default/files/openmoco-circuit.png" medium="image">
			<media:title type="html">OpenMoco Engine Schematic</media:title>
		</media:content>
	</item>
		<item>
		<title>LightRails &#8211; Dynamic External Exposure Control for Time-lapse</title>
		<link>http://roamingdrone.wordpress.com/2009/03/25/lightrails-dynamic-external-exposure-control-for-time-lapse/</link>
		<comments>http://roamingdrone.wordpress.com/2009/03/25/lightrails-dynamic-external-exposure-control-for-time-lapse/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 15:30:01 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robots]]></category>
		<category><![CDATA[Time-lapse Video]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[bulb mode]]></category>
		<category><![CDATA[calculate]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[digital]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[exposure time]]></category>
		<category><![CDATA[Exposure Value]]></category>
		<category><![CDATA[f/stop]]></category>
		<category><![CDATA[intervalometer]]></category>
		<category><![CDATA[light meter]]></category>
		<category><![CDATA[light sensor]]></category>
		<category><![CDATA[lightrails]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[robot]]></category>
		<category><![CDATA[time-lapse]]></category>
		<category><![CDATA[timelapse]]></category>
		<category><![CDATA[TSL230R]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=140</guid>
		<description><![CDATA[I&#8217;ve been sitting on this a little while, and I feel a bit remiss in not sharing it sooner.  I had intended to make it &#8220;perfect&#8221; before sharing, but feel I&#8217;ve reached a point where I&#8217;m not ready to spend all of my effort on this project, and instead wish to work more on OpenMoco [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=140&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><em>I&#8217;ve been sitting on this a little while, and I feel a bit remiss in not sharing it sooner.  I had intended to make it &#8220;perfect&#8221; before sharing, but feel I&#8217;ve reached a point where I&#8217;m not ready to spend all of my effort on this project, and instead wish to work more on OpenMoco (but we&#8217;ll talk more about that soon!).  So, I&#8217;ll share this as a more &#8220;rough&#8221; project.</em></p>
<p>Some time ago, I started out with the <a href="http://roamingdrone.wordpress.com/2008/11/13/arduino-and-the-taos-tsl230r-light-sensor-getting-started/" target="_blank">TSL230R chip</a> from Taos with the intent of producing a (a) my own digital light meter and (b) a dynamic external control system for time-lapse photography.  Certainly, the act of creating my own digital light meter was a smashing success, also having it control my dSLR via a remote cable in bulb mode was also a great success.  Enough so that it should prove an invaluable tool to the DIY pinhole photographer.  (Man, how do you time that 2:35:20 exposure manually? =)</p>
<p>The problem I wanted to solve was a difficult, but common one: how do you effectively manage exposure changes across sunrise and sunset time-lapses with a dSLR?  It sounds very easy, just go into Av or Tv mode!  Of course, life isn&#8217;t that easy.  The standard dSLRs generally only meter and adjust exposure in the very rough terms of 1/6, 1/4, 1/3, or even 1/2 EV steps!  This means it has a sledge hammer where the problem calls for a gentle tapping of a finger.  I set out to create a system that would control the camera externally, metering and adjusting exposure in 1/100 EV steps&#8230;</p>
<p><span id="more-140"></span></p>
<p>Some more information about how this all got started, and some color commentary along the way can be found in these two forum postings over at timescapes.org:</p>
<p><a href="http://www.timescapes.org/phpBB3/viewtopic.php?f=7&amp;t=588" target="_blank">Testing Dynamic External Exposure Control</a></p>
<p><a href="http://www.timescapes.org/phpBB3/viewtopic.php?f=4&amp;t=577" target="_blank">Huge Dynamic Range Change</a></p>
<p><a href="http://timescapes.org/phpBB3/viewtopic.php?f=4&amp;t=326" target="_blank">Sunset Time-lapses</a></p>
<p>Unfortunately, the system is still a bit rough for time-lapse photography in controlling exposure in all conditions, but it can be made to succeed in certain conditions, given practice and patience.  I&#8217;m not going to go into great detail on instructions, as it should be largely evident based on the information below, but you will need the following parts at a minimum to use this code:</p>
<ul>
<li>(1x) <a href="http://www.arduino.cc" target="_blank">Arduino</a> board with Atmega168P chip (will probably work with 328p)</li>
<li>(1x) <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8940" target="_blank">Taos TSL230R</a> light sensor IC</li>
<li>(1x) 16&#215;2 Parallel LCD screen</li>
<li>(1x) 4N28 opto-isolator (isolating camera trigger circuitry)</li>
<li>(5x) SPST mometary switches</li>
<li>(1x) 0.1uF Ceramic Capacitor</li>
</ul>
<p>Effectively, the sensor should be placed remote from the control unit (but within specs of the TSL230R), and the control unit uses an LCD display to display information, and five momentary switches to control operation and input data.  The best configuration I&#8217;ve found for using this for time-lapse is to create a reflector, placing the sensor and the capacitor in a separate enclosure from the control, and place the sensor inside of the reflector.  For a reflector, I simply used three pieces of wood connected like a &#8216;C&#8217;, painted the inside flat white, and mounted the sensor housing inside of the &#8216;C&#8217;, facing downwards.  The reflector could then either be placed in complete shade, or pointed towards the scene.  Either way, the unit should be protected from over-head light changes &#8211; it should either meter the scene on average, or the amount of light read in shade.  Which is better depends on the scene in question &#8212; shooting sunny sky-scenes with dim foregrounds generally require scene metering, whereas equally-lit sky and foregrounds prefer shade-readings.  It is also capable of metering through your eye-piece, but resolution suffers greatly (set TTL F/stop in the UI to enable this mode).</p>
<p>The system is configured with ISO, f/stop, minimum and maximum exposure times, number of EV divisions per step (best left at 100), and shot interval.  The light reading is calculated once per second, and exposure time calculated from the settings and light reading.  EV adjust is set to achieve the proper exposure vs. the metered exposure, and the system is left to run.</p>
<p>Random fluctuations and massive jumps from physical interference (say a dog sniffing at your meter while you&#8217;re napping =) are prevented through the simple application of a &#8216;ev change ceiling&#8217; setting, which prevents any change in calculated EV greater than the ceiling (in x/y EV steps &#8212; e.g.: no change greater than 3/100&#8242;s EV.) &#8212; this method has proven its self as both the most simple and effective means through empirical testing, beating out averaging, weighting, and all other sorts of complicated methods.</p>
<p>If you find this useful, come up with a novel application, or have any questions &#8211; please don&#8217;t hesitate to drop me a comment here.  I&#8217;d love to know what you do with it, or help you if you need it.</p>
<p>The following videos should give you some idea how to assemble and use it:</p>
<span style="text-align:center; display: block;"><a href="http://roamingdrone.wordpress.com/2009/03/25/lightrails-dynamic-external-exposure-control-for-time-lapse/"><img src="http://img.youtube.com/vi/_QQmGMQMAzw/2.jpg" alt="" /></a></span>
<span style="text-align:center; display: block;"><a href="http://roamingdrone.wordpress.com/2009/03/25/lightrails-dynamic-external-exposure-control-for-time-lapse/"><img src="http://img.youtube.com/vi/UK05LFcsx-c/2.jpg" alt="" /></a></span>
<p><em>note: both videos show older versions of the UI and the device, where the sensor was integrated into the controller. This is not recommended. </em></p>
<p>And, here&#8217;s an example of its performance:</p>
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/2988868' width='400' height='300' frameborder='0'></iframe></div>
<p>And, without further ado, here&#8217;s the code.  Each section should be pasted into a seperate tab in the Arduino UI, with the first section of code in the main tab.</p>
<p><em>lightrails.pde:</em></p>
<pre class="brush: cpp;">

/*

 LightRails 1.0
   A dynamic external exposure control system with
   integrated intervalometer for time-lapse
   photography

 Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

#include &lt;LiquidCrystal.h&gt;
#include &lt;avr/pgmspace.h&gt;
#include &lt;MsTimer2.h&gt;

#define TSL_FREQ_PIN 2
#define TSL_S0         6
#define TSL_S1         5
#define TSL_S2         3
#define TSL_S3       4

#define CAMERA_PIN   13

 // buttons

#define B_LT   9
#define B_RT   10
#define B_UP   7
#define B_DN   8
#define B_CT   11

  // max number of setup steps available

#define MAX_SETUP_STEPS   12

  // read frequency for how many milliseconds
  // note: this code only works for 1000 any other value
  // and you need to adjust your frequency calculation

#define READ_TM      1000

  // low and high thresholds for adjusting sensitivity
  // of the TSL230R.  If freq is below LO thresh, it will
  // automatically increase sensitivity.  If it increases
  // beyond the HI thresh, it will decrease sensitivity

#define SENS_THRESH_LO 101
#define SENS_THRESH_HI 7999

  // LCD print buffer
  // set to LCD width + 1

#define SIZE_OF_LCD_BUF 17

 // threshold to accept a frequency change
 // the frequency read off the chip must change by
 // at least this many Hz to accept the change
 // this prevents fluttering.  However, it can cause
 // problems with low-light level changes.  You may need
 // to adjust according to types of shooting you
 // typically do (higher for more day shooting
 // and lower for more night shooting)

#define FREQ_CHG_THRESH  20

 // the minimum exposure gap is the minimum time
 // between triggering exposures (for the cases where
 // exposure_time exceeds interval_time).  At a bare
 // minimum, it should be the minimum amount of time
 // required by your camera to consistently register
 // the completion of one exposure and execution of
 // another.  this time is in milliseconds

#define MIN_EXP_GAP 1000

 // some info about exposure data
 // need iso and f/stop to calculate
 // exposure time.  These are just
 // defaults - they are adjusted via the UI

int   iso_rating = 100;
float f_stop     = 8.0;

 // Maximum Diff % in EV Value calculated from reading to reading
byte ev_diff_ceiling  = 0; 

 // for through-a-lens metering - f-stop of the lens
 // (light read must be calculated)

float ttl_stop = 0.0;

 // default times
unsigned int camera_delay       = 5;
unsigned int min_exp_tm         = 10;
byte         max_exp_tm         = 20;

 // actual delay time in mS

unsigned long real_camera_delay = camera_delay * 1000;

  // running variables

float         uwcm2          = 0; // uw/cm2 calculated 
float         lux            = 0; // Lux caclulated
float         ev             = 0; // EV value calculated
float         exp_tm         = 0; // camera exposure time calculated in 1/x value
float         pre_exp_tm     = 0; // for latching, need previous reading
unsigned long frequency      = 0; // frequency read
unsigned long cur_exp_tm     = 0; // current exposure time in mS
unsigned int  shots_fired    = 0; // how many exposures taken since interval started

bool camera_engaged          = false; // camera currently exposing?
bool light_type              = false; // which spd graph to use - d65 [0] or ilA [1]

 // this is used by the pulse counter.

volatile unsigned long pulse_cnt = 0;

 // for calculating time differences

unsigned long pre_tm         = millis();

unsigned int  freq_tm_diff   = 0; // how much time has passed since last frequency reading
                                  // -- note the int size limit
unsigned long camera_tm_diff = 0; // how much time has passed since last exposure

 // this is used by the sensitivity adjustment
 // to record the amount to divide the freq by
 // to get the uW/cm2 value at 420nm

unsigned int  calc_sensitivity   = 10;

 // this is the frequency calculation multiplier
 // based on what scaling factor is chosen. 
 // set_scaling() will adjust it for you.

byte freq_mult = 1;

 // our previous frequency count
 // -- we set it to fifty so it doesn't swing
 // auto-sensitivity adjustment either way on the first
 // reading

unsigned long last_cnt  = 50;

  // some EV tracking variables

float prev_ev = 0;
float set_ev  = 0;

  // our wavelengths (nm) we're willing to calculate illuminance for (lambda)
int wavelengths[18] = { 380, 400, 420, 440, 460, 480, 500, 520, 540, 560, 580, 600, 620, 640, 660, 680, 700, 720 };
  // the CIE V(l) for photopic vision - CIE Vm(l) 1978 - mapping to the same (l) above
float v_lambda[18]  = { 0.0002, 0.0028, 0.0175, 0.0379, 0.06, 0.13902, 0.323, 0.71, 0.954, 0.995, 0.87, 0.631, 0.381, 0.175, 0.061, 0.017, 0.004102, 0.001047 };

  // CIE SPD graphs for D65 and Illuminant A light sources, again mapping to same lambda as included in wavelengths
float spd_graphs[2][18] = {
  { 49.975500, 82.754900, 93.431800, 104.865000, 117.812000, 115.923000, 109.354000, 104.790000, 104.405000, 100.000000, 95.788000, 90.006200, 87.698700, 83.699200, 80.214600, 78.284200, 71.609100, 61.604000 },
  { 9.795100, 14.708000, 20.995000, 28.702700, 37.812100, 48.242300, 59.861100, 72.495900, 85.947000, 100.000000, 114.436000, 129.043000, 143.618000, 157.979000, 171.963000, 185.429000, 198.261000, 210.365000 }
};

/*

  Let's setup all of our display strings for the LCD

  These are stored as PROGMEM so they don't take up valuable
  SRAM

*/
  // main display strings

// setup strings

const prog_char setup_str1[] PROGMEM  = &quot;ISO&quot;;
const prog_char setup_str2[] PROGMEM  = &quot;Target F/Stop&quot;;
const prog_char setup_str3[] PROGMEM  = &quot;EV Adjust&quot;;
const prog_char setup_str4[] PROGMEM  = &quot;EV Steps&quot;;
const prog_char setup_str5[] PROGMEM  = &quot;Max Exp. - Sec&quot;;
const prog_char setup_str6[] PROGMEM  = &quot;Exposure Cycle&quot;;
const prog_char setup_str7[] PROGMEM  = &quot;Latch&quot;;
const prog_char setup_str8[] PROGMEM  = &quot;Min Exp. - mSec&quot;;
const prog_char setup_str9[] PROGMEM  = &quot;Scale Read&quot;;
const prog_char setup_str10[] PROGMEM = &quot;TTL F/Stop&quot;;
const prog_char setup_str11[] PROGMEM = &quot;Light Source&quot;;
const prog_char setup_str12[] PROGMEM = &quot;EV Change Max&quot;;

PGM_P setup_strings[MAX_SETUP_STEPS] PROGMEM =
 {
   setup_str1,
   setup_str2, 
   setup_str3,
   setup_str4, 
   setup_str6,
   setup_str7,
   setup_str8,
   setup_str5,
   setup_str9,
   setup_str10,
   setup_str11,
   setup_str12
 };

 // buffer for above setup strings
char lcd_print_buffer[SIZE_OF_LCD_BUF];

 // ev adjust can be negative
 //
 // how many EV steps to add or subtract
 // to each EV calculation - UI moves in 1/4EV
 // increments.

float ev_adjust     = 0.0;

 // how many steps per EV to deal with -
 // calculations round to the nearest step
 // and adjustments happen in these steps,
 // e.g.: 10 steps = .1 EV per step,
 // 1 step = 1 EV per step

byte ev_steps     = 100;

 // status flags:
 // B0 = intervalometer enable
 // B1 = latch up
 // B2 = latch down
 // B3 = in setup
 // B4 = latched (exp tm not moved due to latch)
 // B5 = latched to min/max exp tm setting
 // B6 = ev adjust enabled
 // B7 = update setup display

byte status = B00000000;

 // current setup step

byte setup_step  = 0;

 // display type flags
 // 0 = 1/x shutter speed/time (calculated)
 // 1 = ms shutter speed (calculated)
 // 2 = frequency
 // 3 = EV (calculated)
 // 4 = W/m2 (calculated)
 // 5 = sensitivity (10, 100, 1000)
 // 6 = lux (calculated)
 // 7 = scale

byte disp_enable = B10000000;

 // button hit flags (plus a few others)
 // B0 = up
 // B1 = dn
 // B2 = lt
 // B3 = rt
 // B4 = ct
 // B5
 // B6 =
 // B7 = camera exposing (use this to save a var elsewhere)

byte buttons = B00000000;

 // time last button was hit
unsigned long button_hit = 0;

 // init lcd display

LiquidCrystal lcd(14, 14, 15, 16, 17, 18, 19);

void setup() {

 lcd.clear();
 lcd.print(&quot;LightRails/1.0&quot;); 

  // attach interrupt to pin8, send output pin of TSL230R to arduino 8
  // call handler on each rising pulse

 attachInterrupt(0, add_pulse, RISING);

 pinMode(TSL_FREQ_PIN, INPUT);

 pinMode(TSL_S0, OUTPUT);
 pinMode(TSL_S1, OUTPUT);
 pinMode(TSL_S2, OUTPUT);
 pinMode(TSL_S3, OUTPUT);

 pinMode(CAMERA_PIN, OUTPUT);

   // set input button pins

 pinMode(B_LT, INPUT);
 pinMode(B_RT, INPUT);
 pinMode(B_UP, INPUT);
 pinMode(B_DN, INPUT);
 pinMode(B_CT, INPUT);

   // enable pullup resistors
 digitalWrite(B_LT, HIGH);
 digitalWrite(B_RT, HIGH);
 digitalWrite(B_UP, HIGH);
 digitalWrite(B_DN, HIGH);
 digitalWrite(B_CT, HIGH);

  // write TSL sensitivity 1x

 digitalWrite(TSL_S0, HIGH);
 digitalWrite(TSL_S1, LOW);

  // set frequency scaling

 tsl_set_scaling(2); 

}

void loop() {

  // operate camera
  // handle user input
  // update light sensor data

    // calculate how much time has passed
    // both for camera firing and light reading

    // this code requires arduino 012 or any version with
    // compatible millis() overflow and behavior

 freq_tm_diff   += millis() - pre_tm;
 camera_tm_diff += millis() - pre_tm;

 pre_tm          = millis();

  // if intervalometer enabled, enough time has passed,
  // and the camera isn't already engaged
  // - fire camera (camera delay is in seconds)

 if( status &amp; B10000000 &amp;&amp; camera_tm_diff &gt;= real_camera_delay &amp;&amp;  camera_engaged == false ) {

       // re-set camera difference timer
     camera_tm_diff = 0;

       // trigger camera remote
     fire_camera();

      // convert sec to msec for next exposure check
      // always try and use the configured value first
      // (see next operation)

     real_camera_delay = camera_delay * 1000;

       // assure MIN_EXP_GAP threshold is enforced
       // between exposure triggers
       //
       // if the exposure time leaves less than the
       // minimum gap between exposures (MIN_EXP_GAP
       // must be &lt;= real_camera_delay), add the minimum gap
       // to the current exposure time, and make that the
       // interval time before the next shot

     if( cur_exp_tm &gt;= ( real_camera_delay - MIN_EXP_GAP ) )
       real_camera_delay = cur_exp_tm + MIN_EXP_GAP;

       // update count of shots fired
     shots_fired++;

 } // end if( status...   

   // see if the user has pressed any buttons, and handle
   // them if need be

 check_input();

   // if a second has passed, we need to
   // update our calculations

 if( freq_tm_diff &gt;= READ_TM ) {

     // reset time counter

   freq_tm_diff = 0;

    // get current frequency

   frequency = tsl_get_freq(); 

    // ignore changes in frequency below FREQ_CHG_THRESH

   if( last_cnt &gt; 0 &amp;&amp; abs( (long) ( frequency - last_cnt ) ) &lt; FREQ_CHG_THRESH )
     frequency = last_cnt;

     // set other needed values

   if ( frequency &gt; 0 ) {  

       // chip has given us a positive reading

       // calculate power   
     uwcm2     = tsl_calc_uwatt_cm2(frequency);   

     if( uwcm2 &lt;= 0 ) {
         // handle no actual power reading available
       uwcm2 = 0;
       lux   = 0;
     }
      else {

        // there was a positive power reading...

        // calculate lx value using gaussian formula

       lux = calc_lux_gauss(uwcm2);
      }
   }
   else {
       // 0 frequency read from chip - set all values to zero
     uwcm2 = 0;
     lux   = 0;
   }

   if ( lux &lt;= 0 ) {
       // don't try calculating nonsense - we cant calculate
       // an EV with no light.
     lux = 0;
     ev = -6.0;
   }
   else {
       // we have positive lux reading
       // calculate EV from lux reading
     ev = calc_ev(lux);
   }

      // calculate exposure time value

   exp_tm     = calc_exp_tm( ev, f_stop );

      // determine if we need to latch on to a particular exposure
      // as lowest or highest allowed

   if( status &amp; B10000000 &amp;&amp; status &amp; B01100000) {
     // latch high or low enabled - and intervalometer on     

     if( status &amp; B01000000 ) {
         // latch low is enabled (don't increase exposure time)
         // remember that exp_tm is a divisor - so a higher number == faster exposure
       if( exp_tm &gt; pre_exp_tm) {
         exp_tm = pre_exp_tm;
           // indicate that exposure is latched
         status |= B00001000;
       }
       else {
           // reset latch indicator
         status &amp;= B11110111;
           // set new exposure value to keep exp from
           // getting longer than current exp. (new
           // ceiling)
         pre_exp_tm = exp_tm;
       }
     }
     else if( status &amp; B00100000 ) {
         // latch high enabled (don't decrease exposure time)
       if( exp_tm &lt; pre_exp_tm ) {
          exp_tm = pre_exp_tm;
          status |= B00001000;
       }
       else {
         status &amp;= B11110111;
           // new floor
         pre_exp_tm = exp_tm;
       }
     }
   } // end if latch high or low enabled

     // calculate exposure ms
     // we can only go as short as 1ms, so don't
     // try and calculate below that.  Check for
     // 1/1000 ceiling

   if( exp_tm &gt;= 1000 ) {
    cur_exp_tm = 1;
   }
   else {
     cur_exp_tm = calc_exp_ms( exp_tm );
   }

    // check for minimum/max exposure time

   if( cur_exp_tm &lt; min_exp_tm ) {
       // bring time up to min. exposure time
     cur_exp_tm = min_exp_tm;
       // set exposure time ceiling/floor engaged
     status |= B00000100;
   }
     // max exposure time is in seconds
   else if( max_exp_tm &gt; 0 &amp;&amp; cur_exp_tm &gt; ( max_exp_tm * 1000 ) ) {
     cur_exp_tm = max_exp_tm * 1000;
       // set exposure time ceiling/floor engaged
     status |= B00000100;
   }
   else {
       // at neither min nor max exp. time
       // reset exposure time ceiling/floor flag
     status &amp;= B11111011;
   }

         // determine if we need to change sensitivity --
         // two readings in a row must pass our thresholds

   if( frequency &lt; SENS_THRESH_LO &amp;&amp; last_cnt &lt; SENS_THRESH_LO &amp;&amp; calc_sensitivity &lt; 1000 ) {
      tsl_sensitivity( HIGH );
   }
   else if( frequency &gt; SENS_THRESH_HI &amp;&amp; last_cnt &gt; SENS_THRESH_HI &amp;&amp; calc_sensitivity &gt; 10) {
      tsl_sensitivity( LOW );
   }

     // save off current reading so we can see if we need to adjust sensitivity
     // on the next pass

   last_cnt = frequency;

     // set display to update

   status |= B00000001;   

 } // end if(freq_tm_diff &gt; READ_TM)

    //
    // update user interface as the last step in the main
    // loop...
    // 

 if(  status &amp; B00010000 &amp;&amp; status &amp; B00000001 ) {
     // in setup and screen needs updating

       // clear update flag
     status &amp;= B11111110;

       // display setup info

     print_setup_display();
 }
  else if( status &amp; B00000001 ) {
    // on main screen and need to update display

       // clear update flag
     status &amp;= B11111110;

     print_info();

  }

} // end main loop

 // interrupt handler to function as a pulse-counter

void add_pulse() {

  // increase pulse count
 pulse_cnt++;
 return;
}

float float_abs_diff( float f1, float f2 ) {

  float diff = f1 &gt; f2 ? f1 - f2 : f2 - f1;

  if( diff &lt; 0 )
    diff *= 1;

  return(diff);
}
</pre>
<p><em>tsl230r_functions.pde:</em></p>
<pre class="brush: cpp;">

/*

 LightRails - TSL230R Control and Conversion Functions

   Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 unsigned long tsl_get_freq()
 float tsl_calc_uwatt_cm2(unsigned long freq)
 void tsl_sensitivity( bool dir )
 void tsl_set_scaling( int what )

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

unsigned long tsl_get_freq() {

    // we have to scale out the frequency - the only
    // 1:1 frequency pulse we get is 100x scale.  Smaller
    // scaling on the TSL230R requires us to multiply by a factor
    // to get actual frequency

  unsigned long freq = pulse_cnt * freq_mult;
  pulse_cnt = 0;
  return(freq);
}

float tsl_calc_uwatt_cm2(unsigned long freq) {

  // get uW observed - assume 640nm wavelength
  // calc_sensitivity is our divide-by to map to a given signal strength
  // for a given sensitivity (each level of greater sensitivity reduces the signal
  // (uW) by a factor of 10)
  //
  // note: this function does not take sensor size into account
  //       other functions handle this

  float uw_cm2 = (float) freq / (float) calc_sensitivity;

  return(uw_cm2);

}

void tsl_sensitivity( bool dir ) {

  // adjust sensitivity of TSL230R in 3 steps of 10x either direction

  int pin_0 = false;
  int pin_1 = false;

  if( dir == true ) {

      // increasing sensitivity

      // -- already as high as we can get
    if( calc_sensitivity == 1000 )
      return;

    if( calc_sensitivity == 100 ) {
        // move up to max sensitivity
      pin_0 = true;
      pin_1 = true;
    }
    else {
        // move up to med. sesitivity
      pin_1 = true;
    }

      // increase sensitivity divider
    calc_sensitivity *= 10;
  }
  else {
      // reducing sensitivity

      // already at lowest setting

    if( calc_sensitivity == 10 )
      return;

    if( calc_sensitivity == 100 ) {
        // move to lowest setting
      pin_0 = true;
    }
    else {
        // move to medium sensitivity
      pin_1 = true;
    }

      // reduce sensitivity divider
    calc_sensitivity = calc_sensitivity / 10;
  }

    // make any necessary changes to pin states

 digitalWrite(TSL_S0, pin_0);
 digitalWrite(TSL_S1, pin_1);

 return;
}

void tsl_set_scaling ( int what ) {

  // set output frequency scaling for TSL230R
  // when increasing the scaling for divide-by-output, you reduce the
  // freq multiplier by a factor of ten. 
  // e.g.:
  // scale = 2 == freq_mult = 100
  // scale = 10 == freq_mult = 10
  // scale = 100 == freq_mult = 1

  byte pin_2 = HIGH;
  byte pin_3 = HIGH;

  switch( what ) {
    case 2:
      pin_3     = LOW;
      freq_mult = 2;
      break;
    case 10:
      pin_2     = LOW;
      freq_mult = 10;
      break;
    case 100:
      freq_mult = 100;
      break;
    default:
      return;
  }

  digitalWrite(TSL_S2, pin_2);
  digitalWrite(TSL_S3, pin_3);

  return;
}
</pre>
<p><em>camera_controls.pde</em>:</p>
<pre class="brush: cpp;">

/*

   -- Camera Control Functions

 LightRails 1.0
   A dynamic external exposure control system with
   integrated intervalometer for time-lapse
   photography

 Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

void fire_camera() {

  digitalWrite(CAMERA_PIN, HIGH);
    // start timer to stop camera exposure
  MsTimer2::set(cur_exp_tm, stop_camera);
  MsTimer2::start();

    // update camera currently enaged
  camera_engaged = true;

  return;
}

void stop_camera() {

  digitalWrite(CAMERA_PIN, LOW);
    // turn off timer
  MsTimer2::stop();

    // update camera currently enaged
  camera_engaged = false;
}
</pre>
<p><em>lcd_display.pde:</em></p>
<pre class="brush: cpp;">

/*

  -- LCD Display Functions

 LightRails 1.0
   A dynamic external exposure control system with
   integrated intervalometer for time-lapse
   photography

 Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

void print_setup_display() {

   // clear out lcd print buffer

 memset(lcd_print_buffer, 0, SIZE_OF_LCD_BUF);

   // get setup string from hash

 strcpy_P(lcd_print_buffer, (char*)pgm_read_word( &amp;(setup_strings[setup_step])) );

 lcd.clear();
 lcd.setCursor(0, 0);

 lcd.print(lcd_print_buffer);

   // go to second line
 lcd.setCursor(0, 1);

   // determine which setup step to display

 switch(setup_step) {
     case 0:
       lcd.print(iso_rating, DEC);
       break;

     case 1:
             // handle rounding for higher f-stops

       if( f_stop &gt; 7.1 ) {
         print_float((float) int(f_stop));
       }
       else {
         print_float(f_stop);
       }

       break;

     case 2:
       print_float(ev_adjust);
       break;

     case 3:
       lcd.print(ev_steps, DEC);
       break;

     case 4:
       lcd.print(camera_delay, DEC);
       break;

     case 5:
       if( status &amp; B01000000 ) {
         lcd.print('-');
       }
       else if( status &amp; B00100000 ) {
         lcd.print('+');
       }
       else {
         lcd.print('X');
       }
       break;

     case 6:

      lcd.print(min_exp_tm, DEC);
      break;

     case 7:

      lcd.print(max_exp_tm, DEC);
      break;

     case 8:

      lcd.print(freq_mult, DEC);
      break;

     case 9:

      print_float(ttl_stop);
      break;

     case 10:

      lcd.print(light_type, DEC);
      break;

     case 11:

      lcd.print(ev_diff_ceiling, DEC);
      break;

     default:
       break;
   }

return;
}

void print_info() {

   lcd.clear();

   lcd.setCursor(0, 0);

    // display set iso and f-stop  
   lcd.print(iso_rating);
   lcd.print(' ');

   lcd.print('f');

             // handle rounding for higher f-stops
   if( f_stop &gt; 7.1 ) {
     print_float((float) int(f_stop));
   }
   else {
     print_float(f_stop);
   }

     // if intervalometer on, show 'I' indicator
     // and count of shots fired

   if( status &amp; B10000000 ) {
     lcd.setCursor(15,0);
     lcd.print('I');

     if( shots_fired &gt; 999 ) {
       lcd.setCursor(11, 0);
     }
     else if( shots_fired &gt; 99 ) {
       lcd.setCursor(12,0);
     }
     else if( shots_fired &gt; 9 ) {
       lcd.setCursor(13,0);
     }
     else {
       lcd.setCursor(14,0);
     }

     lcd.print(shots_fired, DEC);

   }

    // move to second line 
   lcd.setCursor(0,1);   

   if( disp_enable &amp; B10000000 ) {

         // show exposure time in 1/x notation

        if( exp_tm &gt;= 2 ) {
         float disp_v = 0;

         if( exp_tm &gt;= (float) int(exp_tm) + (float) 0.5 ) {
           disp_v = int(exp_tm) + 1;
         }
         else {
           disp_v = int(exp_tm);
         }

         lcd.print(&quot;1/&quot;);
         lcd.print(exp_tm, DEC);
        }
        else if( exp_tm &gt;= 1 ) {
           // deal with times larger than 1/2 second

         float disp_v = 1 / exp_tm;
           // get first significant digit
         disp_v       = int( disp_v * 10 );     

         lcd.print('.');
         lcd.print(disp_v, DEC);
         lcd.print('&quot;');    
        }
        else {
         int disp_v = int( (float) 1 / exp_tm);

         lcd.print(disp_v, DEC);
         lcd.print('&quot;');

      }
    }

   else if( disp_enable &amp; B01000000 ) {
         // display actual exposure mS
       print_ul(cur_exp_tm);
       lcd.print(&quot;mS&quot;);
   }

   else if( disp_enable &amp; B00100000 ) {
         // display frequency reading
     lcd.print(&quot;Fq &quot;);
     lcd.print(frequency, DEC);

   }

   else if( disp_enable &amp; B00010000 ) {

         // display EV
       lcd.print(&quot;EV &quot;);
       print_float(ev);

       if( ev_adjust &gt; 0 || ev_adjust &lt; 0 ) {
           // show any adjustment made
         lcd.print('[');
         print_float(ev_adjust);
         lcd.print(']');
       }

   } 

   else if( disp_enable &amp; B00001000 ) {
       // uW/m2
     print_float(uwcm2);
     lcd.print(&quot;uW&quot;);

   }
   else if( disp_enable &amp; B00000100 ) {
       // sensitivity level
     lcd.print('S');
     lcd.print(calc_sensitivity, DEC);     

   }

   else if( disp_enable &amp; B00000010 ) {
         // display lux
       lcd.print(&quot;Lx &quot;);
       print_float(lux);

   }

   else if( disp_enable &amp; B00000001 ) {
       // divide-by-factor display
     lcd.print('R');
     lcd.print(freq_mult, DEC);
   }

  lcd.setCursor(14,1);

          // minimum/maximum exposure time enabled?
  if( status &amp; B00000100 )
       lcd.print('M');

           // exposure was latched?        
 if( status &amp; B00001000 )
        lcd.print('L');

}

void print_float( float val ){

  if ( val &lt; 0 ) {
    lcd.print('-');
    val *= -1;
  }    

  print_ul( (unsigned long int) int(val) ); 
  lcd.print('.');

    // add 1 digit for hundreths precision
  if( (val * 100) - (int(val) * 100)  &lt; 10 )
    lcd.print('0');

  print_ul( (val * 100) - (int(val) * 100) );

}   

void print_ul( unsigned long val ) {

    // print unsigned long to lcd

   // clear out lcd print buffer

 memset(lcd_print_buffer, 0, SIZE_OF_LCD_BUF);

 ultoa(val, lcd_print_buffer, 10); 
 lcd.print(lcd_print_buffer);

 return;
}
</pre>
<p><em>photo_calculations.pde:</em></p>
<pre class="brush: cpp;">

/*

 LightRails 1.0
   A dynamic external exposure control system with
   integrated intervalometer for time-lapse
   photography

 Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

/* 

 Functions to calculate photographic values
 from light readings, the following functions are
 found here:

 calc_lux_single*
 calc_lux_gauss
 calc_ev
 calc_exp_tm
 calc_exp_ms

 Last Modified: 2/29/2009, c.a. church
 Original:      10/15/2008, c.a. church
*/ 

/* 

  We always use multiple wavelengths.  This function is
  if you happen to be erm, you know, filming something illuminated
  by a single wavelength light source.  Given the rarity of this
  situation, you'll have to provide the luminous efficiency function
  value yourself.

float calc_lux_single(float uw_cm2, float efficiency) {

    // calculate lux (lm/m^2) for single wavelength, using standard formula:
    // Xv = Xl * V(l) * Km
    // Xl is W/m^2 (calculate actual receied uW/cm^2, extrapolate from sensor size (0.0136cm^2)
    // to whole cm size, then convert uW to W)
    // V(l) = efficiency function (provided via argument)
    // Km = constant, L/W @ 555nm = 683 (555nm has efficiency function of nearly 1.0)
    //
    // Only a single wavelength is calculated - you'd better make sure that your
    // source is of a single wavelength...  Otherwise, you should be using
    // calc_lux_gauss() for multiple wavelengths

  return( ( ( uw_cm2 * ( (float) 1 / (float) 0.0136) ) / (float) 1000000 ) * (float) 100   * efficiency * (float) 683 );
}

*/

float calc_lux_gauss( float uw_cm2 ) {

    // # of wavelengths mapped to V(l) values - better have
    // enough V(l) values!

  int nm_cnt = sizeof(wavelengths) / sizeof(int);

    // watts/m2

  float w_m2 =  ( uw_cm2 * ( (float) 1 / (float) 0.0136 ) / (float) 1000000 ) * (float) 100;

  float result = 0;

    // integrate XlV(l) dl
    // Xl = uW-m2-nm caclulation weighted by the CIE lookup for the given light
    //   temp
    // V(l) = standard luminous efficiency function

  for( int i = 0; i &lt; nm_cnt; i++) {

    if( i &gt; 0) {
      result +=  ( spd_graphs[light_type][i] / (float) 1000000)  * (wavelengths[i] - wavelengths[i - 1]) * w_m2  * v_lambda[i];
    }
    else {
      result += ( spd_graphs[light_type][i] / (float) 1000000) * wavelengths[i] * w_m2 * v_lambda[i];
    }

  }

    // multiply by constant Km and return

  return(result * (float) 683);
}

float calc_ev( float lux ) {

    // calculate EV using APEX method:
    // Ev = Av + Tv = Bv + Sv
    // Bv = log2( B/NK )
    // Sv = log2( NSx )
    // K  = Meter Calibration Constant
    //      14 = Pentax standard
    // N  = constant relationship between Sx and Sv

  float ev = ( log( (float)  0.3 * (float) iso_rating ) / log(2) ) + ( log( lux / ( (float) 0.3 * (float) 14.0 ) ) / log(2) );

   // round down if EV step
   // value is set to whole steps

  if( ev_steps == 1 )
    ev = (float) int(ev);

    // convert to positive value temporarily, if needed
  bool neg_ev = false;

  if( ev &lt; 0 ) {
     neg_ev = true;
     ev *= -1;
   }

   if( ev &gt; int(ev) ) {

      // if ev has a decimal value, determine nearest
      // fraction of EV to round to, based on ev step
      // setting

         // handle rounding to nearest step

       int rem = ( ( ev - int(ev) ) * 100 );    
       int step = 100 / ev_steps;

       for (int i = ev_steps; i &gt; 0; i-- ) {

         if( rem &gt;= step * i) {
           rem = step * i;
           break;
         }
       }

       ev = (float) int(ev) + ((float) rem / 100);

   }

    // reset back to negative EV value
  if( neg_ev == true )
    ev *= -1.0;

    // is there a ceiling set for maximum EV change?
    // if so, handle only moving a maximum amount of &lt;ceiling&gt;
    // steps between readings

  if( ev_diff_ceiling &gt; 0 ) {

    float diff = float_abs_diff( ev, prev_ev );
    float ceiling = (float) ev_diff_ceiling / (float) ev_steps;

    if( diff &gt; ceiling ) {

      if( ev &lt; prev_ev ) {
        ev = prev_ev - ceiling;
      }
      else {
        ev = prev_ev + ceiling;
      }

    }

  }

  prev_ev = ev; 

    // if ev adjust enabled - apply it now 

   ev += ev_adjust;

    // deal with TTL compensation
    // each full aperture step results in one less
    // EV read in, so adjust output
    // up by one EV per stop    

  if( ttl_stop &gt; 0 )
    ev += log( ttl_stop ) / log(sqrt(2));

  return(ev);

}

float calc_exp_tm ( float ev, float aperture  ) {

    // Ev = Av + Tv = Bv + Sv
    // need to determine Tv value, so Ev - Av = Tv
    // Av = log2(Aperture^2)
    // Tv = log2( 1/T ) = log2(T) = 2 ^^ (Ev - Av)

  float exp_tm = ev - ( log( pow(aperture, 2) ) / log(2) );

  float exp_log = pow(2, exp_tm); 

  return( exp_log  );
}

unsigned long calc_exp_ms( float exp_tm ) {

  return( (unsigned long) ( 1000 / exp_tm ) );

    // if you wish to round actual mS for exposure to nearest
    // exposure step (the actual exposure step displayed in 1/x
    // format), un-comment the following code and comment the
    // line above out.
    //
    // Mind you, that doing so will make the device
    // no more accurate than your standard camera's meter.

/*   
      // deal with times less than or equal to half a second
   if( exp_tm &gt;= 2 ) {

     if( exp_tm &gt;= (float) int(exp_tm) + (float) 0.5 ) {
       exp_tm = int(exp_tm) + 1;
     }
     else {
       exp_tm = int(exp_tm);
     }

     return(1000 / exp_tm);

   }
   else if( exp_tm &gt;= 1 ) {
     // deal with times larger than 1/2 second

     float disp_v = 1 / exp_tm;
       // get first significant digit
     disp_v       = int( disp_v * 10 );    
     return( ( 1000 * disp_v ) / 10 );

   }
    else {
      // times larger
     int disp_v = int( (float) 1 / exp_tm);
     return((unsigned long) 1000 * (unsigned long) disp_v);

    }
*/

}
</pre>
<p><em>user_input.pde:</em></p>
<pre class="brush: cpp;">

/*

 -- user input functions

 LightRails 1.0
   A dynamic external exposure control system with
   integrated intervalometer for time-lapse
   photography

 Copyright (c) 2008-2009 C. A. Church drone&lt; a_t &gt;dronecolony.com

 This program is free software: you can redistribute it
 and/or modify it under the terms of the GNU General
 Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at
 your option) any later version.

 This program is distributed in the hope that it will be
 useful, but WITHOUT ANY WARRANTY; without even the
 implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License
 for more details. 

*/

void check_input() {

   // this function determines if any button has been hit,
   // and what to do about it

   // up and down do not require a HIGH (unpressed) reading
   // so that you can hold them down and quickly cycle through
   // values (about 3 changes per second)

 if( digitalRead(B_UP) == LOW &amp;&amp; millis() - button_hit &gt; 300) {

      button_hit = millis();
      take_button_action(0);
      return;
 }

 if( digitalRead(B_DN) == LOW &amp;&amp; millis() - button_hit &gt; 300 ) {
      //pre_dn = true;
      take_button_action(1);
      button_hit = millis();
      return;
 }

 if( digitalRead(B_LT) == LOW) {
  if(buttons &amp; B00100000 &amp;&amp; millis() - button_hit &gt; 300) {  
      buttons &amp;= B11011111;

      take_button_action(2);
      button_hit = millis();
      return;
   }

   buttons &amp;= B11011111;

 }
  else {
    buttons  |= B00100000;
  }

 if( digitalRead(B_RT) == LOW ) {
   if( buttons &amp; B00010000 &amp;&amp; millis() - button_hit &gt; 300) {
      buttons &amp;= B11101111;
      take_button_action(3);
      button_hit = millis();
      return;
   }
  buttons &amp;= B11101111;
 }
 else {
   buttons |= B00010000;
 }

 if( digitalRead(B_CT) == LOW ) {
   if( buttons &amp; B00001000 &amp;&amp; millis() - button_hit &gt; 300) {
      buttons &amp;= B11110111;
      take_button_action(4);
      button_hit = millis();
      return;
   }
   buttons &amp;= B11110111;
 }
 else {
   buttons |= B00001000;
 }

}

void take_button_action( byte button ) {

  // this function operates whatever action is desired when
  // a button is pressed.  called by check_input()

  switch(button) {
    case 0:
      // up hit

      if( status &amp; B00010000 ) {

            // we're in a setup screen...

            // increasing value at current cursor position

          change_setup_value(setup_step, 1);

            // update flag to show change in display value
          status |= B00000001;

          return;
      }
      else {      
        // on main screen - up turns intervalometer on

            // if intervalometer on already, do nothing

          if( status &amp; B10000000 )
            return;

            // turn on intervalometer
          status |= B10000000;
            // save current exposure reading for latch
          pre_exp_tm = exp_tm; 

        }

      break;

    case 1:
      // down hit

      if( status &amp; B00010000 ) {
            // we're in a setup screen     
            // decreasing value at current cursor position

          change_setup_value(setup_step, -1);
          status |= B00000001;

          return;
      }
      else {

           // main menu - turn off intervalometer
           // re-set latch matched (if set)
         status &amp;= B01110111;
         shots_fired = 0;
       }

      break;

   case 2:
     // left button was hit

      // do nothing if in setup menu          
     if( status &amp; B00010000 )
       return;

           // main display, cycle through display values

     if( disp_enable &amp; B10000000 ) {
           // we were already left, move to the furthest right
           // value
         disp_enable = B00000001;
           // set screen to update
         status |= B00000001;
     }
     else {
             // shift current display value left
           disp_enable = disp_enable &lt;&lt; 1;
           status |= B00000001;
     }  

     break;

   case 3:
     // right button was hit

      // do nothing if in setup menu    
     if( status &amp; B00010000 )
         return;       

           // main display, cycle through display values

       if( disp_enable &amp; B00000001 ) {
           // we were already at furthest right value,
           // need to move to furthest left value
         disp_enable = B10000000;

           // set screen to update
         status |= B00000001;
       }
       else {
             // shift current display right
           disp_enable = disp_enable &gt;&gt; 1;
             // set screen to update
           status |= B00000001;
       }

     break;

   case 4:

      // center button hit

      if( status &amp; B00010000 ) {
          // in setup mode - we're going to change which
          // setup value we're displaying

          // set display to update   
        status |= B00000001;

        if( setup_step == MAX_SETUP_STEPS - 1 ) {
            // no more steps to go, exit menu 
          setup_step = 0;
            // set that we're no longer in setup
          status &amp;= B11101111;
          return;
        }

        setup_step++;
        return;

      }
      else {
          // not in setup or input -
          // go into setup mode, tell display
          // to refresh
        status |= B00010001;
        return;
      }

      break;
  }

}

void change_setup_value( byte which, int what ) {

  switch( which ) {
    case 0:

      {

        // change iso value, convert to logarithmic
        // scale first, then add or subtract one step
        // and convert back to arithmetic scale 

       float foo = log(iso_rating) / log(10);

       int din = ( 10 * foo ) + 1;

       din += what;

       if( din &lt; 1 )
          din = 1; 

       float bar = pow(10, (float) ( (float) din - 1) / (float) 10 );

       if( bar &gt; int(bar) ) {
          iso_rating = int(bar) + 1;
       }
        else {
          iso_rating = int(bar);
        }

      }

      break;

    case 1:
      {
          // move f_stop value - move one third step
          // either direction

        float steps = log( f_stop ) / log( sqrt(2) );

        if( what &gt; 0 ) {
          steps += 0.3333;
        }
        else {
          steps -= 0.3333;
        }

        if( steps &lt; 0 )
          steps = 0;

        f_stop = pow( sqrt(2), steps );

      }
      break; 

    case 2:
        // ev adjust moes in 1/4 EV increments

      ev_adjust += (float) what * 0.25;
      break;

    case 3:
        // ev steps determines how many divisions of an EV
        // there are when calculating automatic exposure
        // values.  more steps = better granularity in exposure
        // timing.

      ev_steps += what;
      if( ev_steps &lt; 0 )
        ev_steps = 0;

      break;

    case 4:

      camera_delay += what;

      if( camera_delay &lt; 1 )
        camera_delay = 1;

        // ms delay time
      real_camera_delay = camera_delay * 1000;

      break;    

    case 5: 

        // cycle between latch settings

      if( status &amp; B01000000 ) {
        status &amp;= B10111111;
        status |= B00100000;
      }
      else if( status &amp; B00100000 ) {
        status &amp;= B10011111;
      }
      else {
        status |= B01000000;
      }

      break;

    case 6:

      min_exp_tm += what;

        // don't allow min time to be less than 0
      if( min_exp_tm &lt;= 0 )
        min_exp_tm = 0;

      break;

    case 7:

      max_exp_tm += what;

        // don't allow max time to be less than 0
      if( max_exp_tm &lt;= 0 )
        max_exp_tm = 0;

      break;

    case 8:

        // change scaling:
        // scaling value can be 2, 10, or 100
        // allow wrap around from highest to lowest
        // and vice-versa
      freq_mult += what;

        // we only get to 11 by going up from 10 and
        // we only 1 by going down from 2 - next step
        // either way is 100
      if( freq_mult == 11 || freq_mult == 1 ) {
        tsl_set_scaling(100);
      }
      else if( freq_mult == 9 || freq_mult == 101 ) {
          // if we're moving down from 10, or up from 100
          // move to lowest setting
        tsl_set_scaling(2);
      }
      else {
          // if neither of the above cases is true, then our only
          // destination is 10
        tsl_set_scaling(10);
      }

      break;

    case 9:
      {
          // move ttl_stop value - move one third step
          // either direction

        float steps = log( ttl_stop ) / log(sqrt(2));

        if( steps &lt; 0 )
          steps = 0;

        if( what &gt; 0 ) {
          steps += 0.3333;
        }
        else {
          steps -= 0.3333;
        }

          // for ttl stop, we want to get to zero, if possible
          // for non-ttl readings.  We go ahead and skip every stop below
          // 1.0 for the heck of it. (Very few lenses go below 1.0)

        if( steps &lt; 0 ) {
          ttl_stop = 0.0;
        }
         else {
           ttl_stop = pow( sqrt(2), steps );

            // handle rounding for higher f-stops
           if( ttl_stop &gt; 7.1 )
             ttl_stop = int(ttl_stop);
        }

      }
      break; 

    case 10:

      light_type = light_type == 1 ? 0 : 1;
      break;

    case 11:

      ev_diff_ceiling += what;
      break;

    default:
      break;
  }

 return;
} 
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/140/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/140/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/140/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=140&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2009/03/25/lightrails-dynamic-external-exposure-control-for-time-lapse/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>
	</item>
		<item>
		<title>Add AC Power Outlets to Your Jeep Wrangler Console</title>
		<link>http://roamingdrone.wordpress.com/2009/03/01/add-ac-power-outlets-to-your-jeep-wrangler-console/</link>
		<comments>http://roamingdrone.wordpress.com/2009/03/01/add-ac-power-outlets-to-your-jeep-wrangler-console/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 17:41:28 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Exploring]]></category>
		<category><![CDATA[Jeep Accessories]]></category>
		<category><![CDATA[800 watts]]></category>
		<category><![CDATA[AC inverter]]></category>
		<category><![CDATA[AC power]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[jeep]]></category>
		<category><![CDATA[jk]]></category>
		<category><![CDATA[outlets]]></category>
		<category><![CDATA[power]]></category>
		<category><![CDATA[vectra]]></category>
		<category><![CDATA[wrangler]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=130</guid>
		<description><![CDATA[It&#8217;s always a pain in the butt to try and hook up those little A/C inverters to your 12V DC plugs when you&#8217;re on the road. The laptop needs to be charged, so do the external batteries for the camera equipment, the GPS is already using one plug, etc. Wouldn&#8217;t a 500W work light be [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=130&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s always a pain in the butt to try and hook up those little A/C inverters to your 12V DC plugs when you&#8217;re on the road.  The laptop needs to be charged, so do the external batteries for the camera equipment, the GPS is already using one plug, etc.  Wouldn&#8217;t a 500W work light be a great thing to be able to use when you&#8217;re working on a broken down rig on the trail?</p>
<p>In this entry, I&#8217;ll show one technique for adding two A/C outlets to the back of the jeep&#8217;s console, proving 800 watts of power on tap, ready for your laptop or work lights.  The focus will be on integrating everything so that it looks like it came that way from the factory, and providing control of the inverter through your switch panel.</p>
<p>I used a Vectra 800 Watt (1600 peak) 12V DC to A/C 120V  inverter that I had previously cut up for some presently unknown reason.  There are a number of models from other vendors that look, and seem to operate the same, so the general plan of action should apply for any similar inverter.</p>
<p>The finished product will look like this:</p>
<p><img class="aligncenter" title="ac outlets with weather covers" src="http://dronecolony.com/2008/new_img/jk/power/P2280047.jpg" alt="" width="450" height="338" /></p>
<p><span id="more-130"></span></p>
<p>You&#8217;ll need the following parts:</p>
<ul>
<li>(1) Vectra 800W inverter</li>
<li>(1) SPST momentary switch</li>
<li>(3 pair) Molex connectors (2 or more poles)</li>
<li>(4) 10 gauge crimp lugs</li>
<li>(1) 30 Amp heavy duty fuse assembly</li>
<li>(1) 10 gauge butt connector</li>
<li>(1) 14 gauge male crimp spade</li>
<li>(1) 14 gauge female crimp spade</li>
<li>10 gauge wire</li>
<li>14 gauge wire</li>
<li>18 gauge wire</li>
<li>heat-shrink or electrical tape</li>
</ul>
<p>You&#8217;ll also need the following tools:</p>
<ul>
<li>Soldering iron</li>
<li>Wire crimpers</li>
<li>Wire strippers</li>
<li>Cutters</li>
<li>Philips screw driver</li>
<li>T20 Torx driver</li>
</ul>
<p><strong>Step 1:</strong></p>
<p>Remove the face plate from the power inverter by removing the four screws at the corner of the face plate.<br />
With the face plate laying open, record or mark the relationship of the wires going to the A/C outlets.</p>
<p>Cut the wires leading the A/C outlets and connecting the outlets together, making sure to leave enough of the two internal black and white wires to connect to easily later.  Remove the outlets from the face plate by pressing the side tabs in and pushing them out at the same time.  And unscrew the rubber dust covers from the face plate.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="Inverter disassembled" src="http://dronecolony.com/2008/new_img/jk/power/P2270009.jpg" alt="Inverter disassembled" width="450" height="338" /><p class="wp-caption-text">Inverter disassembled</p></div>
<p><strong>Step 2:</strong></p>
<p>Now, we can either completely remove the small circuit board from the face that contains the LED number display and buttons, or leave it un-touched to retain the ability to monitor voltage input and output.  <em>If you like, you can cut all wires and extend them, mounting the face plate on your dashboard or such. </em>For our purposes, we just want a switch on our switch panel to control the  inverter&#8217;s on/off functionality.</p>
<p>Orient the circuit board such that the first wire to your left is a black wire. Locate the first red, and second black wire on the circuit board, these will be the wires we&#8217;re going to use.  (See photo below.)  <em>If you want to retain the original circuit, solder onto these pads, instead of cutting the wires and soldering to them.</em></p>
<p><em></em></p>
<div class="wp-caption aligncenter" style="width: 460px"><em><em><img title="wires to use for switch" src="http://dronecolony.com/2008/new_img/jk/power/P2270016.jpg" alt="wires to use for switch" width="450" height="338" /></em></em><p class="wp-caption-text">wires to use for switch</p></div>
<p>Cut all of the wires leading to the circuit board, and keep track of the two wires you just identified.</p>
<p><strong>Step 3:</strong></p>
<p>Now, we&#8217;re going to wire our switch to turn the inverter on and off.  A momentary switch will connect our black and red wires.   Use an  SPST momentary switch.  It should be labeled &#8220;off-(on)&#8221; indicating that the &#8216;on&#8217; state is momentary, or only connected for as long as the switch is held down.   Wire one of your molex connectors to the switch, and solder the other to two lengths of 18G wire long enough to go from where you mount the inverter to where your switch is installed.  (I put mine under the passenger seat.)</p>
<p>Now, solder the lengths of wire to the red and black wires we prepared in the previous step.  Clean everything up with heat-shrink.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="wiring up switch to switch panel" src="http://dronecolony.com/2008/new_img/jk/power/P2270031.jpg" alt="wiring up switch to switch panel" width="450" height="338" /><p class="wp-caption-text">wiring up switch to switch panel</p></div>
<div class="wp-caption aligncenter" style="width: 460px"><img title="connecting up power switch wires" src="http://dronecolony.com/2008/new_img/jk/power/P2270030.jpg" alt="connecting up power switch wires" width="450" height="338" /><p class="wp-caption-text">connecting up power switch wires</p></div>
<p><em>note: I used a DPST switch because I had one laying around.  Just connect to one of the normally closed pins and the normally open pin in this situation.</em></p>
<p>Now, our inverter turn on and off with a quick press of the button.  Go ahead and hook the inverter up to a bench power supply if you have one, and verify that the switch works.</p>
<p>If you manage to hook the red wire up to the wrong black wire, don&#8217;t fret &#8211; the worst that will happen is that the inverter will not turn on.</p>
<p><strong>Step 4:</strong></p>
<p>Now, it&#8217;s time to wire up the A/C outlets.  Cut two lengths of 14G wire, long enough to go from the location of the inverter to the location your A/C outlets are to be installed.  Solder each end to one of the large black and white wires found in the inverter.  Solder the other ends to TWO molex connectors, making sure to be consistent about what colors of the molex connector are wired to which of the A/C wires.  We use two connectors, so that we may install and remove the A/C plugs easily.  See this photo:</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="ac lines connected to molex connectors" src="http://dronecolony.com/2008/new_img/jk/power/P2270032.jpg" alt="ac lines connected to molex connectors" width="450" height="338" /><p class="wp-caption-text">ac lines connected to molex connectors</p></div>
<p><em>note: using the same colors on the molex connectors resolves confusion later.  As I only had one color 14G wire, a blue electrical tape tag identifies which is connected to the white wire.</em></p>
<p><em></em><br />
Go ahead and solder the other ends of the molex connectors to the A/C plugs removed from the inverter.  Use only two pins on the molex connector for the A/C lines.  The ground line will need to be connected between the two (as in the original wiring inside the inverter), but use a standard male/female spade for these (see later picture) so they may be connected AFTER installing the plugs.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="wiring up A/C outlets to molex connectors" src="http://dronecolony.com/2008/new_img/jk/power/P2280037.jpg" alt="wiring up A/C outlets to molex connectors" width="450" height="338" /><p class="wp-caption-text">wiring up A/C outlets to molex connectors</p></div>
<p><em>note: the standard molex connectors that I show here can be harvested from computers and numerous other scrap electronics.  These are rated at 7.5A load, more than enough for our purposes.  If you wish to buy new connectors, any type is fine as long as they have a minimum rating of 7A.</em></p>
<p><em><strong>Step 5:</strong><br />
</em></p>
<p>Go ahead and install the inverter in its final location.  For me, I placed it under the passenger seat, other locations can include the rear cargo area, behind the dash, etc.  Just make sure that it gets adequate ventilation, and is protected from the elements.</p>
<p>Run the switch wiring to your switch panel, or wherever you wish to install the switch.  My switch panel is at the lower column panel (like the daystar panel, or 12Vguy&#8217;s panel), so the wires are neatly tucked under the shifting column.  Install your switch now.</p>
<p><strong>Step 6:</strong></p>
<p>We&#8217;re going to remove the rear panel from the console.  The first steps is to push both front seats all the way forward, and remove the four bolts on each side panel of the console using a T20 Torx driver.  Once these bolts have been removed, loosen up the side panels by first popping the plastic retainers by pulling on the rear bottoms of the panels, and then pull up on both panel sides to have them loose at the back.</p>
<p>Now, free the rear panel by using your fingers along the inside edge to pull away from the center, releasing the plastic pins, and backwards to slide off the retaining posts.  If you have power windows, simply pull the wiring harness free.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="rear console panel removed" src="http://dronecolony.com/2008/new_img/jk/power/P2280035.jpg" alt="rear console panel removed" width="450" height="338" /><p class="wp-caption-text">rear console panel removed</p></div>
<p><strong>Step 6: </strong></p>
<p>Prepare the rear panel for cutting by removing the cup holder assembly, and marking the exact locations where you want the A/C outlets to be installed, from the back side.  For all cutting and marking, always work from the rear of the panel, so any mistakes will not affect appearance.</p>
<p>To make the appropriately sized holes, mark two rectangles .85&#8243; tall by .95&#8243; wide.  Cut these with a plastic cutting bit on a dremel tool, working slowly and carefully.</p>
<p>After the holes have been cut, bring the molex connectors through from the outside, and pop the A/C plugs in from the outside.  It should look like this, front and rear:</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="ac plugs installed" src="http://dronecolony.com/2008/new_img/jk/power/P2280040.jpg" alt="ac plugs installed" width="450" height="338" /><p class="wp-caption-text">ac plugs installed</p></div>
<div class="wp-caption aligncenter" style="width: 460px"><img title="ac plugs rear" src="http://dronecolony.com/2008/new_img/jk/power/P2280039.jpg" alt="ac plugs rear" width="450" height="338" /><p class="wp-caption-text">ac plugs rear</p></div>
<p><em>note: the ground pins of the two outlets are now connected together using a simple male/female crimp spade and 14G wire, this way you can always remove them later without cutting any wires.</em></p>
<p>You can now install the original dust covers by replacing the tiny screw with a slightly larger self-tapping plastic screw (there are a few that can be harvested from the inverter its self), put the dust covers in place and mark where the screws should be located.  Start a hole with a tiny drill bit, and then screw them into place with a screwdriver.</p>
<p><strong>Step 7:</strong></p>
<p>Go ahead and put the console back in place, and connect the outlet connectors, but do not bolt anything back in yet.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="ac outlets and console in place" src="http://dronecolony.com/2008/new_img/jk/power/P2280043.jpg" alt="ac outlets and console in place" width="450" height="338" /><p class="wp-caption-text">ac outlets and console in place</p></div>
<p>Now, we&#8217;re going to run power to the inverter.  For this, we will need two lengths of 10G wire long enough to reach from the battery to the inverter.  Since mine is installed under the passenger seat, I use the foam-filled hole in the passenger side of the firewall to run the wires.  Simply use your fingers to pop off the side dash panel, and then run a long screwdriver through the foam-filled hole to open a path.  Run the first wire through.  To make life easier, you can use the first wire as a fish for the second by pushing it several inches back through the firewall, and taping the second wire to it as shown below.  Then, simply pull both wires through.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="using first wire as fish for second" src="http://dronecolony.com/2008/new_img/jk/power/P2280044.jpg" alt="using first wire as fish for second" width="450" height="338" /><p class="wp-caption-text">using first wire as fish for second</p></div>
<p>The wires are then run behind the kick panel along the door back to the passenger seat.  You can get enough slack in the panel by simply lifting up where the plastic retainer is near the seat. The first wire we will hook up will be the ground wire.</p>
<p><strong>IMPORTANT SAFETY NOTE:</strong></p>
<p><strong>It is imperative that you <em>always</em> hook up the wire ends to the invert <em>first</em> before hooking them to the battery.  Imagine holding the hot wire end, with it connected to the battery, and letting it touch anything metal on your vehicle.  The results can be quite shocking!</strong></p>
<p>Take the end of the wire nearest the inverter that will be used as a ground wire, and crimp a round wire lug to the end.  Remove the screw for the inverter&#8217;s black post, slip the lug on it, and securely screw the post back down.</p>
<p>Now, take the positive wire, and crimp a lug on its end, and repeat the process of attaching it to the inverter.</p>
<p><strong>Step 8:</strong></p>
<p>We&#8217;ll prepare the battery end of the positive wire by using a butt joint to connect it to a 30A high-load fuse assembly, and then crimping on a wire lug to the other end of the fuse assembly.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="positive wire prepared for battery connection" src="http://dronecolony.com/2008/new_img/jk/power/P2280045.jpg" alt="positive wire prepared for battery connection" width="450" height="338" /><p class="wp-caption-text">positive wire prepared for battery connection</p></div>
<p><em>note: if you wish to only have the inverter work when the vehicle is on, you may omit this step and wire to an appropriate fuse location in the fuse box under the hood, instead.</em></p>
<p>Add a crimp lug to the end of the ground wire at this point as well.</p>
<p><strong>Step 9:</strong></p>
<p>First attach the ground wire to the negative pole of the battery, and then the positive wire to the positive pole using 12 and 10mm sockets or wrenches.  Be very careful to not let your wrench or ratchet touch anything metal on the vehicle &#8211; including that huge ground strap going to the hood &#8211; while operating on the positive pole.</p>
<p><strong>Step 10:</strong></p>
<p>Turn the jeep on, and test the inverter.  If it doesn&#8217;t turn on when you hit your switch, or you don&#8217;t get power, check these following conditions:</p>
<p>Symptom: nothing happens when you press the switch</p>
<blockquote><p>Check the wiring to the switch and the power to the inverter.  Use a multimeter across both the positive and ground feeds to the inverter, verify that at least 12 DC volts are present here.  If not, correct the battery wiring.</p>
<p>If battery wiring is correct, check the switch wiring.  Make sure you used the proper poles on the switch if not using an SPST switch, and that you used the correct black and red wires from the inverter.  Disconnect it from the battery, and try changing wires.</p></blockquote>
<p>Symptom: the inverter beeps and the fan comes on when the switch is pressed, but no AC power available at the outlets</p>
<blockquote><p>Check the wiring to the outlets.  Make sure to turn the inverter off before doing anything.  Assure that the outlets are wired properly, and there is no possibility of a short between the white and black wires of the inverter.</p>
<p>Make sure the device you plugged in does not exceed the inverters specs, or does not require pure sine wave power.  Use a digital multimeter to validate that you get an AC signal from the ports when turned on.</p></blockquote>
<p><strong>Step 11:</strong></p>
<p>Now that everything works, you can go ahead and button your console back up and screw the side panels back in.  Note that it is difficult to re-install the side panels if they are slightly out of alignment, check their alignment and press down hard on the top while inserting the torx bolts.</p>
<p>Now you&#8217;re all set, you&#8217;ve got two AC outlets that are turned on and off with a simple press of a switch!</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="all done" src="http://dronecolony.com/2008/new_img/jk/power/P2280047.jpg" alt="all done" width="450" height="338" /><p class="wp-caption-text">all done</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/130/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/130/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/130/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=130&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2009/03/01/add-ac-power-outlets-to-your-jeep-wrangler-console/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280047.jpg" medium="image">
			<media:title type="html">ac outlets with weather covers</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2270009.jpg" medium="image">
			<media:title type="html">Inverter disassembled</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2270016.jpg" medium="image">
			<media:title type="html">wires to use for switch</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2270031.jpg" medium="image">
			<media:title type="html">wiring up switch to switch panel</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2270030.jpg" medium="image">
			<media:title type="html">connecting up power switch wires</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2270032.jpg" medium="image">
			<media:title type="html">ac lines connected to molex connectors</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280037.jpg" medium="image">
			<media:title type="html">wiring up A/C outlets to molex connectors</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280035.jpg" medium="image">
			<media:title type="html">rear console panel removed</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280040.jpg" medium="image">
			<media:title type="html">ac plugs installed</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280039.jpg" medium="image">
			<media:title type="html">ac plugs rear</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280043.jpg" medium="image">
			<media:title type="html">ac outlets and console in place</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280044.jpg" medium="image">
			<media:title type="html">using first wire as fish for second</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280045.jpg" medium="image">
			<media:title type="html">positive wire prepared for battery connection</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/jk/power/P2280047.jpg" medium="image">
			<media:title type="html">all done</media:title>
		</media:content>
	</item>
		<item>
		<title>K2 CNC On the Way</title>
		<link>http://roamingdrone.wordpress.com/2009/01/14/k2-cnc-on-the-way/</link>
		<comments>http://roamingdrone.wordpress.com/2009/01/14/k2-cnc-on-the-way/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 15:29:14 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[CNC]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[cnc k2 router mill 2514 prototype build]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=123</guid>
		<description><![CDATA[I&#8217;m very excited, the order has been placed &#8211; this beauty will be arriving at my office within a month or so: Yup, that&#8217;s the K2 2514 benchtop CNC router.  25&#8243;x14&#8243;x5&#8243; work area.  I&#8217;m going to be powering it with a Probotix 3-axis stepper kit, and will be using the porter cable 892 router. (And, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=123&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m very excited, the order has been placed &#8211; this beauty will be arriving at my office within a month or so:</p>
<p><img class="aligncenter" src="http://www.k2cnc.com/shop/prodimages/KT-2514_500.jpg" alt="" width="500" height="500" />Yup, that&#8217;s the K2 2514 benchtop CNC router.  25&#8243;x14&#8243;x5&#8243; work area.  I&#8217;m going to be powering it with a Probotix 3-axis stepper kit, and will be using the porter cable 892 router. (And, possibly, my dremel 300 for PCB work.)  This will let me quickly prototype and build new designs I&#8217;ve been working on.  Now, to get started on an enclosure for it, so it won&#8217;t drive me mad in the studio.  The enclosure will be framed by 80/20 parts, and dampened to reduce the noise of the router.</p>
<p>In the next few months, I&#8217;ll have some exciting announcements regarding motion control applications for time-lapse photograpy.  Stay tuned. =)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/123/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/123/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/123/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=123&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2009/01/14/k2-cnc-on-the-way/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>

		<media:content url="http://www.k2cnc.com/shop/prodimages/KT-2514_500.jpg" medium="image" />
	</item>
		<item>
		<title>Arduino and the TSL230R: Photographic Conversions</title>
		<link>http://roamingdrone.wordpress.com/2008/11/28/arduino-and-the-tsl230r-photographic-conversions/</link>
		<comments>http://roamingdrone.wordpress.com/2008/11/28/arduino-and-the-tsl230r-photographic-conversions/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 19:22:55 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[advanced]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[EV]]></category>
		<category><![CDATA[Exposure Value]]></category>
		<category><![CDATA[light meter]]></category>
		<category><![CDATA[lux]]></category>
		<category><![CDATA[TSL230R]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=105</guid>
		<description><![CDATA[In the previous post on using the Taos TSL230R with the Arduino, I covered the basic operations of the chip, and some essential conversions for going from radiometric to photometric representation of its data. In this post, we&#8217;ll expand on that knowledge to calculate exposure times and apertures using the Exposure Value system and produce [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=105&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://roamingdrone.wordpress.com/2008/11/13/arduino-and-the-taos-tsl230r-light-sensor-getting-started/" target="_blank">previous post</a> on using the Taos TSL230R with the Arduino, I covered the basic operations of the chip, and some essential conversions for going from radiometric to photometric representation of its data.  In this post, we&#8217;ll expand on that knowledge to calculate exposure times and apertures using the <a href="http://en.wikipedia.org/wiki/Exposure_value" target="_blank">Exposure Value </a>system and produce much more accurate <a href="http://en.wikipedia.org/wiki/Lux" target="_self">lux</a> calculations using multiple wavelengths of light.  After reading both of these tutorials, you should have enough information to create your own photographic light meter using a few simple components.</p>
<p><span id="more-105"></span></p>
<p><strong>GETTING STARTED<br />
</strong></p>
<p>Before we go any further, we&#8217;ll bring forward some code from the previous example, and set this as our starting point:</p>
<pre class="brush: cpp;">

/*
   Example code for the Taos TSL230R and
   Arduino.

   C. A. Church - 11/2008

   This work is licensed under a Creative Commons
   Attribution-Share Alike 3.0 license.

*/

  // TSL230R Pin Definitions

#define TSL_FREQ_PIN 2 // output use digital pin2 for interrupt
#define TSL_S0       5
#define TSL_S1       6
#define TSL_S2       7
#define TSL_S3       8  

  // how often to calculate frequency
  // 1000ms = 1s  

#define READ_TM 1000

  // our pulse counter for our interrupt

unsigned long pulse_cnt = 0; 

  // two variables used to track time  

unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;  

  // we'll need to access the amount
  // of time passed  

unsigned int tm_diff = 0;  

  // set our frequency multiplier to a default of 1
  // which maps to output frequency scaling of 100x

int freq_mult = 100;

  // need to measure what to divide freq by
  // 1x sensitivity = 10,
  // 10x sens = 100,
  // 100x sens = 1000

int calc_sensitivity = 10;

void setup() {  

  // attach interrupt to pin2,
  // send output pin of TSL230R to arduino 2
  // call handler on each rising pulse  

  attachInterrupt(0, add_pulse, RISING);  

  // setup TSL230R pins

  pinMode(TSL_FREQ_PIN, INPUT);
  pinMode(TSL_S0, OUTPUT);
  pinMode(TSL_S1, OUTPUT);
  pinMode(TSL_S2, OUTPUT);
  pinMode(TSL_S3, OUTPUT);  

  // 1x sensitivity,
  // divide-by-100 scaling

  digitalWrite(TSL_S0, HIGH);
  digitalWrite(TSL_S1, LOW);
  digitalWrite(TSL_S2, HIGH);
  digitalWrite(TSL_S3, HIGH);
}  

void loop() {

  // check the value of the light sensor every READ_TM ms

  // calculate how much time has passed

  pre_tm = cur_tm;
  cur_tm = millis();

  if( cur_tm &gt; pre_tm ) {
    tm_diff += cur_tm - pre_tm;
  }
  else if( cur_tm &lt; pre_tm ) {
      // handle overflow and rollover (Arduino 011)
    tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
  }

    // if enough time has passed to
    // do a new reading...

  if( tm_diff &gt;= READ_TM ) {

      // re-set the ms counter

    tm_diff = 0;

      // get our current frequency reading

    unsigned long frequency = get_tsl_freq();

      // calculate radiant energy

    float uw_cm2 = calc_uwcm2( frequency );

     // calculate illuminance

    float lux = calc_lux_single( uw_cm2, 0.175 );

  }

}

unsigned long get_tsl_freq() {

  // we have to scale out the frequency --
  // Scaling on the TSL230R requires us to multiply by a factor
  // to get actual frequency

  unsigned long freq = pulse_cnt * freq_mult;

    // reset the pulse counter

  pulse_cnt = 0;

  return(freq);
}

float calc_lux_single(float uw_cm2, float efficiency) {

  // calculate lux (lm/m^2), using standard formula:
  // Xv = Xl * V(l) * Km
  // Xl is W/m^2 (calculate actual receied uW/cm^2, extrapolate from sensor size (0.0136cm^2)
  // to whole cm size, then convert uW to W)
  // V(l) = efficiency function (provided via argument)
  // Km = constant, lm/W @ 555nm = 683 (555nm has efficiency function of nearly 1.0)
  //
  // Only a single wavelength is calculated - you'd better make sure that your
  // source is of a single wavelength... Otherwise, you should be using
  // calc_lux_gauss() for multiple wavelengths

    // convert to w_m2

  float w_m2 = (u_cm2 / (float) 1000000) * (float) 100;

    // calculate lux

  float lux = w_m2 * efficiency * (float) 683;

  return(lux);
}

float calc_uwatt_cm2(unsigned long freq) {

  // get uW observed - assume 640nm wavelength
  // calc_sensitivity is our divide-by to map to a given signal strength
  // for a given sensitivity (each level of greater sensitivity reduces the signal
  // (uW) by a factor of 10)

  float uw_cm2 = (float) freq / (float) calc_sensitivity;

    // extrapolate into entire cm2 area

  uw_cm2 *= ( (float) 1 / (float) 0.0136 );

  return(uw_cm2);

}

void set_scaling ( int what ) {

  // set output frequency scaling
  // adjust frequency multiplier and set proper pin values
  // e.g.:
  // scale = 2 == freq_mult = 2
  // scale = 10 == freq_mult = 10
  // scale = 100 == freq_mult = 100

  int pin_2 = HIGH;
  int pin_3 = HIGH;

  switch( what ) {
    case 2:
      pin_3 = LOW;
      freq_mult = 2;
      break;
    case 10:
      pin_2 = LOW;
      freq_mult = 10;
      break;
    case 100:
      freq_mult = 100;
      break;
    default:
        // don't do anything with levels
        // we don't recognize
      return;
   }

    // set the pins to their appropriate levels

  digitalWrite(TSL_S2, pin_2);
  digitalWrite(TSL_S3, pin_3);

  return;
}

void sensitivity( bool dir ) {

  // adjust sensitivity in 3 steps of 10x either direction

  int pin_0;
  int pin_1;

  if( dir == true ) {

      // increasing sensitivity

      // -- already as high as we can get
    if( calc_sensitivity == 1000 )
      return;

    if( calc_sensitivity == 100 ) {
        // move up to max sensitivity
      pin_0 = HIGH;
      pin_1 = HIGH;
    }
    else {
        // move up to med. sesitivity
      pin_0 = LOW;
      pin_1 = HIGH;
    }

      // increase sensitivity divider
    calc_sensitivity *= 10;
  }
  else {
      // reducing sensitivity

      // already at lowest setting

    if( calc_sensitivity == 10 )
      return;

    if( calc_sensitivity == 100 ) {
        // move to lowest setting
      pin_0 = HIGH;
      pin_1 = LOW;
    }
    else {
        // move to medium sensitivity
      pin_0 = LOW;
      pin_1 = HIGH;
    }

      // reduce sensitivity divider
    calc_sensitivity = calc_sensitivity / 10;
  }

    // make any necessary changes to pin states

 digitalWrite(TSL_S0, pin_0);
 digitalWrite(TSL_S1, pin_1);

 return;
}
</pre>
<p><strong>REFLECTIVE VS. INCIDENT METERING</strong></p>
<p>It is important to understand the different ways we can meter light for photographic purposes.  In reflective metering the light that is measured is that which is reflected off the subject &#8211; that is, you point your meter at the subject being photographed.  In incident metering the light that is measured is that which is incident upon the subject &#8211; that is you stand where your subject is, and point your meter at the light source.</p>
<p>In all of our calculations below, we will be operating from the aspect of reflective light metering.  The formulas vary slightly for incident metering and one should take that into account when designing a project.  Please note as well, that during testing, you should be metering reflected light as well &#8211; you will not get an accurate reading by pointing a light right as the sensor.  Instead, use a sheet of white paper or such and measure the light reflecting off your paper.</p>
<p><strong>EXPOSURE VALUE CALCULATIONS</strong></p>
<p><strong></strong><br />
Exposure Values are used in photography to represent different combinations of shutter speed and aperture that result in the same exposure.  Normally, EV is calculated regardless of actual light &#8211; it&#8217;s a means of expressing a set of camera settings (speed and aperture).  However, if we follow the <a href="http://en.wikipedia.org/wiki/APEX_system" target="_blank">APEX System</a> we find that we can relate EV to a combination of brightness value (Bv) and film/sensor sensitivity (Sv).</p>
<p>In the Additive APEX System, the exposure calculation is defined: <em>Ev = Av + Tv = Bv + Sv</em>.  For an in-depth explanation of how to calculate this, please refer to the article linked above. (Or, just read the code below!)  It should be fairly obvious that, in such a calculation, if we know any three values &#8212; we can determine the fourth.</p>
<p>Our first task will be to calculate the exposure time, in seconds, given the following information: Aperture, ISO, and Lux.  For this, and all calculations, we are going to need the <a href="http://en.wikipedia.org/wiki/Light_meter#Calibration_constant" target="_blank">Light Meter Calibration Constant</a> (K) &#8211; we&#8217;ll use the standard constant for reflective meters made by Pentax, because I&#8217;m a Pentax guy, which is 14. We will also need to know the relationship between between the ASA Arithmetic Speed Value and the ASA Speed Value, which is approximately 0.3.</p>
<p>So, let&#8217;s create a function that will give us the EV for our combination of illuminance and film speed first</p>
<pre class="brush: cpp;">

float calc_ev( float lux, int iso ) {

    // calculate EV using APEX method:
    // Ev = Av + Tv = Bv + Sv

    // We'll use the right-hand side for this operation

    // Bv = log2( B/NK )
    // Sv = log2( NSx )

  float Sv = log( (float) 0.3 * (float) iso ) / log(2);

  float Bv = log( lux / ( (float) 0.3 * (float) 14 ) ) / log(2);

  return( Bv + Sv );

}
</pre>
<p>Note that in the above equation, we use <em>log(x) / log(2) </em>everywhere, this is because the arduino environment does not support log2() by default, and we find that the logarithm of any base other than the natural is the natural logarithm divided by the natural logarithm of the base.  So, we get <em>l2(x)</em> by dividing <em>ln(x)</em> by <em>ln(2)</em>.</p>
<p>Now that we have the relevant EV, to get the exposure time, in seconds, we need to take our Ev calculated from two of the required three values (Bv, Sv, Av) and compare it to the third to get the new value out.</p>
<pre class="brush: cpp;">

float calc_exp_tm ( float ev, float aperture  ) {

    // Ev = Av + Tv = Bv + Sv
    // need to determine Tv value, so Ev - Av = Tv
    // Av = log2(Aperture^2)
    // Tv = log2( 1/T ) = log2(T) = 2^(Ev - Av)

  float exp_tm = ev - ( log( pow(aperture, 2) ) / log(2) );

  float exp_log = pow(2, exp_tm); 

  return( exp_log  );
}
</pre>
<p>Note that this function returns a floating point number that we would divide 1 second by to get the final exposure time.  I.e., it would return 10 for 1/10th second, 1.5 for .5&#8243;, and 0.05 for 20&#8243;.   The following function will make it easy to convert this time into milliseconds for direct exposure control:</p>
<pre class="brush: cpp;">

unsigned int calc_exp_ms( float exp_tm ) {

  unsigned int cur_exp_tm = 0;

  // calculate mS of exposure, given a divisor exposure time  

   if( exp_tm &gt;= 2 ) {

      // deal with times less than or equal to half a second

     if( exp_tm &gt;= (float) int(exp_tm) + (float) 0.5 ) {
         // round up
       exp_tm = int(exp_tm) + 1;
     }
     else {
         // round down
       exp_tm = int(exp_tm);
     }

     cur_exp_tm = 1000 / exp_tm;

   }
   else if( exp_tm &gt;= 1 ) {
     // deal with times larger than 1/2 second

     float disp_v = 1 / exp_tm;
       // get first significant digit
     disp_v       = int( disp_v * 10 );
     cur_exp_tm = ( 1000 * disp_v ) / 10;

   }
    else {
       // times larger than 1 second
     int disp_v = int( (float) 1 / exp_tm);
     cur_exp_tm = 1000 * disp_v;

    }

 return(cur_exp_tm);
}
</pre>
<p>Now we have two functions that will return us the EV equivalent given our brightness and speed values, a third to extrapolate  exposure time from EV and aperture, and a fourth to convert exposure time to mS (for the purposes of controlling a camera, etc.).</p>
<p>It should be fairly obvious at this point as to how to extrapolate other values from combinations of three factors, but here&#8217;s another function that calculates aperture given the combination of Bv, Sv, and Tv. (i.e. you know exposure time but not aperture):</p>
<pre class="brush: cpp;">

float calc_exp_aperture( float ev, float exp_tm ) {

  float exp_apt = ev - ( log( (float) 1 / exp_tm ) / log(2) );
  float apt_log = pow(2, exp_apt);

  return( apt_log );
}
</pre>
<p>So, there you have it &#8211; you now know (well, we hope you do!) how to calculate meaningful photographic data from illuminance data (lux) we were able to calculate in our previous tutorial.</p>
<p><strong>ACCURATE MEASUREMENT OF MULTIPLE WAVELENGTHS</strong></p>
<p><strong><br />
</strong></p>
<p>Ok, so it&#8217;s time to get a little more complicated here.  Up and to this point, we&#8217;ve only been calculating the relative intensity of a single wavelength of light.  It&#8217;s pretty rare that we photograph a subject illuminated by a laser or well-tuned diode that only produces a single wavelength of light.  More than likely, we&#8217;re photographing in daylight, with a flash, or under hot lights in the studio.  To accurately measure these sources, we have to take into account the fact that they are made up of different wavelengths of light, and that each wavelength is more or less efficient (visible to our eyes).</p>
<p>As pointed out previously, we are only going to deal with photoptic vision, that is the way our eyes work in &#8216;bright&#8217; environments.  Our eyes change behavior when the light level drops very low (think in a dark room at night), and scotoptic vision kicks in.  We rarely photograph in levels this dark, so we won&#8217;t cover this type of vision.</p>
<p>To properly calculate the lux for mixed wavelengths, we need to integrate as such: <em>lx = 683 * ∫ V(λ)J(λ) dλ </em></p>
<p>V() is the standard luminosity function we discussed in the earlier post, and J() is the power spectral density function for the given wavelength.  The hard part here is the power spectral density function &#8211; we either have to calculate for a blackbody radiator at a particular temperature using <a href="http://en.wikipedia.org/wiki/Planck%27s_law" target="_blank">Planck&#8217;s Law</a> (which is fairly difficult on the arduino, and is also highly inaccurate for light bulbs and the like) or, we have to figure out this data empirically.  To measure this information for a given light source, we&#8217;d have to use a spectrum analyzer (which we can build with a TSL230R, but that&#8217;s a topic for another day) on that light source.  Fortunately for us, the <a href="http://cvision.ucsd.edu/cie.htm" target="_blank">CIE provides a couple of tables</a>, that give us the PSD values for two illuminants: &#8216;A&#8217;, which corresponds roughly to an incandescent lightbulb, and D65, which corresponds roughly to mid-day sunlight.</p>
<p>We&#8217;ll need to create three arrays to perform this calculation, one holds the wavelengths of light we&#8217;re willing to calculate for (as we have interest in integrating from 0 to infinity), one that holds the luminous efficiency function for each of those wavelengths, and one that gives us the power spectral density function for each wavelength we want to account for.</p>
<p>So, let&#8217;s create our tables and our function:</p>
<pre class="brush: cpp;">

  // our wavelengths (nm) we're willing to calculate illuminance for (lambda)

int wavelengths[18] = { 380, 400, 420, 440, 460, 480, 500, 520, 540, 560, 580, 600, 620, 640, 660, 680, 700, 720 };

  // the CIE V(l) for photopic vision - CIE Vm(l) 1978 - mapping to the same (l) above

float v_lambda[18]  = { 0.0002, 0.0028, 0.0175, 0.0379, 0.06, 0.13902, 0.323, 0.71, 0.954, 0.995, 0.87, 0.631, 0.381, 0.175, 0.061, 0.017, 0.004102, 0.001047 };

  // CIE SPD graph for Illuminant A light sources, again mapping to same lambda as included in wavelengths

float ilA_spd[18] = { 9.795100, 14.708000, 20.995000, 28.702700, 37.812100, 48.242300, 59.861100, 72.495900, 85.947000, 100.000000, 114.436000, 129.043000, 143.618000, 157.979000, 171.963000, 185.429000, 198.261000, 210.365000 };

...

float calc_lux_gauss( float uw_cm2 ) {

    // # of wavelengths mapped to V(l) values - better have
    // enough V(l) values!

  int nm_cnt = sizeof(wavelengths) / sizeof(int);

    // W/m2 from uW/cm2

  float w_m2 =  ( uw_cm2 / (float) 1000000 ) * (float) 100;

  float result = 0;

    // integrate XlV(l) dl
    // Xl = uW-m2-nm caclulation weighted by the CIE lookup for the given light
    //   temp
    // V(l) = standard luminous efficiency function

  for( int i = 0; i &lt; nm_cnt; i++) {

    if( i &gt; 0) {
      result +=  ( ilA_spd[i] / (float) 1000000)  * (wavelengths[i] - wavelengths[i - 1]) * w_m2  * v_lambda[i];
    }
    else {
      result += ( ilA_spd[i] / (float) 1000000) * wavelengths[i] * w_m2 * v_lambda[i];
    }

  }

    // multiply by constant Km and return

  return(result * (float) 683);
}
</pre>
<p>If your background is in anything but calculus or photometry, it can be a bit of a beast to get your head around, but take some time to thoroughly read and understand the above function and tables before using them.  Effectively, we are determining the efficiency function by jumping between two points on our wavelength graph, and estimating the efficiency per nm of wavelength for each nm between our current and last point.  We sum these up, and then multiple by the efficiency constant of 683 (lux per w/cm2 at 555nm) to determine the lux, given the radiometric energy observed for a particular multiple-wavelength light source.  Simply replace any calls to calc_lux_single() with a call to calc_lux_gauss().</p>
<p>That wraps it up for this tutorial on photographic conversions.  You now have enough information to build a basic photographic light meter using an Arduino and a TSL230R light sensor.  In the next tutorial on this subject, we&#8217;ll work on increasing accuracy by calculating for the frequency response curve of the sensor its self, and adjusting for temperature impacts on the dark frequency of the chip.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/105/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=105&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2008/11/28/arduino-and-the-tsl230r-photographic-conversions/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>
	</item>
		<item>
		<title>Arduino and the Taos TSL230R Light Sensor: Getting Started</title>
		<link>http://roamingdrone.wordpress.com/2008/11/13/arduino-and-the-taos-tsl230r-light-sensor-getting-started/</link>
		<comments>http://roamingdrone.wordpress.com/2008/11/13/arduino-and-the-taos-tsl230r-light-sensor-getting-started/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 04:10:57 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robots]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[energy]]></category>
		<category><![CDATA[light]]></category>
		<category><![CDATA[lux]]></category>
		<category><![CDATA[sensor]]></category>
		<category><![CDATA[Taos]]></category>
		<category><![CDATA[TSL230R]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[watt]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=87</guid>
		<description><![CDATA[The TSL230R light sensor IC is an interesting package: a light sensing circuit wrapped up in a clear plastic casing. This neat little device will convert irradiance (the light energy on the surface of the sensor) into frequency. Working with a simple input concept like a frequency means that we won&#8217;t have to build any [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=87&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8940" target="_blank">TSL230R light sensor IC</a> is an interesting package: a light sensing circuit wrapped up in a clear plastic casing.  This neat little device will convert <a href="http://en.wikipedia.org/wiki/Irradiance" target="_blank">irradiance</a> (the light energy on the surface of the sensor) into frequency.  Working with a simple input concept like a frequency means that we won&#8217;t have to build any extra circuitry to get the full range of information from the circuit, and having an accurate measure of radiance means that we&#8217;ll be able to convert easily over to <a href="http://en.wikipedia.org/wiki/Illuminance" target="_blank">illuminance</a>, which is how the light looks to us.  Obviously, once we can answer the question about how light looks, we can use this information to control other things.  (Some great examples are: camera exposure, dimming displays, machine vision, etc.)</p>
<p>This guide is intended to walk you through the basics of interfacing the TSL230 series of chips from Taos with your friendly Arduino microcontroller.  The specifics of the chip&#8217;s operation may not be painfully obvious the first read over the <a href="http://www.taosinc.com/getfile.aspx?type=press&amp;file=tsl230r-lf-e3.pdf" target="_blank">datasheet</a>, but this guide expects you&#8217;ve at least read the important parts: which pins are which, that you can change its sensitivity, and that you can change the scale of the output.</p>
<p><span id="more-87"></span></p>
<p><strong>SETUP</strong></p>
<p><strong><br />
</strong></p>
<p>The only things we&#8217;ll require besides the TSL230R and an arduino is a breadboard, a 0.1uF ceramic capacitor, and some jumper wires.  Wire up the pins on the TSL230R as so:</p>
<ul>
<li>S0-S3: wire each of these to an arduino input, avoid digital in 2, as we&#8217;ll need that</li>
<li>OE: The output enable pin should be brought low by connecting it to GND. <em>This pin enables or disables the output frequency.  Bringing the pin HIGH will result in disabling output, so for our purposes, we&#8217;ll hard-wire it to GND, enabling output and saving an I/O line on the arduino.</em></li>
<li>Vcc: Connect Vcc to +5V from the arduino.  On the hole nearest this pin on the breadboard, connect one leg of your 0.1uF capacitor, and the other to GND.  <em>The capacitor is necessary to help filter the power to prevent fluctuations in the output of the chip.</em></li>
<li>GND: connect to GND</li>
<li>OUT: Connect this pin to digital in 2 on the arduino.  We&#8217;re going to use an interrupt, so we need to hook up to either in 2 or 3.</li>
</ul>
<p>This would be a good time to define the pins in our code:</p>
<pre class="brush: cpp;">
#define TSL_FREQ_PIN 2 // output use digital pin2 for interrupt
#define TSL_S0	     5
#define TSL_S1	     6
#define TSL_S2	     7
#define TSL_S3       8
</pre>
<p><strong>OUTPUT BASICS</strong></p>
<p><strong><br />
</strong></p>
<p>So, now that we&#8217;ve got everything hooked up, let&#8217;s get down to work.  The TSL230 has two types of output: a pulse train, and a square wave.  The pulse train is a series of high pulses that give us the exact frequency being recorded at that time.  Unfortunately, as the pulse high times are in the nano-seconds, they&#8217;re gone before we can effectively measure them.  The square wave output, on the other hand, has a 50% duty-cycle, meaning the high pulses and low pulses are exactly the same length &#8211; 1/2 the frequency.  This allows us to register the high pulses in Arduino&#8217;s micro-second world.</p>
<p>Pins S2 and S3 control the output scaling, the divide-by types (2, 10, and 100) produce the square wave we want. For now, we&#8217;ll choose divide by 100, which has both S2 and S3 high.</p>
<p>The sensitivity controls how many receptors are active on the chip at once.  When its set to higher sensitivity, the chip can register smaller and smaller amounts of light, but loses the ability to register higher levels of light.  For now, we&#8217;ll stick with 1x sensitivity, meaning S0 will be high and S1 will be low.</p>
<p>To read the square wave, you&#8217;ve probably seen examples of using pulseIn() &#8211; this has a couple of disadvantages, the first being that you&#8217;re only measuring one cycle of the frequency (it can change often throughout a second) and the second and most glaring, being that pulseIn() requires a delay while trying to read the input pin.  That means for very low light levels (1 cycle per second) you could be waiting up to an entire second for one measurement!  A much better way is to take a measure of how many pulses there are per second, which will average out any fluctuations, and if we use an interrupt, we can do anything else we like while we count the pulses.</p>
<p>Let&#8217;s go ahead and set everything up, including our interrupt.</p>
<pre class="brush: cpp;">

unsigned long pulse_cnt = 0;

void setup() {

  // attach interrupt to pin2, send output pin of TSL230R to arduino 2
  // call handler on each rising pulse

 attachInterrupt(0, add_pulse, RISING);

 pinMode(TSL_FREQ_PIN, INPUT);
 pinMode(TSL_S0, OUTPUT);
 pinMode(TSL_S1, OUTPUT);
 pinMode(TSL_S2, OUTPUT);
 pinMode(TSL_S3, OUTPUT);

 digitalWrite(TSL_S0, HIGH);
 digitalWrite(TSL_S1, LOW);
 digitalWrite(TSL_S2, HIGH);
 digitalWrite(TSL_S3, HIGH);
}

void loop() {

}

void add_pulse() {

  // increase pulse count
 pulse_cnt++;
 return;
}
</pre>
<p>Notice that our interrupt just increases a counter, that&#8217;s all we need it to do.  We&#8217;re going to check the frequency and re-set it every second in our code.  Note that the interrupt is given the argument RISING, this means that it&#8217;ll only trigger when the signal changes from LOW to HIGH.  We only need to count the pulses per second.</p>
<pre class="brush: cpp;">

 // 1000ms = 1s
#define READ_TM 1000 

...

 // two variables used to track time
unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;

 // we'll need to access the amount
 // of time passed
unsigned int tm_diff = 0;
...

void loop() {

  // check the value of the light sensor every READ_TM ms

    // calculate how much time has passed

 pre_tm   = cur_tm;
 cur_tm   = millis();

 if( cur_tm &gt; pre_tm ) {
	tm_diff += cur_tm - pre_tm;
 }
 else if( cur_tm &lt; pre_tm ) {
           // handle overflow and rollover (Arduino 011)
	tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
 } 

   // if enough time has passed to do a new reading...

 if( tm_diff &gt;= READ_TM ) {

       // re-set the ms counter
   tm_diff = 0;

      // get our current frequency reading
   unsigned long frequency = get_tsl_freq();

 }

}

unsigned long get_tsl_freq() {
    // copy pulse counter and multiply.
    // the multiplication is necessary for the current
    // frequency scaling level.  Please see the
    // OUTPUT SCALING section below for more info

  unsigned long freq = pulse_cnt * 100;

   // re-set pulse counter
  pulse_cnt = 0;

  return(freq);
}
</pre>
<p><strong>CONVERTING FREQUENCY TO ENERGY</strong></p>
<p><strong><br />
</strong></p>
<p>In the above code, we&#8217;ve gotten the frequency by counting the number of high pulses per second.  This will work fine for our purposes, for the time being.  The frequency sent to us by the chip correlates to a particular amount of radiant energy being received by it.  We need to convert it to a more useful representation, and our target is a measurement of micro-watts (uW) per centimeter squared (cm2).  The datasheet shows us a graph (figure 1) on page 4 that shows us that at a wavelength of 640nm, and 1x sensitivity, the relationship between uW/cm2 and the frequency is a ratio of 1:10.  Or, the energy is 1/10th the frequency &#8212; uW/cm2 = Freq / 10.</p>
<p>An important point, saved for the last page of the datasheet, is that the actual sensor has an area of about 0.92mm2.  This is about 0.0092cm2, whereas the application note found <a href="http://www.taosinc.com/getfile.aspx?type=press&amp;file=taosdn5.pdf" target="_blank">here </a>indicates a size of 0.0136cm2 &#8211; I prefer this number.  The size of the sensor is important, as we need to figure out how much energy is landing on a square centimeter of space, but we&#8217;re much smaller than that.  We&#8217;ll need to multiply up the conversion to figure how much radiant energy would be landing in the square centimeter that surrounds us.</p>
<p>Also note that the sensor is more or less sensitive to other wavelengths than 640nm, so we&#8217;ll work straight from the graph in the datasheet figure 1, and stick with 640nm.  Here&#8217;s a function to convert the frequency into uW/cm2:</p>
<pre class="brush: cpp;">
float calc_uwatt_cm2(unsigned long freq) {

  // get uW observed - assume 640nm wavelength 

    // note the divide-by factor of ten,
    // maps to a sensitivity of 1x

  float uw_cm2 = (float) freq / (float) 10;

    // extrapolate into entire cm2 area

  uw_cm2       *= ( (float) 1 / (float) 0.0136 );

  return(uw_cm2);

}
</pre>
<p>Now we have a measure of not only the uW observed, but we would likely observe, were we to have a sensor that was actually 1cm2.</p>
<p><strong>INCREASING SENSITIVITY</strong></p>
<p>So, the room goes dark, and your frequency lingers around, erm, 2.  The TSL230R has a more sensitivity than you might imagine, but you&#8217;re going to give up some of your bright-end for it.  You&#8217;ll be able to go from 0.1 uW to 0.001, at maximum sensitivity.  The ramification of this, is that you&#8217;re going to have to change the divide-by factor for converting frequency to energy.</p>
<p>If your readings are pretty low, and you&#8217;ve done everything else right, it&#8217;s time to up the sensitivity a bit.</p>
<pre class="brush: cpp;">

  // need to measure what to divide freq by
  // 1x sensitivity = 10,
  // 10x sens       = 100,
  // 100x sens      = 1000

int calc_sensitivity = 10;

...

void sensitivity( bool dir ) {

  // adjust sensitivity in 3 steps of 10x either direction

  int pin_0;
  int pin_1;

  if( dir == true ) {

      // increasing sensitivity

      // -- already as high as we can get
    if( calc_sensitivity == 1000 )
      return;

    if( calc_sensitivity == 100 ) {
        // move up to max sensitivity
      pin_0 = true;
      pin_1 = true;
    }
    else {
        // move up to med. sesitivity
      pin_0 = false;
      pin_1 = true;
    }

      // increase sensitivity divider
    calc_sensitivity *= 10;
  }
  else {
      // reducing sensitivity

      // already at lowest setting

    if( calc_sensitivity == 10 )
      return;

    if( calc_sensitivity == 100 ) {
        // move to lowest setting
      pin_0 = true;
      pin_1 = false;
    }
    else {
        // move to medium sensitivity
      pin_0 = false;
      pin_1 = true;
    }

      // reduce sensitivity divider
    calc_sensitivity = calc_sensitivity / 10;
  }

    // make any necessary changes to pin states

 digitalWrite(TSL_S0, pin_0);
 digitalWrite(TSL_S1, pin_1);

 return;
}

float calc_uwatt_cm2(unsigned long freq) {

  // get uW observed - assume 640nm wavelength
  // calc_sensitivity is our divide-by to map to a given signal strength
  // for a given sensitivity (each level of greater sensitivity reduces the signal
  // (uW) by a factor of 10)

  float uw_cm2 = (float) freq / (float) calc_sensitivity;

    // extrapolate into entire cm2 area

  uw_cm2       *= ( (float) 1 / (float) 0.0136 );

  return(uw_cm2);

}
</pre>
<p>Now we have a function, that we can call with HIGH to increase sensitivity, LOW to decrease sensitivity, and our frequency conversion to energy scales for us.</p>
<p>In short &#8211; the higher sensitivities allow you to differentiate very low amounts of light.  Use them in darker settings, and 1x sensitivity out in bright or daylight settings.</p>
<p><strong>OUTPUT SCALING</strong></p>
<blockquote><p>Edit: Some days you eat pie and some days you eat crow.  After imploring dear readers, that you pay attention to the datasheet and which pins are which, I went and had mine all mixed up while working on the scaling portion of this tutorial.  You guessed it, I was all wrong.  The following text has been changed as of 11/25/08, and now stands as correct instructions.<br />
<strong><br />
</strong></p></blockquote>
<p>A topic we haven&#8217;t touched on yet is the impact of output scaling.  Output frequency scaling changes the way the chip reports frequency to you.  Like sensitivity, frequency scaling allows you to measure different ranges of frequency.  The divide by 2 method provides the lowest range of frequency, but with the most amount of resolution, divide by ten covers the mid-range of frequency with a moderate amount of<br />
resolution, and divide by 100 covers the high range of frequency with low resolution.</p>
<p>Frequency scaling says that the chip will report one value representing the average value read for <em>x</em> periods &#8211; where <em>x</em> is 2, 10, or 100.  Simply stated: multiply the frequency you read by the scaling level you have set.  For example, in divide-by-2, you multiply your reading by two, and divide-by-100, you multiply your reading by one hundred.</p>
<p>Here&#8217;s some code to handle changing the output scaling:</p>
<pre class="brush: cpp;">

  // set our frequency multiplier to a default of 1
  // which maps to output frequency scaling of 100x

int freq_mult = 100;

...

void set_scaling ( int what ) {

  // set output frequency scaling
  // adjust frequency multiplier and set proper pin values
  // e.g.:
  // scale = 2 == freq_mult = 2
  // scale = 10 == freq_mult = 10
  // scale = 100 == freq_mult = 100

  int pin_2 = HIGH;
  int pin_3 = HIGH;

  switch( what ) {
    case 2:
      pin_3     = LOW;
      freq_mult = 2;
      break;
    case 10:
      pin_2     = LOW;
      freq_mult = 10;
      break;
    case 100:
      freq_mult = 100;
      break;
    default:
        // don't do anything with levels
        // we don't recognize
      return;
  }

    // set the pins to their appropriate levels

  digitalWrite(TSL_S2, pin_2);
  digitalWrite(TSL_S3, pin_3);

  return;
}

unsigned long get_tsl_freq() {

    // we have to scale out the frequency --
    // Scaling on the TSL230R requires us to multiply by a factor
    // to get actual frequency

  unsigned long freq = pulse_cnt * freq_mult;

    // reset the pulse counter

  pulse_cnt = 0;

  return(freq);
}
</pre>
<p>Now, we can change the output scaling at whim, and since we modified the frequency function, we don&#8217;t have to change any other code.</p>
<p>Use a lower output scaling for moderate levels of light or to tell minute differences in levels, or use higher scaling for brighter areas, but with less ability to tell the difference between small amounts.  For most photographic applications, you&#8217;ll prefer divide-by-10 or divide-by-100, to prevent constant jitter, whereas live luminance measurement applications will prefer divide-by-2.</p>
<p><strong>CONVERTING TO WHAT WE SEE</strong></p>
<p>You&#8217;ve probably heard the term <a href="http://en.wikipedia.org/wiki/Lux" target="_blank">Lux</a> before, as in &#8220;lux meter&#8221; or, this light produces this many &#8220;lux&#8221;.  Lux is, essentially, the measure of perceived brightness falling on, or coming from an amount of surface.  We&#8217;ll be using a surface size of square meters, m2, in our examples.  Now, note that we&#8217;re talking about &#8220;perceived&#8221;, as in perceived with our eyes.  To our eyes, different wavelengths of light register as brighter or less bright.  This is called photometry, what we&#8217;ve been dealing with up to this point is measuring actual energy, which is radiometry.</p>
<p>To go from the radiometric (actual) data to photometric (perceived) data, we&#8217;ll need to convert the energy into lumens per square meter (lux) from micro-watts per square centimeter.  In the process, we&#8217;ll need to determine how bright the light appears to us.  We&#8217;ll use the <a href="http://en.wikipedia.org/wiki/Luminous_efficiency" target="_blank">luminous efficiency function</a> to do this.  Now, this function is dependent on wavelength &#8211; our eyes perceive different wavelengths more or less brightly.  To keep matters simple, we&#8217;ll pretend like our light source is monochromatic &#8212; that is consists of only a single wavelength.  We&#8217;ll pick the same wavelength we have been using, 640nm.</p>
<p>To perform this conversion, we&#8217;ll need to find the luminous efficiency of 640nm.  Fortunately for us, this is empirical data, so we can just look it up in the <a href="http://cvision.ucsd.edu/lumindex.htm" target="_blank">CIE table</a>.  We&#8217;ll use CIE Vm(l) from 1978, and find that 640nm has an efficiency of 0.175.</p>
<pre class="brush: cpp;">
...

void loop() {

  // check the value of the light sensor every READ_TM ms

    // calculate how much time has passed

 pre_tm   = cur_tm;
 cur_tm   = millis();

 if( cur_tm &gt; pre_tm ) {
	tm_diff += cur_tm - pre_tm;
 }
 else if( cur_tm &lt; pre_tm ) {
           // handle overflow and rollover (Arduino 011)
	tm_diff += ( cur_tm + ( 34359737 - pre_tm ));
 } 

   // if enough time has passed to do a new reading...

 if( tm_diff &gt;= READ_TM ) {

       // re-set the ms counter
   tm_diff = 0;

      // get our current frequency reading
   unsigned long frequency = get_tsl_freq();

      // calculate radiant energy
   float uw_cm2 = calc_uwcm2( frequency );

      // calculate illuminance
   float lux    = calc_lux_single( uw_cm2, 0.175 );

 }

}

...

float calc_lux_single(float uw_cm2, float efficiency) {

    // calculate lux (lm/m^2), using standard formula:
    // Xv = Xl * V(l) * Km
    // Xl is W/m^2 (calculate actual receied uW/cm^2, extrapolate from sensor size (0.0136cm^2)
    // to whole cm size, then convert uW to W)
    // V(l) = efficiency function (provided via argument)
    // Km = constant, lm/W @ 555nm = 683 (555nm has efficiency function of nearly 1.0)
    //
    // Only a single wavelength is calculated - you'd better make sure that your
    // source is of a single wavelength...  Otherwise, you should be using
    // calc_lux_gauss() for multiple wavelengths

      // convert to w_m2
  float w_m2 = (u_cm2 / (float) 1000000) * (float) 100;

      // calculate lux
  float lux  = w_m2 * efficiency * (float) 683;

  return(lux);
}
</pre>
<p>And, there you have it &#8211; you can now calculate the Lux for a single wavelength.  Now, obviously most light sources we deal with produce light in many wavelengths at once, but we&#8217;ll save the more complex calculations for our next post on the subject.  <a href="http://roamingdrone.wordpress.com/2008/11/28/arduino-and-the-tsl230r-photographic-conversions/" target="_blank">In the next one</a>, we&#8217;ll cover calculating lux for multiple wavelengths, converting to Exposure Value (EV), calculating exposure time from EV/aperture/ISO, and other conversions.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/87/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/87/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/87/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=87&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2008/11/13/arduino-and-the-taos-tsl230r-light-sensor-getting-started/feed/</wfw:commentRss>
		<slash:comments>64</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>
	</item>
		<item>
		<title>Big Bend National Park &#8211; little places</title>
		<link>http://roamingdrone.wordpress.com/2008/10/10/big-bend-national-park-little-places/</link>
		<comments>http://roamingdrone.wordpress.com/2008/10/10/big-bend-national-park-little-places/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 13:58:52 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Exploring]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Robots]]></category>
		<category><![CDATA[Time-lapse Video]]></category>
		<category><![CDATA[Big Bend]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[desert]]></category>
		<category><![CDATA[motion control]]></category>
		<category><![CDATA[pentax]]></category>
		<category><![CDATA[sigma]]></category>
		<category><![CDATA[time-lapse]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=80</guid>
		<description><![CDATA[Time-lapse clips from my recent trip:<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=80&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Time-lapse clips from my recent trip:</p>
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/1927455' width='400' height='300' frameborder='0'></iframe></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/80/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/80/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/80/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=80&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2008/10/10/big-bend-national-park-little-places/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>
	</item>
		<item>
		<title>Back from Big Bend</title>
		<link>http://roamingdrone.wordpress.com/2008/10/03/back-from-big-bend/</link>
		<comments>http://roamingdrone.wordpress.com/2008/10/03/back-from-big-bend/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 18:44:22 +0000</pubDate>
		<dc:creator>c.a. church</dc:creator>
				<category><![CDATA[Exploring]]></category>
		<category><![CDATA[Photography]]></category>
		<category><![CDATA[Big Bend]]></category>
		<category><![CDATA[camping]]></category>
		<category><![CDATA[desert]]></category>
		<category><![CDATA[hiking]]></category>
		<category><![CDATA[jeep]]></category>
		<category><![CDATA[jk]]></category>
		<category><![CDATA[National Park]]></category>
		<category><![CDATA[off-roading]]></category>
		<category><![CDATA[vacation]]></category>

		<guid isPermaLink="false">http://roamingdrone.wordpress.com/?p=77</guid>
		<description><![CDATA[Went out to Big Bend National Park this past Sunday, and got back last night. Nothing like four, quiet-filled nights of complete solitude in the desert to get a man back on his feet and ready to return to the city! Returned from my third yearly exodus to the Chihuahan Desert un-harmed, save a few [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=77&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Went out to <a href="http://www.nps.gov/bibe/">Big Bend National Park</a> this past Sunday, and got back last night.  Nothing like four, quiet-filled nights of complete solitude in the desert to get a man back on his feet and ready to return to the city!  Returned from my third yearly exodus to the Chihuahan Desert un-harmed, save a few cactus spines and some bug bites here and there.</p>
<p>My original plan had been to shoot lots of photos and time-lapse, spending two nights in the Telephone Canyon area along the Old Ore Rd, and then moving onto one night at the base of Juniper Canyon, then a solo overnight trip up the canyon to the South Rim, to shoot sunrise/sunset with a great view, then back down and one night at the Fresno site near Mariscal Mine, to shoot some time-lapse of the mine there.  However, by Tuesday, my plans had changed due to the complete lack of any clouds in the sky (I&#8217;m obsessed with good clouds when shooting landscape =), and the disturbingly thick haze.  Visibility was limited to a few miles, and photography a much more difficult task.  With a thick haze and no clouds, my plans to shoot time-lapse from the South Rim were largely dashed, so I changed my plans to spend half a day going out to Terlingua, then day-hike Juniper Canyon, and then skipping out on the mine (which I&#8217;ve been to every time I&#8217;ve been there), to spend some time nearer the basin at Croton Springs.</p>
<p>On my first day-hike, I had intended to leave at sunrise and hike up the Telephone Canyon trail to either the Strawhouse trailhead or the canyon its self by lunch time, and then turn back.  Expecting to make good timing, I took a liter and a half of water, and set out.  Of course, the morning is always beautiful on the TC trail, but like last year, my plans were quickly dashed.  Last year, my best friend and I tried the same hike, but got distracted before we&#8217;d even made it a quarter of a mile down the trail &#8212; we set off down a gully on an attempt to climb Alto Relex, which of course we succeeded in &#8211; eating our lunch on the mountain top.  This year though, I was first slowed down a bit by the difficulty in following the rarely-hiked trail through the rocks and thick brush &#8211; trying to squint into the rising sun to find the cairns.  As soon as the terrain got easier, and the trail less difficult to follow, I moved into a brisk 4 1/2mph walk &#8211; expecting to make up my lost time this way.  Given that it&#8217;s still morning, I&#8217;m of course looking at any rocks in the sun in my path for sunning snakes.  I&#8217;m not, however, looking down in the shady spots like the little gully crossings, and this almost proved to be the trip&#8217;s undoing.  Moving a little less carefully than I should, down into a gully I get one of those &#8220;internal danger&#8221; alerts.  You know, that feeling you get right before you do something incredibly silly that results in broken bones or your girlfriend scowling at you for a week&#8230;  I stop my step, and pull back, to see that I had come within six inches of stepping right on a black-tail rattlesnake.  Too cold and too reliant on his camouflage  to even rattle, I would&#8217;ve certainly had an issue had I stepped on him.  Realizing that I should slow down, I brought the pace back to just below 2mph, and there went all of my plans for the hike.  By 11am, I had just made it to the first trail intersection, barely even halfway to the Strawhouse Trail, with almost 4 miles to go to the canyon.  Without a cloud in the sky at the moment, and already sweating and having drunk a half-liter of water, I sat down, ate a snack, and then turned my happy butt back around.  The TC trail is not one to push yourself on, given that it may be a week or more before anyone else tries it this time of year &#8211; and they&#8217;ll likely stop in the first couple of miles and turn back, as I just did.</p>
<p>That afternoon, I would head back up to Roy&#8217;s place ruins, and shoot some time-lapse there, while the last clouds I&#8217;d see for the week passed over, and then explored to creek bed to the north of the Telephone Canyon 2 site. (Just follow the old, blocked off road north for a few hundred yards, and then a wonderful creek bed can be hiked east quite a ways.)  The last night at Telephone Canyon would be spent shooting some sunset time-lapses and drinking beer.</p>
<p>Tuesday morning, I made a quick drive out of the rest of the Old Ore Rd, southbound, not spending much time to explore, as last year we had done plenty of that here.  Of course, you should spend time to check out the large creek bed with lots of Tinaja&#8217;s about halfway down the rd.  Just notice when you head down into a tiny valley, and then see a large gravel wash to your left.  Park in this wash, and then head down the creekbed, a few spots require careful footing to continue down, but reaching the bottom is well worth it, with every other rock having a fossil in it.</p>
<p>Made it back to panther junction and informed them of my plan changes (they were warning me against taking the juniper canyon trail to the south rim, they seem overly cautious, but they&#8217;re probably used to less well-prepared travelers.  Their warnings of &#8220;oh, that&#8217;s a 4&#215;4 only road&#8221; [of course, I have a great 4x4, and there's nothing out there that actually requires me to put it in 4-wheel-drive.] were usually found to be a wide, beautiful, fast-driving gravel road.), and then headed on to Juniper Canyon, and made a quick 2-hour hike of the first half of the trail.  Almost regretted ditching my plans to backpack up it, but not having to assemble my pack seemed like a good compromise.  =)  Twisted Shoe is a great campsite well away from all of the others &#8211; the kind that can offer peace and quiet even during the crowded winter season.  The road leading there, again, rough riding but easy enough for almost any vehicle to make it.</p>
<p>The next day took me to Terlingua Ranch and Terlingua.  Neither feeling worth the drive, but the drive through the Terlingua Ranch Road, and the Christmas Mountains worth the let-down.  Terlingua can barely lay claim to being a ghost-town as the do, but the cemetery offered some great photo opportunities.  It was hot on the Old Maverick road that afternoon, reading 91F ambient (feels like 120 in the sun), but the ability to hold a high speed on this easy road kept the roof temperature pretty low&#8230;  The Jeep JK is well-known to become a bit of an oven with the black, uninsulated fiberglass freedom top.  Out here, it&#8217;s better to just roll the windows down than run the A/C &#8211; the moving air will do a better job to clear the heat out of the upper reaches than the A/C will.</p>
<p>Finally, camping nearer to civilization at Croton Springs, I took an easy evening hike up the creek beds until some water made it impassible, then hiked the nearby rises until I had just enough light to make it back.  A nice dinner and some decent sunset time-lapse rounded out the trip.</p>
<p>Can&#8217;t wait to go back!  Just wish it wasn&#8217;t 600 miles away =(</p>
<p>Here&#8217;re a few snapshots, I didn&#8217;t take many of these, but I did shoot over 40 gigs of time-lapse and landscape shots.  Anything worth keeping will find its way to my <a href="http://shutterdrone.wordpress.com" target="_blank">photo blog</a>.</p>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Old Ore Rd Near McKinney Springs" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9280016.jpg" alt="Old Ore Rd Near McKinney Springs" width="500" height="375" /><p class="wp-caption-text">Old Ore Rd Near McKinney Springs</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Approaching Alto Relex in the McKinney Hills" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9280025.jpg" alt="Approaching Alto Relex in the McKinney Hills" width="500" height="375" /><p class="wp-caption-text">Approaching Alto Relex in the McKinney Hills</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Roys Peak from the Telephone Canyon Trail" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290037.jpg" alt="Roys Peak from the Telephone Canyon Trail" width="500" height="375" /><p class="wp-caption-text">Roy&#39;s Peak from the Telephone Canyon Trail</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Black Tail Rattlesnake" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290044.jpg" alt="Black Tail Rattlesnake" width="500" height="375" /><p class="wp-caption-text">Black Tail Rattlesnake</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="TC #2 Campsite" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290048.jpg" alt="TC #2 Campsite" width="500" height="375" /><p class="wp-caption-text">TC #2 Campsite</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Creekbed NorthEast of TC#2 Campsite" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290056.jpg" alt="Creekbed NorthEast of TC#2 Campsite" width="500" height="375" /><p class="wp-caption-text">Creekbed NorthEast of TC#2 Campsite</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="The Jeep Poses in the Sunset" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290062.jpg" alt="The Jeep Poses in the Sunset" width="500" height="375" /><p class="wp-caption-text">The Jeep Poses in the Sunset</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Time-lapse Shooting" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290070.jpg" alt="Time-lapse Shooting" width="500" height="375" /><p class="wp-caption-text">Time-lapse Shooting</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="At 2.7lbs, a Veritable Taj Mahal" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290073.jpg" alt="At 2.7lbs, a Veritable Taj Mahal" width="500" height="375" /><p class="wp-caption-text">At 2.7lbs, a Veritable Taj Mahal</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Southbound Old Ore Rd" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300081.jpg" alt="Southbound Old Ore Rd" width="500" height="375" /><p class="wp-caption-text">Southbound Old Ore Rd</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Rd. to Juniper Canyon" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300095.jpg" alt="Rd. to Juniper Canyon" width="500" height="375" /><p class="wp-caption-text">Rd. to Juniper Canyon</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Trail Into Juniper Canyon" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300103.jpg" alt="Trail Into Juniper Canyon" width="500" height="375" /><p class="wp-caption-text">Trail Into Juniper Canyon</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Campsite at Twisted Shoe" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300106.jpg" alt="Campsite at Twisted Shoe" width="500" height="375" /><p class="wp-caption-text">Campsite at Twisted Shoe</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Terlingua Ranch Rd." src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010129.jpg" alt="Terlingua Ranch Rd." width="500" height="375" /><p class="wp-caption-text">Terlingua Ranch Rd.</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="A Stones Throw From Mexico" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010137.jpg" alt="A Stones Throw From Mexico" width="500" height="375" /><p class="wp-caption-text">A Stone&#39;s Throw From Mexico</p></div>
<div class="wp-caption aligncenter" style="width: 510px"><img title="Sunset at Croton Springs" src="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010144.jpg" alt="Sunset at Croton Springs" width="500" height="375" /><p class="wp-caption-text">Sunset at Croton Springs</p></div>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/roamingdrone.wordpress.com/77/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/roamingdrone.wordpress.com/77/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/roamingdrone.wordpress.com/77/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=roamingdrone.wordpress.com&amp;blog=3592744&amp;post=77&amp;subd=roamingdrone&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://roamingdrone.wordpress.com/2008/10/03/back-from-big-bend/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/f626c98c568a807c7f17e1bb77c076bd?s=96&#38;d=identicon&#38;r=PG" medium="image">
			<media:title type="html">shutterdrone</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9280016.jpg" medium="image">
			<media:title type="html">Old Ore Rd Near McKinney Springs</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9280025.jpg" medium="image">
			<media:title type="html">Approaching Alto Relex in the McKinney Hills</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290037.jpg" medium="image">
			<media:title type="html">Roys Peak from the Telephone Canyon Trail</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290044.jpg" medium="image">
			<media:title type="html">Black Tail Rattlesnake</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290048.jpg" medium="image">
			<media:title type="html">TC #2 Campsite</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290056.jpg" medium="image">
			<media:title type="html">Creekbed NorthEast of TC#2 Campsite</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290062.jpg" medium="image">
			<media:title type="html">The Jeep Poses in the Sunset</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290070.jpg" medium="image">
			<media:title type="html">Time-lapse Shooting</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9290073.jpg" medium="image">
			<media:title type="html">At 2.7lbs, a Veritable Taj Mahal</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300081.jpg" medium="image">
			<media:title type="html">Southbound Old Ore Rd</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300095.jpg" medium="image">
			<media:title type="html">Rd. to Juniper Canyon</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300103.jpg" medium="image">
			<media:title type="html">Trail Into Juniper Canyon</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/P9300106.jpg" medium="image">
			<media:title type="html">Campsite at Twisted Shoe</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010129.jpg" medium="image">
			<media:title type="html">Terlingua Ranch Rd.</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010137.jpg" medium="image">
			<media:title type="html">A Stones Throw From Mexico</media:title>
		</media:content>

		<media:content url="http://dronecolony.com/2008/new_img/blog/roaming/bigbend2008/PA010144.jpg" medium="image">
			<media:title type="html">Sunset at Croton Springs</media:title>
		</media:content>
	</item>
	</channel>
</rss>
