<?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>GigaMegaBlog</title>
	<atom:link href="http://www.gigamegablog.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gigamegablog.com</link>
	<description>Powered by GigaMegaWatts</description>
	<lastBuildDate>Sat, 05 May 2012 19:37:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Beaglebone Coding 101: Buttons and PWM</title>
		<link>http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-and-pwm/</link>
		<comments>http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-and-pwm/#comments</comments>
		<pubDate>Sat, 17 Mar 2012 03:18:25 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Beaglebone]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1177</guid>
		<description><![CDATA[Updated Mar 20: Corrected the settings in the &#8220;Controlling PWM Using the File System&#8221; section. Updated Mar 21: Corrected the max PWM frequency &#8211; definitely not 250 Hz! Updated Mar 25: Correct PWM settings example: set duty_cycle to 0 before &#8230; <a href="http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-and-pwm/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>Updated Mar 20: Corrected the settings in the &#8220;Controlling PWM Using the File System&#8221; section.<br />
Updated Mar 21: Corrected the max PWM frequency &#8211; definitely not 250 Hz!<br />
Updated Mar 25: Correct PWM settings example: set duty_cycle to 0 before changing the PWM frequency. </em></p>
<p><em>Update May 5: Wherefore art thou, PWM?  <strong>In kernel version 3.2.14 (released in April), PWM disappeared from the file system.</strong>  I haven&#8217;t read an explanation of why it was removed, or when it will return.  If you need to access the PWM registers through the file system, my advice is to stick with kernel version 3.2.13.  </em></p>
<p><em>Depending on which image you are running, you may find the 3.2.13 kernel in your /boot folder.  If not, you can download it from <a href="http://www.gigamegablog.com/docs/uImage-3.2.13" target="_blank">http://www.gigamegablog.com/<wbr>docs/uImage-3.2.13</wbr></a> (md5sum is </em><wbr><em>1f62bc400c76a4b174c5ae7ba50afe</em><wbr><em>9e). Copy uImage-3.2.13 to uImage on your boot partition, as described in the <a href="#EnablingPWM">Enabling PWM Support in the Kernel</a> section below.</em></wbr></wbr></p>
<p>My earlier articles [<a href="http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/">1</a>, <a href="http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/">2</a>] on Beaglebone coding ignored one of the basics: digital input.  The main reason I skipped it is that the I only knew how to handle input by polling, and polling is lame.  I decided to wait until I had some Python code to handle input using interrupts, and write about that instead.</p>
<p>Well, here we are, a couple of months later, and &#8230; um &#8230; it turns out that polling is cool.  Interrupts are lame.  You know who uses interrupts?  Microsoft!  Need I say more?</p>
<p>I&#8217;ll also cover a relatively new addition to the Beaglebone&#8217;s kernel, PWM.</p>
<h2>Digital Input</h2>
<p>The Beaglebone has a number of pins that default to GPIO mode, and all of them are initially configured for input, not output: the receive feature is enabled, and the GPIO direction flag is set to &#8220;in&#8221;.</p>
<p>If you take a look at the pin mux settings for these pins, you&#8217;ll notice they are similar, but not the same.</p>
<p>For example, here is Port 8 Pin 3:</p>
<pre>root:/sys/kernel/debug/omap_mux# cat gpmc_ad6
 name: gpmc_ad6.gpio1_6 (0x44e10818/0x818 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: gpmc_ad6 | mmc1_dat6 | NA | NA | NA | NA | NA | gpio1_6</pre>
<p>And here is Port 8 Pin 11:</p>
<pre>root:/sys/kernel/debug/omap_mux# cat gpmc_ad13
 name: gpmc_ad13.gpio1_13 (0x44e10834/0x834 = 0x0027), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: gpmc_ad13 | lcd_data21 | mmc1_dat5 | mmc2_dat1 |
 NA | NA | NA | gpio1_13</pre>
<p>Both pins are configured for Mode 7 (GPIO mode), but Pin 3&#8242;s mux setting is x37, and Pin 11&#8242;s is x27.</p>
<p>From the mux register description in the AM335x Technical Reference, we know that this means both pins are configured for input (Received enabled), but Pin 3 is set to use pullup resistors, and Pin 11 is set to use pulldown resistors.</p>
<p><img class="aligncenter" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-19-44-PM.jpg" alt="" width="624" height="352" /></p>
<p>By default, then, Pin 3 reads HIGH when nothing is connected to it, and Pin 11 reads LOW.</p>
<p>Sure enough, if we export the pin, then look at its value, we see that it is a 1 for Pin 3:</p>
<pre>root:/sys/class/gpio# echo 38 &gt; export
root:/sys/class/gpio# cd gpio38/
root:/sys/class/gpio/gpio38# cat value
 1</pre>
<p>&#8230;and a zero for Pin 11:</p>
<pre>root:/sys/class/gpio# echo 45 &gt; export
 root:/sys/class/gpio# cd gpio45
 root:/sys/class/gpio/gpio45# cat value
 0</pre>
<p>I have no idea why these default settings were chosen: possibly to give creators of capes more plug-and-play flexibility, possibly to give me yet another opportunity to write about mux settings, or maybe they just couldn&#8217;t decide.  However, when you hook up a circuit you really do have to make a choice.</p>
<p>With Pin 3&#8242;s setting, a button (or any other digital input device), needs to connect to Ground when the button is pressed.  If you connect it to a voltage pin, nothing good will come of it, but quite possibly a lot of bad.</p>
<p>The GPIO pins on the Beaglebone are quite fragile, compared to the <a href="http://www.arduino.cc">Arduino</a>&#8216;s or <a href="http://www.netduino.com">Netduino</a>&#8216;s.   The Arduino is happy with 5V of input, but can also work with 3.3V.  The Netduino prefers 3.3V, but is 5V &#8220;tolerant&#8221;, meaning you can get away with it.  The Beaglebone, on the other hand, is decidedly intolerant of 5V.  Hook it up to 5V, even for a split second, and it will die.  I wish I could say that I learned this by reading about it, but you can trust me on this one.</p>
<p>The GPIO pins are also more delicate than the Arduino when it comes to current.</p>
<p>According to <a href="http://groups.google.com/group/beaglebone/browse_thread/thread/768b0a98413bc6ca/4c58adcb376fe38f?show_docid=4c58adcb376fe38f">this post</a>  by Beaglebone hardware designer Gerald Coley, the recommended max output current through a pin is 4-6 mA, and the max input current is 8 mA.  On the Arduino, it is 40 mA.  (Based on my own experience, the Beaglebone seems to be tolerant of higher currents: I&#8217;ve measured 60 mA coming out of a GPIO pin.  That was a different Beaglebone than the one that died, by the way. What can I say: I&#8217;m the Michael Vick of electronics!)</p>
<p>For this reason, I think it&#8217;s safest to configure a digital input pin with a pull-up resistor, and connect the button to ground.  If you go the other way and use a pull-down resistor, be very certain you don&#8217;t accidentally hook it up to the 5V pins, and be sure to use an external resistor too &#8211; the internal pull-down resistor won&#8217;t knock down the current for you.</p>
<p>The photo below shows 2 pushbuttons connected to 2 GPIO pins: Port 9 Pins 12 (purple wire) and 15 (green wire).</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/03/HPIM1017.jpg"><img class="aligncenter size-large wp-image-1187" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/03/HPIM1017-1024x768.jpg" alt="" width="640" height="480" /></a></p>
<p>Pin 12 is configured with a pull-up resistor by default.  (Note that there is a typo in the System Reference Manual: the pin name is gpmc_ben1, not gpmc_be1n. )</p>
<pre>root:/sys/kernel/debug/omap_mux# cat gpmc_ben1
 name: gpmc_ben1.gpio1_28 (0x44e10878/0x878 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: gpmc_ben1 | mii2_col | NA | mmc2_dat3 | NA | NA | mcasp0_aclkr | gpio1_28</pre>
<p>So, the circuit for connecting a button is quite simple:</p>
<ul>
<li>Pin 12 to Button (purple wire)</li>
<li>Button to Ground</li>
</ul>
<p>When the button is pressed, the value will change from 1 to 0, making the button behave like a normally closed button (unless you actually have a normally closed button &#8211; hey, so that&#8217;s what those crazy NC buttons are for!). Be sure to account for this in your code.</p>
<pre>root:/sys/class/gpio# echo 60 &gt; export
root:/sys/class/gpio# cd gpio60
root:/sys/class/gpio/gpio60# cat value
0</pre>
<p>Pin 15 is, by default, configured to use pull-down resistors.</p>
<pre>root:/sys/kernel/debug/omap_mux# cat gpmc_a0
name: gpmc_a0.gpio1_16 (0x44e10840/0x840 = 0x0027), b NA, t NA
mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
signals: gpmc_a0 | mii2_txen | rgmii2_tctl | rmii2_txen | NA | NA | NA | gpio1_16</pre>
<p>You can, of course, change that mux setting if you want to use the same simple button circuit as with Pin 12, but for the sake of variety I&#8217;ve hooked it up as-is:</p>
<ul>
<li>Pin 15 to button</li>
<li>Button to 1K resistor</li>
<li>Resistor to 3.3V</li>
</ul>
<p>The resistor value is actually quite unimportant, as long as it&#8217;s 550R or higher.  While the Beaglebone&#8217;s GPIO pins don&#8217;t like high current, they have no problem with very low current, so 1K, 10K or 100K resistors should all work.</p>
<p>With the button connected to Pin 15 held down, we get a value of 1:</p>
<pre>root:/sys/class/gpio# echo 48 &gt; export
root:/sys/class/gpio# cd gpio48
root:/sys/class/gpio/gpio48# cat value
1</pre>
<p>As promised, I&#8217;ll be showing some code that reads the buttons using some cutting edge polling technology, but first let&#8217;s take a look at PWM.<br />
<a name="EnablingPWM"></a><br />
<h2>Enabling PWM Support in the Kernel</h2>
<p>PWM support was added to version 3.2 of the Angstrom kernel.  (I believe it was initially in 3.2.0, but I didn&#8217;t start working with it until 3.2.6.)  These kernel updates were delivered via opkg updates in February.</p>
<p>Unfortunately, while opkg delivers the new kernels, it doesn&#8217;t activate them.  That requires some manual intervention.  Let me walk you through it&#8230;</p>
<p>First, check what kernel version you are currently running</p>
<pre>root:~# uname -r
3.2.6+</pre>
<p>If you have 3.2.6+ (or later), then great, you’re ready to go.  Skip ahead to the <strong>Activating the PWM Clock</strong> section below.</p>
<p>Otherwise, you’ll need to update the kernel.</p>
<p>Check to see what kernels have been installed by opkg:</p>
<pre>root:~/tmp# ls -l /boot
total 12180
-rwxr-xr-x 1 root root      33 Feb 14 18:31 uEnv.txt
lrwxrwxrwx 1 root root      13 Mar  7 20:26 uImage -&gt; uImage-3.2.9+
-rw-r--r-- 1 root root 3042328 Jan 26 12:49 uImage-3.1.0+
-rw-r--r-- 1 root root 3135840 Feb 10 03:57 uImage-3.2.0+
-rw-r--r-- 1 root root 3137472 Feb 22 05:37 uImage-3.2.6+
-rw-r--r-- 1 root root 3140088 Mar  6 13:47 uImage-3.2.9+</pre>
<p>Right now (mid March), the latest and greatest is 3.2.9+.</p>
<p>If you don’t have the 3.2.x kernels listed in /lib/modules, then be sure to update your packages:</p>
<pre>opkg update
opkg upgrade</pre>
<p>If the opkg fairy still didn’t leave a new kernel under your pillow, then you might need to upgrade to a new image on the SD card.</p>
<p>Currently, the latest image is the February 14<sup>th</sup> “2012.02” version, which shipped with Revision 5 of the Beaglebone.  You can download it from the <a href="http://www.angstrom-distribution.org/demo/beaglebone/">Beaglebone Demo page</a>  or from <a href="http://circuitco.com/support/index.php?title=BeagleBone#Image_Files">CircuitCo </a>.  Circuitco’s page has instructions for installing the image to an SD card using Windows.  This image comes with the 3.2.5+ kernel, which supports PWM, but after giving it a spin you&#8217;ll probably want to go ahead and upgrade to the latest kernel anyway.</p>
<p>When opkg delivers the kernels, it doesn’t install them.   To start using a new kernel, you need to manually install it onto the boot partition of the SD card &#8211; you can easily do this right from the Beaglebone command prompt.</p>
<p>Begin by mounting the boot partition.  You need to use a directory as a mount point: I&#8217;m using one called tmp:</p>
<pre>root:~# mkdir tmp
root:~# mount /dev/mmcblk0p1 tmp</pre>
<p>If you look at the mount point, you should see the following files:</p>
<pre>root:~# ls tmp
Docs     LICENSE.txt  README.htm    u-boot.img  uImage
Drivers  MLO          autorun.inf  info.txt    uEnv.txt</pre>
<p>Overwrite the uImage with the latest kernel file from /boot:</p>
<pre>root:~# cp /boot/uImage-3.2.9+ tmp/uImage</pre>
<p>Unmount to make sure everything is nicely tucked away on the SD card, then reboot:</p>
<pre>root:~# umount tmp
root:~# shutdown -r now</pre>
<p>After rebooting, your system should report the new kernel:</p>
<pre>root:~# uname -r
3.2.9+</pre>
<h2>Activating the PWM Clock</h2>
<p>By default, the 3.2 kernel supports PWM, but doesn&#8217;t enable it.  If you try to use it through the file system, you&#8217;ll get &#8220;segmentation errors&#8221; and a lot of other moaning and groaning from the kernel.</p>
<p>As explained in <a href="https://groups.google.com/d/msg/beagleboard/alKf67dwMHI/b9W2igN6Lr4J">this post</a> on the Beagleboard group, the PWM clock needs to be enabled before you start using PWM.</p>
<p>The clock control register is documented in the AM335x Technical Reference Manual as follows:</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/03/PWMClockReg.jpg"><img class="aligncenter size-full wp-image-1190" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/03/PWMClockReg.jpg" alt="" width="628" height="292" /></a></p>
<p>The clock register isn&#8217;t exposed through the file system, so the only way to change this setting is by directly updating the register in memory.  Fortunately <a href="https://groups.google.com/d/msg/beagleboard/alKf67dwMHI/jPKUUvDTP6AJ">another post</a> in the Beagleboard group provided the necessary code:</p>
<p>I&#8217;ve put a copy of the code <a href="http://www.gigamegablog.com/docs/setPWMReg.py">here</a>.  To run it on the Beaglebone:</p>
<pre>root:~# opkg install python-mmap
root:~# wget http://www.gigamegablog.com/docs/setPWMReg.py
root:~# python setPWMReg.py</pre>
<p>You should see:</p>
<pre>Register CM_PER_EPWMSS1_CLKCTRL was 0x30000
Register CM_PER_EPWMSS1_CLKCTRL changed to 0x2</pre>
<p>So, the IDLEST field is initially set to Disable &#8211; the code clears that field, and set the MODULEMODE field to ENABLE.</p>
<p>Having got the clock up and running, we&#8217;re ready to control the PWM settings through the file system.</p>
<h2>Controlling PWM Using the File System</h2>
<p>There are 2 pins on Port 9 that, by default, are configured for PWM, Pins 14 and 16.  The Beaglebone System Reference manual identifies these as EHRPWM1A and EHRPWM1B; to the file system, they are ehrpwm.1:0 and ehrpwm.1:1, respectively.</p>
<p>The &#8220;EHR&#8221; part means Enhanced High Resolution.  There is also a second type of PWM pin on the Beaglebone, called ECAP, or Enhanced Capture.  The 2 types of PWM pins have similar settings exposed through the file system, as explained in the <a href="http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide">AM335x PWM Driver&#8217;s Guide</a> on the TI web site.</p>
<p>To me, the most important difference between the 2 type of PWM is that I can&#8217;t get ECAP to work.  So, let&#8217;s give the EHR PWM a whirl.</p>
<p>A good way to experiment with the PWM settings is to connect the positive pin of an LED to one of these pins, and negative pin of LED to ground.  You can safely do so without using a resistor, assuming the LED can be powered by the 3.3V that comes out of these pins.</p>
<p>A garden variety red or white LED should be fine &#8211; in the photo below, I have a red LED connected to pin 14.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/03/HPIM1028.jpg"><img class="aligncenter size-large wp-image-1191" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/03/HPIM1028-1024x768.jpg" alt="" width="640" height="480" /></a></p>
<p><em>[Updated Apr 25: Added the mux mode settings] </em></p>
<p>For starters, set the mux mode settings for the 2 pins to Mode 6 for EHRPWM:</p>
<pre>root:~# echo 6 &gt; /sys/kernel/debug/omap_mux/gpmc_a2
root:~# echo 6 &gt; /sys/kernel/debug/omap_mux/gpmc_a3</pre>
<p>There are a variety of PWM settings exposed through the file system, as described in <a href="http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide">the PWM Driver&#8217;s Guide</a>, but the two key ones are period_freq, which is the frequency in Hz, and duty_percent, the duty cycle setting.</p>
<p>The following will blink the LED slowly, once per second: <em>[Updated Mar 25: Before changing the period_freq  setting, duty_percent should be set to 0.  Otherwise, the value of duty_percent might be (silently and mysteriously) reset to another value]</em></p>
<pre>root:~# cd /sys/class/pwm/ehrpwm.1:0
<em>root:/sys/class/pwm/ehrpwm.1:0# echo 0 &gt; duty_percent</em>
root:/sys/class/pwm/ehrpwm.1:0# echo 1 &gt; period_freq
root:/sys/class/pwm/ehrpwm.1:0# echo 50 &gt; duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 1 &gt; run</pre>
<p>The following settings will cause the LED to glow dimly <em>[Corrected Mar 20]</em></p>
<pre>root:/sys/class/pwm/ehrpwm.1:0# echo 0 &gt; run
<em>root:/sys/class/pwm/ehrpwm.1:0# echo 0 &gt; duty_percent</em>
root:/sys/class/pwm/ehrpwm.1:0# echo 200 &gt; period_freq
root:/sys/class/pwm/ehrpwm.1:0# echo 20 &gt; duty_percent
root:/sys/class/pwm/ehrpwm.1:0# echo 1 &gt; run</pre>
<p>To make the LED glow more brightly:</p>
<pre>root:/sys/class/pwm/ehrpwm.1:0# echo 80 &gt; duty_percent</pre>
<p>It&#8217;s safe to change the duty_percent setting on the fly, without changing the other settings first.</p>
<p>The TI guide advises checking the availability of the PWM pin first:</p>
<pre>root~:/sys/class/pwm/ehrpwm.1:0# cat request
 ehrpwm.1:0 is free</pre>
<p>I haven&#8217;t seen it return anything except &#8220;free&#8221; yet, so I&#8217;m not sure under which circumstances it returns &#8220;busy&#8221;.  But, feel &#8220;free&#8221; to check.</p>
<p>With the second PWM port, right next door,  I decided to try a high-power LED with this one, the <a href="http://www.cree.com/products/xlamp7090_xre.asp">CREE XLAMP</a>. This is actually a good use of PWM, since without it the CREE&#8217;s brightness makes it a pain to work with.  (I blinded me with science!)</p>
<p>Here, the GPIO pin&#8217;s current restriction is a problem: the CREE won’t even flicker with the max recommended output current of 6mA.  The 300 mA that flows out of the 3.3V port will do the trick, though.</p>
<p>To control the flow using PWM, you can use a transistor.  I used a common NPN &#8220;switching&#8221; transistor, the 2N2222.</p>
<p>The base of the transistor can be connected to the PWM pin, through a resistor. The resistor keeps the current within the recommended 4-6 mA for a GPIO pin.  I used a 1K resistor, but as with the digital input sensors the exact value doesn&#8217;t matter as long as you&#8217;re above 550R:  you don&#8217;t need much current to control the transistor base.</p>
<ul>
<li>Pin 16 to 1K resistor.</li>
<li>Resistor to Base</li>
<li> 3.3V to positive pad of XLAMP</li>
<li>Negative pad of XLAMP to Collector of 2N2222</li>
<li>Emitter of 2N2222 to ground</li>
</ul>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/03/XLAMP-PWM-Circuit.jpg"><img class="aligncenter size-large wp-image-1193" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/03/XLAMP-PWM-Circuit-1024x768.jpg" alt="" width="640" height="480" /></a></p>
<p>With this circuit, and a duty cycle of just 1%, the XLAMP is no longer blinding (though still surprisingly bright).</p>
<p>A couple of things to note about the frequency setting:</p>
<ul>
<li><em>Corrected Mar 21</em>: As pointed out by muhoo in the Comments section, you can take the PWM frequency well past 250 Hz.  The key is to set the duty_cycle to zero before changing the frequency.  I&#8217;m not sure what the actual maximum frequency is, but the file system allows it to be set to 10 Mhz:</li>
</ul>
<div>
<pre># echo 0 &gt; run
# echo 0 &gt; duty_percent
# echo 10000000 &gt; period_freq
# echo 50 &gt; duty_percent
# echo 1 &gt; run
# cat period_freq
10000000
# cat period_ns
100</pre>
</div>
<div><span style="font-size: small;"><span style="line-height: 24px;"><br />
</span></span></div>
<ul>
<li><del>The maximum is 250 Hz.  I actually couldn&#8217;t find this documented anywhere, but currently setting it to anything above that value returns an error message.  (There is an alternative setting of period_ns, but the minimum for that is 4 million &#8211; same difference.)</del></li>
</ul>
<pre><del>root:/sys/class/pwm/ehrpwm.1:0# echo 251 &gt; period_freq sh: echo: write error: Invalid argument</del></pre>
<ul>
<li>The frequency setting is shared between ehrpwm.1:0 and ehrpwm.1:1 &#8212; if you change it for one, the other will be automatically set to the same frequency.  So, unlike the duty_percent, you&#8217;ll probably want to set the &#8220;run&#8221; flag to 0 for both PWM devices before changing it.</li>
</ul>
<h2>Programmer&#8217;s Show And Tell</h2>
<p>There aren&#8217;t many interesting ways to combine digital input and PWM output, and I&#8217;ve set out to prove this with some sample Python code  I&#8217;ve used one of the buttons and the 2 PWM-driver LEDs from earlier in the article.  Press the button and the lights come on.  Press and hold the button, and light state toggles between on and off.  Whee!</p>
<p>You can download the program from my <a href="http://code.google.com/p/gigamega-micro/downloads/detail?name=ButtonsAndLights.py">Google Code site</a>.</p>
<p>There are, however, a few things worth pointing out in the code.</p>
<p>Firstly, I&#8217;ve (ahem) borrowed the <a href="https://github.com/jadonk/bonescript/blob/master/bonescript/bone.js">pin mode table</a> from <a href="https://github.com/jadonk/bonescript">bonescript</a> in order to implement Python versions of pinMode, digitalRead and digitalWrite .</p>
<p>Python&#8217;s Dictionary is an easy-going data type: you can store anything in it, including another dictionary.  This  is similar to node.js, so the syntax of the bone_pins definition is almost identical to its bonescript counterpart:</p>
<pre>bone_pins = { "P8_1": { "name": "DGND" },
 "P8_2": { "name": "DGND" },
 "P8_3": { "name": "GPIO1_6", "gpio": gpio1+6, "mux": "gpmc_ad6", "eeprom": 26 },
 "8_4" : . . .</pre>
<p>Adding more information to a pin definition is just a matter of adding another entry to the dictionary.  So, to extend the table to include PWM pins, I just added a &#8220;pwm&#8221; key &#8230;</p>
<pre>"P9_14": { "name": "EHRPWM1A", "gpio": gpio1+18, "mux": "gpmc_a2", "eeprom": 34, "pwm" : "ehrpwm.1:0" },
 "P9_16": { "name": "EHRPWM1B", "gpio": gpio1+19, "mux": "gpmc_a3", "eeprom": 35, "pwm" : "ehrpwm.1:1" },</pre>
<p>To check if a pin supports pwm:</p>
<pre>if not "pwm" in bone_pins[pin]:
   print "ERROR: pin %s does not support PWM" %  pin</pre>
<p>Like node.js, Python provides a command line for experimenting with code without running the full application. So, you can take advantage of these functions by loading the module, then calling the functions manually.</p>
<p>This is somewhat quicker and a lot easier than controlling the settings from the Linux command prompt.  For example, to set Port 8 Pin 5 for input, then check the current input value (you&#8217;ll need to run python from the directory that contains ButtonsAndLights.py):</p>
<pre>root:~# python
&gt;&gt;&gt; import ButtonsAndLights as bb
&gt;&gt;&gt; bb.pinMode("P8_5", "in")
 setting /sys/kernel/debug/omap_mux/gpmc_ad2 to 0x37
 getting direction /sys/class/gpio/gpio34/direction
 exporting GPIO 34
 Exported /sys/class/gpio/gpio34/direction is in

 &gt;&gt;&gt; bb.digitalRead("P8_5")
 /sys/class/gpio/gpio34/value is 1
 1</pre>
<p>The extra &#8220;verbiage&#8221; are some print statements in the Python code for debugging purposes &#8211; I haven&#8217;t fully cleaned up the code yet to make it more usable as a plug-in module. For a more polished and better performing Python implementation of digital I/O functions, take a look at <a href="https://github.com/alexanderhiam/PyBBIO">PyBBIO</a>.  This code interacts with the GPIO pins using direct register access, rather than the file system, so PyBBIO should prove much faster, perhaps fast enough to handle the microsecond-level timing needed to implement device drivers.</p>
<p>I&#8217;ve also implemented pwmMode, pwmStart and pwmStop functions.  (This time I didn&#8217;t go with the Arduino naming convention &#8211; I can&#8217;t bring myself to refer to PWM as &#8220;analogWrite&#8221; like those bohemian Arduinoists.).</p>
<pre>def pwmWrite(pin, frequency, duty_cycle, start = True):
 """ Changes settings of specified PWM pin (e.g. "P9_14") and optionally enables it.
 Note that frequency and duty_cycle can be omitted to leave them unchanged """

def pwmStart(pin):
 """ Turn on PWM on the specified pin. PWM settings must previously have been passed to pwmWrite() """

def pwmStop(pin):
 """ Turn off PWM on the specified pin """</pre>
<p>These, too, can be used from the Python command line.  To set Port 9 Pin 14 to run at 200 Hz 80%:</p>
<pre>&gt;&gt;&gt; bb.pinMode("P9_14", "pwm")
 setting /sys/kernel/debug/omap_mux/gpmc_a2 to 0x6
&gt;&gt;&gt; bb.pwmWrite("P9_14", 200, 80)
&gt;&gt;&gt; bb.pwmStop("P9_14")</pre>
<p>Last, and least, there is the polling for digital input:</p>
<pre>lastButtonState = digitalRead(BUTTON_NC_PIN)
while 1 == 1:
    buttonState = digitalRead(BUTTON_NC_PIN)

    # NOTE: will return another value if unable to read
    if buttonState == HIGH or buttonState == LOW: 
         if buttonState != lastButtonState:
         # do stuff
    time.sleep(BUTTON_POLL_INTERVAL / 1000.0)</pre>
<p>While polling is, um, rather quaint, the AM335x is fast enough that it doesn&#8217;t significantly slow things down &#8211; the polling done in the sample code, once every 250 ms, spends about 99% of its time sleeping.</p>
<p>However, polling becomes somewhat less quaint when you&#8217;ve got a lot of digital inputs or sensors to keep track of, so I&#8217;m still looking for an interrupt driven solution for GPIO pins.  If anyone has that working from Python on a Beaglebone, please let me know.</p>
<h2>Wrapping Up</h2>
<p>These are still early days for the Beaglebone, and some of the basic building blocks for hobbyists are yet to fall in place.  No big surprise, of course: when the Arduino first appeared (back in the day, naught-5 I believe it was) it lacked libraries for things like LCDs and I2C sensors, but over the next few years those were written and became standardized.</p>
<p>But I&#8217;ve noticed quite a few interesting projects over the last month pushing out the boundaries of what can be done with userspace applications, like the aforementioned PyBBIO project,  and this <a href="https://github.com/kkeller/Nokia5110">bonescript project that writes to a Nokia 5110 display</a>.</p>
<p>The kernel continues to leap ahead with new releases every few weeks: kernel maven Koen Kooi recently posted a <a href="https://groups.google.com/forum/#!msg/beagleboard/24aV4A-l7Io/4I2U7naIqosJ">proposed roadmap</a> for what lies ahead.</p>
<p>The Beaglebone has also popping up on some popular hobbyist sites, like <a href="http://blog.makezine.com/2012/03/14/how-to-get-started-with-the-beaglebone/">Make Magazine</a> and <a href="http://hackaday.com/2012/03/07/vintage-vt100-terminal-computing-with-a-beaglebone/">Hack-A-Day</a>.</p>
<p>It&#8217;s quite fun to watch a platform grow from the ground up!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-and-pwm/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>Beaglebone Linux 101: Assigning a Static IP Address with Connman</title>
		<link>http://www.gigamegablog.com/2012/02/06/beaglebone-linux-101-assigning-a-static-ip-address-with-connman/</link>
		<comments>http://www.gigamegablog.com/2012/02/06/beaglebone-linux-101-assigning-a-static-ip-address-with-connman/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 00:10:43 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Beaglebone]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1160</guid>
		<description><![CDATA[My article on configuring Angstrom Linux included instructions for setting a static IP address. Sometime after posting that article, I realized that the instructions work great unless you happen to reboot. Then, the settings reverted to the default of using &#8230; <a href="http://www.gigamegablog.com/2012/02/06/beaglebone-linux-101-assigning-a-static-ip-address-with-connman/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My <a href="http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/">article on configuring Angstrom Linux</a> included instructions for setting a static IP address. Sometime after posting that article, I realized that the instructions work great unless you happen to reboot. Then, the settings reverted to the default of using a DHCP server.</p>
<p>Ooops!</p>
<p>It turns out that this sleight-of-hand is the work, aptly enough, of a package named <a href="http://connman.net/">Connman</a>.</p>
<p>This newfangled connection manager is, in some ways, a good fit for the Beaglebone, since it was designed to run on memory-constrained embedded Linux systems. It was originally developed for use on 2 Linux platforms that have struggled, Meego and Moblin, but we won&#8217;t hold that against it.</p>
<p>However, Connman presents one big problem for Beaglebone users: it&#8217;s rather difficult to configure from the command line.</p>
<p>It doesn&#8217;t come with a command line configuration tool, but it does provide some well documented APIs that command line applications can use. As such, the best command line interface right now can be found in a package intended to test that the APIs are working correctly: <em>connman-tests</em>.</p>
<p>To install the package:</p>
<pre>opkg install connman-tests</pre>
<p>This will install a set of Python scripts in <em>/usr/lib/connman/test</em>.</p>
<p>To check your current configuration:</p>
<pre>cd /usr/lib/connman/test/
./get-services</pre>
<p>The output should look like the following:</p>
<pre>[ /net/connman/service/<strong>ethernet_405fc276b749_cable</strong> ]
 IPv6.Configuration = { Method=auto Privacy=disabled }
 AutoConnect = false
 Proxy.Configuration = { }
 Name = Wired
 Nameservers = [ 206.47.244.104 206.47.199.155 ]
 Provider = { }
 Favorite = true
 Domains.Configuration = [ ]
 State = online
 Proxy = { Method=direct }
 Nameservers.Configuration = [ ]
 LoginRequired = 0
 IPv6 = { }
 Domains = [ lan ]
 Ethernet = { Interface=eth0 MTU=1500 Method=auto 
Address=xx:xx:xx:xx:xx:xx }
 Security = [ ]
 IPv4.Configuration = { Method=dhcp }
 Type = ethernet
 Immutable = false
 IPv4 = { Netmask=255.255.255.0 Gateway=192.168.1.1 
Method=dhcp Address=192.168.1.161 }</pre>
<p>The important thing to note here is the service ID at the top of the output, in my case  <em>ethernet_405fc276b749_cable</em>.  (Dumb name for an ethernet cable, if you ask me.)</p>
<p>You can also get the DNS nameserver and gateway IP addresses from this output, if you don&#8217;t already know them.</p>
<p>To change the configuration, you use 2 other scripts, <em>set-ipv4-method</em> and <em>set-nameservers.</em></p>
<p>The syntax for set-ipv4-method is:</p>
<pre>./set-ipv4-method &lt;service&gt; [off|dhcp|manual &lt;address&gt; [netmask] [gateway]]</pre>
<p>The <em>service</em> parm is that long string that appears at the top of the output from the <em>get-services</em> script.</p>
<p>So, to set the Beaglebone to use a static IP address of 192.168.1.2, with a gateway of 192.168.1.1, I entered:</p>
<pre>./set-ipv4-method ethernet_405fc276b749_cable manual 
192.168.1.2 255.255.255.0 192.168.1.1</pre>
<p>To set the DNS nameservers, use <em>set-nameservers. </em> The syntax is:</p>
<pre>./set-nameservers &lt;service&gt; [nameserver*]</pre>
<p>In my case, I entered</p>
<pre>./set-nameservers ethernet_405fc276b749_cable 206.47.244.104 
206.47.199.155</pre>
<p>That&#8217;s it: after entering those 2 commands, you&#8217;ll be running with the new network settings, no reboot required. (Though, if you plan to blog about it, a reboot is definitely recommended!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2012/02/06/beaglebone-linux-101-assigning-a-static-ip-address-with-connman/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Beaglebone Linux 101: Configuring Angstrom Linux</title>
		<link>http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/</link>
		<comments>http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 00:01:46 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Beagleboard]]></category>
		<category><![CDATA[Beaglebone]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1126</guid>
		<description><![CDATA[My previous two articles about the Beaglebone (here and  here) focused on using it as a development platform for handling Arduino-like tasks: interacting with digital, analog and serial devices. In this article I&#8217;m going to cover the basics of using &#8230; <a href="http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My previous two articles about the <a href="http://beagleboard.org/bone">Beaglebone</a> (<a href="http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/">here </a>and  <a href="http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/">here</a>) focused on using it as a development platform for handling Arduino-like tasks: interacting with digital, analog and serial devices.</p>
<p>In this article I&#8217;m going to cover the basics of using the Beaglebone in a different but complementary role: as a network-connected Linux computer.</p>
<p>If you&#8217;re not already familiar with Linux you might be tempted to ignore this aspect of the Beaglebone &#8212; once you&#8217;ve figured out how to copy programs onto the Beaglebone and run them,  you&#8217;re good to go.  However,  by doing some basic Linux configuration you can open up a lot of extra functionality, such as editing files on the Beaglebone directly from your desktop PC, or making the Beaglebone command line more user friendly.</p>
<p>I&#8217;m going to focus on the <a href="http://www.angstrom-distribution.org/">Angstrom Linux</a> distribution that is included in the microSD card packaged with each Beaglebone. Angstrom is not as widely used as other flavours of Linux, like Ubuntu or Fedora. This can be a frustrating to newcomers, since you&#8217;re less likely to figure out how to do things by Googling for the answer. However, Angstrom is well suited to a memory and storage-constrained platform like the Beaglebone, being bloat-free and able to squeeze out more performance from the ARM processor.</p>
<p>I should also mention off the top that I&#8217;m not going to show you how to run a spreadsheet, browser or any other GUI applications on the Beaglebone. That <em>is</em> possible, even without a cape that has a video port (by using VNC), but I think you&#8217;re likely to be disappointed. The Beaglebone&#8217;s memory and CPU constraints will cause a GUI system to be annoyingly slugglish . Think of it more as an Arduino on steroids, not a poor man&#8217;s PC.</p>
<h2>Configuring a terminal on Windows</h2>
<p>(Sorry Mac and Linux users &#8211; the first couple of sections are Windows-centric.)</p>
<p>Whether you connect to the Beaglebone via USB or over the network using SSH, the best terminal software to use on Windows is PuTTY.</p>
<p>You might be scared off after a glimpse of <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">PuTTY&#8217;s plain Jane website</a> – it looks like a relic from the early days of the Internet. Trust me, though: PuTTY is the way to go. Unlike other Windows terminal programs, it &#8220;gets&#8221; Linux. It may not be the best all-around terminal program, but it’s the best Windows client for a Linux server.</p>
<p>PuTTY is bristling with options, but for the most part the default settings are fine.  When the Beaglebone is connected via USB, select Serial, fill in the COM port ID, and change the Speed to 115200.  When connecting over the network, select SSH and fill in the IP address.  You should also fill in a  name in the Saved Sessions textbox and click Save.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-55-51-PM.jpg"><img class="aligncenter size-full wp-image-1134" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-55-51-PM.jpg" alt="" width="461" height="446" /></a></p>
<p>With the default settings, you&#8217;ll find that some keys don&#8217;t work as expected.  For example, neither Home nor End will work when editing the command line.  To fix this, under Connection &#8211;&gt; Data, change the Terminal-type from the default of xterm to linux.</p>
<p>While you are in this window, you can also fill in a default username for logins. (Which, come to think of it, must be &#8220;root&#8221;, since you haven&#8217;t read the &#8220;Creating a user&#8221; section yet).</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-38-11-PM.jpg"><img class="aligncenter size-full wp-image-1133" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-38-11-PM.jpg" alt="" width="461" height="445" /></a></p>
<p>One other less-than-obvious thing about PuTTY is the way it handles copy-and-paste: Ctrl-C and Ctrl-V won&#8217;t work.  Instead, any text you highlight on the terminal is automatically copied to the Windows clipboard, and Shift-Insert is the shortcut for Paste.</p>
<h2>Transferring and editing files from Windows</h2>
<p>The other important piece of software you should install on Windows is something to  transfer files to the Beaglebone. If you aren&#8217;t yet comfortable with using Linux command line editors, then this tool is vital, since you are going to need to edit some files below.</p>
<p>For this, you&#8217;ll need to access the Beaglebone over the network (i.e. not a COM port), and use a Windows program called <a href="http://winscp.net/eng/index.php">WinSCP</a>.  The only default setting you&#8217;ll have to change is the File Protocol: the Angstrom demo image&#8217;s SSH server, Dropbear, doesn&#8217;t support SFTP.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-42-46-PM.jpg"><img class="aligncenter size-full wp-image-1132" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-42-46-PM.jpg" alt="" width="519" height="369" /></a></p>
<p>You can use WinSCP to transfer files back and forth between Windows and the Beaglebone but, more importantly, you can also use it to edit files directly on the Beaglebone, safely from the comfort of your Windows desktop.</p>
<p>I know, I know, eventually you&#8217;ll want to cut the Windows apronstrings and learn to Esc-Alt-whatever in a command line editor. But having GUI training wheels will save you a lot of frustration as you get started</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-51-46-PM.jpg"><img class="aligncenter size-full wp-image-1131" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-28-2012-9-51-46-PM.jpg" alt="" width="993" height="503" /></a></p>
<h2>Creating a user</h2>
<p>Angstrom Linux initially contains just a root user. I suspect a lot of people like it that way – root is God, so why bother running as a mere mortal instead? I would actually agree: since you&#8217;re almost certainly using it as a single user development platform, go crazy, have fun, be root.</p>
<p>However, if your Beaglebone is going to be accessible from a network, and especially if it&#8217;s going to be accessible over the Internet, disabling the root login is a wise security precaution: having to guess the user-ID makes the Beaglebone much harder to crack.</p>
<p>(Needless to say, if you aren’t going to disable root logins, then for-the-love-of-God give the root user-ID a password!)</p>
<p>My own approach is to login with my user-ID, then switch to root when needed (generally about 10 seconds after logging in, admittedly).</p>
<p>To create a new user-ID, johndoe:</p>
<pre><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">beaglebone:~#</span></span></span><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">useradd johndoe</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">beaglebone:~# passwd johndoe</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">Enter new UNIX password:</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">Retype new UNIX password:</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">passwd: password updated successfully</span></span></span></pre>
<p>To give the root user a password:</p>
<pre><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">beaglebone:~# passwd</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">Enter new UNIX password:</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">Retype new UNIX password:</span></span></span>
<span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">passwd: password updated successfully</span></span></span></pre>
<h2>Switching to root</h2>
<p>So you&#8217;ve logged in as an ordinary user, and have quickly discovered that you need to be root to actually do anything, including pretty much all of the steps below. To switch to root</p>
<pre>beaglebone:~$ su</pre>
<p>The password you enter is the root password, not the user&#8217;s. This ain&#8217;t Ubuntu, son.</p>
<p>If you find that you prefer Ubuntu&#8217;s way of doing things, you can install the sudo package:</p>
<pre>beaglebone:~# opkg install sudo</pre>
<p>I think this is well worth doing, if only for the comedy element.  <em>sudo</em> is the most uptight piece of software that I&#8217;ve come across.   The first time you use <em>sudo</em>, you&#8217;ll get a bossy warning:</p>
<pre>We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.</pre>
<p>After you enter your password, <em>sudo</em> will shriek and run off to tell on you:</p>
<pre>johndoe is not in the sudoers file.  This incident will be reported.</pre>
<p>To fix this, you don&#8217;t directly edit the /etc/sudoers file &#8212; oh no, that would be too easy.  Instead, you (logged in as root, of course) run <em>visudoer</em>, which forces you to grapple with the notorious vi editor.</p>
<p>If you haven&#8217;t lost your nerve yet, you can add your user-ID to the User Privilege section:</p>
<pre>##
## User privilege specification
##
root ALL=(ALL) ALL
johndoe ALL=(ALL) ALL</pre>
<p>I suspect that the creator of sudo would have a conniption if he saw you make such a crude change (the rules governing sudoer configuration are rather elaborate), but what do you have to lose: your actions have already been reported.</p>
<h2>Disabling root SSH login</h2>
<p>This step is optional, especially if your Beaglebone isn&#8217;t accessible from the Internet.  In fact, if you&#8217;re using WinSCP to edit system files then <em>don&#8217;t</em> disable the root login &#8211; you can&#8217;t switch to root from within WinSCP.</p>
<p>If you still want to do it, you can disable root login by specifying the &#8220;-w&#8221; command line parm when running the SSH server, <a href="http://matt.ucc.asn.au/dropbear/dropbear.html">Dropbear</a>.</p>
<p>Ordinarily, Dropbear configuration is done by setting options in file /etc/default/dropbear.  This used to work in Angstrom.  However, they&#8217;ve recently switched to launching Dropbear in a way that doesn&#8217;t use any configuration file.</p>
<p>As far as I know, the only way to change the dropbear configuration now is to edit the ExecStart line in a well-hidden file: /lib/systemd/system/dropbear@.service:</p>
<pre>beaglebone:/lib/systemd/system$ cat dropbear@.service
[Unit]
Description=SSH Per-Connection Server
Requires=dropbearkey.service
After=syslog.target dropbearkey.service
[Service]
ExecStart=-/usr/sbin/dropbear -i -r /etc/dropbear/dropbear_rsa_host_key -p 22<strong><span style="color: #000000;"> -w</span></strong>
ExecReload=/bin/kill -HUP $MAINPID
StandardInput=socket</pre>
<p>Note the &#8220;-w&#8221; at the end of the ExecStart line &#8211; I added that to disable the root login.</p>
<p>To restart Dropbear, you still reference the old (but ultimately unused) init.d script:</p>
<pre>/etc/init.d/dropbear restart</pre>
<h2>Changing the host name</h2>
<p>This is purely optional, unless you have multiple Beaglebones, but it&#8217;s an easy way to personalize things:</p>
<p>Edit /etc/hostname and change <em>beaglebone</em> to your new host name.</p>
<p>Then, edit /etc/hosts and make the same change there. Leave the rest of the file as is: it should look something like this when are done, with <em>yourhostname</em> being replaced with – yeah, you got it:</p>
<pre>cat /etc/hosts
127.0.0.1 localhost.localdomain localhost
127.0.0.1 yourhostname</pre>
<p>Your command line prompt won&#8217;t display your shiny new device name until you reboot:</p>
<pre>shutdown –r now</pre>
<h2>Using a static IP address</h2>
<p><em>Updated 2/6/12: The instructions in this section don&#8217;t work when using Connman to handle network connections (which is the default for Angstrom Linux on the Beaglebone) &#8212; it will revert to using DHCP after rebooting.  See <a href="http://www.gigamegablog.com/2012/02/06/beaglebone-linux-101-assigning-a-static-ip-address-with-connman/">Beaglebone Linux 101: Assigning a Static IP Address with Connman</a>)</em></p>
<p>This step is also optional, if you have a DHCP server and don&#8217;t mind using its choice of IP address. Unlike the Beagleboard XM, the Ethernet adapter on the Beaglebone always uses the same MAC address, which means that the IP address assigned by the DHCP server won&#8217;t change each time you boot.</p>
<p>Setting a static IP  address requires editing <em>/etc/network/interfaces</em>.  The default version of this file in the Angstrom demo image looks like this:</p>
<pre>beaglebone:~$ cat /etc/network/interfaces
# /etc/network/interfaces -- configuration file for ifup(8), ifdown(8)
# The loopback interface
auto lo
iface lo inet loopback
# Wireless interfaces
iface wlan0 inet dhcp
wireless_mode managed
wireless_essid any
wpa-driver wext
wpa-conf /etc/wpa_supplicant.conf
iface atml0 inet dhcp
# Wired or wireless interfaces
auto eth0
<strong>iface eth0 inet dhcp</strong>
iface eth1 inet dhcp
# Ethernet/RNDIS gadget (g_ether)
# ... or on host side, usbnet and random hwaddr
iface usb0 inet static
address 192.168.7.2
netmask 255.255.255.0
network 192.168.7.0
gateway 192.168.7.1
# Bluetooth networking
iface bnep0 inet dhcp</pre>
<p>You need to replace the &#8220;iface eth0 inet dhcp&#8221; line with hard-coded settings for your IP address, gateway, and DNS servers. (Oh, and you might want to do it while connected to the Beaglebone via the USB cable, rather than Ethernet, in case you mess things up).</p>
<p>Comment out the &#8221;iface eth0 inet dhcp&#8221; line and add new lines with the correct IP addresses in the address, gateway, and dns-nameservers address (don&#8217;t just copy mine &#8211; that&#8217;s cheating):</p>
<pre>#iface eth0 inet dhcp
iface eth0 inet static
<strong>address 192.168.1.2</strong>
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
<strong>gateway 192.168.1.1</strong>
<strong>dns-nameservers 192.168.1.1</strong></pre>
<p>To test your settings, cross your fingers and enter:</p>
<pre>/etc/init.d/networking restart</pre>
<p>Then check to see that you have the new IP address:</p>
<pre>ifconfig eth0</pre>
<p>and gateway…</p>
<pre>netstat –nr</pre>
<p>and DNS server:</p>
<pre> 
cat/etc/resolv.conf</pre>
<p>Ha, were you worried? Me neither!</p>
<h2>Setting the time zone</h2>
<p>You probably noticed shortly after connecting your Beaglebone to the Internet that it  automatically figured out the date and time, sort of: everything except the time zone.</p>
<p>The demo image includes a &#8220;cron&#8221; job that uses NTP to get the correct date and time. You can see this by entering:</p>
<pre>crontab -l
30 * * * * /usr/bin/ntpdate -b -s -u pool.ntp.org</pre>
<p>Every 30 minutes, it will run the ntpdate command to update the system date and time.</p>
<p>The system determines the time zone using a file called /etc/localtime. Don&#8217;t try editing this file – instead, you point it at the correct time zone under /usr/share/zoneinfo. To see what&#8217;s available:</p>
<pre> ls -lr /usr/share/zoneinfo/</pre>
<p>These files in the zoneinfo directory are installed by package tzdata.</p>
<p>Don&#8217;t feel bad if they don&#8217;t include your town – they missed mine too. However, you should be able to find your time zone, or another city in it. For me, I set the timezone by entering:</p>
<pre>rm /etc/localtime
ln -s /usr/share/zoneinfo/America/New_York /etc/localtime</pre>
<p>Note that &#8220;ln -s&#8221; creates a pointer to an existing file &#8211; make sure you get the parms in the right order.</p>
<p>Reboot to update the system time.</p>
<h2>Updating packages</h2>
<p>If you haven&#8217;t updated the Linux packages on your Beaglebone before, and you&#8217;re using one of the early Angstrom images (the original 11-16-11 image, or the 12-26-11 image) you&#8217;re in for a treat. A movie, perhaps, or dinner, or a long romantic walk on the moonlight. As long as it takes an hour or two, cause the first package update is sloooooow.</p>
<p>I don&#8217;t know why, but there has been a steady stream of package updates released since the Beaglebone came out. Usually, Angstrom is a &#8220;sleepier&#8221; distribution – just the occasional bug fix or security update. I&#8217;m guessing that package development for the Beaglebone is more active because the platform is new, and package updates will become less frequent over time.</p>
<p>The basics of updating packages is to remember 2 commands:</p>
<pre>Opkg update
Opkg upgrade</pre>
<p>The first updates your local copy of the list of available packages, and the second does the updating. It&#8217;s all automated – you shouldn&#8217;t see any prompts, so no need to stand around watching it go&#8230; and go &#8230;.</p>
<p>.. phew, done! After the first batch of updates, it&#8217;s a good idea to reboot.</p>
<p>After awhile, the &#8220;opkg upgrade&#8221; will begin to mutter complaints when it&#8217;s done – stuff like:</p>
<pre>Collected errors:
* check_data_file_clashes: Package shadow wants to install file /etc/login.defs
But that file is already provided by package * shadow-sysroot
* check_data_file_clashes: Package shadow wants to install file /etc/login.defs
But that file is already provided by package * shadow-sysroot</pre>
<p>Yada yada yada.  Whatever.</p>
<p>Honestly, you generally don&#8217;t have to do anything to fix the errors – as other packages get updated, the problems get fixed. If they don&#8217;t, there is always Google.</p>
<h2>Installing packages</h2>
<p>The demo image comes with a lot of software, but there are thousands of other packages available. To see everything that is out there, you can enter:</p>
<pre>opkg list</pre>
<p>That&#8217;s a lot of packages! If you have an idea of what you are looking for, use grep to filter the results:</p>
<pre>Opkg list | grep "python"</pre>
<p>To install the package</p>
<pre>Opkg install &lt;packagename&gt;</pre>
<p>If you can&#8217;t find what you want that way, try the online <a href="http://www.angstrom-distribution.org/repo/">Angstrom package browser</a>. It has a more convenient interface, and it&#8217;s possible that the package you&#8217;re looking for isn&#8217;t listed by opkg but can be found on the web site (in the dreaded &#8220;unstable&#8221; branch &#8211; scary!).</p>
<p>For example, my preferred command line editor is <a href="http://www.gnu.org/software/emacs/">Emacs</a>, but that doesn&#8217;t appear in the output of &#8220;opkg list&#8221;.  It is, however, <a href=" http://www.angstrom-distribution.org/repo/?pkgname=emacs">listed in the package browser</a>.</p>
<p>The &#8220;available versions&#8221; section lists 2 options:</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-3-33-26-PM.jpg"><img class="aligncenter size-full wp-image-1139" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-3-33-26-PM.jpg" alt="" width="847" height="351" /></a></p>
<p>The 2 available versions are for the &#8220;Angstrom 2011.03&#8243; release, and the Beaglebone is running a more recent release, currently Angstrom 2012.01.  That&#8217;s why &#8220;opkg list&#8221; didn&#8217;t include emacs.</p>
<p>I don&#8217;t know why emacs isn&#8217;t made available in the new release &#8212; it could be lack of popularity, or a lower priority for conversion and testing, or a horrendous incompatibility with other packages.  However, since emacs is a user app that few other packages make use of, a horrendous incompatibility seems unlikely.  (And I&#8217;ve been running emacs on the Beaglebone for several weeks with no problems).</p>
<p>The Beaglebone is compatible with armv7a packages, so when that platform is available you should select it.  (Packages compiled for earlier versions of ARM processors will generally also run on the Beaglebone, but more slowly)</p>
<p>You can just click on the link to download it, and copy the package over via WinSCP, or use wget to download it directly to the Beaglebone:</p>
<pre> wget <a href="http://www.angstrom-distribution.org/feeds/unstable/ipk/glibc/armv7a/base/emacs_22.3-r1.6_armv7a.ipk">http://www.angstrom-distribution.org/feeds/unstable/ipk/glibc/armv7a/base/emacs_22.3-r1.6_armv7a.ipk</a></pre>
<p>To install it, just specify the filename instead of the package name:</p>
<pre>opkg install emacs_22.3-r1.6_armv7a.ipk</pre>
<p>You&#8217;ll likely find that it complains about a missing dependency file, liblockfile:</p>
<pre>Installing emacs (22.3-r1.6) to root...
Collected errors:
 * satisfy_dependencies_for: Cannot satisfy the following dependencies for emacs:
 * liblockfile (&gt;= 1.06) *
 * opkg_install_cmd: Cannot install package emacs.</pre>
<p>Yada yada yada.  Actually, this one we can fix.</p>
<p>The package browser web page for emacs, above, lists liblockfile as a dependency.  You can click on the link to <a href=" http://www.angstrom-distribution.org/repo/?pkgname=liblockfile">open up the liblockfile page </a>and download it from there, or enter the following to download the dependency and install both packages:</p>
<pre>wget http://www.angstrom-distribution.org/feeds/2011.03/ipk/glibc/armv7a/base/liblockfile_1.06-r1.6_armv7a.ipk
opkg install liblockfile_1.06-r1.6_armv7a.ipk emacs_22.3-r1.6_armv7a.ipk</pre>
<h2>Other useful opkg commands</h2>
<p>To remove a package</p>
<pre><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">opkg remove &lt;packagename&gt;</span></span></span></pre>
<p>To rip a package from the grasp of a protesting opkg (generally because you intend to replace the package with one that provides the same files):</p>
<pre lang="en-US"><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">opkg remove &lt;packagename&gt; --force-removal-of-dependent-packages</span></span></span></pre>
<p>To get more information about a package:</p>
<pre lang="en-US"><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">opkg info packagename</span></span></span></pre>
<p>To get a list of files that are installed by the package:</p>
<pre lang="en-US"><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">opkg files packagename</span></span></span></pre>
<p lang="fr-CA">(Which only works after you&#8217;ve already installed the package - so much for look before you leap!)</p>
<p lang="fr-CA">To find the package that installed a specific file:</p>
<pre lang="fr-CA">opkg search '&lt;path_to_file&gt;'</pre>
<p lang="fr-CA">e.g.</p>
<pre lang="fr-CA">opkg search '/bin/ps.procps'
procps - 3.2.8-r4</pre>
<p lang="fr-CA">The search function supports wildcards:</p>
<pre lang="fr-CA">opkg search '*bash*'</pre>
<h2>Automating package updates</h2>
<p>There are some people, who we&#8217;ll call &#8220;sissies&#8221;, who would argue that automating package updates is dangerous and irresponsible, since the updates might fail and you don&#8217;t want to leave your system in an unstable state.</p>
<p>Others, who we&#8217;ll call &#8220;real men&#8221;, think that the package update process is reliable enough that it rarely requires manual intervention. And, besides, you can always check the logs to detect any problems. It&#8217;s not like you&#8217;re going to forget to check the logs, right?</p>
<p>Personally, I&#8217;m a sissy. I&#8217;m also forgetful, so I&#8217;ve automated opkg anyway. Needless to say, I rarely bother to look at the output logs. (I know what I&#8217;ll find.. &#8220;Collected errors: yada yada yada&#8221;. Whatever.)</p>
<p>If you&#8217;re a real man, you can add a line to the crontab to automatically update your system.</p>
<p><em>[2/2/12: the following script was updated to add error handling]</em></p>
<p>First, create a script to run.  I use the following:</p>
<pre>#!/bin/sh
# runopkg.sh
# Update packages and append output to log file
/usr/bin/opkg update
# opkg update returns 0 if OK, 1 if error
if [ $? = 0 ]; then
    /usr/bin/opkg upgrade &amp;&gt;&gt; /var/log/opkgupgrade.log
    echo "opkg complete rc $?  $(date)" &gt;&gt; /var/log/opkgupgrade.log
else
    echo "ERROR: opkg update returned $?" &gt;&gt; /var/log/opkgupgrade.log
fi</pre>
<p>You can download this file from my site:</p>
<pre>beaglebone:~# wget http://www.gigamegablog.com/docs/runopkg.sh</pre>
<p>&#8230;make it executable&#8230;</p>
<pre>beaglebone:~# chmod u+x runopkg.sh</pre>
<p>&#8230;then add this script to the list of scheduled cron tasks:</p>
<pre>beaglebone:~# crontab -e
30 * * * * /usr/bin/ntpdate -b -s -u pool.ntp.org
33 3 * * * /home/root/runopkg.sh</pre>
<p>By default, the &#8220;crontab -e&#8221; command invokes the vi editor, which you&#8217;ll either love or hate.  Probably hate.</p>
<p>If you stored runopkg.sh in a directory other than the root home folder, be sure to enter the correct path in the crontab line.</p>
<p>The example above runs the update process every day at 3:33 am, and appends both the info and error messages to a log file. It checks the return code after running opkg update. Sometimes it fails to connect to one of the repositories, and it is safest not to do an upgrade with an incomplete list of updates.</p>
<h2>Customizing the command line</h2>
<p>Angstrom provides a standard Bash command line shell without any customizations: no <em>.profile</em> or <em>.bashrc</em> file.</p>
<p>Everybody&#8217;s got their own idea of how to make Bash more useful, but here are some common customizations to get you started.</p>
<p>First, create a file named .profile in  your home directory with the following contents:</p>
<pre># ~/.profile: executed by Bourne-compatible login shells.
if [ -f ~/.bashrc ]; then
 . ~/.bashrc
fi
# path set by /etc/profile
# export PATH
mesg n</pre>
<p>If you like, you can download this file directly from my site. Make sure you store it in your home folder .</p>
<pre>beaglebone:~# wget http://www.gigamegablog.com/docs/.profile</pre>
<p>This is an extremely plain .profile which mainly has one purpose: to activate the .bashrc file.</p>
<p>Next, create a file called .bashrc in your home directory with the following contents:</p>
<pre># ~/.bashrc: executed by bash(1) for non-login shells.
export PS1='\h:\w\$ '
umask 022
# You may uncomment the following lines if you want `ls' to be colorized:
export LS_OPTIONS='--color=auto'
# eval `dircolors`
alias ls='ls $LS_OPTIONS'
alias ll='ls $LS_OPTIONS -l'
alias l='ls $LS_OPTIONS -lA'

# Some more alias to avoid making mistakes:
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# shell options
# autocorrect cd commands
shopt -s cdspell
# disable Ctrl-D to logout
set -o ignoreeof
# extended pattern matching
shopt -s extglob</pre>
<p>This file can be downloaded from my site &#8211; it should be stored in your home folder:</p>
<pre>beaglebone:~# wget http://www.gigamegablog.com/docs/.bashrc</pre>
<p>This does the following:</p>
<ul>
<li>shortens the command prompt to just your hostname and the current directory</li>
<li>changes the default permissions for new files you create so that they are writable by you, and just readable for everyone else</li>
<li>turns on colors for your &#8220;ls&#8221; output</li>
<li>creates a few shortcuts for common ls options (ll is the most useful, I think)</li>
<li>adds the &#8220;-i&#8221; parm to the copy, move and delete commands, which prompts you for confirmation when you are about to delete or overwrite a file</li>
<li>automatically fixes some typos in directory names</li>
<li>prevents Ctrl-D from dropping your session</li>
<li>enables <a href="http://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching">extra wildcards for matching files and directories</a></li>
</ul>
<p>By the way, when switching from a regular user to root using the su command, you need to include a hyphen to ensure that the root .profile and .bashrc are used:</p>
<pre>su -</pre>
<h2>Windows networking</h2>
<p>By now, you&#8217;re hopefully starting to look upon your Beaglebone with respect and admiration. You are also probably sick of WinSCP and/or command line editors. Why not welcome your Beaglebone into your Windows network and give it equal standing to your other PCs?</p>
<p>For this, you&#8217;ll need to install Samba.</p>
<pre>opkg install samba</pre>
<p>The correct configuration of Samba is actually quite complicated, or so I would assume since there is an <a href="http://oreilly.com/openbook/samba/book/index.html">entire book on the topic</a> . I haven’t actually read it, so instead I installed a browser-based configuration utility named Swat:</p>
<pre>opkg install xinetd swat</pre>
<p>The <span style="font-family: Georgia, serif; color: #333333;">xinetd utility is the standard way of invoking Swat and many other services that are accessed over the network.  It doesn&#8217;t start the service until it is accessed, which is quite helpful on a memory constrained platform like the Beaglebone.</span></p>
<p lang="en-US">The services are configured by entries in /etc/xinetd.conf or files in /etc/xinet.d, but unfortunately the Swat package currently doesn&#8217;t update either.  So, create a file at <em>/etc/xinetd.d/swat</em>, and paste the following into it:</p>
<pre lang="en-US">service swat
{
   disable = no
   port = 901
   socket_type = stream
   wait = no
   # only_from = localhost
   user = root
   server = /usr/sbin/swat
   log_on_failure += USERID
}</pre>
<p lang="en-US">Note that this configuration uses a port number of 901, allows access to other PCs on the network, and specifies that root is allowed to login.</p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">After changing the xinetd.conf file, you need to restart xinetd:</span></span></p>
<pre lang="en-US"><span style="color: #222222;"><span style="font-family: Courier, monospace;"><span style="font-size: small;">/etc/init.d/xinetd restart</span></span></span></pre>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">You should now be able to open the following address in a browser on another PC: <em>http://&lt;your-beaglebone-ipaddress&gt;:901</em></span></span></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">Login as root at the prompt.</span></span></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">The first thing you&#8217;ll want to do is add a user to Samba &#8212; Samba doesn&#8217;t automatically use the same user-IDs and passwords as Linux.  Ideally, you should add a user that has the same user-ID as a Linux user and Windows user, and the same password as the Windows user &#8211; you&#8217;ll have fewer problems with permissions that way.</span></span></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">Go to the Swat password page and create a user. The interface isn&#8217;t terribly intuitive: fill in the user name and password in the Server Password Management area, then click then &#8220;Add New User&#8221; button.  You&#8217;ll get a subtle confirmation that the user was added, but it doesn&#8217;t display a list of users.</span></span></p>
<p lang="en-US"><img class="aligncenter" src="http://www.gigamegablog.com/wp-content/uploads/2010/12/swat.png" alt="" width="671" height="264" /></p>
<p lang="en-US">Next, click on Shares and add a share for your user&#8217;s home directory.</p>
<p lang="en-US">This step is advisable since, if there isn&#8217;t at least one share that your Windows user-ID is allowed to access, Samba/Windows will keep prompting for your user-ID and password.  If it&#8217;s the first time you are accessing a Samba share, you won&#8217;t know the cause of the problem: the user-ID, the password, or the share.  So, ensure you have access to <em>something</em> by explicitly sharing your user&#8217;s home directory.</p>
<p lang="en-US">The user interface on the Shares page isn&#8217;t very intuitive either: you need to fill in the textbox next to the Create Share button, then click the button</p>
<p lang="en-US"><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-5-32-13-PM.jpg"><img class="aligncenter size-full wp-image-1143" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-5-32-13-PM.jpg" alt="" width="431" height="351" /></a></p>
<p lang="en-US">Note that, by default, new shares are read-only and are <em>not</em> &#8220;available&#8221;. (Grrrr.)  So, you&#8217;ll need to manually change the &#8220;Available&#8221; setting and Read-only setting then click the Commit Changes button.</p>
<p lang="en-US">(When sharing directories other than your home directory, you may want to leave the Read-only setting on.  If your user-ID doesn&#8217;t have write permissions to the underlying Linux directory, don&#8217;t try to make it a writeable share.  It won&#8217;t work.)</p>
<p lang="en-US"><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-5-33-34-PM.jpg"><img class="aligncenter size-full wp-image-1142" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-29-2012-5-33-34-PM.jpg" alt="" width="608" height="799" /></a></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">I’d also suggest you go to the Global page and change the workgroup to whatever your Windows PC uses &#8211; this makes your Beaglebone easily discovered by Windows.</span></span></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">After saving your changes you shouldn&#8217;t have to manually restart Samba, since it continually scans for configuration changes.  However, I often find that a restart is necessary to get your changes to be recognized by Windows:</span></span></p>
<pre lang="en-US">/etc/init.d/samba restart</pre>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">Now, Windows Explorer should be able to see your Beaglebone in your network, with some shares underneath. </span></span></p>
<p lang="en-US"><span style="color: #333333;"><span style="font-family: Georgia, serif;">If you are prompted for a user-ID and password, use the one you entered into Swat’s password page.  If Windows prompts for a new user-ID and password when accessing a share or file, remember that the Linux permissions come into play &#8211; try changing the Linux  directory permissions to give write access to non-root users.</span></span></p>
<h2 lang="en-US">Wrapping Up</h2>
<p lang="en-US">There&#8217;s been some debate in the <a href="http://groups.google.com/group/beagleboard">Beagleboard Google Group</a> about whether it makes sense to have a separate group for the Beaglebone.</p>
<p lang="en-US">IMHO, no.  While the Beaglebone is quite different as an electronics hobbyist platform, it&#8217;s almost completely identical to the Beagleboard when it comes to Linux configuration.  All of the steps I covered in this article also apply to the Beagleboard.</p>
<p lang="en-US">So, when looking for Linux tips and solutions, don&#8217;t ignore postings targeted at the Beagleboard.</p>
<p lang="en-US">Furthermore, while Angstrom has its differences from other Linux distributions, the most commonly used software is the same or very similar.  Dropbear is largely the same as <a href="http://www.openssh.com/">OpenSSH</a>, Busybox is largely the same as the <a href="http://www.gnu.org/software/coreutils/">core GNU utilities</a>, and Angstrom Bash is <a href="http://www.gnu.org/software/bash/">Bash</a>.  Don&#8217;t be discouraged by the lack of documentation on Angstrom or some its utilities.  There&#8217;s a wealth of information out there on SSH, GNU and Bash, and you&#8217;ll find that most of it applies to Angstrom.</p>
<p lang="en-US">The stuff that doesn&#8217;t apply? Ignore it.  Wouldn&#8217;t you rather be coding than reading, anyway?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2012/01/29/beaglebone-linux-101-configuring-angstrom-linux/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Beaglebone Coding 101: Using the Serial and Analog Pins</title>
		<link>http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/</link>
		<comments>http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 02:20:57 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Beagleboard]]></category>
		<category><![CDATA[Beaglebone]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1094</guid>
		<description><![CDATA[[Updated Jan 25: Correction! There is a 1.8V voltage source on the Beaglebone: Port 9 Pin 32.  Thanks to Koen Kooi for the info.  I've updated the text with this information] [Update May 5: In kernel version 3.2.14, the file &#8230; <a href="http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>[Updated Jan 25: Correction! There is a 1.8V voltage source on the Beaglebone: Port 9 Pin 32.  Thanks to Koen Kooi for the info.  I've updated the text with this information]</em></p>
<p><em>[Update May 5: In kernel version 3.2.14, the file system path for the analog pin readings was changed from /sys/devices/platform/tsc to /sys/devices/platform/omap/tsc]</em></p>
<p>This article is my second explaining the fundamentals of coding with the <a href="http://beagleboard.org/bone"><span style="color: #000000;">Beaglebone</span></a>. In the <a href="http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/"><span style="color: #000000;">first article</span></a> I explained some of the mysteries of pin muxing, and gave an example of a very simple usage of a digital pin. This time, I’ll use an analog sensor and serial I/O (just O, actually), to create a time and temperature LCD display.</p>
<p>I have to admit that I’m far from an expert – I’m basically writing about this stuff as I figure it out.</p>
<p>The Beaglebone will hopefully prove to be a ground-breaking product, introducing a lot of electronics hobbyists to embedded Linux programming. Unfortunately, at this point there isn’t much in the way of embedded Linux development tools or tutorials that is geared to newcomers. This should change by the summer of 2012, as <a href="https://github.com/jadonk/bonescript">bonescript</a> expands and more Beaglebone-based projects pop up on blogs and sites like <a href="http://www.instructables.com">Instructables</a>. Until then, it will be one baby step at a time…</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/HPIM0986.jpg"><img class="aligncenter size-full wp-image-1098" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/HPIM0986.jpg" alt="" width="2304" height="1728" /></a></p>
<h2>Analog Input</h2>
<p>The first rule of analog input with the Beaglebone is:<br />
<span style="text-decoration: underline;"><span style="color: #ff0000; text-decoration: underline;">NOTE: Maximum voltage is 1.8V. Do not exceed this voltage. Voltage dividers</span></span><br />
<span style="text-decoration: underline;"><span style="color: #ff0000; text-decoration: underline;"> should be used for voltages higher than 1.8V.</span></span></p>
<p>So sayeth the Beaglebone System Reference Manual (Emphasis theirs. )</p>
<p>I haven’t experimented with what happens if you go above 1.8V, but since they’ve made the warning red and underlined, I’m pretty sure it would not go well.<br />
This limitation is a problem, since:</p>
<ul>
<li><del>There is no pin on the Beaglebone that provides a 1.8V source</del><br />
<em><span style="color: #000000;">[Correction Jan 25 - as pointed out in the comments, there is a pin that provides 1.8V, Port 9 pin 32 (labelled VDD_ADC in the Beaglebone System Reference Manual).    So you can ignore the stuff about voltage dividers and level converters below if you are using an analog sensor that can operate on 1.8V, like a potentiometer.]</span></em></li>
<li>Many analog sensors require a minimum voltage greater than 1.8V</li>
</ul>
<p>So, until someone has a better idea, voltage dividers will be an important part of any Beaglebone analog circuit.</p>
<p>The second most important thing to know about the Beaglebone’s analog input is that the software support seems to be a work-in-progress. The approach I’m taken is based on a <a href="http://dominion.thruhere.net/koen/cms/using-the-analog-pins-on-a-beaglebone">brief blog post</a> by one of the maintainers of the Beaglebone Angstrom demo images. His remarks would suggest that they have a better plan that is under development. As far as I know, the approach taken here is an Angstrom kernel modification that won’t work at all on a Ubuntu image with the vanilla Ubuntu kernel.</p>
<p>Back to the issue of 1.8 max voltage. You have a couple of options in your design:</p>
<ul>
<li><span style="color: #000000;"><em>Added Jan 25: Use Port 9 Pin 32 as your voltage source, if your analog sensor can work on 1.8V</em></span></li>
<li>Use a couple of high precision resistors that can knock 3.3V or 5V down to exactly 1.8V</li>
<li>Use a couple of garden variety resistors to knock the voltage below 1.8V, then modify your software to adjust for the difference</li>
</ul>
<p>Being lazy, I’m going with the latter approach. Being very lazy, I’m not even bothering to hook up the resistors – as shown in the screenshot below, I’m using a tiny breakout board to do the work.</p>
<p>Specifically, this is a <a href="http://www.sparkfun.com/products/8745">Sparkfun Logic Level Converter &#8211; BOB-08745</a>. You’ll see this part recommended quite often in Beagleboard/Beaglebone circles, since it is an inexpensive solution that can handle a range of voltages, and supports 2-way conversion (necessary for I2C).</p>
<p>For the purpose of analog input I’m not using the board as intended &#8211; I&#8217;m taking advantage of a semi-documented hack. The RX pins on this board just use a voltage divider: the voltage going into the “HV” pins comes out as half the amount from the LV pins. The circuit for this, taken from the <a href="http://www.sparkfun.com/datasheets/BreakoutBoards/Level-Converter-v10.pdf">BOB-08745 schematic</a>, is shown below.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-6-23-53-PM.jpg"><img class="aligncenter size-full wp-image-1103" title="Voltage divider for analog input" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-6-23-53-PM.jpg" alt="" width="121" height="192" /></a></p>
<p>If you don’t have a BOB-08745, you can just use a couple of 10K resistors.</p>
<p>Before actually using this type of circuit, measure what voltage you get from the LV end of the voltage divider if the HV end is connected directly to 3.3V. If it isn’t below 1.8V, figure out what’s wrong before you hook it up to the Beaglebone. (Red and underlined, remember?) Don’t worry if the reading isn’t exactly 50% &#8211; we will calibrate the software to handle the variance.</p>
<p>The 2 analog sensors I’m using are a 10K potentiometer and an analog thermistor (temperature sensor), the <a href="http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en027103">Microchip MCP9700A</a>.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/Circuit.jpg"><img class="aligncenter size-full wp-image-1104" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/Circuit.jpg" alt="" width="2304" height="1728" /></a></p>
<p>As you can see from the photos, the connections are:</p>
<p>- Potentiometer and MCP9700A:</p>
<ul>
<li>Input pin to 3.3V (which connects to pins 3 or 4 of Port 9 on the Beaglebone),</li>
<li>Ground pin to ground (connects to pins 1 or 2 of Port 9 of the Beaglebone),</li>
<li>Output pin to one of the RXI pins on the Sparkfun level converter (or to the HV pin on the voltage divider circuit)</li>
<li><em><span style="color: #000000;">Added Jan 25: An alternative for the potentiometer is to connect the input pin to Port 9 Pin 32 (VDD_ADC)., and the output pin directly to the Beaglebone AIN0 pin (pin 39 on Port 9)</span></em></li>
</ul>
<p>- Sparkfun level converter:</p>
<ul>
<li>HV to 3.3V</li>
<li>HV GND and LV GND to Ground</li>
<li>LV RXO for the potentiometer to the Beaglebone AIN0 pin (pin 39 on Port 9, or the outside pin of the 4th row from the “bottom” &#8211; the end opposite the Ethernet port)</li>
<li>LV RXO for the MCP9700A to the Beaglebone AIN1 pin (pin 40 on Port 9, or the inside pin of the 4th row)</li>
</ul>
<p>Note that the LV pin on the level converter isn’t used, since we are just interested in the voltage divider.</p>
<p>The definitive guide to the Beaglebone pin connections is the System Reference Manual. For this project we are just using Port 9, so you can refer to the table below:</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-3-38-57-PM.jpg"><img class="aligncenter size-full wp-image-1102" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-3-38-57-PM.jpg" alt="" width="782" height="801" /></a></p>
<h2>Testing Analog Input</h2>
<p>Remember all that stuff about pin muxing from the first article? You can forget about it for analog in.</p>
<p>As you can see by looking at Table 12 of the Beaglebone System Reference Manual (part of which is shown below), the mux table for all of the analog in pins (AIN1 to AIN6) is empty: the pins can only be used for analog in.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-09-16-PM.jpg"><img class="aligncenter size-full wp-image-1105" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-09-16-PM.jpg" alt="" width="768" height="215" /></a></p>
<p>There actually are entries for these pins in the file system, <em>/sys/kernel/debug/omap_mux</em>, but they have the correct setting by default, and as far as I can tell the Mode setting has no effect on the pins. (The Python code I wrote sets them anyway, but that’s admittedly more out of ignorance than caution.)</p>
<p>So, we can proceed directly to using the pins.</p>
<p>Let’s start with the potentiometer on analog 0 (pin 39 of Port 9). To get the current reading from the pot, enter the following (yes, it’s ain1 for analog 0 – go figure):</p>
<p><em>[Update May 5: In kernel version 3.2.14, the path to the analog pins was changed slightly, from /sys/devices/platform/tsc to /sys/devices/platform/omap/tsc.  The following examples use the original path]</em></p>
<pre>root@beaglebone:~# cat /sys/devices/platform/tsc/ain1
 1807</pre>
<p>A number should be displayed. Turn the pot all the way up and repeat. You’ll see the maximum value.</p>
<p>For me, it’s 3779. Or 3775. Or 3776. It drifts around a little. Go figure.</p>
<p>The analog input pins on the Beaglebone are 12-bit, so the maximum possible value is 4096. This represents a value of 1.8V. At 3779, it’s reading 3779/4096 * 1.8V, or 1.66V, which is about what you would expect with a 10K/10K voltage divider with 3.3V input.</p>
<p>Now, check the MCP7200A thermometer on analog 1 (again, the analog index is off by 1, so it&#8217;s ain2):</p>
<pre>root@beaglebone:~# cat /sys/devices/platform/tsc/ain2
 826</pre>
<p>You should get a relatively low value: if it’s above 1000, either you are in hell or your thermistor isn&#8217;t hooked up correctly.</p>
<p>The formula for converting this reading to a temperature is:</p>
<p>(milliVolts – 500) / 10</p>
<p>The 826 reading I got is 826/4096 * 1.8V, or 362 mV.</p>
<p>Is it cold in here, or is it just me?</p>
<p>It’s just me. The voltage divider knocked the reading from the MCP7200A down by about half, or the actual reading is 362 * 2, or 724 mV. The temperature reading is therefore (724 – 500) / 10, or 22.4. (No, <em>that</em> isn&#8217;t cold, it’s just metric).</p>
<p>Actually, neither the MCP9700A nor this approach is very accurate. The <a href="http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en027103">MCP7200A’s datasheet</a> says it&#8217; typical accuracy is to within 1 degree C . There isn’t anything we can do to improve that, but we can make our calculation more accurate by allowing for slight variances of the resistors in our voltage divider.</p>
<p>To see what effect the voltage divider is having, temporarily hook the input to 3.3V instead of the MCP9700A’s output pin. Then check the value of /sys/devices/platform/tsc/ain2 again.</p>
<p>And again. And again.</p>
<p>I get 3765. And 3762. And 3759.</p>
<p>Given that each 10mV is a degree, that jumping about is a real problem. We’ll plug the average (call it 3762) into the code, then average a bunch of readings to get the temperature, approximately.</p>
<h2>Serial I/O</h2>
<p>The Beaglebone has 6 serial UARTs. One of those, UART0, is connected to the USB port, but that leaves us with 5 to play with. This is quite a step up from the Arduino’s single UART, or the <a href="http://www.netduino.com" target="_blank">Netduino</a>’s 2 UARTs.</p>
<p>All of these are 3.3V UARTs. This is a problem if you’re communicating with a 5V device, but only when receiving data. Some 3.3 microcontrollers, like the Netduino’s, have “5V tolerant” pins, so they can communicate directly with 5V serial devices. But, for the Beaglebone:</p>
<p><span style="text-decoration: underline;"><span style="color: #ff0000; text-decoration: underline;">NOTE: Do not connect 5V logic level signals to these pins or the board will be</span></span><br />
<span style="text-decoration: underline;"><span style="color: #ff0000; text-decoration: underline;"> damaged.</span></span></p>
<p>So sayeth the Beaglebone System Reference Manual.</p>
<p>I assume this means that connecting an UART RX pin directly to the TX pin of a 5V serial device is a bad idea. I did it for awhile, and my Beaglebone lived to tell the tale, but maybe I got lucky.</p>
<p>Were we receiving data from the Serial LCD, then a level converter would be required, like the Sparkfun BOB-08745 described earlier. (Actually a second level converter would be needed, since we would be going between 3.3Vand 5, not 3.3 and 1.8ish.)</p>
<p>However, it will be serial TX only for this project, and all 5V serial devices that I’ve come across handle 3.3V on the RX pin without problems.</p>
<p>In the demo Angstrom image, the pins are <em>not</em> enabled for UART by default. Yup, time for the black art of pin muxing again.</p>
<p>Working with UART1’s mux mode is relatively straightforward. UART1 is the Mode 0 usage for the pin, and as you may recall from <a href="http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/" target="_blank">my first article</a>, the pin name used in the file system are taken from the Mode 0 usage. To check the current settings:</p>
<pre>root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_rxd
 name: uart1_rxd.(null) (0x44e10980/0x980 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: uart1_rxd | mmc1_sdwp | d_can1_tx | NA | NA | NA | NA | NA

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_txd
 name: uart1_txd.(null) (0x44e10984/0x984 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: uart1_txd | mmc2_sdwp | d_can1_rx | NA | NA | NA | NA | NA</pre>
<p>As you can see, both are set to 0&#215;37 by default in the Angstrom demo image. This setting means they are in Mode 7 (as the 2nd line of the output confirms) and that the Receive feature is enabled for both pins.</p>
<p>Let’s briefly take a closer look at the meaning of these mux pins. In my last article I explained the Mode settings, but not the other bits. The full list of the bit settings can be found in Table 9-58 of the AM335x Technical Reference Manual &#8211; you can find a link to it <a href="http://processors.wiki.ti.com/index.php/Device:AM335x:Device_Evaluation">here</a>. I’ll save you the trouble of searching for the table in that 4500-page behemoth:</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-19-44-PM.jpg"><img class="aligncenter size-full wp-image-1107" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-19-44-PM.jpg" alt="" width="624" height="352" /></a></p>
<p>The 2 UART pins currently have a mux setting of 0&#215;37, or 0011 0111. So:</p>
<ul>
<li>The slow slew rate is selected – this might concern me if I knew what it meant.</li>
<li>The Receiver is enabled – we want that for the RX pin, not so much for the TX pin</li>
<li>The pullup/pulldown is set to pullup – not a concern for serial communication</li>
<li>The pullup/pulldown is enabled</li>
<li>The 3 mode bits are all on, to indicate mode 7</li>
</ul>
<p>We want to set both pins to Mode 0, and we also want the receiver disabled on the TX pin:</p>
<pre>root@beaglebone:~# echo 20 &gt; /sys/kernel/debug/omap_mux/uart1_rxd

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_rxd
 name: uart1_rxd.uart1_rxd (0x44e10980/0x980 = 0x0020), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE0
 signals: uart1_rxd | mmc1_sdwp | d_can1_tx | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 0 &gt; /sys/kernel/debug/omap_mux/uart1_txd

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/uart1_txd
 name: uart1_txd.uart1_txd (0x44e10984/0x984 = 0x0000), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE0
 signals: uart1_txd | mmc2_sdwp | d_can1_rx | NA | NA | NA | NA | NA</pre>
<p>Having said all that, I’m actually going to use UART2 for this project.</p>
<p>UART2 is a little trickier, since its pins have other names in the file system. Looking at Table 11 of the Beaglebone System Reference Manual, we see that UART2_TXD is pin 21, and UART2_RXD is pin 22. Table 12 (below) tells us that pin 21’s Mode 0 usage (and therefore the name used in the file system) is spi0_d0, and that UART2_RXD is the Mode 1 usage. For Pin 22, it’s spi0_sclk, and we also want to change it to Mode 1.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-21-55-PM.jpg"><img class="aligncenter size-full wp-image-1108" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/1-22-2012-7-21-55-PM.jpg" alt="" width="932" height="94" /></a></p>
<p>Here are the commands for checking the current settings, and changing the settings to use UART2:</p>
<pre>root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_d0
 name: spi0_d0.(null) (0x44e10954/0x954 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: spi0_d0 | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 1 &gt; /sys/kernel/debug/omap_mux/spi0_d0

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_d0
 name: spi0_d0.(null) (0x44e10954/0x954 = 0x0001), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE1
 signals: spi0_d0 | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_sclk
 name: spi0_sclk.(null) (0x44e10950/0x950 = 0x0037), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7
 signals: spi0_sclk | NA | NA | NA | NA | NA | NA | NA

 root@beaglebone:~# echo 21 &gt; /sys/kernel/debug/omap_mux/spi0_sclk

 root@beaglebone:~# cat /sys/kernel/debug/omap_mux/spi0_sclk
 name: spi0_sclk.(null) (0x44e10950/0x950 = 0x0021), b NA, t NA
 mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE1
 signals: spi0_sclk | NA | NA | NA | NA | NA | NA | NA</pre>
<h2>A Python Time and Temperature Display for the Beaglebone</h2>
<p>I’ve written some Python code to try out the analog and serial pins of the Beaglebone. It gets the temperature from the MCP9700A, and uses the potentiometer to set the backlight of the LCD.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/HPIM0988.jpg"><img class="aligncenter size-full wp-image-1099" title="" src="http://www.gigamegablog.com/wp-content/uploads/2012/01/HPIM0988.jpg" alt="" width="2304" height="1728" /></a></p>
<p>You can <a href="http://code.google.com/p/gigamega-micro/downloads/detail?name=serdisplay.py">download the Python program from my Google Code project page</a>: it&#8217;s just a single file, serdisplay.py.</p>
<p>From the Beaglebone command line, you can download the Python program as follows:</p>
<pre>root@beaglebone:~# wget http://gigamega-micro.googlecode.com/files/gpiotester.py</pre>
<p>I’ve tested the code with the<a href="http://www.sparkfun.com/products/10097"> Sparkfun Serial Enabled LCD Kit</a>, the <a href="http://www.sparkfun.com/products/258">Sparkfun Serial Enabled Backpack</a>. I’ve also coded support for Matrix Orbital serial LCDs, but haven’t tested that yet.</p>
<p>The code uses one Python library that isn’t included in the Angstrom demo image, python-pyserial. To install it:</p>
<pre>root@beaglebone:~# opkg install python-pyserial</pre>
<p>There is no configuration file or command line parameters yet, so any changes to the default settings (the Sparkfun Serial LCD Backpack and a 4-row 20-column LCD) should be made to the code near the top of the program:</p>
<pre># -------------- configurable settings ---------
# settings for UART1
 #DISPLAYPORT = '/dev/ttyO1'
 #RX_MUX = 'uart1_rxd'
 #TX_MUX = 'uart1_txd'
 #MUX_MODE = 0
# settings for UART2
 DISPLAYPORT = '/dev/ttyO2'
 RX_MUX = 'spi0_sclk'
 TX_MUX = 'spi0_d0'
 MUX_MODE = 1
# settings for Serial LCD
 DISPLAY_TYPE = 'SPARKFUN_KIT'
 #DISPLAY_TYPE = 'MATRIX_ORBITAL'
 #DISPLAY_TYPE = 'SPARKFUN'
# settings for analog voltage conversion
 MAX_ANALOG = 3762 # approx 4096 * (1.65/1.8), since voltage divider gives me max of 1.65
 # -- actual values of 3762 based on measurements
# settings for display updates
 TIME_UPDATE_INTERVAL = 1 # every second
 TIME_DISPLAY_ROW = 1
 TEMPERATURE_DISPLAY_ROW = 2
 LCD_NUM_ROWS = 4
 LCD_NUM_COLS = 20
# determines whether debug info is written to the console
 Debug = True
# ---------------------------------------------------------</pre>
<p>Then, just run the program as root:</p>
<pre>root@beaglebone:~# python serdisplay.py</pre>
<p>To stop the program, press Ctrl-Z to put it in the background, then kill the background job:</p>
<pre>root@beaglebone:~# kill %1</pre>
<p>If you want to keep the program running all the time, I’d recommend using the <a href="http://www.gnu.org/software/screen/">GNU Screen</a> utility:</p>
<pre>root@beaglebone:~# screen
&lt;Press enter when prompted&gt;
root@beaglebone:~# python serdisplay.py</pre>
<p>To return to the main command command prompt (leaving the Python program running in the background) press Ctrl-A D.  To go back to the Screen session at any time in the future:</p>
<pre>root@beaglebone:~# screen –r –d</pre>
<p>For troubleshooting, any error messages are written to serdisplay.log in the same directory as serdisplay.py.</p>
<h2>Programmer’s Show And Tell</h2>
<p>Since the focus of this article is the Beaglebone, not Python, I’ll just point out some Beaglebone-specific parts of the code.</p>
<p>The code which initializes the UART for the serial display is:</p>
<pre>DISPLAYPORT = '/dev/ttyO2'
 RX_MUX = 'spi0_sclk'
 TX_MUX = 'spi0_d0'
 MUX_MODE = 1
 BAUDRATE = 9600
 TIMEOUT = 3 # serial port timeout is 3 seconds - only used when reading from display
# MUX settings
 RECEIVE_ENABLE = 32
. . .
open('/sys/kernel/debug/omap_mux/' + RX_MUX, 'wb').write("%X" % (RECEIVE_ENABLE + MUX_MODE))
 # set the TX pin for Mode 0
 open('/sys/kernel/debug/omap_mux/' + TX_MUX, 'wb').write("%X" % MUX_MODE)
 serDisplay = serial.Serial(DISPLAYPORT, BAUDRATE, timeout=TIMEOUT)</pre>
<p>There are Linux character devices assigned to the BeagleBone UARTs: UART1 is /dev/ttyO1, UART2 is /dev/ttyO2, and so on.</p>
<p>From the point of view of the Python program, the Beaglebone’s UART behaves like any other serial port. The code I wrote would work unchanged (aside from the /dev name) when communicating with an XBee, or through a USB-based virtual COM port.</p>
<p>Analog input is a little more finicky. The code which reads the analog value is:</p>
<pre>def readAnalog(pinIndex):
 try:
    # add 1 to pin index to get analog pin sys filename
    reading = open("/sys/devices/platform/tsc/ain" + str(pinIndex + 1), "r").read()

    # sometimes string has trailing nulls - delete them
    val = int(re.sub(r'[^\d]+', '', reading))
    return val
 except:
    log.exception('Error in readAnalog')</pre>
<p>As indicated by the comments, I found that the value read through the file system was sometimes corrupted: it contained nulls, usually after the value, but occasionally imbedded within the value. I’m not sure if this is a Python-specific thing, or other code would also encounter the problem. In Python, you can strip out the null (and any other non-numeric) values using a regular expression:</p>
<pre>val = int(re.sub(r'[^\d]+', '', reading))</pre>
<p>From time to time, the attempt to read the analog value will throw an exception.  So, it&#8217;s best to use a try/except handler like the one above.</p>
<p>One other problem is that the analog value tends to jump around by about 5 points from one reading to the next, even when it should be constant (e.g. from the potentiometer). I adjusted for this by using an average reading for the temperature, and by ignoring potentiometer readings (i.e. LCD brightness settings) that are within 20 of the last setting.</p>
<p>Don’t forget that the analog value is from 0-4096 – 16 times more sensitive than on the Arduino &#8212;  so allow for a greater range of readings.</p>
<h2>Wrapping Up</h2>
<p>Based on my testing of the code in this project, I&#8217;ve found that the Beaglebone’s UARTs are quite reliable and pretty easy to use.  Serial communications should be a relatively easy and trouble-free addition to any Beaglebone project.</p>
<p>Analog in, on the other hand,  has room for improvement.</p>
<p>The approach I used for reading analog input in is good enough for things that don’t require precise accuracy, like the potentiometer or a light meter.  The readings returned by the MCP9700A thermistor are not as stable as they should be.</p>
<p>Fortunately, analog is not the only game in town when it comes to temperature readings, so I plan to experiment with some I2C sensors in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2012/01/22/beaglebone-coding-101-using-the-serial-and-analog-pins/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Beaglebone Coding 101: Blinking an LED</title>
		<link>http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/</link>
		<comments>http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 19:49:49 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Beagleboard]]></category>
		<category><![CDATA[Beaglebone]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1079</guid>
		<description><![CDATA[[Updated Jan 22 - various improvements to the Python sample code at the end of the article] In November, Texas Instruments, Digi-Key and the other members of Beagleboard.org, the Beaglebone.  This is a simpler, more hobbyist-friendly little brother to the &#8230; <a href="http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>[Updated Jan 22 - various improvements to the Python sample code at the end of the article]</em></p>
<p>In November, <a href="http://www.ti.com">Texas Instruments</a>, <a href="http://www.digikey.com">Digi-Key</a> and the other members of <a href="http://beagleboard.org">Beagleboard.org</a>, the <a href="http://beagleboard.org/bone">Beaglebone</a>.  This is a simpler, more hobbyist-friendly little brother to the <a href="http://beagleboard.org/hardware">Beagleboard</a> (which I&#8217;ve written about in <a href="http://www.gigamegablog.com/tag/beagleboard/">past articles</a>).</p>
<p>Compared to the Beagleboards, the Beaglebone is considerably less expensive ($90), provides access to all of its pins, is pin-compatible with 3.3V sensors and devices (aside from analog in, which is still 1.8V), and provides a more friendly &#8220;out of the box&#8221; experience.  As with the Arduino, the only thing you need to get started is a USB cable.</p>
<p>As a developer, my most pleasant surprise with the Beaglebone was the inclusion of an entry-level IDE and scripting language: the <a href="http://c9.io/">Cloud9 IDE</a> configured to run <a href="http://nodejs.org/">node.js</a> and <a href="https://github.com/jadonk/bonescript">bonescript</a>.</p>
<p>With the Beagleboards, there was no &#8220;out of the box&#8221; IDE.  There were plenty of options for developing with the Beagleboard – Texas Instrument&#8217;s Code Composer Studio, Eclipse, or the command-line GCC tools being the most prominent – but all had a fairly steep learning curve just to do something basic, like blink an LED.</p>
<p>One of the most slippery patches on that learning curve is figuring out how to convince the Linux kernel to let your code access the pins.  It&#8217;s nowhere near as simple as Arduino&#8217;s &#8220;<em>digitalwrite(13, HIGH)</em>&#8221; – or, at least, it wasn&#8217;t until bonescript came along.  Although bonescript is still in its very early stages, there is enough meat on it to give the embedded Linux newbie a friendly introduction to coding.</p>
<h2>The Circuit</h2>
<p>The circuit is your garden-variety LED configuration:</p>
<ul>
<li>an LED</li>
<li>a resistor (680R or thereabouts) connected to the negative pin of the LED</li>
<li>a jumper from the positive pin of the LED to the digital pin</li>
<li>a jumper from the resistor to ground</li>
</ul>
<p>The Beaglebone actually has 65 GPIO pins to choose from, but we&#8217;ll go with the one used by the <em>blinkled.js</em> program that is included with bonescript.  This is Pin 3 on Header 8, referred to by the <a href="http://beagleboard.org/static/BONESRM_latest.pdf">Beaglebone System Reference Manual</a> as  GPIO1_6 on Expansion B, but known to Linux as gpmc_ad6.</p>
<p>Say what?</p>
<p>Well, the &#8220;Pin 3 on Header 8&#8243; part is simple enough. If you look at the Beaglebone, Port 8 is one of the 2 double-rows of female headers,  labeled P8 on the circuit board.  (In the figure below, taken from the System Reference Manual, Port 8 is labeled &#8220;Expansion B).</p>
<div class="img aligncenter size-full wp-image-1083" style="width:598px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-5-32-10-PM.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-5-32-10-PM.png" alt="Beaglebone, showing pin P8_3 and Ground" width="598" height="582" /></a>
	<div>Beaglebone, showing pin P8_3 and Ground</div>
</div>
<p>At either end of the headers you&#8217;ll find the rows marked 1 and 2, and 45 and 46.  So, Pin 3 is the 2<sup>nd</sup> row from the top, left column, as indicated in the figure.</p>
<p>The other names for the pin, along with the locations of the ground pins, can be found in the <a href="http://beagleboard.org/static/BONESRM_latest.pdf">System Reference Manual</a>.  If you look at Table 8 – &#8220;Expansion Header P8 Pinout&#8221; (a portion of which is shown below), you&#8217;ll find the pins labeled with their default usages in the Angstrom Linux demo image (the one that comes packaged with the beaglebone on a microSD card).</p>
<div class="img aligncenter size-full wp-image-1082" style="width:586px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-7-42-03-PM.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-7-42-03-PM.png" alt="Default pin settings in Anstrom Linux" width="586" height="227" /></a>
	<div>Default pin settings in Anstrom Linux</div>
</div>
<p>Clearly, Ground is the top row of Port 8, so that&#8217;s the last bit of information we need to know to hook up the circuit.  But we&#8217;ll need to understand that part about pins having &#8220;default usages&#8221; – more on that later.</p>
<h2>Cloud9 IDE and bonescript</h2>
<p>When you boot up the Beaglebone with the microSD card from the box, the Cloud9 IDE is automatically started.  Once you have an  IP address assigned to the Beaglebone (either through its Ethernet port connection or through USB networking), you can load the Cloud9 IDE on your PC browser at http:&lt;beaglebone address&gt;:3000</p>
<p>(I haven&#8217;t tried to use USB networking myself, but the procedure for doing so is explained in <a href="http://beagleboard.org/static/beaglebone/a3/README.htm">Getting started with your new BeagleBone</a>.)</p>
<p>The Cloud9 IDE interface is pretty intuitive.  You select a source code file in the left pane, edit it in a tab in the right pane, and select Debug or Run from the toolbar to execute the code.</p>
<div class="img aligncenter size-full wp-image-1080" style="width:607px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-8-43-35-PM.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-8-43-35-PM.png" alt="Cloud9 IDE" width="607" height="454" /></a>
	<div>Cloud9 IDE</div>
</div>
<p>If you are coming at this from the Arduino, you will notice 3 significant differences from the Arduino IDE:</p>
<ul>
<li>You don&#8217;t upload your code to the board.  The Beaglebone is more like a PC than an Arduino – the code is stored on its file system, and you just run it.</li>
<li>You can debug your code.  Not Arduino&#8217;s form of debugging – print statements to the console (though you can do that too) &#8212; but real debugging, as in breakpoints, watch variables, step-by-step execution.</li>
<li>The coding language is Javascript, not C.  Specifically, it&#8217;s <a href="http://nodejs.org/">node.js</a>, which is Javascript optimized for running on a server, rather than in a browser, by way of some extra libraries.  The &#8220;server&#8221; in this case is the little old Beaglebone.  As you might imagine, node.js is not the fastest environment for running code on the Beaglebone, but for LED blinking and many other types of prototyping, it&#8217;s fast enough.</li>
</ul>
<p>Despite the differences, Arduino coders should find the transition to Cloud9 and bonescript to be quite easy.  The blinkled.js code looks very much like Arduino code.  That&#8217;s no coincidence: the README for the bonescript project, which you can find on its github page <a href="https://github.com/jadonk/bonescript">here</a>,  says that the goal is &#8220;to have something that provides most of the Arduino functions and is generally usable by Summer 2012&#8243;.</p>
<pre><strong>var</strong> ledPin <strong>=</strong> bone.P8_3;
<strong>var</strong> ledPin2 <strong>=</strong> bone.USR3;

setup <strong>=</strong> <strong>function</strong>() {
    pinMode(ledPin, OUTPUT);
    pinMode(ledPin2, OUTPUT);
};

loop <strong>=</strong> <strong>function</strong>() {
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin2, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
    delay(1000);
};</pre>
<p>This code from blinkled.js does the following:</p>
<ul>
<li>defines 2 pins, P8_3 (Port 8, pin 3) and USR3 (which is one of the built-in LEDS on the board, next to the Ethernet port)</li>
<li>sets these pins for Output</li>
<li>loops, turning these 2 LEDs on and off, once per second, ad infinitum</li>
</ul>
<p>If you&#8217;ve attached an LED to pin 3, and you run blinkled.js in Cloud9, you should find it blinking happily away. (There is a dropdown button next to the Run and Debug toolbar icons in Cloud9 to let you choose the file).</p>
<p>It&#8217;s that simple.</p>
<p>I lie.</p>
<p>There is actually considerable complexity behind the code which creates those 2 pin objects, <em>bone.P8_3</em> and <em>bone.USR3</em>.  The complicated code is in one of the 2 &#8220;library&#8221; files in the bonescript folder, <em>index.js</em>.</p>
<h2>Pins and Muxing</h2>
<p>Before we dive into the index.js code, let&#8217;s return to the <a href="http://beagleboard.org/static/BONESRM_latest.pdf">Beaglebone System Reference Manual</a>.  As you&#8217;ll recall, I earlier referred to the &#8220;default usage&#8221; on Port 8 Pin 3.  It has other usages, and the process of telling the board how you want to use that pin is called muxing (short for multiplexing).</p>
<p>The available usages of the pin, and all of the others on the Port 8, are listed in Tables 9 (the first part of which is shown below) and 10 of the System Reference Manual.  Each pin can have up to 8 uses, &#8220;mux mode&#8221; 0 through 7.  The default setting in the Angstrom Image is generally, but not always, mode 7.  Table 8 is the definitive guide to Angstrom&#8217;s default mux setting for each pin.</p>
<div class="img aligncenter size-full wp-image-1081" style="width:724px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-8-06-20-PM.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2012/01/04-01-2012-8-06-20-PM.png" alt="Pin Mux settings from the System Reference Manual" width="724" height="228" /></a>
	<div>Pin Mux settings from the System Reference Manual</div>
</div>
<p>(Incidentally, other Linux distributions for the Beaglebone, such as Ubuntu, will have their own default mux settings.  The board doesn&#8217;t control the mux settings, the software does.  The developers of the Angstrom Linux image on the SD card selected their defaults to be the most commonly used ones by hobbyists, providing a good out-of-the-box experience.)</p>
<p>If you Google &#8220;Beagleboard mux&#8221;, you&#8217;ll find lots of pages explaining the various ways in which you can change the mux setting.  Many of them refer to U-Boot configuration and kernel modules, which are complicated and, fortunately, no longer necessary.  There has been a lot of work done recently at making the mux settings accessible to &#8220;userland&#8221; code by way of the Linux file system.  If you (or your code) wants to read or change the mux setting, it just needs to read or write to a file.</p>
<p>Great.  So which file?</p>
<p>This information used to be hard to come by, scattering amongst various forum and blog posts, or hidden inside code in U-Boot or the linux kernel.  However, if you&#8217;re learning to code with the Beaglebone, I think the best way to learn the mux file system is to look at how bonescript handles it.</p>
<h2>Muxing the bonescript way</h2>
<p>So, back to the Cloud9 IDE.  This time, open up the index.js file in the bonescript directory.  (Note that this part of bonescript is in active development and is likely to change by the time you read this, but the underlying file system will still be the same)</p>
<p>A little ways into the code (line 39 in the current release, bonescript 1.0-r10), you&#8217;ll find the following:</p>
<pre><strong>var</strong> gpio0 <strong>=</strong> 0;
<strong>var</strong> gpio1 <strong>=</strong> gpio0<strong>+</strong>32;
<strong>var</strong> gpio2 <strong>=</strong> gpio1<strong>+</strong>32;
<strong>var</strong> gpio3 <strong>=</strong> gpio2<strong>+</strong>32;

bone <strong>=</strong> exports.bone <strong>=</strong>
{
    P8_1<strong>:</strong> { name<strong>:</strong> "DGND" },
    P8_2<strong>:</strong> { name<strong>:</strong> "DGND" },
    P8_3<strong>:</strong> { name<strong>:</strong> "GPIO1_6", gpio<strong>:</strong> gpio1<strong>+</strong>6, mux<strong>:</strong> "gpmc_ad6" },
    P8_4<strong>:</strong> { name<strong>:</strong> "GPIO1_7", gpio<strong>:</strong> gpio1<strong>+</strong>7, mux<strong>:</strong> "gpmc_ad7" },
    P8_5<strong>:</strong> { name<strong>:</strong> "GPIO1_2", gpio<strong>:</strong> gpio1<strong>+</strong>2, mux<strong>:</strong> "gpmc_ad2" },
    P8_6<strong>:</strong> { name<strong>:</strong> "GPIO1_3", gpio<strong>:</strong> gpio1<strong>+</strong>3, mux<strong>:</strong> "gpmc_ad3" },
    P8_7<strong>:</strong> { name<strong>:</strong> "TIMER4", gpio<strong>:</strong> gpio2<strong>+</strong>2, mux<strong>:</strong> "gpmc_advn_ale" },
    P8_8<strong>:</strong> { name<strong>:</strong> "TIMER7", gpio<strong>:</strong> gpio2<strong>+</strong>3, mux<strong>:</strong> "gpmc_oen_ren" },
. . .
    USR0<strong>:</strong> { name<strong>:</strong> "USR0", gpio<strong>:</strong> gpio1<strong>+</strong>21, led<strong>:</strong> "usr0", mux<strong>:</strong> "gpmc_a5" },
    USR1<strong>:</strong> { name<strong>:</strong> "USR1", gpio<strong>:</strong> gpio1<strong>+</strong>22, led<strong>:</strong> "usr1", mux<strong>:</strong> "gpmc_a6" },
    USR2<strong>:</strong> { name<strong>:</strong> "USR2", gpio<strong>:</strong> gpio1<strong>+</strong>23, led<strong>:</strong> "usr2", mux<strong>:</strong> "gpmc_a7" },
    USR3<strong>:</strong> { name<strong>:</strong> "USR3", gpio<strong>:</strong> gpio1<strong>+</strong>24, led<strong>:</strong> "usr3", mux<strong>:</strong> "gpmc_a8" }</pre>
<p>This table contains 3 important pieces of information:</p>
<ol>
<li>the label that bonescript uses to identify the pins (P8_1, P8_2, etc)</li>
<li>the GPIO pin number (P8_3 is <em>gpio1+6</em>, or 38)</li>
<li>the mux label (P8_3 is <em>gpmc_ad6</em>)</li>
</ol>
<p>The GPIO pin number tells you the directory name you will use to read from or write to the pin.  The mux label tells you the filename you will use to read or write the mux setting.</p>
<p>Let&#8217;s start with the mux setting.  This is handled by some code just below the exports.bone table:</p>
<pre>if(pin.mux) {
 try {
    var muxfile = fs.openSync(
      "/sys/kernel/debug/omap_mux/" + pin.mux, "w"
      );
    fs.writeSync(muxfile, "7", null);
 } catch(ex3) {
    console.log("" + ex3);
    console.log("Unable to configure pinmux for: " + pin.name +
      " (" + pin.mux + ")");
. . .</pre>
<p>There is more to the error handling, but the important part is the reference to &#8220;<em>/sys/kernel/debug/omap_mux/</em>&#8221; + pin.mux.  This is the file used to read and write the mux setting.  In the case of Port 8 Pin 3, the full path is <em>/sys/kernel/debug/omap_mux/gpmc_ad6</em>.</p>
<p>This is the part that is newcomers to pin muxing often trip over: if you want to set a pin to be a GPIO pin, your code needs to reference a filename that appears to be intended for a different usage of the pin (gpmc_ad6).  The mux filename isn&#8217;t taken from its intended usage, it&#8217;s taken from its mode 0 usage.  The mode 0 usage for Port 8 Pin 3 is gpmc_ad6 – we know this from the table in the bonescript code, but the definitive reference for the Beaglebone pin mux modes are Tables 9 and 11 of the <a href="http://beagleboard.org/static/BONESRM_latest.pdf">Beaglebone System Reference Manual</a>.</p>
<p>Having opened the file (<em>fs.openSync</em>), the bonescript code writes a 7 to it (<em>fs.writeSync</em>).  This, as you probably guessed, sets the mux mode to 7, the GPIO mode for that pin.  The process of setting mux modes isn&#8217;t quite as simple as &#8220;write the  mode to a file&#8221;:  the mux mode setting also affects other aspects of the pin, such as whether it can be used for input.  The bonescript code shown above is actually correct only for setting pins to be GPIO Output pins.  The bonescript project will soon support other mux mode settings.</p>
<h2>Blinking LEDs the bonescript way</h2>
<p>Having set the pin to be in digital output mode, the next task is to set it high or low.  You&#8217;ll recall that this was handled in blinkled.js by calling a function called digitalWrite, same as the Arduino does.</p>
<p>The source code for digitalWrite can be found further down in index.js:</p>
<pre>digitalWrite <strong>=</strong> exports.digitalWrite <strong>=</strong> <strong>function</strong>(pin, value)
{
    fs.writeFileSync(gpio[pin.gpio].path, "" <strong>+</strong> value);
};</pre>
<p>OK, so it&#8217;s writing a value to a file, either HIGH (defined as 1) or LOW (0).  But which file?</p>
<p>The code to set that &#8220;path&#8221; property also in index.js, just below where the pin mux setting was done:</p>
<pre>try {
    try {
        fs.writeFileSync("/sys/class/gpio/export", "" + n);
    } catch(ex2) {
        // TODO: If the file is already exported, can we know who did
        // did it so that we aren't opening it twice?  In general, this
        // shouldn't be an error until we have some better resource
        // management.
        //console.log(ex2);
        //console.log("Unable to export gpio: " + n);
    }
    fs.writeFileSync("/sys/class/gpio/gpio" + n + "/direction",
        mode);
    gpio[n].path = "/sys/class/gpio/gpio" + n + "/value";
    return(true);
} catch(ex) {
    // Perhaps we couldn't open it because it was allocated as an LED
    if(pin.led) {
        fs.writeFileSync(
            "/sys/class/leds/beaglebone::" + pin.led + "/trigger",
            "gpio");
        if(mode == OUTPUT) {
            gpio[n].path =
                "/sys/class/leds/beaglebone::" + pin.led +
                "/brightness";
        } else {
            gpio[n].path =
                "/sys/class/leds/beaglebone::" + pin.led +
                "/gpio";
        }
        return(true);
    }
}</pre>
<p>The first thing it does is try to write to a file named &#8220;export&#8221;, specifically , &#8220;/sys/class/gpio/export&#8221;.  The value written is the GPIO pin number, which you&#8217;ll recall was specified in the table earlier in index.js.  For Port 8 Pin 3, it was defined as gpio1+6, or 38.</p>
<p>The export file is a funky weird-ass file: when you write a pin number to it, it (well, the kernel process which monitors that file) creates a directory and a bunch of files that provide interfaces for accessing the pin.  The directory is created at <em>/sys/class/gpio/export/gpioNN</em>. In the case of Port 8 Pin 3, that&#8217;s <em>/sys/class/gpio/export/gpio38</em>.</p>
<p>For the purpose of using a GPIO pin, the two most important files in the <em>gpioNN</em> directory are named <em>direction</em> and <em>value</em>.</p>
<p>The <em>direction</em> file determines whether the pin is going to be used for reading or writing.  As mentioned earlier, you can&#8217;t use a pin for reading without setting flipping a bit in the mux mode setting, so our only choice at this point is output.   The bonescript code writes the value &#8220;out&#8221; to the <em>direction</em> file (i.e. to <em>/sys/class/gpio/export/gpio38/direction</em>).</p>
<p>The code then saves the path to the <em>value</em> file (i.e. <em>/sys/class/gpio/export/gpio38/)</em> in the pin&#8217;s <em>path</em> property.  This, then, explains what the code in the digitalWrite function is doing:</p>
<pre>fs.writeFileSync(gpio[pin.gpio].path, "" <strong>+</strong> value);</pre>
<p>It writes a 1 to the value file (i.e. /sys/class/gpio/export/gpio38/value) to set the pin high (and the turn the LED on) and a 0 to set it low (and the LED off).</p>
<p>But wait, there&#8217;s more!</p>
<p>The bonescript code shown above also has an error handler.</p>
<p>Writing to the export file also tells the kernel that you intend to use that pin.  If the pin is already being used by something more important than your dinky userland application (i.e. the kernel or one of its pals), it will helpfully toss an error at you.</p>
<p>Generally, when your attempt to export a pin fails, you have no option but to go away and sulk.  Something is using that pin, and it might be a hardware driver that won&#8217;t be giving it up any time soon (such as the SD card socket, or an LCD).  There are ways of tracking down what&#8217;s using it, but I won&#8217;t cover them in this post.</p>
<p>One possibility is that the GPIO pin is being used by one of the built-in &#8220;user LEDs&#8221;, USR0 – USR3.  As you can see from the final entries in the bonescript mux table, those LEDs are connected to GPIOs 53-56.  So, the bonescript code checks to see if you&#8217;re trying to write to those GPIOs – if so, it assumes you want to access the user LEDs, and redirects you to their address.</p>
<p>These user LEDs are accessed through a different part of the file system than the GPIOs – technically, they are part of the Beaglebone board, not part of the CPU.  So, they are accessed through the <em>/sys/class/leds/beaglebone</em> directory, not <em>/sys/class/gpio</em>.</p>
<p>The Beagleboard (the &#8216;bone&#8217;s big brother) also has user LEDs, and they are accessed in basically the same way there, so you can find a good explanation of how to write to them in some of the articles written for the Beagleboard.  The command line interface is explained in <a href="http://elinux.org/EBC_Exercise_02_Flashing_an_LED">this article on eLinux</a>.  For C language code that interfaces to the user LEDs, see <a href="http://www.lvr.com/code/led_control.c">this sample</a> from Jan Axelson&#8217;s <a href="http://www.amazon.com/USB-Embedded-Hosts-Developers-Guide/dp/1931448248/ref=ntt_at_ep_dpt_3">USB Embedded Hosts: The Developer&#8217;s Guide</a>.  (This, by the way, is one of the few books currently available that specifically covers Beagleboard programming).</p>
<h2>Blinking LEDs the Python Way</h2>
<p>The directories and paths used by the bonescript code can also be used from other programming languages: pretty much anything that runs on Linux can read and write from the file system.</p>
<p>Here is my own humble contribution, a snippet of Python code which blinks the USR2, USR3 and Port 8 Pin 3 ten times.  It has the advantage of distilling the bonescript code down to the bare bones needed to access that particular pin.</p>
<p><em>[Updated Jan 22 - added support for User LEDs 2 and 3, handle case where pin already exported, and simplified  the file I/O syntax:]</em></p>
<pre class="brush: python; title: ; notranslate">
import time

# put Port 8 Pin 3 into mode 7 (GPIO)
open('/sys/kernel/debug/omap_mux/gpmc_ad6', 'wb').write(&quot;%X&quot; % 7)

try:
   # check to see if the pin is already exported
   open('/sys/class/gpio/gpio38/direction').read()
except:
   # it isn't, so export it
   print(&quot;exporting GPIO 38&quot;)
   open('/sys/class/gpio/export', 'w').write('38')

# set Port 8 Pin 3 for output
open('/sys/class/gpio/gpio38/direction', 'w').write('out')
# we will assume that USR1 and USR 2 are already configured as LEDs

for i in range(10):
   # turn on USR1 and external LED
   open('/sys/class/gpio/gpio38/value', 'w').write(&quot;1&quot;)
   open(&quot;/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness&quot;, 'w').write(&quot;1&quot;)
   # turn off USR2
   open(&quot;/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness&quot;, 'w').write(&quot;0&quot;)

   time.sleep(1)

   # turn off USR1 and external LED
   open('/sys/class/gpio/gpio38/value', 'w').write(&quot;0&quot;)
   open(&quot;/sys/devices/platform/leds-gpio/leds/beaglebone::usr1/brightness&quot;, 'w').write(&quot;0&quot;)
   # turn on USR2
   open(&quot;/sys/devices/platform/leds-gpio/leds/beaglebone::usr2/brightness&quot;, 'w').write(&quot;1&quot;)

   time.sleep(1)

# cleanup - remove GPIO38 folder from file system
open('/sys/class/gpio/unexport', 'w').write('38')
</pre>
<p> The Python code also demonstrates something that the bonescript code doesn&#8217;t handle.  To be a nice little userland app and clean up after yourself, you can write the GPIO pin number to /sys/class/gpio/unexport.  This doesn&#8217;t &#8220;release&#8221; the GPIO to other apps – you never had it locked for your exclusive use in the first place – so unexport&#8217;ing is just a convention to make the gpio file system is a little more manageable.</p>
<p>Since python is already installed on the Angstrom image, you can download the file and run it as follows:</p>
<pre>wget http://gigamega-micro.googlecode.com/files/gpiotester.py
python gpiotester.py</pre>
<h2>Wrapping Up</h2>
<p>If you think that&#8217;s a lot of work in order to blink an LED, you should have tried it a few years ago, when the Beagleboard was first released.</p>
<p>Back in the day, to do anything with a GPIO pin you pretty much had to be an embedded Linux guru, or beg for crumbs of knowledge from the guru&#8217;s table.  (Oh, and good luck getting your LED to light up on 1.8V.  You kids have it easy these days!)</p>
<p>The Beaglebone arrives at a time when the embedded Linux device market is growing by leaps and bounds, both in terms or hardware and development tools.  As a hobbyist (or a budding professional), this is a good time to hop on board the platform.</p>
<p>Incidentally, while the Beaglebone platform is geared for hobbyists and prototypers, the chip it uses is very much targeted at professionals.  The Texas Instruments Sitara AM3359 is a descendent of (and largely code compatible with) the storied OMAP chip family, which powers a lot of consumer gadgets: many of Nokia&#8217;s high-end smartphones like the E90, Motorola&#8217;s Droid line of Android smartphones, the Nook Color and the Kindle Fire.</p>
<p>If you can get to a root command line on one of those devices, you can probably set a GPIO high and low using the same code as above (and if you&#8217;re lucky, cause an inglorious crash).  How cool is that?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2012/01/05/beaglebone-coding-101-blinking-an-led/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Nimbits Gadget Updated</title>
		<link>http://www.gigamegablog.com/2011/12/14/nimbits-gadget-updated/</link>
		<comments>http://www.gigamegablog.com/2011/12/14/nimbits-gadget-updated/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 00:13:54 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[nimbits]]></category>

		<guid isPermaLink="false">http://www.gigamegablog.com/?p=1072</guid>
		<description><![CDATA[I&#8217;ve added a couple of new settings to the Nimbits Google Gadget: graph width and gadget height.  I&#8217;ve updated the &#8220;Minding the Data Store&#8221; article with the details. Nimbits itself was recently updated to version 3.3, and the its web site &#8230; <a href="http://www.gigamegablog.com/2011/12/14/nimbits-gadget-updated/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve added a couple of new settings to the <a href="http://www.google.com/ig/directory?hl=en&amp;gl=us&amp;type=gadgets&amp;url=www.gigamegablog.com/gadgets/nimbits.xml">Nimbits Google Gadget</a>: graph width and gadget height.  I&#8217;ve updated the &#8220;<a href="http://www.gigamegablog.com/2011/05/21/a-nimbits-gadget-minding-the-data-store/">Minding the Data Store</a>&#8221; article with the details.<a href="http://www.gigamegablog.com/wp-content/uploads/2011/12/14-12-2011-7-10-18-PM.jpg"><img class="aligncenter size-full wp-image-1073" title="" src="http://www.gigamegablog.com/wp-content/uploads/2011/12/14-12-2011-7-10-18-PM.jpg" alt="" width="591" height="180" /></a></p>
<p><a href="http://www.nimbits.com/">Nimbits </a>itself was recently updated to version 3.3, and the <a href="http://www.nimbits.com/">its web site</a> has been reorganized to make all of the documentation easy to find.  If you are new to Nimbits, or haven&#8217;t seen it for a while, check it out!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2011/12/14/nimbits-gadget-updated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Pachube Gadget: Programmer&#8217;s Show and Tell</title>
		<link>http://www.gigamegablog.com/2011/11/23/a-pachube-gadget-programmers-show-and-tell/</link>
		<comments>http://www.gigamegablog.com/2011/11/23/a-pachube-gadget-programmers-show-and-tell/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 01:10:47 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pachube]]></category>

		<guid isPermaLink="false">http://gigamegatech.com/?p=1049</guid>
		<description><![CDATA[In my last post, I introduced a Google gadget that I wrote to display graphs of Pachube datastreams.  This gadget takes advantage of the Pachube API to add a few new features that I couldn&#8217;t find in other Pachube gadgets, &#8230; <a href="http://www.gigamegablog.com/2011/11/23/a-pachube-gadget-programmers-show-and-tell/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://gigamegablog.com/2011/11/05/a-pachube-google-gadget-size-matters/">my last post</a>, I introduced <a href="http://www.google.com/ig/directory?type=gadgets&amp;url=www.gigamegablog.com/gadgets/gm-pachube.xml">a Google gadget</a> that I wrote to display graphs of <a href="http://www.pachube.com">Pachube</a> datastreams.  This gadget takes advantage of the Pachube API to add a few new features that I couldn&#8217;t find in other Pachube gadgets, like sizable graphs and support for local time zones.</p>
<p>In this article, I&#8217;d like to explore parts of the Javascript code in the gadget, and describe how they interface with the Pachube API.</p>
<h2>Viewing the Source Code</h2>
<p>As with any iGoogle Gadget, the source code can be viewed by clicking the &#8220;View source&#8221; link in the bottom right of the gadget&#8217;s iGoogle Gadget Directory page – <a href="http://www.google.com/ig/directory?type=gadgets&amp;url=www.gigamegablog.com/gadgets/gm-pachube.xml">my gadget&#8217;s page is here</a>.</p>
<p>However, this will only show you the XML definition for the gadget, since I&#8217;ve put the Javascript in a separate file.  My gadget has 2 different views defined in the XML file, normal and &#8220;canvas&#8221; (i.e. maximized), as you can see at the bottom of the XML file.  Using a separate Javascript file allows the 2 views to use the same code.  Here are direct links to the XML and Javascript files.</p>
<ul>
<li>XML: <a href="http://www.gigamegablog.com/gadgets/gm-pachube.xml">http://www.gigamegablog.com/gadgets/gm-pachube.xml</a></li>
<li>Javascript: <a href="http://www.gigamegablog.com/gadgets/gm-pachube.js">http://www.gigamegablog.com/gadgets/gm-pachube.js</a>.  (It&#8217;s OK to click on it.   Since this Javascript can&#8217;t execute outside of Google&#8217;s gadget container, your browser will just display the source code instead of running it.  Or, you can just right-click the link and save it as a file, you big baby. <img src='http://www.gigamegablog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</li>
</ul>
<h2>The Pachube API</h2>
<p><a href="http://api.pachube.com/v2/">Pachube&#8217;s API documentation</a> is quite good overall, but it can be a little difficult to find the details for a particular feature.</p>
<p>The graphing API I&#8217;m using, for example, is in the &#8220;<a href="http://api.pachube.com/v2/#read-datastream-get-v2-feeds-feed-id-datastreams-datastream-id">Read datastream &#8211; GET  v2/feeds/&lt;feed_id&gt;/datastreams/&lt;datastream_id&gt;</a>&#8221; section.  It&#8217;s just barely there, actually – a passing reference to the all-important PNG parameter, along with a table of parameters you can pass to the API.  (A better way to learn the graphing API is to use Pachube&#8217;s Graph Builder – see the next section).</p>
<p>There are a lot of options for setting the time range of a graph, including some that my gadget doesn&#8217;t support, such as a specific end date.  These options are described in the &#8220;<a href="http://api.pachube.com/v2/#historical-queries">Historical Queries</a>&#8221; section tucked away at the end of that documentation page.</p>
<p>To get a list of datastreams in a feed, I use the &#8220;Read feed&#8221; API, described <a href="http://api.pachube.com/v2/#read-feed-get-v2-feeds-feed-id">here</a>.  As you can see from the JSON example in that section, this is a very handy API that returns a lot of information about the feed and each datastream.</p>
<p>An API key must be passed with most API calls, even when accessing Public feeds.     The <a href="http://api.pachube.com/#authentication">mechanism for passing the key</a> is described on a separate page, the <a href="http://api.pachube.com/">API Overview</a>.  That page also describes <a href="http://api.pachube.com/#time-zones">the timezone parameter</a>.  You&#8217;ll find more information on the API key and time zones later in this post.</p>
<h2>Pachube Graph Builder</h2>
<p>The best way to learn the API syntax for generating a graph is Pachube&#8217;s Graph Builder.  To display it, go to your Feed&#8217;s page on Pachube&#8217;s web site, then click on the gear icon in the lower right of the graph for a datastream, as shown below.</p>
<div class="img aligncenter size-full wp-image-1051" style="width:814px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-7-14-24-PM.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-7-14-24-PM.jpg" alt="Launching the Graph Builder" width="814" height="388" /></a>
	<div>Launching the Graph Builder</div>
</div>
<p>The Graph Builder page allows you to interactively try out various graph parameters, then copy a URL that calls the API to generate that graph.</p>
<div class="img aligncenter size-full wp-image-1052" style="width:917px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-7-41-26-PM.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-7-41-26-PM.jpg" alt="Pachube Graph Builder" width="917" height="600" /></a>
	<div>Pachube Graph Builder</div>
</div>
<h2>Pachube Graph API</h2>
<p>The URL that you&#8217;ll get from the Graph Builder will look something like this:</p>
<pre><a href="https://api.pachube.com/v2/feeds/37080/datastreams/JadePlant.png?width=500&amp;height=300&amp;colour=%238024f1&amp;duration=3hours&amp;title=Jade Plant Moisture&amp;show_axis_labels=true&amp;detailed_grid=true&amp;timezone=Eastern Time (US &amp;amp; Canada)">https://api.pachube.com/v2/feeds/37080/datastreams/JadePlant.png?</a>
   <a href="https://api.pachube.com/v2/feeds/37080/datastreams/JadePlant.png?width=500&amp;height=300&amp;colour=%238024f1&amp;duration=3hours&amp;title=Jade Plant Moisture&amp;show_axis_labels=true&amp;detailed_grid=true&amp;timezone=Eastern Time (US &amp;amp; Canada)"> width=500&amp;height=300&amp;colour=%238024f1&amp;duration=3hours </a>
   <a href="https://api.pachube.com/v2/feeds/37080/datastreams/JadePlant.png?width=500&amp;height=300&amp;colour=%238024f1&amp;duration=3hours&amp;title=Jade Plant Moisture&amp;show_axis_labels=true&amp;detailed_grid=true&amp;timezone=Eastern Time (US &amp;amp; Canada)">&amp;title=Jade Plant Moisture&amp;show_axis_labels=true &amp;detailed_grid=true</a>
   <a href="https://api.pachube.com/v2/feeds/37080/datastreams/JadePlant.png?width=500&amp;height=300&amp;colour=%238024f1&amp;duration=3hours&amp;title=Jade Plant Moisture&amp;show_axis_labels=true&amp;detailed_grid=true&amp;timezone=Eastern Time (US &amp;amp; Canada)">&amp;timezone=Eastern Time (US &amp;amp; Canada)</a></pre>
<p>All Pachube API URLs have the same basic layout, following the <a href="http://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> standard:</p>
<ul>
<li><em>https://api.pachube.com/v2</em> &#8211; All API URLs start with this.  (You can use the non-secure http:// prefix if your coding platform doesn&#8217;t support https, such as an Arduino.)<br />
The V2 refers to Version 2 of the API.  Version 1, which uses a different syntax, is &#8220;deprecated&#8221; (i.e. still supported, but use is discouraged).  Some of the examples you&#8217;ll find on the Web use the V1 API: if there is one /v2 in the URL, it&#8217;s a version 1 call.</li>
<li><em>feeds/37080</em>  - All API URLs for a specific feed will identify the feed # this way.</li>
<li><em>Datastreams/JadePlant.png</em> – All API URLs which deal with a specific datastream will identify it using its ID field (in this case, &#8220;JadePlant&#8221;).  The &#8220;.png&#8221; part is what tells the API that you want a graph.  If you replace that with &#8220;.xml&#8221;, you&#8217;ll get back XML data about your datastream instead.</li>
<li><em>?&lt;parms&gt;</em> – The parameters that follow the question mark are specific to the API call you are making.<br />
Pachube&#8217;s API is pretty easy-going about these parameters: if you pass ones that don&#8217;t apply to the API call, or even ones that don&#8217;t exist at all, the API will just ignore them.<br />
If you&#8217;re familiar with URLs, you might have noticed that the above URL example (copied from the Graph Builder) contains an invalid parameter: the &amp;timezone parameter contains spaces and an ampersand that need to be properly &#8220;escaped&#8221; when including in a URL.  The API doesn&#8217;t tell you this, it just ignores the timezone parameter.  (And, as a result, the X axis of the graph shows UTC times, the default, rather than EST times).</li>
</ul>
<h2>API Keys</h2>
<p>I have to admit that I don&#8217;t have a firm grasp on which APIs and feeds require authentication.  I&#8217;m tempted to just write &#8220;always pass an API key – it can&#8217;t hurt&#8221;.  But that&#8217;s way too simple for this blog, so here&#8217;s my best <span style="text-decoration: line-through;">guess</span> explanation of how it works…</p>
<p>If you tried pasting URLs from the Graph Builder into your browser, you probably noticed that no login was required, and no API key is being passed.  As far as I know, an API key is never required for a graph of a public datastream.</p>
<p>However, the other API used by the gadget, which retrieves a list of datastreams for a specified feed, does require authentication, even if the feed is public.  If you have a neglected browser from which you’ve never logged into Pachube (that blue E icon will probably do), try accessing  the following URL</p>
<pre><a title="http://api.pachube.com/v2/feeds/37080.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29" href="http://api.pachube.com/v2/feeds/37080.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29">http://api.pachube.com/v2/feeds/37080.json? </a>
   <a title="http://api.pachube.com/v2/feeds/37080.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29" href="http://api.pachube.com/v2/feeds/37080.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29">timezone=Eastern%20Time%20%28US%20%26%20Canada%29</a></pre>
<p>You should get a pop-up authentication prompt.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-10-21-PM.jpg"><img class="aligncenter size-full wp-image-1054" title="" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-10-21-PM.jpg" alt="" width="327" height="353" /></a></p>
<p>Private feeds always require authentication, even for a graph.  For example, the following should definitely display an authentication prompt, unless you are a nefarious hacker.</p>
<pre><a href="http://api.pachube.com/v2/feeds/39460.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29">http://api.pachube.com/v2/feeds/39460.json? </a>
   <a href="http://api.pachube.com/v2/feeds/39460.json?timezone=Eastern%20Time%20%28US%20%26%20Canada%29">timezone=Eastern%20Time%20%28US%20%26%20Canada%29</a></pre>
<p>If your application were to try doing the same thing, it would get a &#8220;404 – Authentication Error&#8221;.  When trying to graph a private datastream without an API key, the application gets back a nice &#8220;Server error&#8221; graphic, instead</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-8-33-21-PM.jpg"><img class="aligncenter size-full wp-image-1053" title="" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/16-11-2011-8-33-21-PM.jpg" alt="" width="207" height="105" /></a></p>
<p>To avoid that, the code needs to pass an API key.  The gadget doesn&#8217;t ask you to fill in an API key of your own: instead, I&#8217;ve hard-coded one that has read access to public feeds, but update access to nothing (including my own feeds).</p>
<p>The key is passed in an HTML header field, <a href="http://api.pachube.com/#security-authentication">as specified in the Pachube API documentation</a>.  Various programming languages have various methods for setting the contents of the header field – the Google Gadgets approach<a href="http://code.google.com/apis/gadgets/docs/remote-content.html#Fetch_JSON"> is described in their documentation</a>, and shown below:</p>
<pre class="brush: jscript; title: ; notranslate">
var params = {};
params[gadgets.io.RequestParameters.HEADERS] = {
    &quot;X-PachubeApiKey&quot;: &quot;&lt;your API key&gt;&quot;
};
</pre>
<p>Incidentally, if you&#8217;re using the gadget to graph datastreams in a private feed, you might wonder how my API key has access to your private feed.  Relax, it doesn&#8217;t.  Through some kind of <em>under-the-covers-cached-browser-authentication-cookie-machination</em> (my words, not Pachube&#8217;s), the gadget is allowed to access your private feed on a browser in which you&#8217;ve previously logged into Pachube.  I’ve noticed intermittent “authentication failed” errors when using the gadget with my own private feed, presumably when my cached authentication expires (or the cookie-machinations go awry).</p>
<h2>Time Zones</h2>
<p>According to the <a href="http://api.pachube.com/#security-authentication">API documentation on time zones</a> :</p>
<p><em>There are two places where you can specify the time zone: in your user profile on the website and via a parameter in an API request.</em></p>
<p>I think the intention is that your user profile’s timezone setting is automatically used by the API unless overridden, but it currently doesn’t work that way for graphs.  Perhaps that&#8217;s a bug that will be fixed at some point, but for now you have to pass the <em>timezone</em> parameter to the graph API call, or the X axis will display UTC times.</p>
<p>I had originally planned to have a &#8220;UTC offset&#8221; field in the gadget settings, where you would fill in the # of hours difference between your time zone and UTC: for example, -5 for Eastern Standard Time.</p>
<p>However, when testing I noticed something odd: timezone=-5 gave me UTC minus 5 hours, as expected, but timezone=-4 gave me UTC minus 3 hours.</p>
<p>As described in <a href="http://community.pachube.com/node/821">this post in the Pachube Community forum</a>, if you set the timezone parameter to a numeric value, the API will select the first matching entry in Pachube&#8217;s (rather eclectic) <a href="http://api.pachube.com/#time-zones">list of geographic time zone settings</a>.</p>
<p>For example, timezone=-4 is the same as specifying &#8220;Atlantic Time (Canada), and timezone=-5 is the same as specifying &#8220;Bogota&#8221;.  Rather than being dependent on the local customs of Atlanteans and Bogatians, I gave in and included the full list of geographic timezones in the the gadget&#8217;s Edit Settings page.  (If you have no idea which one on those time zones you are in, ask Pachube, not me.)</p>
<div class="img aligncenter size-full wp-image-1055" style="width:338px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-19-40-PM.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-19-40-PM.jpg" alt="Yes, Virginia, there is a Nuku'alofa" width="338" height="267" /></a>
	<div>Yes, Virginia, there is a Nuku'alofa</div>
</div>
<p>As shown in the Graph Builder section above , another tricky thing to consider when working with timezones is proper encoding of non-URL characters, like spaces and ampersands.  Javascript makes this easy: the gadget&#8217;s code for handling the conversion is simply:</p>
<pre class="brush: jscript; title: ; notranslate">
// replace And with &amp; (Google's Gadget API hates ampersands)
timeZone = timeZone.replace(&quot; and &quot;, &quot; &amp; &quot;);
// use escape function to encode spaces and ampersands in URL
urlSuffix = &quot;timezone=&quot; + escape(timeZone);
</pre>
<p>One last pothole to avoid: Google&#8217;s Gadget API seems to have a particular distaste for ampersands, however they’re encoded: the dropdown list of timezones wouldn&#8217;t display until I took them out.</p>
<h2>Getting the List of Datastreams in a Feed</h2>
<p>Pachube makes it easy to get the list of datastreams in a feed: just one API call returns a variety of properties, including the timestamp and value of the last datapoint received by each datastream.</p>
<p>The Javascript code for doing this is shown below, most of which is from the gadget’s getDatastreamStatus function:</p>
<pre class="brush: jscript; title: ; notranslate">
var urlPrefix = &quot;https://api.pachube.com/v2/&quot;;
var urlSuffix = &quot;timezone=&quot; + escape(timeZone);
var url = urlPrefix + &quot;feeds/&quot; + feedID + &quot;.json&quot; + &quot;?&quot; + urlSuffix;
var params = {};

params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
// NOTE - this API key has READ access only
params[gadgets.io.RequestParameters.HEADERS] = {
    &quot;X-PachubeApiKey&quot;: &quot;nBGUIT63Onke5-sfOoARTvKvkwl45b85wjz5PKDIZkc&quot;

// refresh data if longer than 5 minutes since last request
makeCachedRequest(url, getDatastreamsResponse, params, 300);
</pre>
<p>Yes, that’s an actual, genuine API key that I’ve published – my own, in fact.  As mentioned earlier, this one is defanged, limited to read-only access to public feeds.</p>
<p>The “.json” in the URL specifies that the data is to be returned in JSON format: other options are XML and CSV.  Your choice of format depends primarily on the coding platform you’re using.  Google’s Gadget API supports both XML and JSON, but I went with JSON because it is more light-weight (i.e. faster), a consideration if you’re working with a lot of datastreams.  The CSV option is intended for platforms that don’t support XML or JSON, such as an Arduino.</p>
<p>The code for <em>makeCachedRequest</em> is <a href="http://code.google.com/apis/gadgets/docs/remote-content.html#Cache">taken directly from Google’s API documentation</a>.  The code allows you to override Google’s default caching algorithm for gadget data, which retrieves updated data from the source (i.e. Pachube in this case) every 60 minutes, regardless of how often the user clicks the browser refresh button.  I’m overriding the interval to be every 5 minutes.</p>
<p>Note that the gadget doesn’t automatically update every 5 minutes: the update only occurs when the user first opens the web page containing the gadget, or clicks the refresh button, or when iGoogle refreshes the gadget.  (iGoogle refreshes each gadget once an hour, if the iGoogle page is in the foreground tab).  As far as I know, your gadget code has no way of forcing a refresh to occur.</p>
<p>The response to the API request is returned to the callback function passed as a parameter to makeCachedRequest, a simplified version of which is:</p>
<pre class="brush: jscript; title: ; notranslate">
function getDatastreamsResponse(obj)
{
  if (obj.data === null || typeof obj.data === &quot;undefined&quot;)
  {
    // something’s wrong – check the other obj properties, like obj.error and obj.rc
    . . .
  }

  jsonData = obj.data;

  if (!jsonData.datastreams)
  {
    displayErrorMsg(&quot;No datastreams found in feed&quot;);
    return;
  }

  datastreamList = jsonData.datastreams;
  feedTitle = jsonData.title;
  feedStatus = jsonData.status;
  feedDesc = jsonData.description;
</pre>
<p>The meat of the response is contained in the <em>.data</em> property of the parm passed to the callback function.  If that property is empty, then an error occurred.  Generally the error information is found in <em>obj.error</em> and/or <em>obj.rc</em>.  The former contains an error message as a raw JSON text string, and the latter contains one of the standard HTTP return codes <a href="http://api.pachube.com/#http-status-codes">as listed in Pachube’s documentation</a>.</p>
<p>The data object is bristling with useful information about the feed and datastream.  As shown in the code, I’m getting the feed’s title, status and description from there, as well as a list of datastreams, each of which is itself a JSON object with properties.  The screenshot below shows some of the other properties in this data object as seen in the Google Chrome Javascript console.  For a full list of all of the available properties, see the example in Pachube’s <a href="http://api.pachube.com/v2/#read-feed-get-v2-feeds-feed-id">Get Feeds documentation</a>.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-23-54-PM.jpg"><img class="aligncenter size-full wp-image-1056" title="" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/23-11-2011-6-23-54-PM.jpg" alt="" width="1002" height="355" /></a></p>
<h2>Getting the Datastream Graphs</h2>
<p>The Javascript which handles the calls to the Graph API, <em>displayGraphs()</em>, basically just pieces together the URL for the Graph API,  as explained in the &#8220;Pachube Graph API&#8221; section above.</p>
<p>There are a couple of issues handled here that I didn’t describe earlier.</p>
<p>Unbeknownst to the user (wouldn’t want to worry their pretty little heads, would we?), the code scales down the graph if necessary to fit within Pachube’s limit 300K pixels.</p>
<pre class="brush: jscript; title: ; notranslate">

var MAX_GRAPH_SIZE = 300000;  // Pachube's maximum graph size, in pixels
. . .
var defaultWidth = 320; // in normal gadget mode, 320 is the recommended width
if (graphHeight * graphWidth &gt; MAX_GRAPH_SIZE)
{
  // set to maximum size that will fit within Pachube's limit
  if (graphWidth &gt; defaultWidth)
  {
    graphWidth = defaultWidth;
  }

  graphHeight = Math.floor(MAX_GRAPH_SIZE / graphWidth);
}
</pre>
<p>This is done somewhat crudely, basically yanking the graph width back to 320 pixels, then yanking the height down as needed to fit within the 300K.</p>
<p>Also admittedly quite crude is the support for increasing the graph size when the gadget is maximized.</p>
<pre class="brush: jscript; title: ; notranslate">
// in canvas mode, double the graph size
if (gadgets.views.getCurrentView().getName() === &quot;CANVAS&quot;)
{
  graphHeight *= 2;
  graphWidth *= 2;
  defaultWidth *= 2;
}
</pre>
<p>I’m a little surprised that most gadgets ignore the maximized setting altogether, just displaying the same content in the same cramped size.  I think the problem is one of “discoverability”, to use a Googley term: the feature is disabled by default, and <a href="http://code.google.com/apis/gadgets/docs/ui.html#Dyn_Height">Google’s documentation on the feature</a> confusingly insists on referring to it as “canvas” mode.</p>
<p>As shown in the API documentation, enabling “canvas” mode is just a matter of pasting some boilerplate XML settings into your gadget, like so:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;Content type=&quot;html&quot; view=&quot;home&quot;&gt;
&lt;![CDATA[
 &lt;div id=&quot;content_div&quot;&gt;&lt;/div&gt;
. . .
&lt;script src=&quot;http://www.gigamegablog.com/gadgets/gm-pachube.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
]]&gt;
&lt;/Content&gt;
&lt;Content type=&quot;html&quot; view=&quot;canvas&quot;&gt;
&lt;![CDATA[
 &lt;div id=&quot;content_div&quot;&gt;&lt;/div&gt;
. . .
&lt;script src=&quot;http://www.gigamegablog.com/gadgets/gm-pachube.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
]]&gt;
&lt;/Content&gt;
</pre>
<p>Perhaps Google would prefer that your gadget take on an entirely new form when maximized, since the XML allows for a separate block of Javascript for canvas mode (the “content_div” section).  I wasn&#8217;t that ambitious, so instead I use a script tag to feed the same Javascript code into both the normal and canvas mode XML definitions, then changed the code to check which mode it’s in, as shown in the earlier code sample.</p>
<h2>Wrapping It Up</h2>
<p>If you&#8217;ve read the <a href="http://gigamegablog.com/2011/06/02/a-nimbits-gadget-programmer%e2%80%99s-show-and-tell/">Programmer’s Show and Tell for my Nimbits gadget</a>, you’ll notice that this time I’ve done much  less ranting about how frustrating Google’s Gadget API is to work with.  The API hasn’t changed, but once you know where the potholes are, the drive is a lot smoother. If you intend to write your own gadget I’d suggest you read my earlier rant/article first, since it points out a lot of those potholes.</p>
<p>I’m still dubious about the future of Google gadgets given Google’s newfound <a href="http://www.independent.co.uk/life-style/gadgets-and-tech/news/google-labs-closes-as-firm-focuses-on-making-money-from-its-greatest-hits-2318358.html?action=Popup">emphasis on monetization and focusing on core products</a>.   The iGoogle Developer Blog hasn’t had any new posts since a <a href="http://igoogledeveloper.blogspot.com/2011/05/more-new-features-for-gadget-dashboard.html">May post</a> asking “Did you know we are continuously adding new features” ?  (In fairness, they were referring to the Gadget Dashboard – they stopped adding new features to the gadget API long before May).</p>
<p>Methinks the best browser-based platform for making use of the Pachube API lies elsewhere, perhaps a Google App Engine project <a href="http://community.pachube.com/node/456">like this one</a>. .  The App Engine would give your code a lot more elbow room, and there is so much more to the Pachube API than what I’ve covered here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2011/11/23/a-pachube-gadget-programmers-show-and-tell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Pachube Google Gadget: Size Matters</title>
		<link>http://www.gigamegablog.com/2011/11/05/a-pachube-google-gadget-size-matters/</link>
		<comments>http://www.gigamegablog.com/2011/11/05/a-pachube-google-gadget-size-matters/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 22:34:14 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Pachube]]></category>

		<guid isPermaLink="false">http://gigamegatech.com/?p=1034</guid>
		<description><![CDATA[As described in past articles, I use the Pachube online Database/Internet-Of-Things-Thingee to log data from Tweet-A-Watt and various other sensors. (It&#8217;s pronounced &#8220;Patch-bay&#8221;, apparently, but that won&#8217;t stop me from my thinking &#8220;Pa-Chew-Bee&#8221; every time I see the word. Feel &#8230; <a href="http://www.gigamegablog.com/2011/11/05/a-pachube-google-gadget-size-matters/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As described in <a href="http://gigamegablog.com/2011/03/10/tweet-a-watt-beyond-the-twitter/">past </a><a href="http://gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/">articles</a>, I use the <a href="http://www.pachube.com">Pachube</a> online Database/Internet-Of-Things-Thingee to log data from <a href="http://www.ladyada.net/make/tweetawatt/">Tweet-A-Watt</a> and various other sensors. (It&#8217;s pronounced &#8220;Patch-bay&#8221;, apparently, but that won&#8217;t stop me from my thinking &#8220;Pa-Chew-Bee&#8221; every time I see the word. Feel free to join me.)</p>
<p><a href="http://www.pachube.com"><img class="aligncenter size-full wp-image-1043" title="PachubeLogo" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/PachubeLogo.png" alt="" width="238" height="80" /></a></p>
<p>I like Pachube &#8212; it&#8217;s reliable, well-designed, well-documented, and very much open to hobbyists.  They <a href="http://blog.pachube.com/2011/01/bringing-down-barriers-pachube-service.html">recently did away with paid plans</a> and made all aspects of the site and service free, so I’d encourage you to give them a try. If you need help at getting your data into Pachube, see their <a href="http://api.pachube.com/quickstart/">Quick Start guide</a> and <a href="http://community.pachube.com/tutorials">Tutorials</a>. My article on <a href="http://gigamegablog.com/2011/03/10/tweet-a-watt-beyond-the-twitter/">connecting Tweet-A-Watt to Pachube</a> also contains some tips on getting started, and my article on the <a href="http://gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/">FEZ XBee Sensor</a> shows an easy way to post data to Pachube from Python.</p>
<p>Pachube&#8217;s site provides a page for each of your feeds, showing a graph of the last 24 hours of readings from each of your datastreams. That&#8217;s good if you remember to go look at it, but I&#8217;d prefer that my graphs come to me, via a gadget on my iGoogle home page.</p>
<p><a href="http://www.google.com/ig/directory?type=gadgets&amp;url=apps.pachube.com/google_gadget/gadget.xml">Pachube released a Google Gadget</a> some time ago, and I&#8217;ve been using it for some time. It works well, but there are a few extra features that I really wanted:<br />
- larger graphs, and the ability to resize the gadget container to see them<br />
- a time axis in local time, rather than UTC<br />
- the ability the set the timespan: 12 hours, 1 week, 1 month, etc.<br />
- a Maximized view that shows the graphs in humongous GigaMegaSize</p>
<p>So, I&#8217;ve created a Google Gadget which adds these features, plus a few more.</p>
<p>You can <a href="http://www.google.com/ig/directory?url=www.gigamegablog.com/gadgets/gm-pachube.xml">grab the gadget from the Google Gadgets directory</a>.</p>
<h1>Settings</h1>
<p>Here is a description of the various options available on the Edit Settings dialog.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/GadgetSettings.png"><img class="aligncenter size-full wp-image-1039" title="GadgetSettings" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/GadgetSettings.png" alt="" width="334" height="401" /></a></p>
<p><strong>Feed #</strong>: Numeric Pachube Feed ID</p>
<p><strong>Datastreams</strong>: To graph all datastreams in the feed, leave this field blank. Otherwise, enter the datastream ID and click the Add button. For example, to add the 2 datastreams below&#8230;</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/Datastreams.png"><img class="aligncenter size-full wp-image-1037" title="Datastreams" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/Datastreams.png" alt="" width="638" height="197" /></a></p>
<p>&#8230;type Cactus, click Add, type CatGrass, click Add. The field should then look like this:</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/DatastreamsInputBox.png"><img class="aligncenter size-full wp-image-1038" title="DatastreamsInputBox" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/DatastreamsInputBox.png" alt="" width="309" height="91" /></a></p>
<p><strong>Time Span, Time Span Units</strong> – This determines what period of time will be graphed. As shown in the screenshot, the default is 24 hours. Time Span Units can be set to hours, days, weeks or months.</p>
<p><strong>Show Status</strong>. If true, each graph will be preceded by a line of text giving the Datastream ID, the last reading and the date and time it was received, as shown in this screenshot.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/GraphsDetailed.png"><img class="aligncenter size-full wp-image-1040" title="GraphsDetailed" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/GraphsDetailed.png" alt="" width="290" height="217" /></a></p>
<p><strong>Detailed Grid</strong>. If true, vertical and horizontal grid lines will be displayed, as in the 2 graphs above. If false, only a vertical grid separating each time span unit is displayed, as in the following (GigaMegaSized) graph.</p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/11/GraphWithoutStatus.png"><img class="aligncenter size-full wp-image-1041" title="GraphWithoutStatus" src="http://www.gigamegablog.com/wp-content/uploads/2011/11/GraphWithoutStatus.png" alt="" width="573" height="296" /></a></p>
<p><strong>Axis Labels</strong>: If true, numeric labels are added to the vertical and horizontal axis indicating the range of values. Note that, depending on the time span, these labels tend to overlap in a smaller graph (and I don&#8217;t have any control over the format of the labels). If false, the only labels are the minimum and maximum value of the vertical axis.</p>
<p><strong>Graph Width and Graph Height:</strong> Determines the size of each graph, in pixels. When the gadget is maximized, both sizes are automatically doubled. These values are required, and are initially set to a width of 280 and a height of 100.</p>
<p><strong>Gadget Height:</strong> Determines the height of the overall gadget, in pixels. If not specified, a default of 200 is used. (The gadget width can&#8217;t be set by the code, and varies depending on the browser type and the resolution of the monitor.)</p>
<p><strong>Time zone:</strong> Your local time zone. The default is UTC (aka Greenwich Mean Time). This setting affects the timestamp in the Status field, as well as the labels on the horizontal axis of the grid. The rather eclectic collection of names in the dropdown lists was Pachube’s idea, not mine. (Look <a href="http://api.pachube.com/#time-zones">here</a> if you don’t believe me!)</p>
<h1>Wrapping Up</h1>
<p>I&#8217;d welcome any bug reports or feature requests.</p>
<p>iGoogle’s Gadget framework does a lot of caching sleight-of-hand, so if you find that a change of settings doesn’t appear in the gadget, try refreshing the page. As for features , there are some things I can’t add because they aren’t supported by Pachube’s API yet (multiple datastreams in a graph, for example), but otherwise I’m open to suggestions.</p>
<p>For developers, I plan to write an article in the near future explaining the gadget&#8217;s use of the Pachube API.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2011/11/05/a-pachube-google-gadget-size-matters/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>FEZ XBee Sensor: Hat Trick</title>
		<link>http://www.gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/</link>
		<comments>http://www.gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/#comments</comments>
		<pubDate>Sat, 29 Oct 2011 21:34:26 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[FEZ]]></category>
		<category><![CDATA[Netduino]]></category>
		<category><![CDATA[nimbits]]></category>
		<category><![CDATA[Pachube]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://gigamegatech.com/?p=1011</guid>
		<description><![CDATA[As mentioned at the end of my Watching the Watcher article, the Netduino Plant Light project is going to take a sharp turn at this point, losing both the Netduino and the Plant Light.  I&#8217;m going to spin off some &#8230; <a href="http://www.gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>As mentioned at the end of my <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher article</a>, the <a href="http://gigamegablog.com/tag/netduino/">Netduino Plant Light project</a> is going to take a sharp turn at this point, losing both the Netduino and the Plant Light.  I&#8217;m going to spin off some of the code into a new project, a FEZ XBee Sensor.</p>
<p>Like its predecessor, the XBee Sensor is a <a href="http://www.microsoft.com/en-us/netmf/default.aspx">.Net Micro Framework device</a>, which uses an <a href="http://www.digi.com/xbee/">XBee</a> wireless transceiver to post data to the Internet by way of a Python middleman.</p>
<p>I’m structuring the code to be more flexible, supporting a variety of sensors and logging to a variety of databases.  Personally, I&#8217;m using it to measure plant soil moisture, light levels, temperature and humidity, as described in the &#8220;Hardware Configuration&#8221; section below.</p>
<p>If you decide to use a different mix of sensors (as I&#8217;m sure you will), you&#8217;ll need to make a small change to the C# code, as shown in the Programmer’s Show and Tell section below.  I&#8217;m aiming for a more generic device configuration, where all  sensor devices run exactly the same code, and all sensor configuration is done through Python.</p>
<p>Since a new project gives me an excuse to start playing with new hardware, I&#8217;ve also switched from using the <a href="http://www.netduino.com">Netduino</a> to a rival Micro Net Framework product, the <a href="http://www.ghielectronics.com/catalog/product/256">FEZ Panda</a>.</p>
<p>I&#8217;m not abandoning the Netduino: my own Netduino continues to perform its duties as a Plant Light Controller, and I&#8217;ll do my best to continue to support the Netduino in the XBee Sensor source code.  It’s relatively easy to switch the code between a FEZ and Netduino target.  I’ll point the code changes that are required in the Programmer’s Show and Tell section .</p>
<p>Also, the Python code used in this article is compatible with the Netduino Plant Light controller code from <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a>, so you can have both a Netduino Plant Light Controller and an XBee sensor reporting data to the Python code if you like, or even just the Netduino.</p>
<h2>The FEZ Panda</h2>
<p>The FEZ Panda is one of a line of products from GHI Electronics: Fez Mini, Panda, Panda II and Domino.  The Fez Mini is similar to the Netduino Mini &#8212; both mimic the form factor and pinout of the Basic Stamp &#8212; while the Pandas are similar to the Netduino.  The Domino is a more powerful beast, using a chipset that supports USB Host.</p>
<p style="text-align: center;"><div class="img aligncenter" style="width:620px;">
	<a href="http://www.ghielectronics.com/catalog/product/256"><img src="http://www.ghielectronics.com/images/fpn2_features.jpg" alt="FEZ Panda II" width="620" height="400" /></a>
	<div>FEZ Panda II</div>
</div>
<p>Compared to the Netduino, the Pandas (both versions I and II) have a few advantages that will come in handy when acting as a remote sensor.</p>
<p>1. More pins: 54 digital I/Os, as opposed to the Netduino&#8217;s (and Arduino&#8217;s) 13, and 3 COM ports to the Netduino’s 2.  More analog pins would have been even better, but the Panda only has 6, same as the other platforms.</p>
<p>2. Native code.  This one is huge: the .Net code can invoke &#8220;unmanaged&#8221; native code, which has full access to the microprocessor&#8217;s capabilities, including microsecond-level timing.  This eliminates the Micro Net Framework&#8217;s biggest disadvantage to the Arduino.</p>
<p>3. Ability to store data in flash memory.  The FEZ firmware includes a class that allows .Net code read/write access to 4K of flash memory, analogous to the Arduino&#8217;s Flash library.</p>
<p>4. More documentation!  This one might not excite you as much as it does me (whee!), but GHI&#8217;s <a href="http://www.tinyclr.com/">TinyCLR</a> site offers a ton of documentation covering pretty much every feature of the FEZ platform and the underlying Net Micro Framework.  I’d particularly like to point out the Beginner&#8217;s Guide to .Net Micro Framework, which I feel is still the best publication of any type covering the MNF, and much of which is also applicable to the Netduino.  A Tutorials section was recently added to the TinyCLR site, which has rapidly expanded to cover a lot of very useful features, again many of them applicable to the Netduino.  (Both the Beginners Guide and the Tutorials section can be found on the <a href="http://www.tinyclr.com/support/">TinyCLR Support page</a>).</p>
<p>Back in the <a href="http://gigamegablog.com/2011/04/23/netduino-a-little-help-from-its-friends/">Netduino: A Little Help From Its Friends article</a>, I used an Arduino as a helper to the Netduino.  It handled a couple of actions that the Netduino (and Micro Net Framework) couldn’t do: read data from the DHT11 temperature/humidity sensor and saving settings to Flash memory.  The FEZ Panda can actually do both these things itself.    Smarter than the average bear!</p>
<p>By the way, the difference between the Panda and Panda II is that the latter contains a micro SD card socket, and adds female headers for most of the additional digital pins, which are repositioned to be accessible even when an Arduino shield is in place.  I&#8217;m using Panda Is (<a href="http://www.ghielectronics.com/catalog/product/135">currently being sold off by GHI at the ridiculously low price of $15</a>), but everything that I&#8217;m doing in this project will also work on a Panda II.   The code will work almost unchanged – all you have to do is remove the Project Reference to <em>FEZPanda_&#8230;</em> and replace it with <em>FezPandaII_&#8230;</em>, as shown in the screenshot.</p>
<div class="img aligncenter size-full wp-image-1018" style="width:475px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/Panda2Reference.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/Panda2Reference.png" alt="Selecting Panda II Assembly" width="475" height="404" /></a>
	<div>Selecting Panda II Assembly</div>
</div>
<h2>Hardware Configuration</h2>
<p>At this point, the XBee Sensor project is geared towards supporting analog sensors plus one particular digital sensor, the DHT11/DHT22 temperature and humidity sensor. I’m using the analog ports as moisture and light sensors, but any analog sensor that can run on 3.3V should work without code changes.</p>
<p>The XBee Sensors are intended to be used without displays, but when first configuring them it’s handy to connect an LCD to see what they’re doing (or failing to do). So, I added an optional “Debug LCD”, which displays the current sensor readings, as well as any Exceptions or other error messages.</p>
<p>I’ve written the code so that, if the LCD isn’t connected, it shrugs and keeps going.  However, if your device seems to behave erratically when the LCD is disconnected, you can disable use of the LCD by removing the DEBUG_LCD compiler flag (as shown in the Programmer&#8217;s Show And Tell section below).</p>
<p>You can also select the type of LCD using a compiler flag.  LCD support is basically the same as in the Netduino Plant Light Controller code, with the addition of the <a href="http://www.adafruit.com/products/292">Adafruit i2c / SPI character LCD backpack</a> &#8212; more details on that support are also in the Programmer&#8217;s Show And Tell section.</p>
<p>If you are using an LCD, you’ll probably want to add a button to D7, to toggle the backlight on or off.</p>
<h2>Soil Moisture Sensors</h2>
<p>The soil moisture sensors use the same approach as in the <a href="http://www.instructables.com/id/Garduino-Gardening-Arduino/">Garduino</a> project.  I built mine from</p>
<ul>
<li>A pair of galvanized nails.  I think any nails will do, as long as they&#8217;re galvanized and big-assed, I’m using Tree Island Gold 4” 20d Hot Dip Galvanized nails</li>
<li>2 lengths of 20 AWG wire, long enough to go from the plant pot to the Panda</li>
<li>a 10K resistor, connecting the analog in to ground</li>
</ul>
<p>As you can see from the photo, one end of each wire is soldered to a nail, then covered with heat shrink tubing to keep it attached tight.  The other end of the wires connect to the Panda.  One wire connects directly to 3.3V, and the other other wire is split: it connects directly to an analog port, then connects through a 10K resistor to ground.</p>
<p style="text-align: center;"><div class="img aligncenter size-large wp-image-1017" style="width:640px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/MoistureSensorWIringCorrected.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/MoistureSensorWIringCorrected-1024x764.jpg" alt="Moisture Sensor Wiring - Click to Enlarge" width="640" height="477" /></a>
	<div>Moisture Sensor Wiring - Click to Enlarge</div>
</div>
<p>I found that the screw connectors on the Adafruit Wing Protoboard is ideal for this setup, since the screw connectors firmly hold the wires in place , and the protoboard layout makes it easy to add the resistor-to-ground connection.  The Adafruit board also provides 4 spare screw connectors, in the upper-right of the above photo – I used mine to provide the extra 3.3V connections required for this project.</p>
<p>The Garduino actually uses 5V, but 3.3V works just as well for this purpose, with similar calibration.  My oldest moisture sensor has been in service for almost 3 months now, with no apparent degradation of the nails or weird behaviour in the voltage readings.  (No electrocuted plants either – the 10K resistor ensures that the current is too low to hurt either plants or humans).</p>
<p>The light sensor is a garden variety (nyuk nyuk) cadium sensor that uses the exact same circuit as the moisture sensors: one wire connected to 3.3V, and the other split between an analog pin and ground through a 10K resistor.</p>
<p>Here is what the XBee Sensor looks like with all its accoutrements:</p>
<div class="img aligncenter size-large wp-image-1014" style="width:640px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/100_0021.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/100_0021-1024x764.jpg" alt="FEZ XBee Sensor - Up and Running" width="640" height="477" /></a>
	<div>FEZ XBee Sensor - Up and Running</div>
</div>Here is an alternative configuration.  This one uses a Serial LCD, the <a href="http://www.seeedstudio.com/depot/grove-base-shield-p-754.html?cPath=132_134">SeeedStudio Grove Base Shield</a>, and connects the moisture sensor wires to a <a href="http://www.seeedstudio.com/depot/grove-protoshield-p-772.html?cPath=175">Grove Prototype Twig</a>.  The prototype twig works pretty well for connecting the moisture sensors, since it has plenty of room for the resistor connections to ground, and it supports 2 sensors per twig.  However, it uses 5V by default, so I snipped the power cable and wired it to 3.3V instead.</p>
<div class="img aligncenter size-large wp-image-1015" style="width:640px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/100_0026.jpg"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/100_0026-1024x764.jpg" alt="FEZ XBee Sensor - The Next Generation" width="640" height="477" /></a>
	<div>FEZ XBee Sensor - The Next Generation</div>
</div>
<h2>Temperature/Humidity Sensor</h2>
<p>I have the DHT11 from the <a href="http://gigamegablog.com/2011/04/23/netduino-a-little-help-from-its-friends/">A Little Help From Its Friends</a> article connected to one of my XBee Sensor configurations, and the DHT11&#8242;s big brother, the <a href="http://www.sparkfun.com/products/10167">DHT22</a>, connected to another.</p>
<p>The code used to read from the 2 devices is identical – the only difference is how the .Net code parses the data to retrieve the temperature and humidity values.</p>
<p>As mentioned earlier, the Panda&#8217;s support for native “RLP” (Runtime Loadable Procedures) code means that it can handle the microsecond-level timing required by the DH22 and DHT11.</p>
<p>The RLP code that I’m using comes from <a href="http://code.tinyclr.com/project/339/dht11-temperature-sensor-using-rlp/">this project on GHI&#8217;s TinyCLR site</a>.  The description of the project only mentions the DHT11, but the RLP code works for the DHT22 too.</p>
<p>I&#8217;ve modified the code slightly to prevent an infinite loop if anything goes wrong with the communication, and added a few comments to explain why the code is doing what it&#8217;s doing. My modified version, along with a compiled .elf file and all of the files needed to build the .elf, can be <a href="http://gigamega-micro.googlecode.com/files/DHT11%20DHT22%20RLP.zip">downloaded</a> from <a href="http://code.google.com/p/gigamega-micro/">my Google Code project page.</a> </p>
<p>(By the way, if you Google for the DHT11 or DHT22 datasheet, you&#8217;ll probably find a &#8220;Chinglish” version that&#8217;s awfully hard to understand.  A better datasheet can be found <a href="http://www.humiditycn.com/pic/20119221814042568.pdf">here</a>: it refers to the RHT21, but that&#8217;s identical to the DHT22 as far as the communication is protocol is concerned).</p>
<p>The native code isn&#8217;t something that you copy and paste into Visual Studio alongside your C# code – instead, it is built using a separate piece of open source software with the charming name of Yagarto (Yet Another GNU ARM Toolchain).</p>
<p>An introduction to generating RLPs with Yagarto can be found in <a href="http://wiki.tinyclr.com/index.php?title=RLP_Getting_Started">TinyCLR&#8217;s tutorial</a>.  I&#8217;d recommend you use <a href="http://www.itcrowd.be/getting-started-with-ghi-rlp">this more extensive tutorial</a> instead, which covers a few small but important steps skipped by the TinyCLR tutorial.</p>
<p>However, if you&#8217;d rather not learn Yet Another Anything at this time, the good news is that you can just use the .elf file that is included with the source code for this article.  It should work with any DHT11 or DHT22 connected to any of the FEZ devices that use the USBizi100 chipset: Fez Mini, Panda, or Panda II.</p>
<p>You will have to get your own unlocking code from GHI, to paste into the Visual Studio project. It&#8217;s a quick and painless, if somewhat mystifying, process:</p>
<p>1. Create a MyGHI account here: <a href="http://www.tinyclr.com/register/">http://www.tinyclr.com/register/</a></p>
<p>2. Once registered, login and click on the My Account link.</p>
<p>3. Click on the RLP Access Code link</p>
<p>4. Click the checkbox to agree to the &#8220;Technology Access Agreement&#8221; (which I assume is the whole point of this process), click Submit and your access code will be e-mailed to you.</p>
<p>The access code is pasted into the Visual Studio project, as shown in the Programmer&#8217;s Show and Tell section below.  The first time you run the unlock command on a FEZ device, it sets aside 10K for RLP use, then reboots.  The device remains unlocked after that, until the next time you update the firmware.</p>
<p>I&#8217;m not sure what exactly the unlock command does to your FEZ device, but based on my experience it’s a safe thing to try.  It doesn&#8217;t cause any instability or change the way that you debug your code.  If you decide you&#8217;d rather have the 10K back for .Net code, then you can remove RLP support by reloading the FEZ firmware.</p>
<p>I should point out one &#8220;gotcha&#8221; regarding the DHT11/DHT22 support, which probably applies to any RLP code that is timer-dependent.  You need to invoke the RLP subroutines from the main thread of the .Net application, not from a timer or event handler.  When I tried reading invoking the code from the timer thread that reads the other sensors, I found that the code ran slightly too slowly to keep up with the signals being sent from the DHT22 (which explains why I modified the code to break out of an infinite loop).  When invoked from the main thread, the code is rock solid – I haven’t noticed any failed readings in the weeks that I&#8217;ve been running it.</p>
<p>You might be wondering if RLP support is worth all the trouble.  If all you want is to support the DHT11/22, then you actually have an alternative to RLP: <a href=" http://code.tinyclr.com/project/289/dht11---temperature-and-humidity-sensor/">this TinyCLR Code project</a> describes an alternative approach using just managed C# code and a clever hardware hack (which would probably also work with a Netduino, by the way).  However,  I really think RLP is worth learning, since it opens up support for all kinds of accessories previously off-limits to Micro Net Framework devices, such as Graphical LCDs and audio input.  For examples, <a href="http://code.tinyclr.com/#do=searchProjects&amp;keywords=rlp">do a search of &#8220;RLP&#8221; in the TinyCLR Code section</a>.  Pretty much anything that the Arduino supports can (in theory) also be supported for Fez using RLP.</p>
<h2>XBee</h2>
<p>The XBee configuration at both the FEZ and Python end is the same as in the <a href="http://gigamegablog.com/2011/08/03/netduino-meets-world/">Netduino Meets World</a> article, with one exception. The Python code will now be using the XBee in API mode, and its XBee (but not the one at the FEZ end) must therefore have its API mode enabled.</p>
<p>The easiest way to do this is to open a console connection to the XBee (as described in Netduino Meets World), and enter</p>
<pre>+++
ATAP 1
ATWR</pre>
<p>Or, if you prefer, you can use the X-CTU Windows application to turn on API mode.</p>
<div class="img aligncenter size-full wp-image-1020" style="width:461px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/XCTU.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/XCTU.png" alt="X-CTU setting for API Mode" width="461" height="594" /></a>
	<div>X-CTU setting for API Mode</div>
</div>
<p>Note that the XBee address at the FEZ still needs to be hard-coded as “1”, even if you are using multiple XBee Sensors, or both XBee Sensors and a Netduino Plant Light Controller.  This isn’t a problem yet, since the FEZ/Netduino code doesn’t care what it receives, and the Python code doesn’t use the address to identify what it is receiving.  That will change in a future stage of the project</p>
<h2>Python Middleware</h2>
<p>The Python code has the same role as in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article: it forwards the sensor readings to a data repository on the Internet.</p>
<p>I’ve expanded the Python code to support 2 different repositories: <a href="http://www.nimbits.com">Nimbits</a> and <a href="http://www.pachube.com">Pachube</a>.  I’ve also expanded the configuration file to give you a bit more control over which sensors are posted to which sites.</p>
<p>The Python code is compatible with the Netduino Plant Light controller that was created in my previous blog posts.</p>
<p>You can <a href="http://gigamega-micro.googlecode.com/files/SensorRelay.zip">download the Python code and sample configuration file</a> from <a href="http://code.google.com/p/gigamega-micro/">my Google Code project page</a>.  Note that I’ve renamed them to better reflect their role: SensorRelay.py.</p>
<p>The sample configuration file looks like this:</p>
<pre># Configuration file for SensorRelay.py
# ----------- General App Settings ------------
# XBEEPORT = \.COMxx &lt;-- on some systems, Windows COM port 
#   must be specified in this format
XBEEPORT = COMxx
# USBPORT = COMyy
LOGFILENAME = SensorRelay.log
LOGDATA = False
SENDTIME = True
DEBUG = True
# -------- Sensor Settings -----------
#  - sensor line format is &lt;Netduino Sensor ID&gt; 
# = &lt;Nimbits Data Point ID OR Pachube Datastream ID&gt;
#[,Update Interval in seconds]
[Nimbits 1]
NIMBITS_SERVER = http://app.nimbits.com
NIMBITS_USERID = you@wherever.com
NIMBITS_API_KEY = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UPDATE_INTERVAL = 300
A1 = ASensor,60
A2 = AnotherSensor
T1 = TemperatureSensor,1500
H1 = HumiditySensor
[Pachube 1]
PACHUBE_FEED_ID = nnnnn
PACHUBE_API_KEY = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
UPDATE_INTERVAL = 300
A1 = ASensor,60
A3 = AThirdSensor
T1 = TemperatureSensor
H1 = HumiditySensor</pre>
<p>The settings are:</p>
<p>XBEEPORT = The serial port that the XBee is connected to.  On a Linux box, this would have a different format, like /dev/ttyUSBn.</p>
<p>USBPORT = The (very optional) serial port that an XBee Sensor is directly connected to.  (Technically, this would make it a FEZ USB/XBee Sensor – nice acronym!)</p>
<p>Note that you can use an XBEEPORT or a USBPORT, or both.  Just comment out or delete the one you aren’t using.</p>
<p>In the Python code in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article, I mentioned that the XBEEPORT setting could actually be set to the port of a USB-connected Netduino.  Why did I break that out to a separate USBPORT setting now?  The Python code now sends data to the XBEEPORT using the lower-level XBee API, while it still uses a generic Serial interface to a USB-connected device.</p>
<p>LOGFILENAME – The filename (or full path and filename) to which sensor data is logged in CSV format.  Note that, unlike the Python code in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article, errors and debug messages aren’t written to this file – they are written to a file named SensorRelayError.log instead, in the directory from which SensorRelay.py is run.</p>
<p>LOGDATA – This is used to enable or disable the logging of data to LOGFILENAME.   If your Python code is running on a ultra low power device like the Beagleboard, with just an SD card as its disk drive, then turning off data logging saves some wear-and-tear on the SD card.</p>
<p>SENDTIME – If true, the date and time will be sent to the XBeeSensor each minute.  You’ll want to leave this turned off if you’re using an XBee Sensor, but you should turn it on if you’re using the Netduino Plant Light Controller from my previous blog posts.</p>
<p>DEBUG – If true, debug messages will be written to both the console and the XBeeSensorError.log file.</p>
<p>The sensor configuration sections of the configuration file must always start with a name in square brackets, like “[Nimbits 1]”.  (The name can be whatever you like, actually, as long as you don’t use it more than once).  There must be at least 1 sensor configuration section, but you can have multiple sections if you want to send your data to multiple data repositories.</p>
<p>Personally, I use three: 1 for the public Nimbits app server (to test my code with the latest version of Nimbits), one for my personal Google App Server installation of Nimbits (to which I log more frequently), and one for Pachube, so that I can play around with its API too.</p>
<p>The Nimbits settings are identical to the ones used in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article – please see it for details.</p>
<p>The Pachube settings are almost the same as the Nimbits settings, but the lingo is somewhat different.  For details on getting started with Pachube, see my <a href="http://gigamegablog.com/2011/03/10/tweet-a-watt-beyond-the-twitter/">Tweet-A-Watt: Beyond the Twitter</a> article</p>
<p>PACHUBE_FEED_ID = The numeric feed ID.  (A Pachube Feed is a group of datastreams.  A datastream is the Pachube equivalent of a Nimbits Data Point.)  If you want to send different sensor readings to different feeds, you should create multiple Pachube sections in your configuration file (e.g. [Pachube 1], [Pachube 2]).</p>
<p>PACHUBE_API_KEY = A Pachube API key that you’ve generated, and which has write access to your feeds.</p>
<p>UPDATE_INTERVAL = As with Nimbits, this determines how often the sensor data will be posted to Pachube, in seconds.  Note that Pachube has a rate limiter that depends on the <a href="https://pachube.com/plans">type of plan</a> you have.  Each datastream update counts as a separate API call, so if you have 5 datastreams, that is 5 API calls.</p>
<p>SENSOR_ID = DATASTREAM_ID[, UPDATE_INTERVAL] = Determines which sensor reading received from the XBee Sensor will be sent to which Pachube datastream, optionally overriding the default update interval.  For example</p>
<pre>A1 = ASensor,60</pre>
<p>&#8230;means that sensor A1 received from the XBee Sensor will be sent to Pachube Datastream ASensor, every 60 seconds.</p>
<h1>Programmer’s Show and Tell</h1>
<h2>.Net Code</h2>
<p>As before, you can get the .Net code from <a href="http://code.google.com/p/gigamega-micro/">my Google Code page</a> in either of 2 ways:</p>
<ol>
<li>If you are familiar with Subversion, you use any SVN client (my favorite is <a href="http://tortoisesvn.net/">TortoiseSVN</a>) to get a copy of all the project files.  The SVN URL is <a href="https://gigamega-micro.googlecode.com/svn/trunk">https://gigamega-micro.googlecode.com/svn/trunk</a>, and the code for this article is in the XBeeSensor article.</li>
<li>Or, download the good old .zip file from the Downloads section of the Google Code project. <a href="http://gigamega-micro.googlecode.com/files/GMM_FEZXBeeSensor.zip">Here is a direct link to the code for this article</a>.</li>
</ol>
<p>I&#8217;m using the <a href="http://microliquidcrystal.codeplex.com/">MicroLiquidCrystal </a>library to add support for an i2c-connected LCD. The solution file will look for this project, and grumble if it can&#8217;t find it.  If you aren&#8217;t using an i2c LCD, you should remove the Reference to the MicroLiquidCrystal library from the project References list.  Otherwise, you&#8217;ll need to download the MicroLiquidCrystal source code and store it in the XBeeRemoteSensor solution folder..</p>
<p>While the .Net code is a totally separate project from the Netduino Plant Light controller, a lot of its contents will be familiar if you’ve read the Show and Tell sections of my previous blog posts.</p>
<p>Switching from the Netduino to the FEZ doesn’t require many changes to the code.  The underlying .Net Micro Framework codebase is 100% identical, and very little of the XBee Sensor code makes use of features that are specific to the Netduino or FEZ.  Where it does, I’ve used &#8220;#if&#8221; conditional compiler flags to include the correct code.</p>
<p>By the way, I’ve switched to putting compiler flags in the Project properties, as shown in the screenshot below, rather than hard-coding them with #define statements.  The default flag is “FEZ” – if you want to use a Netduino instead of a FEZ device, remove “FEZ” from the Conditional Compilation Symbols</p>
<div class="img aligncenter size-full wp-image-1016" style="width:736px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/Compiler-Flags.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/Compiler-Flags.png" alt="Compiler Flags" width="736" height="445" /></a>
	<div>Compiler Flags</div>
</div>
<p>In addition to getting the compiler flag right, the project’s References need to point to the right set of assemblies. For the FEZ Panda, use GHI’s libraries; for the Netduino, use SecretLabs’.  Your references lists should look like the one below – if you’ve got exclamation marks next to the GHIElectronics libraries, then perhaps you haven’t installed the FEZ SDK yet?  Otherwise, any problems are likely due to differences in the versions of the GHI libraries that I’m using and the ones you’re using – just delete the 3 GHI libraries from the References list, then add them back from the list on your PC.</p>
<div class="img aligncenter size-full wp-image-1019" style="width:264px;">
	<a href="http://www.gigamegablog.com/wp-content/uploads/2011/10/References.png"><img src="http://www.gigamegablog.com/wp-content/uploads/2011/10/References.png" alt="Project References List" width="264" height="238" /></a>
	<div>Project References List</div>
</div>
<p>The compiler flags take care of the rest.  For example, the “using” statements at the top of each class ensure that the proper assemblies are being used:</p>
<pre class="brush: csharp; title: ; notranslate">
#if FEZ
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
#if DHT22 || DHT11
using GHIElectronics.NETMF.Native;
#endif
#else
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
#endif&lt;/pre&gt;
</pre>
<p>Near the top of Program.cs, you’ll find the following code:</p>
<pre class="brush: csharp; title: ; notranslate">
// !!!!!!!!!!!!!!!! USER MUST SET THE FOLLOWING 3 LINES!!!!!!!!!!!!!!!!!!!!!!!

const int NUM_ANALOG_SENSORS = 5; // number of analog sensors

#if FEZ

static FEZ_Pin.AnalogIn[] sensorPins = new FEZ_Pin.AnalogIn[] { FEZ_Pin.AnalogIn.An0, FEZ_Pin.AnalogIn.An1,

FEZ_Pin.AnalogIn.An2, FEZ_Pin.AnalogIn.An3, FEZ_Pin.AnalogIn.An4};

#else

static Cpu.Pin[] sensorPins = new Cpu.Pin[] { Pins.GPIO_PIN_A0, Pins.GPIO_PIN_A1, Pins.GPIO_PIN_A, Pins.GPIO_PIN_A3, Pins.GPIO_PIN_A4 };

#endif

static string[] sensorIDs = new

string[] { &quot;M1&quot;, &quot;M2&quot;, &quot;M3&quot;, &quot;M4&quot;, &quot;L1&quot;, &quot;T1&quot;, &quot;H1&quot; };

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
</pre>
<p>By default, this is configured for 5 analog sensors, A0 – A4, as well as a DHT22 providing temperature and humidity readings.  You’ll need to modify this to match your own configuration.  Note that, if using a DHT11 or DHT22, the 2 sensor IDs for temperature and humidity should be added to the end of the sensorIDs array.  The tags you use for sensorIDs can be anything you like, but they need to match the sensor IDs in the Python configuration file, SensorRelay.cfg.</p>
<p>Note that the above code uses a different syntax to reference analog pins on a FEZ device as compared to the Netduino.  This difference in syntax applies to the digital pins too.  While the pins might be in the same location on the outside, they map to very different CPU pins internally.</p>
<p>As mentioned earlier, I’ve added support for the <a href="http://www.adafruit.com/products/292">Adafruit i2c/SPI Character LCD backpack</a>.  This required very little code, since the backpack is supported by the <a href="http://microliquidcrystal.codeplex.com/">MicroLiquidCrystal .Net library</a> that I used in the Netduino Plant Light Controller code.</p>
<p>The backpack is enabled by adding MLC_I2C to the compiler flags.</p>
<p>There is only 1 I2C port on the FEZ devices (as with the Netduino), and the .Net Micro Framework is able to figure out which pins the i2c interface uses.  So, the i2c LCD initialization code just passes the number of rows and columns:</p>
<pre>lcd = new clsLCD_MLC(4, 20);</pre>
<p>Beyond that, the LCD interface is identical to the one used by parallel LCDs, as described in earlier articles about the Netduino Plant Light Controller.  One catch, though: I2C is quite slow compared to other LCD interfaces, and if you have multiple threads writing to the LCD, there is a good chance that one will interrupt another in mid-communication, causing the LCD to hang go all garbly.  To prevent this, I use the Monitor method of .Net’s Threading library:</p>
<pre class="brush: csharp; title: ; notranslate">
static string lcdLock = &quot;LockMe!&quot;;

. . .

try
{
	if (blnDisableLCD)
	{
		return;
	}

	// prevent other thread from writing to lcd at same time (mandatory for I2C LCD)
	Monitor.Enter(lcdLock);

	. . .

	for (int i = 0; i &lt;= intLastRow; i++)
	{
		lcd.SelectLine((byte)(i + 1), true);
		lcd.WriteStringToLCD(strLCDBuffer[i]);

	}
finally
{
	Monitor.Exit(lcdLock);
}
</pre>
<p>Support for the DHT11 or DHT22 temperature/humidity sensor is enabled by adding the &#8220;DHT11&#8243; or &#8220;DHT22&#8243; compiler flag.  As mentioned earlier, this makes uses of the FEZ support for native RLP code.  The DHT11/DHT22 code won’t work at all if you’re using a Netduino.</p>
<p>All RLP code is initialized in basically the same way:</p>
<p>-          Call RLP.Enable</p>
<p>-          Call RLP.Unlock, passing it the values that you received in the e-mail.  Just copy and paste the “RLP.Unlock” statement from the e-mail into the code.</p>
<p>-          Load the RLP code (an ELF file) from your projects Resources section</p>
<p>-          Call GetProcedure for each RLP function that you want to call.</p>
<pre class="brush: csharp; title: ; notranslate">

RLP.Enable();

//TODO - If your device isn't already unlocked,
//  you MUST paste YOUR ID and byte array into the code below
//RLP.Unlock();

byte[] elf_file = Resources.GetBytes(Resources.BinaryResources.dht11_rlp);
RLP.LoadELF(elf_file);

RLP.InitializeBSSRegion(elf_file);

ReadDHT = RLP.GetProcedure(elf_file, &quot;ReadDHT&quot;);
DHTSetup = RLP.GetProcedure(elf_file, &quot;Setup&quot;);

// We don't need this anymore
elf_file = null;
Debug.GC(true);
</pre>
<p>If the initialization succeeds, you can then call the DHTSetup function in the RLP code, passing it the pin that the DHT11 or DHT22 is connected to:</p>
<pre class="brush: csharp; title: ; notranslate">

// Call setup function - use Di4 for DHT22
if (DHTSetup != null)
{
	success = DHTSetup.Invoke((int)(FEZ_Pin.Interrupt.Di4));
}
if (success == 0)
{
	Debug_WriteToLCD(&quot;DHT Setup failed!&quot;);
	DHTSetup = null; // disable use of DHT22
}
else
{
	// give DHT time to stabilize
	Thread.Sleep(1000);
}
</pre>
<p>To read the temperature and sensor data, call the ReadDHT function.  It returns a 5-byte array:</p>
<pre>int intResult = ReadDHT.Invoke(bytArray);</pre>
<p>Up to this point, the code used for the DHT11 and DHT22 is 100% identical.  The only difference is how the 5-byte array is processed to extract the temperature and humidity:</p>
<pre class="brush: csharp; title: ; notranslate">

if ((intTotal &amp; 255) == bytArray[4])
{

#if DHT22
	int intValues = 256 * (bytArray[2] &amp; 0x7f) + bytArray[3];
	if ((bytArray[2] &amp; 0x80) != 0)
	{
		intValues *= -1;
	}
	fltTemperature = intValues;
	fltTemperature /= 10;
#endif
#if DHT11
	fltTemperature = bytArray[2];
#endif

	Debug_WriteToLCD(&quot;Temp &quot; + fltTemperature.ToString(&quot;F1&quot;));

#if DHT22
	intValues = 256 * bytArray[0] + bytArray[1];
	fltHumidity = intValues;
	fltHumidity /= 10;
#endif
#if DHT11
	fltHumidity = bytArray[0];
#endif

	Debug_WriteToLCD(&quot;Hum &quot; + fltHumidity.ToString(&quot;F1&quot;));
}
else
{
	Debug_WriteToLCD(&quot;Checksum failed&quot;);
}
</pre>
<h2>Python Code</h2>
<p>The Python code is based on that described in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article, but with some notable improvements.</p>
<p>I’ve rewritten the logging code to follow proper Python standards.  So, instead of dumping error messages and debug information in the same file that contains the sensor data, I’m using the standard <a href="http://docs.python.org/library/logging.html">Python logging library</a>:</p>
<pre class="brush: python; title: ; notranslate">

logging.basicConfig(level=logging.DEBUG,

format='%(asctime)s %(levelname)s %(message)s',

filename='SensorRelayError.log')

log = logging.getLogger()
</pre>
<p>Note that you can change the level of logging, and the log file name, by changing this line of code.  For example, if you wanted to have debug messages sent just to the console, but not the log file, change logging.DEBUG to logging.ERROR.</p>
<p>Exception logging now follows Python standards as well, with the full stack trace being written to the log.  For example:</p>
<pre class="brush: python; title: ; notranslate">

try:

    . . .

except:

    log.exception('Error sending to pachube, datapoint ' + dataPoint)
</pre>
<p>The resulting error message in the log includes all the fixings:</p>
<pre>2011-09-19 17:40:06,180 ERROR Error sending to pachube,
   datapoint PlantLight1
Traceback (most recent call last):
File "SensorRelay.py", line 51, in sendToPachube
pac.put()
File "build/bdist.linux-armv7l/egg/eeml/datastream.py", line 45, in put
conn.request('PUT', self._url, self._eeml.toeeml().toxml(),
   {'X-PachubeApiKey': self._key})
File "/usr/lib/python2.6/httplib.py", line 914, in request
self._send_request(method, url, body, headers)
File "/usr/lib/python2.6/httplib.py", line 951, in _send_request
self.endheaders()
File "/usr/lib/python2.6/httplib.py", line 908, in endheaders
self._send_output()
File "/usr/lib/python2.6/httplib.py", line 780, in _send_output
self.send(msg)
File "/usr/lib/python2.6/httplib.py", line 739, in send
self.connect()
File "/usr/lib/python2.6/httplib.py", line 720, in connect
self.timeout)
File "/usr/lib/python2.6/socket.py", line 547, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):</pre>
<p>The Xbee is no longer being treated as a generic serial interface, as it was in the <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a> article.  Instead, I’m using the<a href="http://code.google.com/p/python-xbee/"> Python XBee library</a>, which reads and writes data using the XBee’s API.</p>
<p>To be honest, there is no great advantage to using the XBee API at this point.  I’ve found it to be quite stable – after the Python code opens the XBee port after startup, the port stays open and keeps working regardless of what’s going on at the sensor end of the connection.  The serial port interface to the XBee was just as stable. However, the API lets me send data to a specific remote sensor device, and lets me know which remote sensor device I’m receiving data from, something which will be necessary later in the project.</p>
<p>The code which communicates with the XBee is similar to the serial interface described in the Show and Tell section of <a href="http://gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Watching the Watcher</a>.  The only significant difference is that I can now define a callback to activated when data is received, rather than having to poll for incoming  data:</p>
<pre class="brush: python; title: ; notranslate">

if XBEEPORT:
    try:
        serXBee = serial.Serial(XBEEPORT, BAUDRATE, timeout=TIMEOUT)
        serXBee.close() # workaround for known problem when running on Windows
        serXBee.open()
        xbee = XBee(serXBee, callback=readXBeeData)
</pre>
<p>The callback function receives a “frame” as its parameter.  To get to the sensor data sent by the FEZ (i.e. the same data that would be received from the XBee when it is used as a serial device), just access the frame.data property.  Note that the frame has a bunch of other potentially useful properties, as shown in the code below.</p>
<pre class="brush: python; title: ; notranslate">

def readXBeeData(frame):
    global buf
    try:
        frame_id = frame['id']
        # source address is 2-bytes binary (e.g. x00x01)
        # this also works: source_addr = struct.unpack('&gt;h', frame['source_addr'])
        source_addr = ord(frame['source_addr'][0]) * 256 + ord(frame['source_addr'][1])
        # rssi (signal strength) is 1-byte binary
        rssi = ord(frame['rssi'])
        data = frame['rf_data']
        if DEBUG:
            print &quot;read_frame, id=&quot;, frame_id, &quot;, source_addr=&quot;, source_addr, &quot;, rssi=&quot;, rssi, &quot;, data=&quot;, data
            log.debug(&quot;read_frame, id=&quot; + str(frame_id) + &quot;, source_addr=&quot; + str(source_addr) + &quot;, rssi=&quot; + str(rssi) + &quot;, data=&quot; + data)
        if frame_id == &quot;rx&quot;:
            processXbeeData(data)
</pre>
<p>When sending data to the FEZ, you need to package the data into a frame.  I found that the syntax for doing this is surprisingly unGooglable: the Python XBee library is more commonly used to send the XBee a command (e.g. set D2 high), not a custom data string.  The trick is to format the data in a “TX” command.  Note that I’m adding an ending null to the data – this makes the Python code compatible with the Netduino Plant Light Controller code used in previous blog posts.</p>
<pre class="brush: python; title: ; notranslate">
        if xbee:
            strData = strPrefix + &quot;:&quot; + strCommand
            # HACK - append null to data to make it look like serial data to the other end
            xbee.send(&quot;tx&quot;, dest_addr = 'x00x01', data=strData + 'x00')
</pre>
<p>When sending data to Pachube from Python, I originally used the <a href="https://github.com/petervizi/python-eeml/">python-eeml library</a>, as described in the <a href="http://gigamegablog.com/2011/03/10/tweet-a-watt-beyond-the-twitter/">Tweet-A-Watt: Beyond the Twitter</a> article.  However, that library still uses the Pachube V1 API, which was limited to numeric datastream IDs.  Since the XML EEML format contains a bunch of optional data that I’m not using, I decided to simplify things and use Python’s standard <a href="http://docs.python.org/library/urllib2.html">urllib2 library</a>instead:</p>
<pre class="brush: python; title: ; notranslate">

        # Note - the following codes uses the V2 Pachube API and CSV data format
        url = 'http://api.pachube.com/v2/feeds/' + siteconfig[&quot;PACHUBE_FEED_ID&quot;]
           + '/datastreams/' + dataPoint + '.csv?_method=put'
        # HACK round to 3 decimal places and drop trailing zeros : technically not needed, but makes Pachube output nicer looking
        data = (&quot;%.3f&quot; % floatValue).rstrip('0').rstrip('.')
        headers = {'X-PachubeApiKey': siteconfig[&quot;PACHUBE_API_KEY&quot;]}
        if DEBUG:
            print url
            print data
            print headers
        req = urllib2.Request(url, data, headers)
        try:
            response = urllib2.urlopen(req)
        except urllib2.HTTPError, e:
            log.exception('Error code ' + e.code + ' sending to pachube, datapoint ' + dataPoint)
            return False
        except urllib2.URLError, e:
            log.exception('Reason code ' + e.reason + ' sending to pachube, datapoint ' + dataPoint)
            return False
</pre>
<p>Note the code adds an  “X-PachubeApiKey” setting to the HTTP header, something that isn&#8217;t well documented for the urllib2 library.</p>
<h2>Wrapping Up</h2>
<p>Whew, another super-sized article.  Believe it or not, it takes even longer to write than it does to read!  The upside is that I’ve had the code running for over a month now, so I can report that the FEZ XBee Sensor is a reliable platform with no[t too many] bugs.</p>
<p>I’m quite impressed with the FEZ Panda.  Its support for native code and for Output Compare (another Arduino feature that isn’t supported by the .Net Micro Framework) opens up a lot of new opportunities. GHI updates the firmware quite frequently – more often than Secret Labs does with Netduino – and I suspect they will be first out of the gate with support for the newly released <a href="http://blogs.msdn.com/b/netmfteam/archive/2011/10/04/version-4-2-rtm.aspx">.Net Micro Framework 4.2</a></p>
<p>Next, though, I’m going to turn my attention to the other end of the data stream, the data repositories.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2011/10/29/fez-xbee-sensor-hat-trick/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Netduino: Watching the Watcher</title>
		<link>http://www.gigamegablog.com/2011/08/23/netduino-watching-the-watcher/</link>
		<comments>http://www.gigamegablog.com/2011/08/23/netduino-watching-the-watcher/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 22:16:50 +0000</pubDate>
		<dc:creator>dwatts</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[Netduino]]></category>
		<category><![CDATA[nimbits]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://gigamegatech.com/?p=996</guid>
		<description><![CDATA[Note: This article is an installment in a series about building a plant light controller (and beyond) on the Netduino microcontroller platform.  For previous articles in the series, click here.  It’s been a few months now since the Netduino in this &#8230; <a href="http://www.gigamegablog.com/2011/08/23/netduino-watching-the-watcher/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>Note: This article is an installment in a series about building a plant light controller (and beyond) on the Netduino microcontroller platform.  For previous articles in the series, click </em><em><a href="http://gigamegablog.com/tag/netduino/">here</a></em><em>.</em></p>
<p> It’s been a few months now since the Netduino in this project, with the help of <a href="http://www.sparkfun.com/products/10097">its Arduino cousin</a>, learned to <a href="http://gigamegablog.com/2011/04/23/netduino-a-little-help-from-its-friends/">measure the temperature and humidity</a> in the room.  It&#8217;s faithfully reporting this data on its LCD… I think.  Who really knows what it&#8217;s doing when I&#8217;m not around?  It might be sleeping, or watching Fox News, or doing God-knows-what with its &#8220;cousin&#8221;.</p>
<p> Clearly, this situation demands a nanny cam.  But my eyes ache at the thought of reviewing hours of footage of an LCD displaying temperature and humidity data (… I think).</p>
<p>Fortunately, now that the Netduino is <a href="http://gigamegablog.com/2011/08/03/netduino-meets-world/">connected to the Internet</a>, we have a better option: online data monitoring.</p>
<h2> The Asocial Network: Rise of the Machines</h2>
<p> You’ve probably read recently of a rising trend, <a href="http://en.wikipedia.org/wiki/Internet_of_Things">The Internet of Things</a>.  It is becoming increasingly easy to hook devices and sensors up to the Internet, where they can report their status, receive instructions, play Farmville, and murder us in our sleep.</p>
<p> The backbone of this system is the online data repository, which records the data and allows you to view the results..  I’ve written before of two of the early entrants in the field, <a href="http://www.pachube.com">Pachube </a>and <a href="http://www.nimbits.com">Nimbits</a>. </p>
<p><a href="http://oreilly.com/catalog/0636920013037"><img class="alignright size-medium wp-image-998" title="" src="http://www.gigamegablog.com/wp-content/uploads/2011/08/iot-194x300.jpg" alt="" width="194" height="300" /></a>In this article, I’ll be connecting the Netduino to Nimbits via a Python middleman.  As explained in <a href="http://gigamegablog.com/2011/08/03/netduino-meets-world/">my last article</a>, I prefer this approach to a common alternative, connecting the Netduino directly to an Ethernet connection.  If you’re interested in trying that approach instead, there’s <a href="http://oreilly.com/catalog/0636920013037">a whole book that shows you how</a>.</p>
<p> Both Pachube and Nimbits use a REST API to receive data from sensors.  In past articles, I showed the Python code I use to <a href="http://gigamegablog.com/2011/03/10/tweet-a-watt-beyond-the-twitter/">send Tweet-A-Watt data to Pachube</a> and <a href="http://gigamegablog.com/2011/03/28/tweet-a-watt-beyond-the-twitter-part-deux/">to Nimbits</a>.  I’m using the same API here.</p>
<p> My article on <a href="http://gigamegablog.com/2011/03/28/tweet-a-watt-beyond-the-twitter-part-deux/">using Tweet-A-Watt with Nimbits </a>also covers the process of creating an account on the Nimbits server, getting an API key, and creating Data Points.  You’ll need to do all these things in order to receive data from the Netduino.  Your Nimbits settings are saved in the Python configuration file, explained below.</p>
<h2>Netduino Configuration</h2>
<p>The Netduino hardware and software is unchanged from the previous stage of the project, <a href="http://gigamegablog.com/2011/08/03/netduino-meets-world/">Netduino Meets World</a>.  You’ll need to have XBees configured at both the Netduino and Python ends of the configuration – details are in <a href="http://gigamegablog.com/2011/08/03/netduino-meets-world/">Netduino Meets World</a>.</p>
<p>Well, actually, you don&#8217;t need XBees if the Netduino is located quite close to the PC that&#8217;s running Python.  This was true for the Netduino Meets World article as well, I just forgot to mention in there.  Since we&#8217;re using the XBees as a generic serial device, a USB connection will also work with no software changes needed.  I have one of my Netduino&#8217;s connected by USB to a Beagleboard XM running Python. </p>
<p>You can&#8217;t use the Netduino&#8217;s USB port for this, but you can connect the pins to TTL-to-USB adapter.  One option is the 3.3V FTDI cable that I described way back in the <a href="http://gigamegablog.com/2010/12/29/netduino-time-and-weather/">Netduino: Time and Weather article</a>.  A slightly cheaper option is an FTDI breakout board – I&#8217;m using <a href="http://www.sparkfun.com/products/718 ">this one from Sparkfun</a> and can confirm that it works fine with the code accompanying this article.</p>
<h2>Configuring the Python Interface</h2>
<p>The Python code, TimeRelay.py, builds upon the foundation of the Python program used last time, TimeServer.py.  TimeServer was configured using command line switches – since there are a lot more settings now, I’ve switched to using a configuration file.  You can <a href="http://gigamega-micro.googlecode.com/files/TimeRelay.zip">download the Python code and sample configuration file</a> from <a href="http://code.google.com/p/gigamega-micro/">my Google Code page</a>, here.</p>
<p>The configuration file contains the following settings.   The ones that you have to fill in are marked in italics.</p>
<pre># Configuration file for TimeRelay.py
# SERIALPORT = \.COMxx &lt;-- Windows COM port must be specified in this format
SERIALPORT = /dev/ttyUSB0
LOGFILENAME = TimeRelay.log
DEBUG = True
NIMBITS_SERVER = http://app.nimbits.com
<em>NIMBITS_USERID = </em>
<em>NIMBITS_API_KEY = </em>
NIMBITS_UPDATE_INTERVAL = 300
# Sensor IDs - format is &lt;Netduino Sensor ID&gt; = &lt;Nimbits Data Point ID&gt;[,Nimbits Update Interval in seconds]
H1 = PlantRoomHumidity,1800
T1 = PlantRoomTemperature</pre>
<p>The first 3 settings correspond to the command line parameters in the program’s predecessor, as listed in the last article:</p>
<ul>
<li>SERIALPORT – Specifies the serial port that the XBee is connected to.  Note the unusual format of the serial port name for Windows PCs &#8212; this is required by the <a href="http://pyserial.sourceforge.net/">PySerial</a> library.</li>
<li>LOGFILENAME – The logfile has an expanded role – in addition to any error messages, it also records the data readings received from the Netduino in a comma-delimited format.  You can disable the local logging feature by leaving this setting blank (i.e. deleting “TimeRelay.log” from that line).</li>
<li>DEBUG – Turns on debug messages written to the console.  This is on by default, since it is quite useful for troubleshooting.</li>
</ul>
<p>The Nimbits settings are taken from your Nimbits account:</p>
<ul>
<li>NIMBITS_SERVER -  The default setting, app.nimbits.com, is the public Nimbits server.  If you don’t want to rub shoulders with the unwashed masses, you can setup your own private Nimbits server on Google App Engine – you would then enter your GAE server name here (e.g. whatever.appspot.com).  (Both Nimbits and GAE are free when used for this purpose.  I briefly described the process of setting up a Nimbits server in the “Rolling Your Own” section of <a href="http://gigamegablog.com/2011/03/28/tweet-a-watt-beyond-the-twitter-part-deux/">my Nimbits article</a>)</li>
<li>NIMBITS_USERID – This is the Gmail address you used when creating your Nimbits account.</li>
<li>NIMBITS_API_KEY – This key is e-mailed to you when you click the “Secret Key” toolbar button in your Nimbits server console. </li>
<li>NIMBITS_UPDATE_INTERVAL – This specifies how often Nimbits will be updated with the latest sensor reading.  The default is 300 seconds (i.e. 5 minutes), but you can override this for individual sensors on the sensor lines at the bottom of hte configuration file.  Note that the Netduino will send a new measurement every 60 seconds, regardless of what you configure here – the Python app will  send Nimbits an average of all the readings since the last update.</li>
</ul>
<p>The sensor settings are used to link the sensor IDs hard-coded in the Netduino application with the Data Point Names that you created in Nimbits.  The default settings assume Data Point names of PlantRoomTemperature and PlantRoomHumidity – if you use other names (as you might if you don’t actually have a Plant Room), then fill them in on these lines of the configuration file.</p>
<p>Note that the settings shown above will send a new humidity reading to Nimbits every 30 minutes, while the temperature will be sent using the default interval of 5 minutes.  Feel free to change this depending on how meteorologically active your home is.</p>
<h2>Activate Sensors</h2>
<p>After you’ve finished updating TimeRelay.cfg, run TimeRelay.Py and watch the console.</p>
<p>The program will start by listing the settings it found in the configuration file, then will open the serial port and wait for something to happen.</p>
<p>If a Netduino running the code from the last article is powered on,  and you left the “Debug” setting turned on in the TimeRelay.cfg file, you should see a temperature and humidity reading displayed within a minute.  A message showing the REST API call that sends the data to Nimbits should be displayed in 5 minutes (or whatever interval you used in the TimeRelay.cfg file). </p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/08/22-08-2011-8-32-54-PM.jpg"><img class="aligncenter size-full wp-image-1001" title="Python console receiving sensor data" src="http://www.gigamegablog.com/wp-content/uploads/2011/08/22-08-2011-8-32-54-PM.jpg" alt="" width="670" height="423" /></a></p>
<p>Switch to your Nimbits web page, double-click on the Data Point in the left hand pane, and the Data Channels pane should update with the newly received value.  </p>
<p><a href="http://www.gigamegablog.com/wp-content/uploads/2011/08/22-08-2011-8-33-38-PM.jpg"><img class="aligncenter size-large wp-image-1002" title="Nimbits Data Points" src="http://www.gigamegablog.com/wp-content/uploads/2011/08/22-08-2011-8-33-38-PM-1024x198.jpg" alt="" width="640" height="123" /></a></p>
<p>There are a bunch of useful settings that you can experiment with in the Data Points dialog.  I use the Idle Alarm setting to tell me when something has gone wrong with Netduino/Python configuration, and the High and Low Value alert to tell me when something has gone terribly wrong with my home.</p>
<p>The Nimbits web page also has some nifty built-in graphing capabilities.  These have recently changed with the release of Nimbits 3.2, and will continue to evolve, so see the <a href="http://www.nimbits.com">Nimbits web page</a> and <a href="http://nimbits.blogspot.com/">Nimbits blog</a> for the latest.</p>
<p>Since I have a fairly large number of data points that I like to glance at from time to time, I wrote <a href="http://www.google.com/ig/directory?type=gadgets&amp;url=www.gigamegablog.com/gadgets/nimbits.xml">a Google Gadget</a> to display line charts in the iGoogle page.  I also wrote <a href="http://gigamegablog.com/2011/05/21/a-nimbits-gadget-minding-the-data-store/">a blog post describing its development</a>.  Check it out and let me know of any new features you’d like to see. (Or feel free to <a href="http://gigamega-micro.googlecode.com/files/Nimbits%20Google%20Gadget.zip">take the code</a> and add the features yourself).</p>
<h2>Programmer’s Show and Tell</h2>
<p>Although the Netduino code isn’t new, I haven’t previously explained in the sensor data handling.</p>
<p>The upload process is run on yet another timer.  This is hardcoded to occur every 60 seconds &#8212; nothing magical about that interval, and it could certainly be changed as needed.</p>
<p>Since we’re using the XBee as a generic serial interface, all the Netduino needs to do is write the data to the serial port.  The sensor ID is hard-coded, and each reading is ended with a CR/LF – a &#8220;crude but effective&#8221; message format. I haven’t noticed any problems with data being garbled or truncated:</p>
<pre class="brush: csharp; title: ; notranslate">

// upload sensor readings once a minute
timerUploadSensors = new Timer(new TimerCallback(uploadSensorData),
 null, 60000, 60000);

. . .
private static void uploadSensorData(object data)
{
 string strReading = &quot;&quot;;
 if (blnHumidityUpdated)
 {
  blnHumidityUpdated = false;
  // make copy of humidity reading, since it
  //    could be overwritten at any time
  strReading += &quot;H1:&quot; + strHumidity + &quot;rn&quot;;
 }
 if (blnTempUpdated)
 {
  blnTempUpdated = false;
  // make copy of temperature reading, since it
  //    could be overwritten at any time
  strReading += &quot;T1:&quot; + strTempDHT11 + &quot;rn&quot;;
 }
 uart.WriteToUART(strReading);
}
</pre>
<p>The Python code is a little more interesting.</p>
<p>First, I&#8217;ve added a workaround for a known problem with the PySerial library when running on Windows.  When PySerial tries to open the COM port it thinks that its already open – the workaround is to always close it before opening it.  Trippy but effective, and the workaround doesn’t cause problems on other OSes:</p>
<pre class="brush: python; title: ; notranslate">
ser = serial.Serial(SERIALPORT, BAUDRATE, timeout=TIMEOUT)
ser.close() # workaround for known problem when running on Windows
ser.open()
</pre>
<p>The code which reads TimeRelay.cfg demonstrates some of Python’s file- and string-handling power.  Five lines of code is all that is required to open a file, read its contents, parse the lines, and store them in a dictionary. </p>
<pre class="brush: python; title: ; notranslate">

def readConfigFile():

    #global config

    for line in open(CONFIGFILE):

        if line.strip()[0] != &quot;#&quot;: # skip comment lines

            parts = line.split(&quot;=&quot;, 1)

            if len(parts) == 2:

                config[parts[0].strip()] = parts[1].strip()
</pre>
<p>The sensor readings received from the Netduino are stored in a dictionary.  The key is the sensor ID (e.g. “T1”) and the value is a List with format:</p>
<pre>&lt;# of readings since last upload&gt;,
&lt;total of readings since last update&gt;,
&lt;date/time of last upload&gt; </pre>
<p>Python dictionaries are cool because they can store any object as their value, and the object type can be different for different entries in the same dictionary.  Less cool is the fact that Python throws an exception if you try to read a dictionary key that doesn’t exist yet, so be sure to check to see if an earlier reading is already stored there.</p>
<p>&nbsp;</p>
<pre class="brush: python; title: ; notranslate"> 
# add this reading to the sensor's list
if sensor in sensorValues:
    sensorValues[sensor][0] = sensorValues[sensor][0] + 1
    sensorValues[sensor][1] = sensorValues[sensor][1] + float_value
    if DEBUG:
        print &quot;found sensorValue&quot;, sensor, sensorValues[sensor]           
else:           
    sensorValues[sensor] = [1, float_value, datetime.datetime.now()]
    if DEBUG:
        print &quot;adding new sensorValue&quot;, sensor, sensorValues[sensor] 
</pre>
<p>Note that Python isn&#8217;t too picky about variable types except when it is.  If &#8220;<em>sensorValues[sensor][1]</em> &#8221;or &#8220;<em>float_value&#8221;</em> weren&#8217;t both floating point values, an Exception would be thrown when they are added together.</p>
<p>The code that sends the data to Nimbits uses the <a href="http://code.google.com/p/nimbits-server/wiki/CurrentValueService">CurrentValue REST API</a>.  This API has a dual role of writing new values and reading the most recent value, but we’re only using it to write data here.</p>
<p>The code starts out with a hack, to round the value to 3 decimal places before sending it. This is done for purely asthetic reasons, so that the readings displayed in the Nimbits web page look nice and tidy.  I call it a hack because rounding a number shouldn’t require this degree of string manipulation.  (Note to Pythonistas: I’m criticizing my code, not your language. Peace out.)</p>
<pre class="brush: python; title: ; notranslate"> 
# HACK round to 3 decimal places and drop trailing zeros
#  - technically not needed, but makes Nimbits output nicer looking
stringValue = (&quot;%.3f&quot; % value).rstrip('0').rstrip('.') 

try:
    LogMsg(dataPoint + &quot;,&quot; + stringValue)
    url = (NIMBITS_SERVER + &quot;/service/currentvalue?value=&quot; +
        stringValue + &quot;&amp;point=&quot; + dataPoint.replace(&quot; &quot;, &quot;+&quot;) +
   &quot;&amp;email=&quot; + NIMBITS_USERID +
        &quot;&amp;secret=&quot; + NIMBITS_API_KEY)

    urllib.urlopen(url)
    return True
except IOError:
    print 'Error sending to nimbits'
    print sys.exc_info()[0]
</pre>
<p>The REST API call is a 2-liner, another example of Python’s power and simplicity compared to .Net.  (Note to Microsoft Fanboys: I’m on your side. Peace out.)  The only trick is to replace spaces in the Data Point name with plus signs, this being a URL and all.</p>
<p>Note that it isn’t necessary to send a timestamp with the data – the CurrentValue API assumes the value has a current timestamp unless otherwise specified.  Good thing, that, since working with time zones in Python can be a nightmare.  (Note to Pythonistas: yeah, now I’m criticizing your language).</p>
<p>Unfortunately the Nimbits CurrentValue API doesn’t return a value to indicate whether the API call was successful, so the Python code won’t write an error message to the console or log file if something goes wrong.  My first indication that something is wrong is generally when Nimbits&#8217; &#8220;Idle Alarm&#8221; sends me an e-mail.</p>
<h2> Wrapping Up</h2>
<p>The Netduino project has admittedly become quite unwieldy, with each stage heaping on more hardware and/or software to the previous stage.    It&#8217;s unlikely that anyone but me has all of the Netduino hardware add-ons needed to make use of all the software&#8217;s features.</p>
<p>In the next article in the series, I&#8217;m going to switch to a slimmed-down Netduino software image for a sensor node, that consists of only a Netduino, an XBee, and a few new analog sensors.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gigamegablog.com/2011/08/23/netduino-watching-the-watcher/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

