<?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/"
	>

<channel>
	<title>SteveKamerman.com</title>
	<atom:link href="http://www.stevekamerman.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.stevekamerman.com</link>
	<description>Blog about pretty much everything</description>
	<lastBuildDate>Sat, 23 Jul 2011 19:05:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>What&#8217;s up with WURFL?</title>
		<link>http://www.stevekamerman.com/2011/07/whats-up-with-wurfl/</link>
		<comments>http://www.stevekamerman.com/2011/07/whats-up-with-wurfl/#comments</comments>
		<pubDate>Sat, 23 Jul 2011 04:39:50 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Mobile Device Detection]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[ScientiaMobile]]></category>
		<category><![CDATA[Tera-WURFL]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=308</guid>
		<description><![CDATA[There&#8217;s been a lot of talk about WURFL lately and with good reason. On June 6, 2011 I launched ScientiaMobile along with my business partners, Luca Passani and Krishna Guda.  If you&#8217;re reading my blog you probably know that I am the author of the popular mobile device detection library Tera-WURFL.  I wrote Tera-WURFL back [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>There&#8217;s been a lot of talk about <a href="http://wurfl.sourceforge.net" target="_blank">WURFL</a> lately and with good reason. On June 6, 2011 I launched <a href="http://www.scientiamobile.com/">ScientiaMobile </a>along with my business partners, <a href="http://www.scientiamobile.com/about">Luca Passani and Krishna Guda</a>.  If you&#8217;re reading my blog you probably know that I am the author of the popular mobile device detection library Tera-WURFL.  I wrote Tera-WURFL back in 2006, when the world of mobile devices was completely scattered in every direction.  At the time, the vast majority of mobile devices did not support a common set of capabilities, like MP3, MMS or HTML.  Instead, your best bet was to write a terrible-looking, but fairly well behaved XHTML-MP site using very conservative tags.  WURFL solved this problem nicely by accurately matching a visiting user to a device profile that allowed you to serve a WAP page to a Nokia 3360, an XHTML-MP page to a Motorola RAZR and an HTML page to a 1st-gen iPhone.</p>
<p>Since 2006 there have been a lot of changes, particularly in the capabilities of mobile browsers.  Thanks to Apple Webkit, even lower-end phone are able to browse sites without catastrophic rendering issues (still a terrible UX, just not a catastrophe).  With all these changes, however, one thing has remained: <em>mobile device fragmentation</em>.  Device fragmentation means that the capabilities and methods of interacting with mobile devices are constantly spreading in different directions, none compatible with the other.  Technically this problem is driven by consumers, since we always want the next cool feature.  What happens is that manufacturers battle it out in an attempt to be the first to release a device that has an edge over the competition, like Near Field Communications and glasses-free 3D Displays.  The problem is that manufacturers release devices with these features before the industry has settled on a standard for interacting with them.</p>
<p>So what does this have to do with WURFL?  Luca Passani and I have seen the writing on the wall and we realize that this problem of device fragmentation has had some temporary relief by the massive market share by Apple and Android devices, but things are starting to get worse fast.  Every day we are seeing new devices and incomplete software features that make mobile web programming a nightmare!  For example, everyone is very excited about HTML5, but how do you know if the device you&#8217;re targeting supports the HTML5 features that you need?  One option is to use a high-level JavaScript abstraction framework like jQuery Mobile.  This is very slick on my super fast Snapdragon-powered HTC Inspire 4G, but how will it work on a typical off the shelf phone?  What about BlackBerry OS 6/7, MeeGo, Symbian^3, WebOS and WP7?  Good luck.</p>
<p>What Luca and I decided to do is to join forces and refocus our full attention on the problem.  In June we <a href="http://www.scientiamobile.com/pr">publicly announced</a> the merger of the WURFL project and the Tera-WURFL project into a single company called ScientiaMobile (<a href="http://tech.groups.yahoo.com/group/wmlprogramming/message/34031" target="_blank">original WMLProgramming message</a>).  Now that we&#8217;re on the same team, Luca and I are able to work more closely on the problem of device fragmentation and detection.  In addition to better APIs and more consistent data, we&#8217;re bringing some awesome new products to market that will make it easier for organizations of all sizes to get started with mobile device detection.  Right now, we are polishing up a product that has always been near the top of my feature requests:  WURFL Cloud.  WURFL Cloud is something that we&#8217;ve been secretly working on for some time and it is now in it&#8217;s Beta-testing phase.  We are spending a lot of time to make sure this service is very fast and accurate from day 1 (by the way, you can drop us a line at <a href="mailto:wurfl-cloud-beta@scientiamobile.com">wurfl-cloud-beta@scientiamobile.com</a> to get your Beta license).  Unlike the standard WURFL APIs, WURFL Cloud is a hosted device detection service that is always updated and maintained by the WURFL Team.</p>
<p>Throughout this process, we have chosen to follow our roots.  WURFL has always been a Free and Open Source project and it still is.  We value our community and are excited to bring WURFL to the next level while keeping it in the public domain.  At ScientiaMobile, in addition to the FOSS APIs, we are now selling commercial licenses and support for our APIs as well.  Under this new dual-licensing scheme we are able to help organizations that are not comfortable with the restrictions of the open source license.</p>
<p>As we say at ScientiaMobile: <strong>WURFL has Graduated</strong>!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2011/07/whats-up-with-wurfl/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HAProxy 1.4.15 for Ubuntu 11.04</title>
		<link>http://www.stevekamerman.com/2011/07/haproxy_ubuntu/</link>
		<comments>http://www.stevekamerman.com/2011/07/haproxy_ubuntu/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 04:31:27 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[deb]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[haproxy]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=300</guid>
		<description><![CDATA[If you&#8217;re not familiar with HAProxy, you&#8217;re missing out! HAProxy is a very intelligent high-availability reverse proxy that operates all the way up to Layer 7. Unlike Nginx (another good choice), HAProxy is not a webserver, it is designed with only high availability and load balancing in mind. Another great feature is that it&#8217;s a [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re not familiar with HAProxy, you&#8217;re missing out!  HAProxy is a very intelligent high-availability reverse proxy that operates all the way up to Layer 7.  Unlike Nginx (another good choice), HAProxy is not a webserver, it is designed with only high availability and load balancing in mind.  Another great feature is that it&#8217;s a lot cheaper than your typical Layer 7 Load Balancer, free <img src='http://www.stevekamerman.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>There are plenty of good articles out there on HAProxy, but I couldn&#8217;t find any Debian/Ubuntu packages for the latest version (1.4.15).  The Ubuntu 11.04 repo&#8217;s newest version is 1.4.8, but if you want some of the cool new features of 1.4.9-1.4.15, you have to build it from scratch.  This process isn&#8217;t too painful, but I&#8217;ve got a lot of servers to put HAProxy on and I don&#8217;t want dpkg / apt-get to freak out and install the old HAProxy in order to satisfy a dependency.</p>
<p>For this reason, I&#8217;ve created an <a href="http://www.stevekamerman.com/haproxy/haproxy_1.4.15_amd64.deb">Ubuntu 11.04 x64 HAProxy package</a> with TCP Splicing, Full Transparent Proxies and PCRE enabled:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HA-Proxy version 1.4.15 2011/04/08<br />
Copyright 2000-2010 Willy Tarreau &lt;w@1wt.eu&gt;<br />
<br />
Build options :<br />
&nbsp; TARGET &nbsp;= linux26<br />
&nbsp; CPU &nbsp; &nbsp; = native<br />
&nbsp; CC &nbsp; &nbsp; &nbsp;= gcc<br />
&nbsp; CFLAGS &nbsp;= -O2 -march=native -g -fno-strict-aliasing<br />
&nbsp; OPTIONS = USE_LINUX_SPLICE=1 USE_LINUX_TPROXY=1 USE_PCRE=1<br />
<br />
Default settings :<br />
&nbsp; maxconn = 2000, bufsize = 16384, maxrewrite = 8192, maxpollevents = 200<br />
<br />
Encrypted password support via crypt(3): yes<br />
<br />
Available polling systems :<br />
&nbsp; &nbsp; &nbsp;sepoll : pref=400, &nbsp;test result OK<br />
&nbsp; &nbsp; &nbsp; epoll : pref=300, &nbsp;test result OK<br />
&nbsp; &nbsp; &nbsp; &nbsp;poll : pref=200, &nbsp;test result OK<br />
&nbsp; &nbsp; &nbsp;select : pref=150, &nbsp;test result OK<br />
Total: 4 (4 usable), will use sepoll.</div></div>
<p>Feel free to grab <a href="http://www.stevekamerman.com/haproxy/haproxy_1.4.15_amd64.deb">haproxy_1.4.15_amd64.deb</a> (502k SHA1: 8b2ecf05544e0f6531e50bf40261e0b112db61e9)<br/><br />
You can also grab the sources from here: <a href="http://www.stevekamerman.com/haproxy/">http://www.stevekamerman.com/haproxy/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2011/07/haproxy_ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rebuilding a Sony Vaio Battery</title>
		<link>http://www.stevekamerman.com/2011/04/rebuilding-a-sony-vaio-battery/</link>
		<comments>http://www.stevekamerman.com/2011/04/rebuilding-a-sony-vaio-battery/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 00:30:40 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Random Projects]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=275</guid>
		<description><![CDATA[Recently the battery in my aging laptop (Sony Vaio VGN-NR498E) took a nose dive.  This is to be expected after 4 years or so, so I was not too upset about it.  What I am upset about, is the fact that Sony doesn&#8217;t seem to sell a genuine replacement for the battery.  The original is [...]]]></description>
			<content:encoded><![CDATA[<p>Recently the battery in my aging laptop (Sony Vaio VGN-NR498E) took a nose dive.  This is to be expected after 4 years or so, so I was not too upset about it.  What I am upset about, is the fact that Sony doesn&#8217;t seem to sell a genuine replacement for the battery.  The original is a VGP-BPS9/B and the only &#8220;Sony&#8221; batteries I found online were from unreputable sources and cost around $150.  I decided to take the battery apart and see if I could replace the cells directly, but in the process I had to break most of the battery connections and it did not seem trivial to replace them.  After whining about it for a week I opted to buy a <a href="http://www.buy.com/prod/new-laptop-battery-for-sony-vaio-vgn-nr490e-w-vgn-nr498-vgn-nr498e/q/loc/101/217537673.html">third party battery off Buy.com</a> for $59.</p>
<div id="attachment_276" class="wp-caption alignleft" style="width: 160px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/1_repl_bat.jpg"><img class="size-thumbnail wp-image-276" title="Battery Shipment Contents" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/1_repl_bat-150x150.jpg" alt="" width="150" height="150" /></a><p class="wp-caption-text">Battery Shipment Contents</p></div>
<p>I received the shipment within 5 days and inside I found the battery, a couple pages of instructions and a mini CD.  There was also a written warning in poorly translated English stating that I needed to update the BIOS in order to use the battery.  It was so poorly translated that I couldn&#8217;t even get a loose interpretation of some of the text.  For example, &#8220;You&#8217;re system may isn&#8217;t suitable for this software or has already not renewed at first the bios file of factory&#8221;  (side note: is it really that hard to get a fluent English-speaker to proof read your instructions?).  Anyway, the instructions suggested that I may damage the battery and/or system if I didn&#8217;t update my BIOS before plugging in the battery, so I popped in the CD which presumably contained the update.  The CD was blank.  I ended up finding the necessary software on a site mentioned in their instructions, but the software gave me a vague warning that my BIOS was not supported and even after I forced the update the software crashed.  At this point I gave up on bricking my laptop via a failed BIOS update and opted to plug it in and hope for the best.  The battery showed about a 40% charge but the laptop said it was not charging it (I don&#8217;t haveSony&#8217;s anti third-party battery software installed).  After much frustration and trying different combinations of removing and replacing the battery at different times, I decided to take the Steve approach and hack it <img src='http://www.stevekamerman.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<div id="attachment_277" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/2_bat_comp.jpg"><img class="size-medium wp-image-277" title="Battery Comparison" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/2_bat_comp-300x157.jpg" alt="" width="300" height="157" /></a><p class="wp-caption-text">Original Sony battery (top) and replacement (bottom)</p></div>
<p style="text-align: center;">
<p>I had already taken my original battery apart and thrown the dead cells away, so I don&#8217;t have any pictures of it, but it looked almost exactly the same as the replacement: 6x 3.6V battery cells and a controller card.  Batteries are nothing but a means of storing power, so the controller must be responsible for communicating things like battery capacity and charging status.  I decided to transplant the new battery cells onto the old Sony controller and give it a shot; in short, it worked!  Here&#8217;s the process in pictures.</p>
<h3>Step 1: Take batteries apart &#8211; remove 4 screws and pry top cover off, then gently pry out the batteries and controller card.</h3>
<div id="attachment_278" class="wp-caption aligncenter" style="width: 650px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/3_repl_bat.jpg"><img class="size-large wp-image-278" title="Replacement Battery" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/3_repl_bat-1024x279.jpg" alt="" width="640" height="174" /></a><p class="wp-caption-text">Replacement Battery</p></div>
<h3>Step 2: Remove the controller card from the batteries by desoldering the four metal tabs that connect to the different battery junctions.  I used desoldering wick, flux and a hot soldering iron.</h3>
<div id="attachment_279" class="wp-caption aligncenter" style="width: 650px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/4_control_comp.jpg"><img class="size-large wp-image-279" title="Controller Comparison" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/4_control_comp-1024x404.jpg" alt="" width="640" height="252" /></a><p class="wp-caption-text">A closeup of the new controller (attached), and the original Sony controller next to it.</p></div>
<h3>Step 3: Solder the battery leads to the new controller.</h3>
<div id="attachment_281" class="wp-caption alignleft" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/5_solder.jpg"><img class="size-medium wp-image-281" title="Solder Sony Controller" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/5_solder-300x179.jpg" alt="" width="300" height="179" /></a><p class="wp-caption-text">Solder Sony Controller</p></div>
<div id="attachment_282" class="wp-caption alignleft" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/6_done_solder.jpg"><img class="size-medium wp-image-282" title="Finished Controller" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/6_done_solder-300x94.jpg" alt="" width="300" height="94" /></a><p class="wp-caption-text">Finished Controller</p></div>
<div style="clear: both;"></div>
<h3>Step 4: Reassemble the battery and secure it with some hot glue.</h3>
<div id="attachment_284" class="wp-caption alignleft" style="width: 205px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/8_glue.jpg"><img class="size-medium wp-image-284 " title="Glue the Batteries and Controller" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/8_glue-195x300.jpg" alt="" width="195" height="300" /></a><p class="wp-caption-text">Glue the Batteries and Controller</p></div>
<div id="attachment_288" class="wp-caption alignleft" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2011/04/9_done1.jpg"><img class="size-medium wp-image-288 " title="Finished Battery" src="http://www.stevekamerman.com/wp-content/uploads/2011/04/9_done1-300x87.jpg" alt="" width="300" height="87" /></a><p class="wp-caption-text">Finished Battery</p></div>
<div style="clear: both;"></div>
<h3>Step 5: Once the top cover is replaced, put the battery back in the computer &#8211; you&#8217;re done!</h3>
<p>For best results you will also need to recalibrate the battery by letting it charge completely, then unplugging the power cable and let the battery discharge until it&#8217;s completely dead.  I let my new battery charge overnight, then discharged it in the morning.  Incredibly, the new battery kept the laptop alive for over 3 hours &#8211; a significant improvement over the 5-10 minutes I was getting before!</p>
<p>If you are going to attempt this, you should know that there is a very real possibility that things could go horribly wrong if, for example, you wired the battery pack in backwards.  You could destroy the charging circuit in your laptop or even melt it down into a heap of plastic and potentially burn down your house in the process.  That having been said, if you know what you&#8217;re doing, this is a great way to recover an investment in a low-grade battery!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2011/04/rebuilding-a-sony-vaio-battery/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Tera-WURFL 2.1.4 Finally Released!</title>
		<link>http://www.stevekamerman.com/2011/02/tera-wurfl-2-1-4-finally-released/</link>
		<comments>http://www.stevekamerman.com/2011/02/tera-wurfl-2-1-4-finally-released/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 01:58:37 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mobile Device Detection]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tera Projects]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[Tera-WURFL]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=266</guid>
		<description><![CDATA[After a lot of development and tons of regression testing, Tera-WURFL 2.1.4 is finally ready for release. There has finally been a break in commits on the GitHub repo for more that a week, and no bug reports on the development branch. Changes from Tera-WURFL 2.1.3 Switched to better XML Parser (old parser, SimpleXML will [...]]]></description>
			<content:encoded><![CDATA[<p>After a lot of development and tons of regression testing, <a title="Tera-WURFL Downloads" href="http://www.tera-wurfl.com/wiki/index.php/Downloads#Stable_2.1.4" target="_blank">Tera-WURFL 2.1.4</a> is finally ready for release.  There has finally been a break in commits on the <a title="Tera-WURFL GitHub Repo" href="https://github.com/kamermans/Tera-WURFL/" target="_blank">GitHub repo</a> for more that a week, and no bug reports on the development branch.</p>
<h2>Changes from Tera-WURFL 2.1.3</h2>
<ul>
<li>Switched to better XML Parser (old parser, SimpleXML will still be used if XMLReader is missing)</li>
<li>Improved matching for Apple, Android, Nokia, BlackBerry / RIM, DoCoMo, KDDI, LG and OperaMini</li>
<li>Allowed preloading a custom TeraWurflConfig so the default is ignored</li>
<li>Updated source documentation</li>
<li>Updated instructions</li>
<li>Greatly improved cmd_line_admin.php</li>
<li>Converted line endings to \n</li>
<li>Various bugfixes</li>
<li>Improved Remote Client</li>
<li>Added builtin regression testing (thanks digitalronin!). Tip: from the shell, go to the test/ dir and type &#8220;rake sanity&#8221; to make sure your patches are compatible with the loaded WURFL</li>
<li>Moved default config to &#8220;TeraWurflConfig.php.example&#8221; so your config isn&#8217;t overwritten</li>
<li>Fixed MSSQL DB Connector bug</li>
</ul>
<p>If you rely on Android or BlackBerry detection, you will really want to get version 2.1.4 &#8211; it will significantly improve detection of these devices.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2011/02/tera-wurfl-2-1-4-finally-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Keep oom_killer from killing your server!</title>
		<link>http://www.stevekamerman.com/2011/01/keep-oom_killer-from-killing-your-server/</link>
		<comments>http://www.stevekamerman.com/2011/01/keep-oom_killer-from-killing-your-server/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 17:52:34 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=257</guid>
		<description><![CDATA[Even though RAM is cheap these days, there are some conditions in which your Linux server could run out of it completely. Just the other day, I noticed my main hosting server went down &#8211; I could still ping it, but DNS, SSH and Apache2 were not responding, so I had to call the datacenter [...]]]></description>
			<content:encoded><![CDATA[<p>Even though RAM is cheap these days, there are some conditions in which your Linux server could run out of it completely.  Just the other day, I noticed my main hosting server went down &#8211; I could still ping it, but DNS, SSH and Apache2 were not responding, so I had to call the datacenter to have them reboot my system.  After analyzing the system, I realized that some unknown process ate up all the memory <em>and</em> all the swap space!  I used <a title="Cacti" href="http://www.cacti.net/" target="_blank">Cacti</a> to monitor my server&#8217;s performance, and so I could see that it took a nose-dive after getting hit with a few million requests in a couple days (these were raw mobile device detection requests).  After the system ran out of memory, it started swapping.  This lasted for about 2 weeks before depleting the swap space, at which point it struggled on for another 18 hours.  At this point, it was critically starved of memory and oom_killer (Out of Memory Killer) was invoked to start killing processes in a vain attempt to free up memory.  The oom_killer seems to have very little intelligence as to which processes to kill first, as sshd and named were early victims.  After this episode, I decided to create a script that adjusts the order in which key processes were killed, to make sure I have access to the server in the event of a memory leak or OOM condition.</p>
<h2>oom_adjust.sh to the rescue!</h2>
<p>I&#8217;ve created oom_adjust.sh to adjust (and periodically readjust via cron) the order in which the processes may be killed by oom_killer.  The script uses a config file called <strong>oom_adjust.conf</strong> (by default it looks for it in /etc) in which you can list processes and the oom_adj value that you want to give them.  The possible values are from -17 (never kill) to 15 (kill first).</p>
<p><strong>oom_adjust.conf</strong></p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;"># Adjust process oom_adj values so they are more or less likely to be killed in an oom event</span><br />
<span style="color: #666666; font-style: italic;"># procname oom_adj</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Keep sshd ALIVE</span><br />
sshd <span style="color: #660033;">-17</span><br />
<br />
<span style="color: #666666; font-style: italic;"># DNS is very important to me too</span><br />
named <span style="color: #660033;">-8</span><br />
<br />
<span style="color: #666666; font-style: italic;"># I'd prefer that MySQL stays alive, but it's not required</span><br />
mysqld <span style="color: #660033;">-1</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Apache2 is a memory hog, but I'll give it a fighting chance</span><br />
<span style="color: #666666; font-style: italic;"># I'm giving it 0 since the workers will respawn at 0 anyway</span><br />
apache2 <span style="color: #000000;">0</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Sphinx search is cool, but I can live without it if an oom occurs</span><br />
searchd <span style="color: #000000;">3</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Memcache is in the same boat as Sphinx search</span><br />
memcached <span style="color: #000000;">3</span><br />
<br />
<span style="color: #666666; font-style: italic;"># I only use mongodb for testing on this server</span><br />
mongod <span style="color: #000000;">5</span><br />
<br />
<span style="color: #666666; font-style: italic;"># It would be nice if smtpd stayed up, so I still get alerts</span><br />
smtpd <span style="color: #000000;">5</span><br />
<br />
<span style="color: #666666; font-style: italic;"># These services can be killed first</span><br />
pure-ftpd <span style="color: #000000;">10</span><br />
pure-ftpd-mysql <span style="color: #000000;">10</span><br />
snmpd <span style="color: #000000;">10</span><br />
fail2ban-server <span style="color: #000000;">10</span><br />
ntpd <span style="color: #000000;">10</span><br />
authdaemond <span style="color: #000000;">10</span><br />
saslauthd <span style="color: #000000;">10</span><br />
qmgr <span style="color: #000000;">10</span><br />
pickup <span style="color: #000000;">10</span></div></div>
<p>Here is the main script, which I&#8217;ve symlink&#8217;d into /usr/sbin for convinience.<br />
<strong>oom_adjust.sh</strong></p>
<div class="codecolorer-container bash geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/bin/sh</span><br />
<br />
<span style="color: #666666; font-style: italic;"># oom_adjust.sh Out of Memory Killer (oom_killer) Priority Adjustment Script</span><br />
<span style="color: #666666; font-style: italic;"># by Steve Kamerman &lt;stevekamerman@gmail.com&gt;, Jan 2011</span><br />
<span style="color: #666666; font-style: italic;"># http://www.stevekamerman.com</span><br />
<br />
<span style="color: #007800;">OOM_ADJ_FILE</span>=<span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>oom_adjust.conf<br />
<br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-f</span> <span style="color: #007800;">$OOM_ADJ_FILE</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;oom_adjust.sh: config file <span style="color: #007800;">$OOM_ADJ_FILE</span> was not found&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">2</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span><br />
<span style="color: #000000; font-weight: bold;">fi</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;oom_adjust.sh is setting oom_killer priorities&quot;</span><br />
<span style="color: #000000; font-weight: bold;">for</span> LINE <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$OOM_ADJ_FILE</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/^[# \t].*/d'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'/^$/d'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/ /:/'</span><span style="color: #000000; font-weight: bold;">`</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">NAME</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$LINE</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> <span style="color: #660033;">-d</span><span style="color: #ff0000;">&quot;:&quot;</span> -f1<span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #007800;">ADJ</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$LINE</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> <span style="color: #660033;">-d</span><span style="color: #ff0000;">&quot;:&quot;</span> -f2<span style="color: #000000; font-weight: bold;">`</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot; &nbsp;Setting <span style="color: #007800;">$NAME</span> to <span style="color: #007800;">$ADJ</span>&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> PID <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">pidof</span> <span style="color: #007800;">$NAME</span><span style="color: #000000; font-weight: bold;">`</span>; <span style="color: #000000; font-weight: bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$ADJ</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>proc<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$PID</span><span style="color: #000000; font-weight: bold;">/</span>oom_adj<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #000000; font-weight: bold;">done</span><br />
<span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">0</span></div></div>
<p>If your distro uses <strong>/etc/rc.local</strong>, you can put call this script there to apply the adjustments on startup.  I also call it on my servers via crontab every night to keep the processes in check, in case they have respawned/restarted with a different PID.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2011/01/keep-oom_killer-from-killing-your-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Understanding a Mouse Scroll Wheel</title>
		<link>http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/</link>
		<comments>http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/#comments</comments>
		<pubDate>Sat, 18 Dec 2010 20:30:11 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Random Projects]]></category>
		<category><![CDATA[arduino]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=243</guid>
		<description><![CDATA[Having been rather addicted to understanding electronics lately, I&#8217;m always looking for something to play with. Last week I was about to throw out a broken wireless Microsoft mouse, but I caught myself and ended up taking it apart. I dug down to the scroll wheel and found out it was a nice little rotary [...]]]></description>
			<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="350" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://www.youtube.com/v/GZNnjDrU9p0" /><embed type="application/x-shockwave-flash" width="425" height="350" src="http://www.youtube.com/v/GZNnjDrU9p0"></embed></object></p>
<p>Having been rather addicted to understanding electronics lately, I&#8217;m always looking for something to play with.  Last week I was about to throw out a broken wireless Microsoft mouse, but I caught myself and ended up taking it apart.</p>
<div id="attachment_244" class="wp-caption alignleft" style="width: 235px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/12/DSC00256.jpg"><img class="size-medium wp-image-244 " title="Rotary Encoder from a Mouse" src="http://www.stevekamerman.com/wp-content/uploads/2010/12/DSC00256-225x300.jpg" alt="" width="225" height="300" /></a><p class="wp-caption-text">Rotary Encoder from a Mouse</p></div>
<p>I dug down to the scroll wheel and found out it was a nice little rotary encoder &#8211; there&#8217;s an LED pointed at two phototransistors (light detectors) in it, as well as a circle of tiny black posts that pass between the LED and the detectors, as you can see to the left.  When the posts pass in front of the detectors, the Arduino reads them and is able to determine which direction they are going and increments or decrements a variable that I can access.</p>
<p>It took me about 4 hours to figure out how to hook this thing up, so I figured I would share the info in case someone else wants to use a rotary encoder from a Microsoft mouse in their project.<br />
<br/><br />
If you are holding the encoder so that the rotating half is facing you and the wires are facing down, the pinout is as follows:</p>
<p>Pin 1: Photo Sensor 1<br />
Pin 2: Vcc<br />
Pin 3: Photo Sensor 2<br />
Pin 4: IR LED +<br />
Pin 5: IR LED -</p>
<p>Unlike most of the examples I found for using a rotary encoder, this one requires +Vcc on Pin 2 &#8211; power will not flow the other way.  The LED power is very picky too;  I am powering it from the 5v regulated supply on my Arduino through a 1k resistor to keep the right amount of light in the encoder.  Too much light and both sensors will be high for too long and too little, neither will go high.  The hardest part to figure out was the voltage divider circuit for the sensors.  I could get them working ok on an analog input &#8211; swinging between about 80-600, but it wasn&#8217;t clean enough to input as digital until I found the right resistor: 10k.  This nicely divides the input between ground and +5v so the encoder can be read.</p>
<p>Here is the Arduino sketch for the project as shown in the video above:</p>
<div class="codecolorer-container c geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// Arduino Rotary Encoder from Mouse Scroll Wheel</span><br />
<span style="color: #666666; font-style: italic;">// and SparkFun 4 Digit Serial 7-Segment Display</span><br />
<span style="color: #666666; font-style: italic;">// by Steve Kamerman 12/18/2010</span><br />
<span style="color: #666666; font-style: italic;">// http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/</span><br />
<br />
<span style="color: #666666; font-style: italic;">// These MUST be on interrupt pins!</span><br />
<span style="color: #339933;">#define encoderPinA 2</span><br />
<span style="color: #339933;">#define encoderPinB 3</span><br />
<br />
<span style="color: #339933;">#define displayTXPin 10</span><br />
<span style="color: #339933;">#define displayRXPin 11</span><br />
<br />
<span style="color: #666666; font-style: italic;">// used only for sprintf()</span><br />
<span style="color: #339933;">#include &lt;stdio.h&gt;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// If you don't have NewSoftSerial, grab it from:</span><br />
<span style="color: #666666; font-style: italic;">// http://arduiniana.org/libraries/NewSoftSerial/</span><br />
<span style="color: #339933;">#include &lt;NewSoftSerial.h&gt;</span><br />
NewSoftSerial displaySerial<span style="color: #009900;">&#40;</span>displayRXPin<span style="color: #339933;">,</span> displayTXPin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// the value - this must be volatile because it is modified</span><br />
<span style="color: #666666; font-style: italic;">// during an interrupt function and used in a normal function</span><br />
<span style="color: #993333;">volatile</span> <span style="color: #993333;">unsigned</span> <span style="color: #993333;">int</span> encoderPos <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #993333;">void</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// setup the encoder</span><br />
&nbsp; pinMode<span style="color: #009900;">&#40;</span>encoderPinA<span style="color: #339933;">,</span> INPUT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; pinMode<span style="color: #009900;">&#40;</span>encoderPinB<span style="color: #339933;">,</span> INPUT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; attachInterrupt<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> readEncoderA<span style="color: #339933;">,</span> CHANGE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; attachInterrupt<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> readEncoderB<span style="color: #339933;">,</span> CHANGE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp;<br />
&nbsp; <br />
&nbsp; <span style="color: #666666; font-style: italic;">// setup the display</span><br />
&nbsp; pinMode<span style="color: #009900;">&#40;</span>displayTXPin<span style="color: #339933;">,</span> OUTPUT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; displaySerial.<span style="color: #202020;">begin</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">9600</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// reset display</span><br />
&nbsp; displaySerial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;v&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// Set display brightness</span><br />
&nbsp; displaySerial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #208080;">0x7A</span><span style="color: #339933;">,</span> BYTE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; displaySerial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #208080;">0x05</span><span style="color: #339933;">,</span> BYTE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #666666; font-style: italic;">// set the display to &quot; &nbsp; 0&quot;</span><br />
&nbsp; displaySerial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;xxx0&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> loop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; displayNumber<span style="color: #009900;">&#40;</span>encoderPos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;">// prints the given number, right justified padded with spaces</span><br />
<span style="color: #666666; font-style: italic;">// sprtinf() is not a great idea if you want to save space</span><br />
<span style="color: #666666; font-style: italic;">// but I'm really not too worried about it :)</span><br />
<span style="color: #993333;">void</span> displayNumber<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> num<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; sprintf<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%4d&quot;</span><span style="color: #339933;">,</span> num<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; displaySerial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> readEncoderA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HIGH<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; encoderPos <span style="color: #339933;">+=</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinB<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> LOW<span style="color: #009900;">&#41;</span><span style="color: #339933;">?</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; encoderPos <span style="color: #339933;">+=</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinB<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HIGH<span style="color: #009900;">&#41;</span><span style="color: #339933;">?</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #993333;">void</span> readEncoderB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinB<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HIGH<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; encoderPos <span style="color: #339933;">+=</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> HIGH<span style="color: #009900;">&#41;</span><span style="color: #339933;">?</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; encoderPos <span style="color: #339933;">+=</span> <span style="color: #009900;">&#40;</span>digitalRead<span style="color: #009900;">&#40;</span>encoderPinA<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> LOW<span style="color: #009900;">&#41;</span><span style="color: #339933;">?</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">:</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2010/12/understanding-a-mouse-scroll-wheel/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Home Temperature Monitor</title>
		<link>http://www.stevekamerman.com/2010/12/home-temperature-monitor/</link>
		<comments>http://www.stevekamerman.com/2010/12/home-temperature-monitor/#comments</comments>
		<pubDate>Sun, 05 Dec 2010 19:47:15 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Random Projects]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[cacti]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=226</guid>
		<description><![CDATA[Yes, I&#8217;m still on the electronics kick. This is something I&#8217;ve been wanting to do as part of a complete home automation project down the road: monitor the temperature of the different rooms / zones in my house. Now that I&#8217;ve got a few Arduinos laying around and some thermal probes (thermistors) from some broken [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, I&#8217;m still on the electronics kick. This is something I&#8217;ve been wanting to do as part of a complete home automation project down the road: monitor the temperature of the different rooms / zones in my house. Now that I&#8217;ve got a few Arduinos laying around and some thermal probes (thermistors) from some broken Radio Shack temperature displays, I&#8217;ve got the hardware necessary to make it happen! I first installed the thermal probes in the ceilings of the master bedroom, my daughter&#8217;s bedroom and our living room in locations that I thought were least affected by vents, fans, lights and other sources of heat. Here&#8217;s a picture of the probe in my living room:</p>
<div id="attachment_227" class="wp-caption aligncenter" style="width: 489px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/12/TempMonitor_Thermistor.jpg"><img class="size-full wp-image-227" title="Thermal Probe in my Living Room" src="http://www.stevekamerman.com/wp-content/uploads/2010/12/TempMonitor_Thermistor.jpg" alt="" width="479" height="529" /></a><p class="wp-caption-text">Thermal Probe in my Living Room</p></div>
<p>Next, I connected the three probes to my Arduino&#8217;s Analog Inputs using the thermistors as voltage dividers between +5VDC and Ground.  In order to detect the temperatures and make them accessible via the Arduino&#8217;s serial interface, I used a few examples on the Arduino site as the basis for this program, which waits for a character to be sent to the serial port, then outputs the temperatures:</p>
<div class="codecolorer-container c geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;math.h&gt;</span><br />
<span style="color: #666666; font-style: italic;">//Schematic:</span><br />
<span style="color: #666666; font-style: italic;">// [Ground] ---- [10k-Resister] -------|------- [Thermistor] ---- [+5v]</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |</span><br />
<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Analog Pin 0</span><br />
<br />
<span style="color: #993333;">double</span> Thermistor<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> RawADC<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// Inputs ADC Value from Thermistor and outputs Temperature in Celsius</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// &nbsp;requires: include &lt;math.h&gt;</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// Utilizes the Steinhart-Hart Thermistor Equation:</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp;Temperature in Kelvin = 1 / {A + B[ln(R)] + C[ln(R)]^3}</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// &nbsp; &nbsp;where A = 0.001129148, B = 0.000234125 and C = 8.76741E-08</span><br />
&nbsp;<span style="color: #993333;">long</span> Resistance<span style="color: #339933;">;</span> &nbsp;<span style="color: #993333;">double</span> Temp<span style="color: #339933;">;</span><br />
&nbsp;Resistance<span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">10240000</span><span style="color: #339933;">/</span>RawADC<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">10000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;Temp <span style="color: #339933;">=</span> log<span style="color: #009900;">&#40;</span>Resistance<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp;Temp <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span> <span style="color: #339933;">/</span> <span style="color: #009900;">&#40;</span><span style="color:#800080;">0.001129148</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color:#800080;">0.000234125</span> <span style="color: #339933;">*</span> Temp<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color:#800080;">0.0000000876741</span> <span style="color: #339933;">*</span> Temp <span style="color: #339933;">*</span> Temp <span style="color: #339933;">*</span> Temp<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// Convert Kelvin to Celsius</span><br />
&nbsp;Temp <span style="color: #339933;">=</span> Temp <span style="color: #339933;">-</span> <span style="color:#800080;">273.15</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #666666; font-style: italic;">// Convert to Fahrenheit</span><br />
&nbsp;Temp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Temp <span style="color: #339933;">*</span> <span style="color:#800080;">9.0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span> <span style="color:#800080;">5.0</span> <span style="color: #339933;">+</span> <span style="color:#800080;">32.0</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #b1b100;">return</span> Temp<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> printDouble<span style="color: #009900;">&#40;</span><span style="color: #993333;">double</span> val<span style="color: #339933;">,</span> byte precision<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; Serial.<span style="color: #202020;">print</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#40;</span>val<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp;<span style="color: #666666; font-style: italic;">//prints the int part</span><br />
&nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> precision <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// print the decimal point</span><br />
&nbsp; &nbsp; <span style="color: #993333;">unsigned</span> <span style="color: #993333;">long</span> frac<span style="color: #339933;">,</span> mult <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; byte padding <span style="color: #339933;">=</span> precision <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>precision<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> mult <span style="color: #339933;">*=</span><span style="color: #0000dd;">10</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>val <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> frac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>val <span style="color: #339933;">-</span> <span style="color: #993333;">int</span><span style="color: #009900;">&#40;</span>val<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> mult<span style="color: #339933;">;</span> <span style="color: #b1b100;">else</span> frac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#40;</span>val<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> val<span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> mult<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">unsigned</span> <span style="color: #993333;">long</span> frac1 <span style="color: #339933;">=</span> frac<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>frac1 <span style="color: #339933;">/=</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span> padding<span style="color: #339933;">--;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>padding<span style="color: #339933;">--</span><span style="color: #009900;">&#41;</span> Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;0&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span>frac<span style="color: #339933;">,</span>DEC<span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #993333;">void</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; Serial.<span style="color: #202020;">begin</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">115200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #339933;">#define ZoneOne 1 &nbsp; // Analog Pin 0</span><br />
<span style="color: #339933;">#define ZoneTwo 2 &nbsp; // Analog Pin 1</span><br />
<span style="color: #339933;">#define ZoneThree 3 &nbsp; // Analog Pin 2</span><br />
<br />
<span style="color: #993333;">double</span> temp<span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> inByte <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> sensorDelay <span style="color: #339933;">=</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #993333;">void</span> loop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>Serial.<span style="color: #202020;">available</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; inByte <span style="color: #339933;">=</span> Serial.<span style="color: #202020;">read</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Zone1:&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; printDouble<span style="color: #009900;">&#40;</span>Thermistor<span style="color: #009900;">&#40;</span>analogRead<span style="color: #009900;">&#40;</span>ZoneOne<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; delay<span style="color: #009900;">&#40;</span>sensorDelay<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Zone2:&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; printDouble<span style="color: #009900;">&#40;</span>Thermistor<span style="color: #009900;">&#40;</span>analogRead<span style="color: #009900;">&#40;</span>ZoneTwo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; delay<span style="color: #009900;">&#40;</span>sensorDelay<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Zone3:&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; printDouble<span style="color: #009900;">&#40;</span>Thermistor<span style="color: #009900;">&#40;</span>analogRead<span style="color: #009900;">&#40;</span>ZoneThree<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot; &quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>I had an old laptop with a dead battery that I wasn&#8217;t using, so I loaded it with Ubuntu 10.10 x64, Apache, MySQL, PHP and Cacti and put it up in the attic, connected to the Arduino via USB.  I went through the painfully dry Cacti Documentation and wrote a custom Perl script that Cacti uses to poll the Arduino for temperatures:</p>
<div class="codecolorer-container perl geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="perl codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span><br />
<br />
<span style="color: #000000; font-weight: bold;">use</span> Device<span style="color: #339933;">::</span><span style="color: #006600;">SerialPort</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">use</span> Time<span style="color: #339933;">::</span><span style="color: #006600;">HiRes</span> <span style="color: #000066;">qw</span><span style="color: #009900;">&#40;</span> usleep <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># Serial Settings</span><br />
<span style="color: #0000ff;">$PORT</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;/dev/ttyUSB0&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span> <span style="color: #339933;">=</span> Device<span style="color: #339933;">::</span><span style="color: #006600;">SerialPort</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">new</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$PORT</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;Can't Open $PORT: $!&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">baudrate</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">115200</span><span style="color: #009900;">&#41;</span> &nbsp; <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;failed setting baudrate&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">parity</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;none&quot;</span><span style="color: #009900;">&#41;</span> &nbsp; &nbsp;<span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;failed setting parity&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">databits</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">8</span><span style="color: #009900;">&#41;</span> &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;failed setting databits&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">handshake</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;none&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;failed setting handshake&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">write_settings</span> &nbsp; &nbsp;<span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;no settings&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">read_const_time</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">write</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;x&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$ob</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">read</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">chomp</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;$_<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">undef</span> <span style="color: #0000ff;">$ob</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">exit</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; usleep<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1000</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000066;">undef</span> <span style="color: #0000ff;">$ob</span><span style="color: #339933;">;</span></div></div>
<div id="attachment_228" class="wp-caption alignleft" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/12/HouseTempGraph.png"><img class="size-medium wp-image-228" title="Cacti Graph of my Home's Temperature" src="http://www.stevekamerman.com/wp-content/uploads/2010/12/HouseTempGraph-300x210.png" alt="" width="300" height="210" /></a><p class="wp-caption-text">Cacti Graph of my Home&#39;s Temperature</p></div>
<p>Lastly, I put a nice graph together that shows a comparison of the three temperatures over time, with a composite average of all three.  Now I can see that my daughter&#8217;s room spikes to nearly 90 deg when the heat comes on &#8211; ouch!  Using this data I am better able to adjust the vents in each room to keep the temperature consistent throughout the house.  Next I want to take one of those cheap LCD picture displays and tie it to the Cacti graph and put it near the thermostat so I can think twice about turning on the heat or AC!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2010/12/home-temperature-monitor/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Arduino Parking Assistant</title>
		<link>http://www.stevekamerman.com/2010/11/arduino-parking-assistant/</link>
		<comments>http://www.stevekamerman.com/2010/11/arduino-parking-assistant/#comments</comments>
		<pubDate>Sun, 21 Nov 2010 21:05:32 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Random Projects]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[LinkedIn]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=204</guid>
		<description><![CDATA[I recently bought  a 2010 Honda Accord Crosstour and was shocked to see how large it really is in my garage!  When it&#8217;s parked correctly, I have about 18 inches behind it and 26 in front of it, when it&#8217;s not, I can&#8217;t shut the garage door, or I can&#8217;t walk in front of it. [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignleft" style="width: 370px"><a href="http://www.sparkfun.com/products/9950"><br />
<img class=" " title="Arduino" src="http://static.sparkfun.com/images/products/00666-03-L.jpg" alt="Arduino Duemilanove" width="360" height="360" /></a><p class="wp-caption-text">Arduino Duemilanove</p></div>
<p>I recently bought  a 2010 Honda Accord Crosstour and was shocked to see how large it really is in my garage!  When it&#8217;s parked correctly, I have about 18 inches behind it and 26 in front of it, when it&#8217;s not, I can&#8217;t shut the garage door, or I can&#8217;t walk in front of it.  As a fun project, I decided to make a device that would let me know when I&#8217;m exactly in position!</p>
<p>Enter the Arduino.  The Arduino is an open-source microcontroller board that can programmed with a C-like language called Processing via USB.  It&#8217;s a great way to leverage your programming skills to interact with the world around you.  In order to help me park my car, I used an ultrasonic range finder from Radio Shack called the PING))) Parallax.  This device has a transmitter, receiver and a few processing chips on it.  It sends out a signal and listens for the echo, then returns the total time duration in microseconds.  Since sound travels one inch in about 74 microseconds, you can take this time and divide it by 74 to get the total distance that the sound traveled, then divide it by 2 since you only care about the distance <em>too</em> the object, not its return trip.  My plan was to put the range finder in the back of garage and use three LEDs to show me if my car was too far, too close or parked just the right distance away.  I wrote the code below to get a distance reading every 1.5 seconds, and if the distance changed since the last time it was polled, my car (or something in the garage) must have moved.  In this case, the Arduino starts polling for changes every 100ms and lights up an orange LED if it is over 26 inches away, a green LED if it is between 26 and 20 inches and a red LED if it is under 20 inches away.  I mounted the LEDs on a piece of aluminum and attached it to the wall so I could see it from my car while I&#8217;m parking.  After I&#8217;m finished parking and the Arduino sees that nothing has moved in over 10 seconds, it turns all the LEDs off and starts polling at 1.5 seconds again.  Simple and effective!</p>
<div class="codecolorer-container cpp geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666;">// PING))) Sensor</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> pingPin <span style="color: #000080;">=</span> <span style="color: #0000dd;">7</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// Indicator LEDs</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> tooFarPin <span style="color: #000080;">=</span> <span style="color: #0000dd;">13</span><span style="color: #008080;">;</span> &nbsp; &nbsp; <span style="color: #666666;">// Orange LED</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> justRightPin <span style="color: #000080;">=</span> <span style="color: #0000dd;">12</span><span style="color: #008080;">;</span> &nbsp;<span style="color: #666666;">// Green LED</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> tooClosePin <span style="color: #000080;">=</span> <span style="color: #0000dd;">11</span><span style="color: #008080;">;</span> &nbsp; <span style="color: #666666;">// Red LED</span><br />
<br />
<span style="color: #666666;">// Distance Thresholds</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> outOfRange <span style="color: #000080;">=</span> <span style="color: #0000dd;">108</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> tooFar <span style="color: #000080;">=</span> <span style="color: #0000dd;">26</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> tooClose <span style="color: #000080;">=</span> <span style="color: #0000dd;">20</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #666666;">// Sensor Polling Delay (ms)</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> idleSenseDelay <span style="color: #000080;">=</span> <span style="color: #0000dd;">1500</span><span style="color: #008080;">;</span><br />
<span style="color: #666666;">// High-Speed Polling Timeout</span><br />
<span style="color: #0000ff;">const</span> <span style="color: #0000ff;">int</span> idleTimeout <span style="color: #000080;">=</span> <span style="color: #0000dd;">10000</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">int</span> senseDelay <span style="color: #000080;">=</span> <span style="color: #0000dd;">1500</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #ff0000; font-style: italic;">/* &nbsp;States<br />
0 = Out of range (no car present)<br />
1 = Too Far<br />
2 = Just Right<br />
3 = Too Close<br />
*/</span><br />
<span style="color: #0000ff;">int</span> currentState <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">int</span> lastState <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">unsigned</span> <span style="color: #0000ff;">long</span> lastDistanceChange<span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">long</span> distance<span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">void</span> setup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; lastDistanceChange <span style="color: #000080;">=</span> millis<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; pinMode<span style="color: #008000;">&#40;</span>tooFarPin, OUTPUT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooFarPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; pinMode<span style="color: #008000;">&#40;</span>justRightPin, OUTPUT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>justRightPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; pinMode<span style="color: #008000;">&#40;</span>tooClosePin, OUTPUT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooClosePin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">void</span> loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">long</span> duration, newDistance<span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666;">// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:</span><br />
&nbsp; &nbsp; pinMode<span style="color: #008000;">&#40;</span>pingPin, OUTPUT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>pingPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; delayMicroseconds<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>pingPin, HIGH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; delayMicroseconds<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">5</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>pingPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666;">// The same pin is used to read the signal from the PING))): a HIGH</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// pulse whose duration is the time (in microseconds) from the sending</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// of the ping to the reception of its echo off of an object.</span><br />
&nbsp; &nbsp; pinMode<span style="color: #008000;">&#40;</span>pingPin, INPUT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; duration <span style="color: #000080;">=</span> pulseIn<span style="color: #008000;">&#40;</span>pingPin, HIGH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; newDistance <span style="color: #000080;">=</span> duration <span style="color: #000040;">/</span> <span style="color: #0000dd;">74</span> <span style="color: #000040;">/</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>distance <span style="color: #000040;">!</span><span style="color: #000080;">=</span> newDistance<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666;">// Something is moving, increase polling rate</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; lastDistanceChange <span style="color: #000080;">=</span> millis<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; senseDelay <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; distance <span style="color: #000080;">=</span> newDistance<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; currentState <span style="color: #000080;">=</span> getState<span style="color: #008000;">&#40;</span>distance<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>currentState <span style="color: #000040;">!</span><span style="color: #000080;">=</span> lastState<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666;">// State changed</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; indicateState<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>senseDelay <span style="color: #000040;">!</span><span style="color: #000080;">=</span> idleSenseDelay <span style="color: #000040;">&amp;&amp;</span> <span style="color: #008000;">&#40;</span>millis<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">-</span> lastDistanceChange <span style="color: #000080;">&gt;</span> idleTimeout<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666;">// Idle Timeout has Passed, turn off LEDs</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooFarPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>justRightPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooClosePin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; senseDelay <span style="color: #000080;">=</span> idleSenseDelay<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; lastState <span style="color: #000080;">=</span> currentState<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; delay<span style="color: #008000;">&#40;</span>senseDelay<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">int</span> getState<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">long</span> distance<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>distance <span style="color: #000080;">&gt;=</span> outOfRange<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>distance <span style="color: #000080;">&gt;=</span> tooFar<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>distance <span style="color: #000080;">&gt;=</span> tooClose<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span><br />
<br />
<span style="color: #0000ff;">void</span> indicateState<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666;">// Turn off the LEDs that are on</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>lastState<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooFarPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>justRightPin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooClosePin, LOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>currentState<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooFarPin, HIGH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">2</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>justRightPin, HIGH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">3</span><span style="color: #008080;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; digitalWrite<span style="color: #008000;">&#40;</span>tooClosePin, HIGH<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span></div></div>
<p>And here it is, the finished product!</p>
<div id="attachment_221" class="wp-caption alignleft" style="width: 310px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/11/ArduinoParkAssist.png"><img class="size-medium wp-image-221" title="Fritzing Sketch" src="http://www.stevekamerman.com/wp-content/uploads/2010/11/ArduinoParkAssist-300x220.png" alt="" width="300" height="220" /></a><p class="wp-caption-text">Fritzing Sketch</p></div>
<div id="attachment_210" class="wp-caption alignleft" style="width: 310px"><a href="http://www.parallax.com/tabid/768/ProductID/92/Default.aspx"><img class="size-medium wp-image-210 " title="PING))) Parallax" src="http://www.stevekamerman.com/wp-content/uploads/2010/11/100_2179-300x225.jpg" alt="" width="300" height="225" /></a><p class="wp-caption-text">PING))) Parallax</p></div>
<div id="attachment_211" class="wp-caption alignleft" style="width: 235px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/11/100_2180.jpg"><img class="size-medium wp-image-211" title="Arduino ParkAssist" src="http://www.stevekamerman.com/wp-content/uploads/2010/11/100_2180-225x300.jpg" alt="" width="225" height="300" /></a><p class="wp-caption-text">Arduino ParkAssist</p></div>
<div id="attachment_212" class="wp-caption alignleft" style="width: 244px"><a href="http://www.stevekamerman.com/wp-content/uploads/2010/11/100_2181.jpg"><img class="size-medium wp-image-212" title="LED Indicator" src="http://www.stevekamerman.com/wp-content/uploads/2010/11/100_2181-234x300.jpg" alt="" width="234" height="300" /></a><p class="wp-caption-text">LED Indicator</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2010/11/arduino-parking-assistant/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Just Released: Tera-WURFL 2.1.3 Stable</title>
		<link>http://www.stevekamerman.com/2010/09/just-released-tera-wurfl-2-1-3-stable/</link>
		<comments>http://www.stevekamerman.com/2010/09/just-released-tera-wurfl-2-1-3-stable/#comments</comments>
		<pubDate>Sat, 18 Sep 2010 21:44:54 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mobile Device Detection]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[Tera-WURFL]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=195</guid>
		<description><![CDATA[I&#8217;ve been delaying the Tera-WURFL 2.1.3 release since mid-July because of the large number of feature requests and improvements coming in, but the time has come to release it. I&#8217;m still waiting for the unit test code to stabilize a bit before I put it into the tree, but if you are interested in it, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been delaying the Tera-WURFL 2.1.3 release since mid-July because of the large number of feature requests and improvements coming in, but the time has come to release it.  I&#8217;m still waiting for the unit test code to stabilize a bit before I put it into the tree, but if you are interested in it, <a href="http://github.com/kamermans" target="_blank">follow me on GitHub</a> and you should see it soon.</p>
<p>Here&#8217;s a short list of features and improvements in Tera-WURFL 2.1.3:</p>
<ul>
<li>Native support for MongoDB</li>
<li>Better support and performance for Microsoft SQL Server</li>
<li>Command line administration utility</li>
<li>Better webservice performance using JSON</li>
<li>Better Python client with JSON support</li>
<li>Improved performance in MySQL5</li>
<li>Device Images are available via the PHP webservice client</li>
<li>Loaded WURFL version is now tracked in the DB</li>
<li>MySQL connector allows for alternate port</li>
<li>Better overall detection</li>
</ul>
<p>If you&#8217;re a command line junky like me, I think you&#8217;ll really like the CLI administration tool.  To use it, just go to your <strong>Tera-WURFL/admin/</strong> directory and type <strong>php cmd_line_admin.php</strong></p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># php cmd_line_admin.php<br />
<br />
Tera-WURFL Stable 2.1.3<br />
The command line WURFL updater for Tera-WURFL<br />
Loaded WURFL: www.wurflpro.com - 2010-09-09 04:08:06<br />
Last Updated: Wed, 15 Sep 2010 20:38:59 -0500<br />
---------------------------------------<br />
Usage: php cmd_line_admin.php [OPTIONS]<br />
<br />
Option &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Meaning<br />
--help &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Show this message<br />
--update= &nbsp; The source of the WURFL file:<br />
Update from your local wurfl.xml file:<br />
--update=local<br />
Update from wurfl.sourceforge.net:<br />
--update=remote<br />
--clearCache &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Clear the device cache<br />
--rebuildCache &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Rebuild the device cache by redetecting all<br />
cached devices using the current WURFL<br />
--stats &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Show statistics about the Tera-WURFL Database</div></div>
<p>You can update the WURFL by passing the <strong>&#8212;-update=local</strong> or <strong>&#8211;update=remote</strong> parameter (crontab will like this):</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># php cmd_line_admin.php --update=remote<br />
Downloading WURFL from http://downloads.sourceforge.net/project/wurfl/WURFL/latest/wurfl-latest.zip ...<br />
<br />
done (/testtw/2.1.3/mongo/data/wurfl.xml: 14.80 MB [897.30 KB compressed])<br />
Downloaded in 4.6609511375427 sec @ 1.58 Mbps<br />
<br />
Database Update OK<br />
Total Time: 22.146492004395<br />
Parse Time: 3.8051941394806 (TeraWurflXMLParser_SimpleXML)<br />
Validate Time: 0.024373054504395<br />
Sort Time: 1.2780990600586<br />
Patch Time: 0.50953578948975<br />
Database Time: 8.9265999794006<br />
Cache Rebuild Time: 7.6026899814606<br />
Number of Queries: 2456<br />
PHP Memory Usage: 54.49 MB<br />
--------------------------------<br />
WURFL Version: www.wurflpro.com - 2010-09-17 15:50:54 (Fri Sep 17 15:56:32 -0500 2010)<br />
WURFL Devices: 13687<br />
PATCH New Devices: 39<br />
PATCH Merged Devices: 1</div></div>
<p>You can also see stats on the Tera-WURFL database:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"># php cmd_line_admin.php --stats<br />
Tera-WURFL Stable 2.1.3<br />
Database Type: MongoDB (ver MongoDB 1.6.2)<br />
Loaded WURFL: www.wurflpro.com - 2010-09-17 15:50:54<br />
Last Updated: Sat, 18 Sep 2010 15:28:05 -0500<br />
Config File: /testtw/2.1.3/mongo/TeraWurflConfig.php<br />
---------- Table Stats -----------<br />
<br />
&gt; MERGE<br />
Rows: &nbsp; &nbsp;13726<br />
Devices: 6229<br />
Size: &nbsp; &nbsp;30.00 MB<br />
<br />
&gt; CACHE<br />
Rows: &nbsp; &nbsp;522<br />
Size: &nbsp; &nbsp;1.23 MB</div></div>
<p>Head over to <a href="http://www.tera-wurfl.com">Tera-WURFL.com</a> and give <a href="http://www.tera-wurfl.com/wiki/index.php/Downloads#Current_Version">version 2.1.3</a> a try!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2010/09/just-released-tera-wurfl-2-1-3-stable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tera-WURFL 2.1.3 Database Roundup</title>
		<link>http://www.stevekamerman.com/2010/09/tera-wurfl-2-1-3-database-roundup/</link>
		<comments>http://www.stevekamerman.com/2010/09/tera-wurfl-2-1-3-database-roundup/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 17:37:12 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mobile Device Detection]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[LinkedIn]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[Tera-WURFL]]></category>

		<guid isPermaLink="false">http://www.stevekamerman.com/?p=188</guid>
		<description><![CDATA[I&#8217;ve been working hard on Tera-WURFL 2.1.3 lately.  I&#8217;ve been meaning to release it for over a month now, the problem is that I just keep finding improvements to make.  Since Tera-WURFL&#8217;s development is now hosted on GitHub, you can always see what I&#8217;m doing and grab a copy for yourself.  New in version 2.1.3 [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working hard on Tera-WURFL 2.1.3 lately.  I&#8217;ve been meaning to release it for over a month now, the problem is that I just keep finding improvements to make.  Since Tera-WURFL&#8217;s development is now <a title="Tera-WURFL on GitHub" href="http://github.com/kamermans/Tera-WURFL" target="_blank">hosted on GitHub</a>, you can always see what I&#8217;m doing and grab a copy for yourself.  New in version 2.1.3 is a <a title="MongoDB" href="http://www.mongodb.org" target="_blank">MongoDB</a> Database Connector.  I keep getting pounded by people about NoSQL and I haven&#8217;t given it a fair chance until now.  Simon Harris from <a title="PointBeing.net" href="http://www.pointbeing.net" target="_blank">www.pointbeing.net</a> was nice enough to contribute the initial MongoDB connector, and I&#8217;ve spent a few days working on it and testing it against MySQL5.  At first the performance seems outstanding &#8211; almost double that of MySQL5 &#8211; but I noticed some inconsistencies with my tests, so I built a benchmarking script and an comparison tool that automatically tests one installation against another and checks for consistency.  I&#8217;ve tested three different database connectors against each other and my memcached-based Tera-WURFL Enterprise.</p>
<h2>Testing Setup</h2>
<p>In order to test the Database Connectors, I brought up a virtual machine on an under-utilized ESXi server (dual 6-core Opterons and 32GB FB-DDR3).</p>
<p>Virtual Machine Specs:</p>
<ul>
<li> 4x Opteron 2.2GHz cores</li>
<li>12GB FB-DDR3 RAM</li>
<li>20GB of storage on a SAS array over MPIO iSCSI</li>
<li>Ubuntu Server 10.04.1</li>
<li>MySQL 5.1</li>
<li>MongoDB 1.7.0</li>
</ul>
<p>This machine doesn&#8217;t have extremely fast CPUs, just a lot of them.  At any rate, the specs were consistent so I was able to get a reasonable test result.  In order to test the performance of the DBs, I ran about 66,000 unique user agents (these are UAs that are not easily matched and create a lot of DB load) through the connectors and measured the rate at which they detected them.</p>
<h2>The results</h2>
<p>The following results are the average speed at which the different DB Connectors detected the test user agents.  The two graphs show the difference between uncached and cached detections.  For each database, I ran the test with the all the WURFL capabilities loaded (blue) and with only ['product_info']['is_wireless_device'] loaded (red) to get an idea of the performance benefit of using Tera-WURFL&#8217;s CAPABILITY_FILTER option.</p>
<p><img class="alignnone size-full wp-image-189" title="uncached_detection_2.1.3" src="http://www.stevekamerman.com/wp-content/uploads/2010/09/uncached_detection_2.1.3.png" alt="Uncached Device Detection Performance in Tera-WURFL 2.1.3" width="640" height="397" /></p>
<p>* note: memcached is not capable of serving uncached detections, so it is left out of this test.</p>
<p><img class="alignnone size-full wp-image-190" title="cached_detection_2.1.3" src="http://www.stevekamerman.com/wp-content/uploads/2010/09/cached_detection_2.1.3.png" alt="Cached Device Detection Performance in Tera-WURFL 2.1.3" width="640" height="397" /></p>
<h2>Conclusion</h2>
<p>I was very surprised by these results so I tested them repeatedly just to be sure.  I was so excited that MongoDB would be the clear winner here, but it just isn&#8217;t the case for uncached detections.  Mongo did fare well when serving the cached full capabilities &#8211; 63% higher than MySQL5.  MS SQL Server 2005 was particularly painful to test.  By comparison, MongoDB took about 8 minutes to churn though all 66,000 user agents, but my initial test with MS SQL Server was 3 hours and 8 minutes.  Since I tested all the other connectors on Ubuntu Server, and the MS SQL Server connector requires Microsoft&#8217;s PHP SQL Server Driver, I had to run the tests on a different VM.  On this VM I was getting between 1-3 uncached detections per second, but I moved the testing to my development laptop (2.8GHz Core 2 Duo, 4GB RAM and a Samsung 250GB SSD) and was able to achieve better results.  MySQL fared very well overall and remains at the top of the list.  I have not mentioned the MySQL Nested Set connector before, but it&#8217;s been included in Tera-WURFL for a couple versions now.  It just extends the MySQL5 connector and adds right and left values to all of the devices in the WURFL so it can return the complete fallback tree for a given WURFL ID in a single indexed query.  Unfortunately, this seems to provide a negligible improvement in speed.  I would still recommend it for environments where the webserver is on a different host than the database.</p>
<p>Look for Tera-WURFL 2.1.3 to be released within a couple weeks.  I&#8217;m trying to get some unit-testing code integrated before I release it.</p>
<p>*** UPDATE ***</p>
<p>I&#8217;ve retested MongoDB and MySQL5 again on my production server against a typical distribution of 44887 user agents.  The performance was much better, but the MySQL &lt;-&gt; MongoDB performance was proportional to the first results:</p>
<p><center></p>
<table border="1">
<col width="50"></col>
<col width="101"></col>
<col width="108"></col>
<col width="101"></col>
<col width="108"></col>
<tr height="20">
<td width="50" height="20"></td>
<td style="text-align: center;" colspan="2" width="209">Uncached</td>
<td style="text-align: center;" colspan="2" width="209">Cached</td>
</tr>
<tr height="20">
<td height="20"></td>
<td>All&nbsp;Capabilities</td>
<td>Min&nbsp;Capabilities</td>
<td>All&nbsp;Capabilities</td>
<td>Min&nbsp;Capabilities</td>
</tr>
<tr height="20">
<td style="text-align: right;" height="20">MySQL</td>
<td align="right">303</td>
<td align="right">510</td>
<td align="right">2735</td>
<td align="right">7740</td>
</tr>
<tr height="20">
<td style="text-align: right;" height="20">MongoDB</td>
<td align="right">195</td>
<td align="right">255</td>
<td align="right">3182</td>
<td align="right">6154</td>
</tr>
</table>
<p></center></p>
]]></content:encoded>
			<wfw:commentRss>http://www.stevekamerman.com/2010/09/tera-wurfl-2-1-3-database-roundup/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

