<?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>New Bright Idea</title>
	<atom:link href="http://newbrightidea.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://newbrightidea.com</link>
	<description>peripatetic creativity</description>
	<lastBuildDate>Tue, 06 Apr 2010 16:01:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Finding popular images in Apache Logs</title>
		<link>http://newbrightidea.com/?p=83</link>
		<comments>http://newbrightidea.com/?p=83#comments</comments>
		<pubDate>Mon, 01 Feb 2010 20:59:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=83</guid>
		<description><![CDATA[<p>I&#8217;m sure there are a million web pages out there that cover this already but here&#8217;s how I do it:</p>
<p>First, grep the interesting URIs out of the access log.  Here I look for everything ending in .png or .jpg &#8211; a better regex would filter out all the Wordpress stuff, all the thumbnails, all the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m sure there are a million web pages out there that cover this already but here&#8217;s how I do it:</p>
<p>First, grep the interesting URIs out of the access log.  Here I look for everything ending in .png or .jpg &#8211; a better regex would filter out all the Wordpress stuff, all the thumbnails, all the stuff that didn&#8217;t return 200, etc.</p>
<pre>
cat logs/www_log | awk '{print $7}' | grep -E "\.jpg|\.png$"
</pre>
<p>Then a quick awk script will indicate the number of times each image has been downloaded.  Because this script keeps all the image URIs in an associative array, it probably won&#8217;t scale to millions of images.  (But it will scale to millions of hits on a few images)</p>
<pre>
awk '{ if ($0 in linecount) linecount[$0]++; else linecount[$0] = 1} END { for (elem in linecount) print elem" "linecount[elem] }' | sort -r -n -k 2 | wc -l
</pre>
<p>Pipe the two commands together for UNIXy goodness.  Produces output like so (with a more aggressive filter regex in step 1):</p>
<pre>
/wp-content/uploads/2010/01/IMG_7203.jpg 1543
/wp-content/uploads/2010/01/IMG_5761.jpg 1466
/wp-content/uploads/2010/01/IMG_5765.jpg 857
/wp-content/uploads/2010/01/IMG_5764.jpg 732
/wp-content/uploads/2010/01/IMG_5763.jpg 678
/wp-content/uploads/2010/01/IMG_7197.jpg 409
/wp-content/uploads/2010/01/IMG_7198.jpg 406
/wp-content/uploads/2010/01/box-plans-6.jpg 102
/wp-content/uploads/2010/01/box-plans-5.png 87
/wp-content/uploads/2010/01/box-plans-4.png 34
/wp-content/uploads/2010/01/box-plans-2.png 33
/wp-content/uploads/2010/01/box-plans-1.png 26
/wp-content/uploads/2010/01/box-plans-3.png 22
</pre>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=83</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Frustromantic Box, Part 4: Software</title>
		<link>http://newbrightidea.com/?p=63</link>
		<comments>http://newbrightidea.com/?p=63#comments</comments>
		<pubDate>Wed, 20 Jan 2010 08:08:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[frustromantic]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=63</guid>
		<description><![CDATA[<p>The final post in the Frustromantic Box series deals with the software side of things.</p>
<p>I&#8217;ll just let the code speak for itself, mostly.  I just want to say &#8220;thanks&#8221; to all the Arduino developers for the great libraries, and to Mikal Hart in particular for his work on the TinyGPS and NewSoftSerial libraries.</p>

#include &#38;lt;TinyGPS.h&#38;gt;
#include &#38;lt;NewSoftSerial.h&#38;gt;
#include [...]]]></description>
			<content:encoded><![CDATA[<p>The final post in the Frustromantic Box series deals with the software side of things.</p>
<p><span id="more-63"></span>I&#8217;ll just let the code speak for itself, mostly.  I just want to say &#8220;thanks&#8221; to all the Arduino developers for the great libraries, and to Mikal Hart in particular for his work on the <a href="http://arduiniana.org/libraries/tinygps/" target="_blank">TinyGPS</a> and <a href="http://arduiniana.org/libraries/NewSoftSerial/" target="_blank">NewSoftSerial</a> libraries.</p>
<pre class="brush: cpp;">
#include &amp;lt;TinyGPS.h&amp;gt;
#include &amp;lt;NewSoftSerial.h&amp;gt;
#include &amp;lt;LiquidCrystal.h&amp;gt;
#include &amp;lt;SoftwareServo.h&amp;gt;
#include &amp;lt;math.h&amp;gt;
#include &amp;lt;EEPROM.h&amp;gt;
#include &amp;lt;avr/interrupt.h&amp;gt;

/*
 * This code is in the public domain.
 */

#define RXPIN 2
#define TXPIN 3

#define POLULUPIN 5

#define LIDPIN 6
#define DRAWERPIN 4
#define IRPINA 0

#define EARTH_RADIUS 6378.1f
#define DEG_TO_RAD 0.0174532925f

#define TOFINO_LAT 49.122444f
#define TOFINO_LON 125.900871f

#define XXXX_LAT 0.0f
#define XXXX_LON 0.0f

#define HOME_LAT 64.0f
#define HOME_LON 128.0f

#define GPS_DELAY_MS 60000

/* 5km is pretty generous, but
   better safe than sorry, right? */
#define DIST_THRESHOLD 5.0f

#define ADDR_TRIES 0
#define ADDR_STAGE1 1
#define ADDR_STAGE2 2
#define ADDR_BACKDOOR 3

TinyGPS gps;
SoftwareServo drawerServo;
SoftwareServo lidServo;

/* Set up the NewSoftSerial to talk to the GPS */
NewSoftSerial nss(RXPIN,TXPIN);

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

unsigned long waitUntil;
int attemptsRemaining;

void setup() {
  pinMode(POLULUPIN, OUTPUT);
  Serial.begin(9600);
  Serial.print( &amp;quot;In setup.\n&amp;quot; );
  nss.begin(4800);
  lcd.begin(2,16);
  lcd.clear();
  lcd.setCursor(0,0);

  /* Check how many tries are left */
  attemptsRemaining = EEPROM.read(ADDR_TRIES);
  Serial.print( &amp;quot;Attempts Remaining: &amp;quot; );
  Serial.print( attemptsRemaining, DEC );
  Serial.print(&amp;quot;\n&amp;quot;);
  if ( attemptsRemaining == 0xFF )
  {
    // First time through
    Serial.print( &amp;quot;First time through, initializing EEPROM\n&amp;quot; );
    initializeEEPROM();
    Serial.print( &amp;quot;Locking lid\n&amp;quot; );
    lockLid();
    shutdown();
  }
  lcd.print( &amp;quot; ...Loading...&amp;quot; );
}

void loop()
{
  waitUntil = millis() + 2000;
  if ( waitForBackdoor() )
  {
    /* If we get here, then the backdoor was triggered */
    unlockLid();
    shutdown();
  }
  else if ( EEPROM.read( ADDR_BACKDOOR ) != 0 )
  {
    // clear the backdoor flag, if it was set from a previous
    // run.  this lets us try to unlock the backdoor multiple times
    // in case the first try jammed or something.
    lockLid();
    EEPROM.write( ADDR_BACKDOOR, 0 );
    shutdown();
  }

  if ( attemptsRemaining &amp;lt;= 0 )
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print( &amp;quot; No More Tries!&amp;quot; );
    delay(5000);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print( &amp;quot;   Return to&amp;quot; );
    lcd.setCursor(0,1);
    lcd.print( &amp;quot;     Russ&amp;quot; );
    delay(5000);
    shutdown();
  }

  // ... Normal Operation begins here
  bool stage1Complete = (EEPROM.read(ADDR_STAGE1) != 0);
  bool stage2Complete = (EEPROM.read(ADDR_STAGE2) != 0);

  waitUntil = millis() + 120000;
  if ( !stage1Complete )
  {
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print( &amp;quot; Searching  for &amp;quot; );
    lcd.setCursor(0,1);
    lcd.print( &amp;quot;     Signal     &amp;quot; );
    float stage1Dist = 100.0f;
    if ( distanceTo( TOFINO_LAT, TOFINO_LON, &amp;amp;stage1Dist ) )
    {
      /* If we get here, we received a valid distance measurement */
      if ( stage1Dist &amp;lt; DIST_THRESHOLD )
      {
        EEPROM.write( ADDR_STAGE1, 0xFF );
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Stage One&amp;quot; );
        lcd.setCursor(0,1);
        lcd.print( &amp;quot;Complete!&amp;quot;);
        unlockDrawer();
      }
      else
      {
        /* Sorry, try again */
        decrAttemptsRemaining();
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Access Denied!&amp;quot; );
        lcd.setCursor(0,1);
        lcd.print( attemptsRemaining );
        lcd.print( &amp;quot; tries left&amp;quot; );
        delay(25000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Out of Range&amp;quot; );
        lcd.setCursor(0,1);
        lcd.print( stage1Dist );
        lcd.print( &amp;quot; km&amp;quot; );
      }
      delay(25000);
      shutdown();
    }
    else
    {
      /* We never received a good GPS signal */
      failNoSignal();
    }
  }
  else if ( !stage2Complete )
  {
    /* This chunk of code is just different enough from stage 1
       to make it awkward to write in a loop. */
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print( &amp;quot; Searching  for &amp;quot; );
    lcd.setCursor(0,1);
    lcd.print( &amp;quot;     Signal     &amp;quot; );
    float stage2Dist = 100.0f;
    if ( distanceTo( XXXX_LAT, XXXX_LON, &amp;amp;stage2Dist ) )
    {
      if ( stage2Dist &amp;lt; DIST_THRESHOLD )
      {
        EEPROM.write( ADDR_STAGE2, 0xFF );
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Stage Two&amp;quot; );
        lcd.setCursor(0,1);
        lcd.print( &amp;quot;Complete!&amp;quot; );
        unlockLid();
      }
      else
      {
        decrAttemptsRemaining();
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Access Denied!&amp;quot; );
        lcd.setCursor(0,1);
        lcd.print( attemptsRemaining );
        lcd.print( &amp;quot; tries left&amp;quot; );
        delay(25000);
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print( &amp;quot;Out of Range&amp;quot; );
        lcd.setCursor(0,1);
        if ( stage2Dist &amp;lt; 10 )
        {
          lcd.print( &amp;quot;? km&amp;quot; );
        }
        else if ( stage2Dist &amp;lt; 100 )
        {
          lcd.print( &amp;quot;?? km&amp;quot; );
        }
        else if (stage2Dist &amp;lt; 1000 )
        {
          lcd.print( &amp;quot;??? km&amp;quot; );
        }
        else
        {
          lcd.print( &amp;quot;???? km&amp;quot; );
        }
      }
      delay(25000);
      shutdown();
    }
    else
    {
      failNoSignal();
    }
  }
  else
  {
    // Game Over!
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print( &amp;quot;      Game&amp;quot; );
    lcd.setCursor(0,1);
    lcd.print( &amp;quot;      Over!&amp;quot; );
    delay(10000);
    shutdown();
  }
  // We should never get here, but just in case...
  shutdown();
}

/*
 * Tries to calculate the distance to the specified lat+lon, using the GPS sensor.
 * Returns true iff the sensor returned a valid reading.
 * On successful return, result will hold the great circle distance to the specified point.
 */
bool distanceTo( float targetLat, float targetLon, float* result)
{
  int numFixes = 0;
  while ( millis() &amp;lt; waitUntil )
  {
    if (nss.available())
    {
      int c = nss.read();
      if (gps.encode(c))
      {
        unsigned long fix_age;
        float flat,flon;
        gps.f_get_position(&amp;amp;flat, &amp;amp;flon, &amp;amp;fix_age);
        if ( fix_age &amp;gt; 60000 ) continue;
        if ( numFixes &amp;lt; 5 )
        {
          numFixes++;
          continue;
        }
        flat = fabs(flat);
        flon = fabs(flon);

        float dist = gcd( flat * DEG_TO_RAD, flon * DEG_TO_RAD, targetLat * DEG_TO_RAD, targetLon * DEG_TO_RAD );
        *result = dist;
        return true;
      }
    }
  }
  return false;
}

/*
 * This is a super-kludge to turn off all pin-change interrupts.
 * It will disable all serial functionality.  Pretty much the
 * only way to restore the Arduino to a usable state after calling this
 * function is to cut the power and reboot.  Which is a little tricky to do
 * if you're running on USB _and_ a battery pack.
 *
 * I use this as a hack to get NewSoftSerial and SoftwareServo to play nice
 * with each other, but I think that the latest version of NewSoftSerial has
 * a much cleaner fix for this.
 */
void disablePCI()
{
  PCICR = 0;
  PCMSK2 = 0;
  PCMSK0 = 0;
  PCMSK1 = 0;
}

// Blocks until IR code received
// or expiry is reached (returns true iff code received)
// reads the waitUntil variable to determine how long
// to wait for the backdoor.
bool waitForBackdoor()
{
  uint8_t pulseCount = 0;
  unsigned long pulseStart;
  bool pulseActive;

  while ( millis() &amp;lt; waitUntil )
  {
    int irval = analogRead(IRPINA);
    if (irval &amp;lt; 0x0F)
    {
      // pulse started
      if ( !pulseActive )
      {
        pulseActive = true;
        pulseStart = millis();
      }
    }
    else
    {
      if ( pulseActive )
      {
        pulseActive = false;
        unsigned long duration = millis() - pulseStart;
        if ( (duration &amp;gt; 5) &amp;amp;&amp;amp; (duration &amp;lt; 15) )
        {
          pulseCount++;
        }
      }
    }
  }
  /* 4 or more pulses within the duration specified by waitUntil will unlock the backdoor. */
  if (pulseCount &amp;gt;= 4)
  {
    EEPROM.write( ADDR_BACKDOOR, 0xFF );
    return true;
  }
  return false;
}

/*
 * This function only works when the Arduino is running off a battery pack.
 * When running on USB, maybe stick an infinite loop at the end?
 */
void shutdown()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( &amp;quot; Shutting Down.&amp;quot;);
  delay(2000);
  digitalWrite( POLULUPIN, HIGH );
}

void unlockDrawer()
{
  // disablePCI _MUST_ be called prior to any servo operations!
  disablePCI();
  drawerServo.attach(DRAWERPIN);
  // this &amp;quot;stepping&amp;quot; is only necessary due to limitations of the Software Servo library,
  // which is an obsolete version of the Servo library that I used before
  // I diagnosed the problem with the pin change interrupts and never
  // had time to replace.
  for ( int i = 150; i &amp;gt;= 5; i-- )
  {
    drawerServo.write(i);
    SoftwareServo::refresh();
    delay(15);
  }
  drawerServo.detach();
}

void rotateLidServo(bool lock, int steps)
{
  disablePCI();
  // In my setup, the lid servo is a continuous rotation servo and so writing an angular
  // value to it makes it go a little crazy.
  lidServo.attach(LIDPIN);
  lidServo.write((lock) ? 0 : 180);
  for ( int i = 0; i &amp;lt; steps; i++ )
  {
    SoftwareServo::refresh();
    delayMicroseconds(15000);
  }
  lidServo.detach();
}

void unlockLid()
{
  // give it a bit more juice on the &amp;quot;unlock&amp;quot; just in case
  rotateLidServo(false, 10);
}

void lockLid()
{
  rotateLidServo(true, 7);
}

/*
 * Great Circle Distance calculation.  If anyone knows a fixed-point version
 * of this function I'd love to see it.
 */
float gcd(float lat_a, float lon_a, float lat_b, float lon_b)
{
  float d = acos(sin(lat_a)*sin(lat_b)+cos(lat_a)*cos(lat_b)*cos(lon_a-lon_b));
  return fabs(EARTH_RADIUS * d);
}

void decrAttemptsRemaining()
{
  attemptsRemaining--;
  // save the new state.
  EEPROM.write(ADDR_TRIES, attemptsRemaining);
}

void failNoSignal()
{
  decrAttemptsRemaining();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( &amp;quot;Access Denied!&amp;quot; );
  lcd.setCursor(0,1);
  lcd.print( attemptsRemaining );
  lcd.print( &amp;quot; tries left&amp;quot; );
  delay(5000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print( &amp;quot;No Signal!&amp;quot; );
  delay(5000);
  shutdown();
}

/* This function resets the box to its original state. */
void initializeEEPROM()
{
  // 101 Tries remaining
  EEPROM.write(ADDR_TRIES, 101);
  EEPROM.write(ADDR_STAGE1, 0);
  EEPROM.write(ADDR_STAGE2, 0);
  EEPROM.write(ADDR_BACKDOOR, 0);
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=63</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The Frustromantic Box, Part 3: Electronics</title>
		<link>http://newbrightidea.com/?p=56</link>
		<comments>http://newbrightidea.com/?p=56#comments</comments>
		<pubDate>Wed, 20 Jan 2010 07:23:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[frustromantic]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=56</guid>
		<description><![CDATA[<p>In this series&#8217; third post I describe the electronics involved in the Frustromantic Box.</p>
<p>The electronics involved in the Frustromantic Box are pretty straightforward.  I hooked everything up on a SparkFun Protoshield based on the instructions here, which I think are slightly out of date now.  I think the attached block diagram explains everything pretty clearly, [...]]]></description>
			<content:encoded><![CDATA[<p>In this series&#8217; third post I describe the electronics involved in the Frustromantic Box.</p>
<p><span id="more-56"></span><a href="http://newbrightidea.com/wp-content/uploads/2010/01/BoxDiag.pdf"><img class="alignleft size-medium wp-image-57" title="BoxDiag" src="http://newbrightidea.com/wp-content/uploads/2010/01/BoxDiag-220x300.png" alt="" width="220" height="300" /></a>The electronics involved in the Frustromantic Box are pretty straightforward.  I hooked everything up on a <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=7914" target="_blank">SparkFun Protoshield</a> based on the instructions <a href="http://www.atomicsalad.com/archive/2007/03/11/tutorial_sparkfun_protoshield_assembly_use.php" target="_blank">here</a>, which I think are slightly out of date now.  I think the attached block diagram explains everything pretty clearly, but here&#8217;s a bit more detail: apart from the Arduino&#8217;s I/O pins, the connections form two power planes and a ground plane.  The 6V output of the Polulu switch runs the Arduino (which I guess regulates it to 5V), the servos and the illuminated switch.  The 5V output of the Arduino powers the LCD display, the GPS module and the IR receiver.</p>
<p>The block diagram doesn&#8217;t show the power supply.  I used 4xAA&#8217;s, which hook up to the GND and VIN pins on the Polulu switch.</p>
<p>I had a real problem processing the output of the PNA4612 module when the batteries are even slightly discharged.  This might be something I could correct in software, but if I were doing it again, I&#8217;d probably just run a barrel jack through the side of the box, similar to what Mikal did on the <a href="http://arduiniana.org/projects/the-reverse-geo-cache-puzzle" target="_blank">original puzzle box</a>.</p>
<p>By the time I got the electronics finished up, I was running out of time before Christmas.  Rather than solder everything to the prototype board, I just left it on the solderless breadboard and epoxied the $*#% out of it.</p>
<p>Continue to <a href="http://newbrightidea.com/?p=63">Part 4: Software</a></p>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=56</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The Frustromantic Box, Part 2: Assembly</title>
		<link>http://newbrightidea.com/?p=23</link>
		<comments>http://newbrightidea.com/?p=23#comments</comments>
		<pubDate>Fri, 15 Jan 2010 22:26:06 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[frustromantic]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=23</guid>
		<description><![CDATA[<p>The Frustromantic Box is my implementation of Mikal Hart&#8217;s Reverse Geocache Puzzle.  In Part 1 of this series I gave an overview of the project and its parts list.  This post describes how I cut the pieces and put them together.

<p>
I wanted the box to be 1&#8242;x1&#8242;x5 1/2&#8243;, with a 3/4&#8243; lid.  I chose [...]]]></description>
			<content:encoded><![CDATA[<p>The Frustromantic Box is my implementation of Mikal Hart&#8217;s <a href="http://arduiniana.org/projects/the-reverse-geo-cache-puzzle/">Reverse Geocache Puzzle</a>.  In Part 1 of this series I gave an overview of the project and its parts list.  This post describes how I cut the pieces and put them together.<br />
<span id="more-23"></span><br />
<div style="width:45%; float: left; padding-right: 0%; display: inline;" class="post_column_1"><p><br />
I wanted the box to be 1&#8242;x1&#8242;x5 1/2&#8243;, with a 3/4&#8243; lid.  I chose those dimensions for convenience, but it turned out to be a pretty good fit for all the internals.  If I&#8217;d made it any smaller, things would&#8217;ve been pretty tight.</p>
<p>The final product was made from cherry and birch veneer plywood, but I built a prototype first out of pine and fir.  To reiterate: if you&#8217;re a novice woodworker like me, a prototype is a <strong><em>very</em></strong> good idea. I still wasted about $50 worth of cherry, but it could&#8217;ve been a lot worse.</p>
<p>Both the lid and the box are composed of four &#8220;edge&#8221; pieces.  Each piece is one foot long, which means that when you account for the kerf of the saw blade, a 4&#8242; length of wood isn&#8217;t quite enough.  So I went with 5&#8242; lengths and had a bit left over.  I used the extra for the drawer facade and to test the stain on.</p>
<p>Both the lid and the box are assembled with mitre joints.  The lid uses edge mitres, much like a picture frame.  The box uses face mitres.  All joints are reinforced with biscuits.  I chose this type of joint because I figured it would be strong enough if I reinforced it (so far, so good) and because I didn&#8217;t have the time, ability or equipment for a more complicated joint.</p>
<p>Before I cut the mitres, though, I cut a rabbet in each piece with my router.  The rabbet on the box pieces will form a pocket for the bottom of the box to fit in.  The rabbet on the lid pieces will hold the &#8220;instrument panel&#8221; &#8211; the LCD display, power button and GPS sensor.  I don&#8217;t have a router table, but this wasn&#8217;t a problem except for the very ends of the stock, where the router sort of rounded the corner a little bit.  Since I was using 5&#8242; lengths, I just trimmed about 1/8&#8243; off each end after I finished to square them up again.</p>
<p>Note the rabbet dimensions &#8211; they&#8217;re different between the lid and the box.  The 1/2&#8243; by 1/4&#8243; rabbet on the lid means that the panel will overlap the lid by 1/2&#8243;, which will gives a lot of surface to glue on.  The 1/4&#8243; depth means that the 1/4&#8243; birch ply will be flush with the lid.  For the box, the 1/2&#8243; by 3/8&#8243; rabbet means that I&#8217;ll have to double up the 1/4&#8243; ply for the bottom &#8211; I think this will make the bottom a little more sturdy.  The 3/8&#8243; depth goes halfway through the stock &#8211; it doesn&#8217;t give a lot of surface to glue on but combined with the 1/2&#8243; height it should be enough.</p>
<p>I cut the mitres in two steps: first I cut 4 1&#8242; pieces out of the stock, then I cut the mitres in each piece.  It seemed easier that way.  I found that it&#8217;s more important that the pieces are exactly the same length, instead of exactly 1&#8242; each.  Even a small change in the length of each piece will make the box noticeably out of square.  Finally, make sure that your mitres are all pointing the right way!  The <strong>outside</strong> edge or face must be 12&#8243;!</p>
<p>Once the mitres were cut I began work on the drawer.  The easiest thing for me to do was to get a couple of wooden boxes from Ikea and &#8220;repurpose&#8221; them.  The drawer itself is called a &#8220;MOLGER&#8221; (love those Ikea product names) and the &#8220;shell&#8221; that holds the drawer is called a BJURÖN.  The shell is a little too wide for the drawer, so there&#8217;s more wiggle room than I&#8217;d like, but it works.  It&#8217;s also much taller than necessary, but it provides a convenient mount point for the lid servo.</p>
<p>I picked one box piece to be the &#8220;front&#8221;, cut a notch in it that matched the height of the drawer (plus the width of the rabbet) and cut a piece of cherry for the drawer&#8217;s facade.  Since I cut the rabbet first, and had about 12&#8243; left over, making the facade was really easy.  I&#8217;m not 100% happy with how it turned out because the wood grain is totally inconsistent with the rest of the box, but I don&#8217;t know how I could&#8217;ve avoided that.</p>
<p>I chiseled a small niche in one of the box pieces to mount the IR sensor.  In Mikal&#8217;s project I think he extended a barrel jack through the side of the box to use as a &#8220;back door&#8221;.  I originally thought that it would be neater to use an IR sensor, and then trigger the backdoor with a remote control.  In hindsight, Mikal&#8217;s solution has the very great advantage that he can activate the back door even if the batteries are dead.  Wish I&#8217;d thought of that &#8211; d&#8217;oh.  The IR sensor sits in the niche, mounted in epoxy glue.  I drilled a small hole in the niche through to the exterior of the box, and filled the hole with epoxy as well.  It&#8217;s very hard to tell that there&#8217;s anything there at all &#8211; I don&#8217;t think my wife&#8217;s even noticed it.</p>
<p>Finally, I used a biscuit joiner to cut niches in each mitre and assembled the box and lid pieces with biscuits and glue.  I did a lot of dry-fit testing to make sure that everything lined up, and I used a couple of Lee Valley speed clamps to apply pressure evenly on all corners.</p>
<p>My choice of hinges made assembly very difficult, because I can only open the lid to about 45 degrees.  Because it was such a pain to assemble, I didn&#8217;t attach the instrument panel to the lid or the plywood to the bottom of the box until the very last step.  Using regular hinges and a proper illuminated pushbutton switch would have made this part a lot easier.</p>
<p>Here&#8217;s a <a href="http://newbrightidea.com/wp-content/uploads/2010/01/frustromantic-plans.zip">.zip</a> file containing the SketchUp plans shown below.  Please note that the drawer dimensions are approximate.</p>
<p>Continue to <a href="http://newbrightidea.com/?p=56">Part 3: Electronics</a><br />
</div><br />
<div style="width:320px; float: left; padding-right: 5%; display: inline;" class="post_column_1"><p><br />

<a href='http://newbrightidea.com/?attachment_id=24' title='Step 1: Raw Materials'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-1-150x150.png" class="attachment-thumbnail" alt="Step 1: Raw Materials" title="Step 1: Raw Materials" /></a>
<a href='http://newbrightidea.com/?attachment_id=36' title='Step 2: Cut rabbets'><img width="150" height="99" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-2-e1263591678503-150x99.png" class="attachment-thumbnail" alt="Step 2: Cut rabbets" title="Step 2: Cut rabbets" /></a>
<a href='http://newbrightidea.com/?attachment_id=38' title='Step 3: Cut pieces'><img width="150" height="95" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-3-e1263590705974-150x95.png" class="attachment-thumbnail" alt="Step 3: Cut pieces" title="Step 3: Cut pieces" /></a>
<a href='http://newbrightidea.com/?attachment_id=37' title='Step 4: Cut Mitres'><img width="150" height="107" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-4-e1263590917723-150x107.png" class="attachment-thumbnail" alt="Step 4: Cut Mitres" title="Step 4: Cut Mitres" /></a>
<a href='http://newbrightidea.com/?attachment_id=40' title='Step 5: Prepare Drawer'><img width="150" height="103" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-5-e1263591758129-150x103.png" class="attachment-thumbnail" alt="Step 5: Prepare Drawer" title="Step 5: Prepare Drawer" /></a>
<a href='http://newbrightidea.com/?attachment_id=41' title='Step 6: Assembly'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/box-plans-6-150x150.jpg" class="attachment-thumbnail" alt="Step 6: Assembly" title="Step 6: Assembly" /></a>
<br />
</div></p>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=23</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Frustromantic Box, Part 1: Intro</title>
		<link>http://newbrightidea.com/?p=15</link>
		<comments>http://newbrightidea.com/?p=15#comments</comments>
		<pubDate>Fri, 15 Jan 2010 04:02:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[frustromantic]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=15</guid>
		<description><![CDATA[<p>A few months ago, Hack A Day featured an ingenious hack called the Reverse Geocache Puzzle by a gentleman named Mikal Hart (please note that &#8220;Reverse Geocache Puzzle&#8221; is Mikal&#8217;s trademark &#8211; my unabashed clone of his project will hereafter be known as the Frustromantic Box).  As soon as I saw it, I knew I [...]]]></description>
			<content:encoded><![CDATA[<p>A few months ago, <a title="Hack A Day: fresh hacks, served daily." href="http://hackaday.com" target="_blank">Hack A Day</a> featured an ingenious hack called the <a title="Reverse Geocache Puzzle" href="http://arduiniana.org/projects/the-reverse-geo-cache-puzzle/" target="_blank">Reverse Geocache Puzzle</a> by a gentleman named Mikal Hart (please note that &#8220;Reverse Geocache Puzzle&#8221; is Mikal&#8217;s trademark &#8211; my unabashed clone of his project will hereafter be known as the Frustromantic Box).  As soon as I saw it, I knew I had to build one.  It took a <em><strong>lot</strong></em> longer than I thought it would, but I had the finished product ready in time for my wife&#8217;s Christmas present.  She still hasn&#8217;t opened it, so I have to be a little cagey here.</p>
<p>I&#8217;ll describe this project in a series of posts.  This post &#8211; the first &#8211; will go over the high-level design of the box.</p>
<ul>
<li><a href="http://newbrightidea.com/?p=23">Part 2: Assembly</a></li>
<li><a href="http://newbrightidea.com/?p=56">Part 3: Electronics</a></li>
<li><a href="http://newbrightidea.com/?p=63">Part 4: Software</a></li>
</ul>
<p><span id="more-15"></span>The goal of the project is to produce a box that is locked from the inside and will only unlock itself at a specific location.  The Frustromantic Box actually has two locks (a lid and a drawer) that can be toggled independently.  Here&#8217;s the parts list:</p>
<p><strong>Woodworking Parts:</strong></p>
<ul>
<li>5&#8242; of cherry 1&#8243;x6&#8243; for the sides of the box</li>
<li>5&#8242; of cherry 1&#8243;x3&#8243; for the lid of the box</li>
<li>1/4 sheet (4&#8242;x2&#8242;) of 1/4&#8243; birch veneer plywood.  This is more than necessary, but it was the smallest amount I could buy.</li>
<li>Small can of Varathane Gel Stain (602 Cherry)</li>
<li>Small can of Varathane Professional Clear Finish (Clear Gloss 900)</li>
</ul>
<p>I bought all the above supplies from Windsor Plywood.  If you&#8217;re a novice woodworker like me, I <em><strong>strongly</strong></em> recommend building a prototype out of pine first.  I used a router, a mitre saw, a table saw, a biscuit joiner and a scroll saw to cut the various pieces to size.  I used a couple of <a href="http://www.leevalley.com/wood/page.aspx?c=2&amp;p=31162&amp;cat=1,43293" target="_blank">these speed clamps</a> to assemble the pieces.</p>
<p><strong>Electronics Parts:</strong></p>
<ul>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=666">Arduino Duemilanove</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=7914" target="_blank">Arduino Protoshield</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=7916" target="_blank">Mini Self-Adhesive Breadboard</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=709" target="_blank">HD44780 LCD Display</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8807" target="_blank">Icecube Light Pipe Switch</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=8903">Polulu Pushbutton Power Switch LV</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=9347">Full Rotation servo</a></li>
<li><a href="http://www.sparkfun.com/commerce/product_info.php?products_id=465" target="_blank">EM406A GPS Sensor</a></li>
<li>Hitec HS-81 servo</li>
<li>Panasonic PNA4602M IR Receiver</li>
</ul>
<p>You can tell from the links, I ordered almost all the parts from Sparkfun.  Those guys are great.  However, the Light Pipe switch was a real pain to use.  If I were to do it again I think I&#8217;d order <a href="http://www.seeedstudio.com/depot/metal-push-button-momentary-w-blue-led-p-158.html?cPath=60_36">this pushbutton switch</a> from Seeedstudio (also a great place) which is the same one that Mikal used in his project.  The HS-81 servo I picked up from a local hobby store when I decided to add a locking drawer to the box.  The IR Receiver is used to activate the &#8220;back door&#8221;, I just had it lying around from an earlier project.  The full rotation servo is unnecessary and makes the Arduino software a little more complicated than necessary.  In hindsight I probably should&#8217;ve got <a href="http://www.sparkfun.com/commerce/product_info.php?products_id=9064">this servo</a> instead.</p>
<p><strong>Miscellaneous Parts:</strong></p>
<ul>
<li>1/4&#8243; eyelets (I got a pack of these from Home Depot)</li>
<li>1&#8242; threaded pushrod + clevises (also from the local hobby shop)</li>
<li>1/4&#8243; dowel (Home Depot)</li>
<li><a href="http://www.ikea.com/ca/en/catalog/products/50149353">Ikea MOLGER toiletry container thingy</a></li>
<li><a href="http://www.ikea.com/us/en/catalog/products/70066097">Ikea BJURÖN plant container thingy</a></li>
<li>2&#8242;x2&#8242; velvety cloth (I&#8217;ve no idea what the proper name for this textile is, I used it to cover the bottom of the box)</li>
<li><a href="http://www.leevalley.com/hardware/page.aspx?c=2&amp;p=40647&amp;cat=3,41241">Lee Valley Concealed Lid Hinges</a> (this was a bad idea)</li>
</ul>
<p>The eyelet holes should be just big enough to accomodate the pushrod, with a little bit of wiggle room.  We will transform the Ikea bits into a crude drawer.   I recommend against using the concealed lid hinges.  My experience with those hinges is, you can either have the lid flush with the top of the box when closed, or you can have the lid open a full 90 degrees.  You can&#8217;t have both.  If I were to do it over again, I&#8217;d just use some nice stainless steel hinges and chisel out whatever notches are necessary.</p>
<p>I didn&#8217;t take any pictures of the build process, so I&#8217;ll show that using some SketchUp models.  But here are a few shots of the finished product:</p>

<a href='http://newbrightidea.com/?attachment_id=26' title='Box Exterior 2'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_7197-150x150.jpg" class="attachment-thumbnail" alt="" title="Box Exterior 2" /></a>
<a href='http://newbrightidea.com/?attachment_id=27' title='Box Exterior 1'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_7198-150x150.jpg" class="attachment-thumbnail" alt="" title="Box Exterior 1" /></a>
<a href='http://newbrightidea.com/?attachment_id=28' title='Box Internals'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_7203-150x150.jpg" class="attachment-thumbnail" alt="" title="Box Internals" /></a>
<a href='http://newbrightidea.com/?attachment_id=77' title='Lid Latch'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_5765-150x150.jpg" class="attachment-thumbnail" alt="" title="Lid Latch" /></a>
<a href='http://newbrightidea.com/?attachment_id=78' title='Arduino Wiring Rat&#039;s Nest'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_5764-150x150.jpg" class="attachment-thumbnail" alt="" title="Arduino Wiring Rat&#039;s Nest" /></a>
<a href='http://newbrightidea.com/?attachment_id=79' title='Drawer Latch'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_5763-150x150.jpg" class="attachment-thumbnail" alt="" title="Drawer Latch" /></a>
<a href='http://newbrightidea.com/?attachment_id=80' title='Box Lid'><img width="150" height="150" src="http://newbrightidea.com/wp-content/uploads/2010/01/IMG_5761-150x150.jpg" class="attachment-thumbnail" alt="" title="Box Lid" /></a>

<p>Continue to <a href="../?p=23">Part 2: Assembly</a></p>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=15</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Android Swingworker</title>
		<link>http://newbrightidea.com/?p=8</link>
		<comments>http://newbrightidea.com/?p=8#comments</comments>
		<pubDate>Thu, 14 Jan 2010 22:03:27 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://newbrightidea.com/?p=8</guid>
		<description><![CDATA[<p>I&#8217;ve been fooling around with the Android development platform. It&#8217;s quite an adjustment, coming from the iPhone world.  I thought I&#8217;d post a simple equivalent to the SwingWorker class that works with Android&#8217;s Event Dispatch Thread. Here it is:</p>

package ca.razorwire.util;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

public abstract class UIWorker
{
  private static final ExecutorService __execSvc;
 [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been fooling around with the Android development platform. It&#8217;s quite an adjustment, coming from the iPhone world.  I thought I&#8217;d post a simple equivalent to the SwingWorker class that works with Android&#8217;s Event Dispatch Thread. Here it is:</p>
<pre class="brush: java;">
package ca.razorwire.util;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

public abstract class UIWorker
{
  private static final ExecutorService __execSvc;
  private static final Handler __edtHandler;

  private static final String TAG = &quot;UIWorker&quot;;

  static
  {
    __execSvc = Executors.newSingleThreadExecutor();
    __edtHandler = new Handler( Looper.getMainLooper() );
  }

  public abstract void doInBackground();

  public void done()
  {
    // Log.d(TAG, &quot;done() executing in thread &quot; + Thread.currentThread().getName() );
    // This space intentionally left blank
  }

  public void execute()
  {
    // Log.d(TAG, &quot;execute() executing in thread &quot; + Thread.currentThread().getName() );
    final Runnable doneRunner = new Runnable()
    {
      public void run()
      {
        UIWorker.this.done();
      }
    };

    final Runnable bgRunner = new Runnable()
    {
      public void run()
      {
        // Log.d(TAG, &quot;bgRunner executing in thread &quot; + Thread.currentThread().getName() );
        UIWorker.this.doInBackground();
        __edtHandler.post( doneRunner );
      }
    };
    __execSvc.submit(bgRunner);
  }
}
</pre>
<p>And here&#8217;s a sample usage:</p>
<pre class="brush: java;">
      UIWorker worker = new UIWorker()
      {
        public void doInBackground()
        {
          Log.d( TAG, &quot;Sleeping for a bit.&quot; );
          try { Thread.sleep( 10000 ); } catch ( Exception ignore ) {};
        }
      };
      Log.d( TAG, &quot;Executing worker...&quot; );
      worker.execute();
      Log.d( TAG, &quot;Returned from execute()&quot; );
</pre>
<p>If you uncomment the Log calls in UIWorker, you should see some output like this:</p>
<pre>
07-08 12:14:11.015: DEBUG/rweeks(1078): Executing worker...
07-08 12:14:11.015: DEBUG/UIWorker(1078): execute() executing in threadmain
07-08 12:14:11.025: DEBUG/UIWorker(1078): bgRunner executing in thread pool-1-thread-1
07-08 12:14:11.035: DEBUG/rweeks(1078): Sleeping for a bit.
07-08 12:14:11.035: DEBUG/rweeks(1078): Returned from execute()
07-08 12:14:21.038: DEBUG/UIWorker(1078): done() executing in thread main
</pre>
<p>Public domain code, no guarantees, seems to work.</p>
]]></content:encoded>
			<wfw:commentRss>http://newbrightidea.com/?feed=rss2&amp;p=8</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
