<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>Rascal Micro: small computers for art and science</title>
    <link>http://rascalmicro.com/blog</link>
    <description>Rascal Micro: small computers for art and science</description>
    <pubDate>Wed, 02 May 2012 21:09:11 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Delayed by memory timing errors</title>
      <link>http://rascalmicro.com/blog/2012/05/01/delayed-by-memory-timing-errors</link>
      <pubDate>Tue, 01 May 2012 00:00:00 EDT</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">CyiBoLdLH6cO1BKUAvT3fHh8uhM=</guid>
      <description>Delayed by memory timing errors</description>
      <content:encoded><![CDATA[<p>(This is a pretty technical post, so if that's not your bag, the summary is that there was a problem with the last round of boards, so I'm making a new version that works. Back to the story.)</p>
<p>When I got two new Rascal prototypes back from the assembler last month, I was pretty excited. The new version, Rascal 1.1, cleans up a bunch of little annoyances and adds new features. The previous batch had sold out quickly and, even better, the Rascal was living up to my vision of a relatively easy-to-use board for connecting stuff to the internet.</p>
<p>After some testing, all the new features-- USB ports, the new JTAG port, and the like-- appeared to work well. Unfortunately, there was a problem with the Rascal's RAM, which meant that when the Rascal tried to write data to certain addresses, the data was lost. If that data turned out to be code that was later executed, the Rascal would choke and reset when it tried to execute whatever random data happened to be there before the failed write.</p>
<p>This all seems straightforward in retrospect. In futuro-spect, it took me about a week to narrow down the problem to failing RAM writes.</p>
<h3 id="figuring-out-the-cause">Figuring out the cause</h3>
<p>After watching the board reset a few times, I tried logging the boot messages to see when resets occurred. Some tedious tallying yielded this table of last boot messages from the Linux kernel before reset occurred.</p>
<div class="pygments_monokai"><pre>Reps  Message<br/>----  ------------------------------------------------  <br/>1     Uncompressing Linux... <span class="k">done</span>, booting the kernel.<br/>4     RPC: Registered tcp NFSv4.1 backchannel transport module.<br/>2     INIT: version 2.86 booting<br/>1     mount: mounting /dev/mmcblk0p1 on /mnt/root failed: . . .<br/>4     Setting up IP spoofing protection: rp_filter.<br/>2     Lease of 192.168.10.190 obtained, lease <span class="nb">time </span>43200<br/>1     udevd <span class="o">(</span>403<span class="o">)</span>: /proc/403/oom_adj is deprecated . . .<br/>1     * Starting Avahi mDNS/DNS-SD Daemon: avahi-daemon...done.<br/>2     Populating dev cache<br/>1     INIT: Entering runlevel: 5<br/>14    rascal14 login:<br/></pre></div>

<p>My fellow Artisan's Asylum denizen, Edison, noticed that the resets seemed to only occur after U-boot passed control to the Linux kernel. He suggested that we try making the board reset under U-boot. Looking through the list of U-boot commands, the memory test command, <code>mtest</code>, seemed like it might generate a decent load on the processor, so we gave it a try.</p>
<p>As it turns out, <code>mtest</code> revealed that the processor resets are probably caused by memory write errors in the RAM on the board. The idea is that the kernel gets written to RAM incorrectly when it is copied out of the serial flash. Faced with an invalid instruction in RAM, the processor does the only thing it can do, which is reset itself. Similar failures occurred on both new boards but did not occur with an older board.</p>
<p>The memory errors reported by U-boot looked like this:</p>
<div class="pygments_monokai"><pre>Pattern 0000001E  Writing...            Reading...<br/>Pattern FFFFFFE1  Writing...            Reading...<br/>Pattern 0000001F  Writing...            Reading...<br/>Pattern FFFFFFE0  Writing...            Reading...<br/>Mem error @ 0x2124A33C: found 0049D711, expected FFB6D711<br/>Mem error @ 0x2124A340: found 0049D710, expected FFB6D710<br/></pre></div>

<p>There's a pattern to the errors: the two lower bytes are correct, but the two upper bytes are the inverse of what they should be (0x0049 instead of 0xFFB6, and note that 0xFFB6 + 0x0049 = 0xFFFF). This pattern appeared most of the time. Sometimes, all four bytes of the found value were exactly the inverse of the expected value.</p>
<p>The <code>mtest</code> program writes to every RAM address alternating values from each end of the range of 32 bits, i.e. this sequence: 0xFFFFFFFF, 0x00000000, 0xFFFFFFFE, 0x00000001, . . ., but incrementing the value written by 1 for each memory location in the address space. The <a href="https://github.com/rascalmicro/u-boot-rascal/blob/rascal/common/cmd_mem.c#L901">memory test code</a> is on Github.</p>
<p>The fact that the data read back is the inverse of what we expect, with errors along byte boundaries, rather than random corruption, suggests that the problem is a timing issue, rather than a data or address problem. It looks like two bytes are failing to be written from time to time, so we read back whatever was written during the previous cycle of the memory test, which explains the inverse values. This leads to looking at signal integrity.</p>
<h3 id="this-matter-called-signal-integrity">This matter called "signal integrity"</h3>
<p>"Signal integrity" means making sure that the digital pulses on a circuit board pass between chips without distortion in time or voltage. Sharp-edged pulses, as used in most digital communication, get rounded off because PCB traces have a little bit of capacitance and a little bit of resistance, which together make a low-pass filter. For most signals, this is not a problem, but when you send pulses that are faster than around 100 MHz over distances of more than an inch or so, you have to start being careful. With slow signals, if the sharp edges of your signals get rounded off for a few nanoseconds, you don't care. On the other hand, if you're signaling at 100 MHz, your signals are only 10 nanoseconds long, so you can't afford a few nanoseconds of sagging. Debugging this kind of problem is made more difficult because the average oscilloscope is too slow to capture 100 MHz signals accurately; all the sharp corners get rounded off whether your pulses are getting distorted or not.</p>
<p>There are more problems beyond getting sharp transitions. As signals propagate down PCB traces, they can be reflected back wherever the impedance of the trace changes, just like a wave of water reflects off the side of a tub. These reflections settle out in a few nanoseconds, but that's still a problem for high frequency signals.</p>
<p>Also, you want all of your signals to arrive at the same time. Electrical signals propagate through copper at around half the speed of light in a vacuum, or around 6 inches per nanosecond. This means that for two traces that differ by an inch in length, you get a timing error of around 0.17 ns.</p>
<h3 id="signal-integrity-on-the-rascal">Signal integrity on the Rascal</h3>
<p>Here's a cross-section of the Rascal circuit board. There are 4 layers of copper separated by 3 layers of fiberglass.</p>
<p><img src="/img/rascal-pcb-stackup.png"></p>
<p>The thickness of the green layer (which is actually yellow in real life) means that a 5 mil wide trace has a characteristic impedance of 80-85 ohms. In theory, I could match this impedance with termination resistors near the memory chips to insure that signals don't reflect in nasty ways, but because the memory errors look like timing problems rather than noise from reflections on a few data lines and more parts mean higher costs, I decided not to add them at this point.</p>
<p>My friend Michael has an extremely fast oscilloscope. Using his scope, I was able to take a look at the signals on some of the memory control lines. Here's what they look like. (Apologies for the poor photo-- I wasn't intending to show it to the world.)</p>
<p><img src="/img/memory-error-scope-screen.jpg" width="820px"></p>
<p>The whole screen shows shows two signals for 1/20,000,000th of a second. The green line is the 133 MHz memory clock pulse. The yellow line is the write-enable signal, which pulses low to signal that a write is taking place.</p>
<p>So what the hell does this picture mean? A rough summary is, "That yellow line looks like a noisy mess." In more precise terms, after the green signal crosses the minimum logical high voltage of 2.0 V (AKA V<sub>IH,MIN</sub>), we need the yellow signal (write enable) to stay below the maximum legal logical low voltage, 0.8 V (V<sub>IL,MAX</sub>) for 0.8 ns. You can't tell exactly from this picture, but the yellow signal rises right when the required hold time elapses. In theory, it should work, but given how noisy the signal is, it seems likely that it might slip to the wrong side of the line some of the time.</p>
<h3 id="how-do-we-fix-it">How do we fix it?</h3>
<p>To make the memory timing work right, I wanted to do two things at the same time-- I wanted to make sure all the signals arrive simultaneously and that they're not jammed so close together that currents in one trace induce noise in adjacent traces.</p>
<p>To make the traces the same length, I delved into the fetid depths of the Altium API via Jscript. After Altium emitted the length of each leg, I added them together with a quick Python script. (I'll include the code at the bottom of the post.) This gave me a CSV file that allowed me to calculate the average and standard deviation of the net lengths.</p>
<p>With the help of this tool, I redid the connections between the RAM and the processor with even trace lengths. For the original Rascals, I laid the board out without particular attention to signal integrity. The average memory trace was 2.91 inches with a standard deviation of a whopping 1.24 inches. For Rascal 1.2, the average trace was reduced to 2.15 inches and the standard deviation was 0.23 inches. The picture below shows the original Rascal in blue on the left and the new version in red on the right. You can see that the blue version looks crazy; in the red version, the longest mismatch relative to the clock line roughly 5x better at around 0.7 inches, which corresponds to a delay mismatch of 0.1 nanoseconds.</p>
<p><img src="/img/rascal-trace-length-comparison.png" width="820px"></p>
<p>I also rearranged the decoupling capacitors to minimize the length of their connections to the ground and power planes. I tried to space traces at least 6 mil apart from each other to minimize crosstalk between them. I could have done a more serious analysis of the trace spacing to minimize crosstalk, but as with termination resistors, I opted not to do it until I know I have to. My original, naive Rascal design worked, even though my traces were drastically different lengths, crammed together, and varying in impedance, so my hope is that a layout that doesn't do anything really stupid will succeed.</p>
<h3 id="rascal-12-on-the-way">Rascal 1.2 on the way</h3>
<p>The Rascal 1.2 PCBs have been sent out for assembly in Colorado; I should have the new Rascals back later this week. If they work, I'll have a larger batch up for sale in a few weeks as I already have the PCBs. Otherwise, Rascal 1.2 be cursed, and on to Rascal 1.3!</p>
<h3 id="update">UPDATE</h3>
<p>I got the new Rascals today (May 2, 2012) and they work. I haven't tested them 100% yet, but they both booted correctly, passed a few minutes of memory testing (~1 trillion write/read cycles without error) and loaded a bunch of files in the editor without a hitch.</p>
<h3 id="code">Code</h3>
<p>Here's the Jscript code for talking to Altium; feel free to do whatever you want with it. I'd recommend deleting it and then destroying all storage media it may have tainted.</p>
<div class="pygments_monokai"><pre><span class="kd">var</span> <span class="nx">Board</span><span class="p">;</span> <span class="c1">//IPCB_Board;</span><br/><span class="kd">var</span> <span class="nx">Net</span><span class="p">;</span><br/><span class="kd">var</span> <span class="nx">Iterator</span><span class="p">;</span><br/><span class="kd">var</span> <span class="nx">ReportFile</span><span class="p">;</span><br/><span class="kd">var</span> <span class="nx">address_lines</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;A0&quot;</span><span class="p">,</span><span class="s2">&quot;A1&quot;</span><span class="p">,</span><span class="s2">&quot;A2&quot;</span><span class="p">,</span><span class="s2">&quot;A3&quot;</span><span class="p">,</span><span class="s2">&quot;A4&quot;</span><span class="p">,</span><span class="s2">&quot;A5&quot;</span><span class="p">,</span><span class="s2">&quot;A6&quot;</span><span class="p">,</span><span class="s2">&quot;A7&quot;</span><span class="p">,</span><span class="s2">&quot;A8&quot;</span><span class="p">,</span><span class="s2">&quot;A9&quot;</span><span class="p">,</span><span class="s2">&quot;A10&quot;</span><span class="p">,</span><span class="s2">&quot;A11&quot;</span><span class="p">,</span><span class="s2">&quot;A13&quot;</span><span class="p">,</span><span class="s2">&quot;A14&quot;</span><span class="p">];</span> <span class="c1">// A12, A15+ omitted deliberately</span><br/><span class="kd">var</span> <span class="nx">data_lines</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;D0&quot;</span><span class="p">,</span><span class="s2">&quot;D1&quot;</span><span class="p">,</span><span class="s2">&quot;D2&quot;</span><span class="p">,</span><span class="s2">&quot;D3&quot;</span><span class="p">,</span><span class="s2">&quot;D4&quot;</span><span class="p">,</span><span class="s2">&quot;D5&quot;</span><span class="p">,</span><span class="s2">&quot;D6&quot;</span><span class="p">,</span><span class="s2">&quot;D7&quot;</span><span class="p">,</span><span class="s2">&quot;D8&quot;</span><span class="p">,</span><span class="s2">&quot;D9&quot;</span><span class="p">,</span><span class="s2">&quot;D10&quot;</span><span class="p">,</span><span class="s2">&quot;D11&quot;</span><span class="p">,</span><span class="s2">&quot;D12&quot;</span><span class="p">,</span><span class="s2">&quot;D13&quot;</span><span class="p">,</span><span class="s2">&quot;D14&quot;</span><span class="p">,</span><span class="s2">&quot;D15&quot;</span><span class="p">,</span><span class="s2">&quot;D16&quot;</span><span class="p">,</span><span class="s2">&quot;D17&quot;</span><span class="p">,</span><span class="s2">&quot;D18&quot;</span><span class="p">,</span><span class="s2">&quot;D19&quot;</span><span class="p">,</span><span class="s2">&quot;D20&quot;</span><span class="p">,</span><span class="s2">&quot;D21&quot;</span><span class="p">,</span><span class="s2">&quot;D22&quot;</span><span class="p">,</span><span class="s2">&quot;D23&quot;</span><span class="p">,</span><span class="s2">&quot;D24&quot;</span><span class="p">,</span><span class="s2">&quot;D25&quot;</span><span class="p">,</span><span class="s2">&quot;D26&quot;</span><span class="p">,</span><span class="s2">&quot;D27&quot;</span><span class="p">,</span><span class="s2">&quot;D28&quot;</span><span class="p">,</span><span class="s2">&quot;D29&quot;</span><span class="p">,</span><span class="s2">&quot;D30&quot;</span><span class="p">,</span><span class="s2">&quot;D31&quot;</span><span class="p">];</span><br/><span class="kd">var</span> <span class="nx">control_lines</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;CKE&quot;</span><span class="p">,</span><span class="s2">&quot;CLK&quot;</span><span class="p">,</span><span class="s2">&quot;CS&quot;</span><span class="p">,</span><span class="s2">&quot;CAS&quot;</span><span class="p">,</span><span class="s2">&quot;DQMH1&quot;</span><span class="p">,</span><span class="s2">&quot;DQMH2&quot;</span><span class="p">,</span><span class="s2">&quot;RAS&quot;</span><span class="p">,</span><span class="s2">&quot;WE&quot;</span><span class="p">];</span><br/><span class="kd">var</span> <span class="nx">term_res_lines</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;NetRA3_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA3_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA3_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA3_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA4_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA4_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA4_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA4_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA5_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA5_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA5_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA5_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA6_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA6_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA6_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA6_4&quot;</span><span class="p">];</span> <span class="c1">// NetRA1* and NetRA2* omitted deliberately</span><br/><span class="kd">var</span> <span class="nx">more_res_lines</span> <span class="o">=</span> <span class="p">[,</span><span class="s2">&quot;NetRA7_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA7_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA7_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA7_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA8_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA8_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA8_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA8_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA9_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA9_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA9_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA9_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA10_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA10_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA10_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA10_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA11_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA11_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA11_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA11_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA12_1&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA12_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA12_3&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA12_4&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA13_1&quot;</span><span class="p">,</span> <span class="s2">&quot;NetRA13_2&quot;</span><span class="p">,</span><span class="s2">&quot;NetRA13_3&quot;</span><span class="p">,</span> <span class="s2">&quot;NetRA13_4&quot;</span><span class="p">,</span> <span class="s2">&quot;NetRA14_2&quot;</span><span class="p">,</span> <span class="s2">&quot;NetRA14_3&quot;</span><span class="p">];</span><br/><span class="kd">var</span> <span class="nx">critical_nets</span> <span class="o">=</span> <span class="nx">address_lines</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">data_lines</span><span class="p">,</span> <span class="nx">control_lines</span><span class="p">,</span> <span class="nx">term_res_lines</span><span class="p">,</span> <span class="nx">more_res_lines</span><span class="p">);</span><br/><br/><span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">)</span> <span class="p">{</span><br/>   <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">indexOf</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="p">{</span><br/>      <span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><br/>      <span class="k">while</span> <span class="p">(</span><span class="nx">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span><br/>         <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">===</span> <span class="nx">item</span><span class="p">)</span> <span class="k">return</span> <span class="nx">i</span><span class="p">;</span><br/>      <span class="p">}</span><br/>   <span class="p">}</span><br/><span class="p">}</span><br/><br/><span class="nx">FileName</span> <span class="o">=</span> <span class="s2">&quot;C:\Net_Length_Report.Txt&quot;</span><span class="p">;</span><br/><br/><span class="nx">fso</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ActiveXObject</span><span class="p">(</span><span class="s2">&quot;Scripting.FileSystemObject&quot;</span><span class="p">);</span><br/><span class="nx">ReportFile</span> <span class="o">=</span> <span class="nx">fso</span><span class="p">.</span><span class="nx">CreateTextFile</span><span class="p">(</span><span class="nx">FileName</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span><br/><br/><span class="kd">function</span> <span class="nx">ShowBusLength</span><span class="p">(){</span><br/>    <span class="nx">Board</span> <span class="o">=</span> <span class="nx">PCBServer</span><span class="p">.</span><span class="nx">GetCurrentPCBBoard</span><span class="p">;</span><br/>    <span class="nx">Iterator</span> <span class="o">=</span> <span class="nx">Board</span><span class="p">.</span><span class="nx">BoardIterator_Create</span><span class="p">;</span><br/><br/>    <span class="nx">Iterator</span><span class="p">.</span><span class="nx">AddFilter_ObjectSet</span><span class="p">(</span><span class="nx">MkSet</span><span class="p">(</span><span class="nx">eNetObject</span><span class="p">));</span><br/>    <span class="c1">//Iterator.AddFilter_NetClass(&quot;U5-signals&quot;);</span><br/>    <span class="nx">Iterator</span><span class="p">.</span><span class="nx">AddFilter_LayerSet</span><span class="p">(</span><span class="nx">AllLayers</span><span class="p">);</span><br/>    <span class="nx">Iterator</span><span class="p">.</span><span class="nx">AddFilter_Method</span><span class="p">(</span><span class="nx">eProcessAll</span><span class="p">);</span><br/>    <span class="nx">Net</span> <span class="o">=</span> <span class="nx">Iterator</span><span class="p">.</span><span class="nx">FirstPCBObject</span><span class="p">;</span><br/><br/>    <span class="k">while</span> <span class="p">(</span><span class="nx">Net</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span><br/>        <span class="k">if</span> <span class="p">(</span><span class="nx">critical_nets</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">Net</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span><br/>            <span class="nx">ReportFile</span><span class="p">.</span><span class="nx">WriteLine</span><span class="p">(</span><span class="nx">Net</span><span class="p">.</span><span class="nx">Name</span> <span class="o">+</span> <span class="s2">&quot;,&quot;</span> <span class="o">+</span> <span class="nx">CoordToMils</span><span class="p">(</span><span class="nx">Net</span><span class="p">.</span><span class="nx">RoutedLength</span><span class="p">));</span><br/>        <span class="p">}</span><br/>        <span class="nx">Net</span> <span class="o">=</span> <span class="nx">Iterator</span><span class="p">.</span><span class="nx">NextPCBObject</span><span class="p">;</span><br/>    <span class="p">}</span><br/>    <span class="nx">ReportFile</span><span class="p">.</span><span class="nx">Close</span><span class="p">();</span><br/><br/>    <span class="nx">ReportDocument</span> <span class="o">=</span> <span class="nx">Client</span><span class="p">.</span><span class="nx">OpenDocument</span><span class="p">(</span><span class="s2">&quot;Text&quot;</span><span class="p">,</span> <span class="nx">FileName</span><span class="p">);</span><br/>    <span class="k">if</span><span class="p">(</span><span class="nx">ReportDocument</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span><br/>        <span class="nx">Client</span><span class="p">.</span><span class="nx">ShowDocument</span><span class="p">(</span><span class="nx">ReportDocument</span><span class="p">)</span><br/><span class="p">}</span><br/></pre></div>

<p>Here's the Python script for summing lengths of multi-leg nets.</p>
<div class="pygments_monokai"><pre><span class="kn">import</span> <span class="nn">csv</span><br/><br/><span class="n">r</span> <span class="o">=</span> <span class="n">csv</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">&#39;net-length-report.csv&#39;</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">))</span><br/><span class="n">d</span> <span class="o">=</span> <span class="p">{}</span><br/><span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">r</span><span class="p">:</span><br/>     <span class="n">d</span><span class="p">[</span><span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="n">line</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><br/><span class="n">d</span><span class="p">[</span><span class="s">&#39;zero&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;0.0&#39;</span><br/><br/><span class="n">outfile</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;output.csv&#39;</span><span class="p">,</span> <span class="s">&#39;wb&#39;</span><span class="p">)</span><br/><br/><span class="n">buses</span> <span class="o">=</span> <span class="p">[</span><br/>    <span class="p">(</span><span class="s">&#39;A0&#39;</span><span class="p">,</span><span class="s">&#39;NetRA11_1&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A1&#39;</span><span class="p">,</span><span class="s">&#39;NetRA11_2&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A2&#39;</span><span class="p">,</span><span class="s">&#39;NetRA11_3&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A3&#39;</span><span class="p">,</span><span class="s">&#39;NetRA11_4&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A4&#39;</span><span class="p">,</span><span class="s">&#39;NetRA12_1&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A5&#39;</span><span class="p">,</span><span class="s">&#39;NetRA12_2&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="s">&#39;A6&#39;</span><span class="p">,</span><span class="s">&#39;NetRA12_3&#39;</span><span class="p">),</span><br/>    <span class="p">(</span><span class="n">you</span> <span class="n">get</span> <span class="n">the</span> <span class="n">idea</span><span class="o">--</span> <span class="n">there</span> <span class="n">were</span> <span class="n">more</span> <span class="n">nets</span> <span class="n">listed</span> <span class="n">here</span><span class="p">)</span><br/><span class="p">]</span><br/><br/><span class="k">for</span> <span class="n">leg1</span><span class="p">,</span> <span class="n">leg2</span> <span class="ow">in</span> <span class="n">buses</span><span class="p">:</span><br/>    <span class="n">total</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="n">leg1</span><span class="p">])</span> <span class="o">+</span> <span class="nb">float</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="n">leg2</span><span class="p">])</span><br/>    <span class="n">outfile</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">leg1</span> <span class="o">+</span> <span class="s">&#39;,&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">total</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span><br/><br/><span class="n">outfile</span><span class="o">.</span><span class="n">close</span><span class="p">()</span><br/></pre></div>]]></content:encoded>
    </item>
    <item>
      <title>Open source hardware in Washington, D.C.</title>
      <link>http://rascalmicro.com/blog/2012/04/26/open-source-hardware-in-washington,-d.c.</link>
      <pubDate>Thu, 26 Apr 2012 00:00:00 EDT</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">ShG85cAviWgBS8o8IydSnvN-jKw=</guid>
      <description>Open source hardware in Washington, D.C.</description>
      <content:encoded><![CDATA[<p>Last weekend, I traveled down to Washington, D. C. to visit family; while I was there, I went to an <a href="http://www.publicknowledge.org/event/ohdc-open-source-hardware-comes-dc">open hardware event</a> put on by Public Knowledge on Friday afternoon. The event was organized by Michael Weinberg of Public Knowledge. Cat Johnson has a <a href="http://www.shareable.net/blog/open-source-hardware-goes-to-washington">nice discussion</a> with Michael explaining why they want to introduce policymakers to the idea of open hardware.</p>
<p>In reference to last year's similar event for 3D printing, Michael says,</p>
<p>"If you're a legislator and the first time you ever hear about 3-D printing is someone coming into your office saying, 'This horrible pirate box is ruining my business,' you would have one world view of 3-D printing. If the first time you hear about 3-D printing is someone saying, 'Wow, look at all these new businesses and people who are coming together around technology and creating all these amazing things,' you have a different world view about the subject."</p>
<p>Cat explains that with this approach, "Public Knowledge doesn’t have to spend the first half of a meeting explaining what it is they’re talking about."</p>
<p>The event consisted of two panels about open source hardware, followed by a demo session in the Rayburn Foyer. I watched the panels and had a table in the demo session. The demo I brought for the event is a motor that can have its speed controlled through the internet; the picture below shows its I-am-not-a-terrorist guise.</p>
<p><img src="/img/demo-with-motor-in-case.jpg" width="820px"></p>
<p>The two panels occurred in a small room on the third floor of the Rayburn office building. Each panel was 4 or 5 people. There were around 100 people there; at least 40 of them were open hardware folks; the remainder were either policy people or random geeks who wanted to see the action.</p>
<p>My hometown of Somerville is in Rep. Mike Capuano's district (he used to be mayor of Somerville), but Capuano and his aides were too busy to come to the event.</p>
<h3 id="where-we-stand">Where we stand</h3>
<p>The panelists answered questions from the moderators, Alicia Gibb and Michael Weinberg. The event was filmed, so I won't try to reproduce all the questions and answers here, but it was definitely interesting and informative. Bunnie Huang had a great rant about how everyone involved in the production of electronics should visit the electronics markets in Shenzhen and feel the energy of commerce. (If that intrigues you, read his <a href="http://www.bunniestudios.com/blog/?p=147">great blog post about Shenzhen</a> from a few years ago.) All hardware, with some level of reverse engineering, is open, he pointed out. There are huge markets that don't have the strong IP rights enforcement we have in the US.</p>
<p>To me, the point is that we are making open source hardware even if we don't want to. This forces us to adopt openness by default, so that we get the benefits as well as the detriments.</p>
<p>I was encouraged to see that we have a bunch of smart people on our side. Bunnie, AnnMarie Thomas, David Mellis, and Nathan Seidle are articulate and funny. The demos were impressive. My favorite moment of the day was talking to a janitor who was drawn in by a RepRap 3D printer that was running unattended before the event officially started. Noticing that she was staring at the machine and seemed puzzled, I pointed out the printed-out plastic rabbits on the table and explained that the RepRap was halfway through printing another one. I showed her the pair of new Makerbot Replicators that can print two colors at once. She had the 3D printing epiphany and said something like, "This thing can make you anything you want!" She grabbed a few Makerbot fliers and as she left, she said, "I gotta tell people about this!" She had the altered-world urgency of someone who has just learned that Kennedy is still alive, or discovered that soylent green is people, or seen Nathan's secret tattoo. (Don't bother asking. He just pretends it doesn't exist.) I'm glad that we could help spread the enthusiasm.</p>
<p>The demos went well; I'd estimate that 50-100 people passed through, which is pretty good for a sunny Friday afternoon. I hadn't seen the very cool <a href="http://courseweb.stthomas.edu/apthomas/SquishyCircuits/index.htm">squishy circuits</a> before; somehow, they managed to attract the children in the crowd, which is impressive for an event aimed at adults in suits. The Rascal demo worked perfectly, though I did have a couple moments of terror while setting up. First, it seems that in double-checking my demo, I managed to delete my DHCP server's configuration file. Fortunately, it was easy to switch the Rascal to a static IP. I guess I'm prepared for idiots like me.</p>
<p>Then, in my motor control demo, some of the Javascript code was linked from external servers. When I tested it the night before without an internet connection, the Rascal used cached versions of the code. 12 hours later, the cached versions expired, which left me scrambling for a wireless connection to pull down the code I needed. After some quick modifications to use local code, the demo worked quite well. Several people stopped by to ask when new Rascals would be available for sale, which made my day. (Thanks, Shawn!)</p>
<p>Still, my overall impression was that as a group, we open hardware folks are weak on the policy front. We don't know what policies we want. Worse, we don't even know what outcomes we want. Some of us really don't care about licenses; others think we need them desperately; and still others think licensing hardware is hopeless. We're just setting up the <a href="http://www.oshwa.org/">first open source hardware nonprofit organization</a>. Our most experienced professionals are people like Nathan and Bunnie, who were in college 10 years ago. Generally, we seem like people much more interested in building stuff than public policy. In some contexts, our political inexperience is alarming; Michael Weinberg put it more optimistically: "No, that just means you've made prudent life choices!"</p>
<p>Thanks to Public Knowledge for organizing the event.</p>
<p>(More details about the state of the new Rascal boards coming soon.)</p>]]></content:encoded>
    </item>
    <item>
      <title>The first Rascal 1.1 prototypes have arrived</title>
      <link>http://rascalmicro.com/blog/2012/03/06/the-first-rascal-1.1-prototypes-have-arrived</link>
      <pubDate>Tue, 06 Mar 2012 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">0bmzrtMw19QO4BQHfbPRQFCu0A0=</guid>
      <description>The first Rascal 1.1 prototypes have arrived</description>
      <content:encoded><![CDATA[<p>After a lot of ordering parts, tweaking of PCB layouts, and optimizing the bill of materials, the new Rascals have arrived from the assembler in Colorado. 
<img src="/img/rascal-1.1.jpg" width="820px"></p>
<p>Whenever I build a new version of the Rascal, the big question is, "Have I made some horribly stupid error that has turned all of the parts I sent away to the assembler into landfill stuffing?" So far, I haven't found any landfill-worthy errors.</p>
<p>Here's the list of changes.</p>
<ol>
<li>Added second USB host port and stacked USB connector</li>
<li>Put in a new Ethernet controller (Micrel KSZ8051RNL)</li>
<li>Moved the I<sup>2</sup>C/TWI pins to the Arduino-compatible location</li>
<li>Added I<sup>2</sup>S port for streaming audio</li>
<li>Changed JTAG footprint to work with pogo pins more easily</li>
<li>Switched to black Samtec headers rather than the blue ones, which were chintzy</li>
</ol>
<h3 id="what-works-and-what-doesnt">What works and what doesn't?</h3>
<p>The new Rascal has two USB host ports. (Earlier Rascals have only one, and with a worse connector.) I plugged in an old Logitech webcam I picked up at the MIT flea market a few months ago and it was correctly identified by the kernel, as you can see in the command line snippet below.</p>
<div class="pygments_monokai"><pre><span class="o">[</span>root@rascal1.1<span class="nv">$:</span>~<span class="o">]</span>: lsusb<br/>Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub<br/>Bus 001 Device 002: ID 046d:08b0 Logitech, Inc. QuickCam 3000 Pro <span class="o">[</span>pwc<span class="o">]</span><br/></pre></div>

<p>Both USB ports are at least wired correctly, but I haven't tested them more thoroughly yet.</p>
<p>The hairiest change in this rev of the Rascal was the change to a new ethernet PHY chip, the Micrel KSZ8051. The new chip costs less, uses less power, requires fewer external caps and resistors to make it work, and, most importantly, won't be obsolete any time soon. The macb driver in the Linux kernel correctly identifies the controller, as you can see in the snippet of boot spew below, but the link doesn't come up. I'm not sure where the problem is yet.</p>
<div class="pygments_monokai"><pre>MACB_mii_bus: probed<br/>eth0: Atmel MACB at 0xfffc4000 irq 21 <span class="o">(</span>02:71:82:06:00:14<span class="o">)</span><br/>eth0: attached PHY driver <span class="o">[</span>Micrel KS8051<span class="o">]</span> <span class="o">(</span>mii_bus:phy_addr<span class="o">=</span>ffffffff:00, <span class="nv">irq</span><span class="o">=</span>-1<span class="o">)</span><br/></pre></div>

<p>I haven't tested the I<sup>2</sup>S or I<sup>2</sup>C ports yet.</p>
<p>The new JTAG interface worked for programming the kernel and bootloaders into the serial flash on the Rascal. I had to make a new programming fixture, pictured below. The beige part was printed on the Uprint 3D printer at Artisan's Asylum. The brass pins are pogopins, i.e. their tips are spring-loaded like (upside-down) pogosticks. The 20-pin black connector at lower right will connect to an Atmel JTAG pod, which then connects via USB to a PC.</p>
<p>Having access to high-quality 3D printing on the cheap (that part cost around $10) is definitely changing the way I design stuff. For low volume plastic parts like this, it's a huge improvement over sending stuff out to be machined out of Delrin with a 5 day turn for $500. </p>
<p><img src="/img/jtag-fixture-2012-03-05.jpg" width="820px"></p>
<p>Here's one last photo, which shows the Rascal in the fixture. The pogopins are under the PCB under the clamp.</p>
<p><img src="/img/jtag-fixture-with-rascal-1.1-2012-03-05.jpg" width="820px"></p>
<p>If I can get the ethernet port working under Linux and no other problems emerge, I'll send the 20 remaining PCBs out for assembly, and they'll be available in the store for sale when I get them back. After that will come the first batch of 100 Rascals, which will be a <em>huge</em> milestone.</p>
<p>So far, so good!</p>]]></content:encoded>
    </item>
    <item>
      <title>Rascal 1.1 circuit board released for fabrication</title>
      <link>http://rascalmicro.com/blog/2012/01/31/rascal-1.1-circuit-board-released-for-fabrication</link>
      <pubDate>Tue, 31 Jan 2012 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">-adZ-0MnuhvBrnH1H3mJaeVDXww=</guid>
      <description>Rascal 1.1 circuit board released for fabrication</description>
      <content:encoded><![CDATA[<p>I just sent the Rascal 1.1 PCB off to <a href="http://internationalcircuits.com">International Circuits</a> for fabrication. I'm calling it version 1.1 because the last version, which was officially 0.6, AKA "the beta," turned out to be 1.0-level in quality.</p>
<p>Here's a screenshot of the final layout. (Click for a substantially larger version.)</p>
<p><a href="/img/rascal-1.1-2012-01-31-pcb-snapshot.png"><img src="/img/rascal-1.1-2012-01-31-pcb-snapshot.png" width="820px"></a></p>
<p>Thanks to Jinbuhm Kim of Wiznet for the last-minute suggestion to add pin labels on the underside of the PCB (so you can see them after an Arduino shield is plugged in on top).</p>
<p>A full list of the hardware changes appears in the <a href="http://rascalmicro.com/blog/2012/01/17/the-first-production-rascals-sell-out,-plus-some-color-kinetics-action/">previous blog post</a>. The software will be updated as well-- a new Linux kernel, a new driver to call Python from hardware interrupts, an improved web editor, and some awesome new HTML5 demos from the volunteer sharpshooting development team in England.</p>
<p>If you think the Rascal might be right for your next ridiculous internet machine, sign up for the <a href="http://store.rascalmicro.com">announcement list</a> to get alerted when they're ready.</p>]]></content:encoded>
    </item>
    <item>
      <title>The first production Rascals sell out, plus some Color Kinetics action</title>
      <link>http://rascalmicro.com/blog/2012/01/17/the-first-production-rascals-sell-out,-plus-some-color-kinetics-action</link>
      <pubDate>Tue, 17 Jan 2012 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">NqPkxdXiX_6NIfYP0EQmNzA9lJs=</guid>
      <description>The first production Rascals sell out, plus some Color Kinetics action</description>
      <content:encoded><![CDATA[<p>The first production run of 15 Rascals sold out a few days ago. Thanks to all of you who bought them-- the revenue will go directly back into making the next run.</p>
<p>The next batch of Rascals will be nearly identical to the previous batch. The hardware changes are:</p>
<ol>
<li>Added second USB host port and stacked USB connector</li>
<li>Cheaper, newer, less power-hungry Ethernet controller (Micrel KSZ8051RNL)</li>
<li>Moved the I2C/TWI pins to the Arduino-compatible location</li>
<li>Added I2S port for streaming audio</li>
<li>Changed JTAG and serial debug footprints to work with pogo pins more easily</li>
</ol>
<p>The software will also be improved for the next batch, in part thanks to the people who have been tweaking the code on their Rascals. The editor will have some new features and the set of tested libraries on the Rascal will be much larger. Because the hardware changes are minor, it's likely that the new software will run fine on old Rascals.</p>
<p>The next batch will be delayed because of Chinese New Year, which runs from January 20 - February 5 this year. In the meantime, if you're interested in buying a Rascal, sign up for the <a href="http://store.rascalmicro.com">announcement list</a> to get alerted when they're ready.</p>
<h3 id="making-the-rascal-work-with-color-kinetics-lights">Making the Rascal work with Color Kinetics lights</h3>
<p>Most of my time has been devoted to PCB layout, but I've also been working on some Rascal-controlled light displays around Boston with a <a href="http://newamericanpublicart.com">group of public artists</a> operating out of <a href="http://artisansasylum.com">Artisan's Asylum</a>. Dan Taub of <a href="http://cemmi.org">CEMMI</a> was kind enough to lend me a Color Kinetics light for testing. I've been using a <a href="https://github.com/vishnubob/kinet">Python library written by Giles Hall</a> that wraps DMX512 data in UDP packets using the KiNet protocol. I created a quick demo page consisting of a color picker on a web page. You pick a color and the Rascal tells the light to turn that color.</p>
<p>Here's a short video that shows the demo in action. If you happen to be on Artisan's Asylum's wireless network, you're welcome to <a href="http://rascal14.local/ck.html">test it out</a> yourself-- just look for the light near the Rascal Micro space (#16).</p>
<iframe class="span14" src="http://player.vimeo.com/video/35173486?title=0&amp;byline=0&amp;portrait=0&amp;color=C6433C" height="461" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>]]></content:encoded>
    </item>
    <item>
      <title>Rascal wins Editors' Choice, now with an interview!</title>
      <link>http://rascalmicro.com/blog/2012/01/05/rascal-wins-editors'-choice,-now-with-an-interview!</link>
      <pubDate>Thu, 05 Jan 2012 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">yWlZP2slIYRfJmZ48Gwvd3mXqMY=</guid>
      <description>Rascal wins Editors' Choice, now with an interview!</description>
      <content:encoded><![CDATA[<div class="row">
<img class="span2" src="/img/postscapes-award-badge.png">

<div class="span12">
<p>The Rascal won the <a href="http://postscapes.com/best-iot-open-source-project-2011">Editors' Choice award</a> in the Open Source Project category at <a href="http://postscapes.com">Postscapes</a> a few days ago. Postscapes is a site in South Korea that tracks the "internet of things," which means stuff like the Rascal, more or less. In the aftermath of the contest, Trevor Harwood of Postscapes and I recorded a discussion of the various topics related to connecting stuff to the internet, open source hardware, and the Rascal. Trevor was kind enough to transcribe and discretize the discussion so you can absorb it in palatable chunks.</p>
</div>
</div>

<p><strong>Read/listen to <a href="http://postscapes.com/iot-open-source-computers-a-conversation-with-rascal-creator-brandon-stafford">the interview</a>.</strong></p>
<h3 id="a-brief-rant-about-firewalls-and-port-forwarding">A brief rant about firewalls and port forwarding</h3>
<p>One topic that I had meant to discuss, but forgot about in the heat of battle, is the growing asymmetry of internet connections as the industry matures. The original design of the internet made each computer on the network equal to every other. At least in the US, this is no longer the case. Most incoming connections to our homes and businesses are filtered to prevent people from running their own servers.</p>
<p>Instead of assigning unique addresses to each computer, we use what's called "Network Address Translation," which allows each connection to build its own network behind a firewall, while masquerading as a single computer to the rest of the internet. This works pretty well for surfing the web, but when you want to take off the mask to build the internet of things, it's a problem. Additionally, some connections are filter out incoming requests to ports 80 (HTTP) and 25 (email). This is the case for the least-of-evils, at-least-they're-not-Comcast cable connection from RCN I have at home.</p>
<p>In theory, you can request a block of IP addresses from the <a href="https://www.arin.net/fees/fee_schedule.html">American Registry of Internet Numbers</a>, but the minimum fee for IP addresses is $1250, plus various fees for other details (registration and maintenance of an Autonomous System number and such) and ARIN won't give you addresses without a convincing explanation of why you need them. Even if they relented, you'd still need to pay someone who owns a bunch of telephone poles to run a wire from your house to your local internet exchange or negotiate some kind of deal with the local government to allow you to run the cable yourself.</p>
<p>There are a few workarounds that you can use. If you have control of your router, you can pick a few external ports that aren't blocked by your ISP and forward them to devices on your internal network. If you live in a big apartment building where all you get is wireless access, this won't work unless your landlord likes you a lot and nobody else wants to fight you for those ports. The other option is creating encrypted software tunnels to external servers, but that requires either that you run a server yourself or get access from someone who does.</p>
<p>Anyway, it's a bit of a mess. I wish I had more ideas about how to fix the situation, but I don't. I wish I had grown up in the good old days, when men were men and IP addresses were globally routed.</p>]]></content:encoded>
    </item>
    <item>
      <title>3D printed Rascal base with tapped holes</title>
      <link>http://rascalmicro.com/blog/2011/12/23/3d-printed-rascal-base-with-tapped-holes</link>
      <pubDate>Fri, 23 Dec 2011 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">YpQ-s_gL6_jv9Dpzv93szf4IUak=</guid>
      <description>3D printed Rascal base with tapped holes</description>
      <content:encoded><![CDATA[<p>If you want to mount the Rascal in a metal enclosure, you need a way to hold the board away from the enclosure, so the electronics don't get shorted out. For most of the history of electronics, this sort of task has been accomplished using small, annoying posts called "standoffs." They work, but they're more expensive and fiddly than you'd like.</p>
<p>Now that consumer-grade 3D printers like the <a href="http://www.makerbot.com/">Makerbot</a> Thing-O-Matic are available, printing custom brackets to hold your circuit board is plausible. I've taken a first cut at the design and uploaded the <a href="http://www.thingiverse.com/thing:14894">source files</a> to Thingiverse. If you'd like some brackets for your Rascal and you have access to a 3D printer, you're welcome to download the files and print out some brackets. The print time is around 8 minutes per bracket. They'll work with either #4-40 or M3 fasteners. If you're not sure, use M3 because the metric system is better.</p>
<p>If you'd like to try this out, but you can't find a 3D printer, you might try checking with your local hackerspace, which you can find on the <a href="http://hackerspaces.org/wiki/List_of_Hacker_Spaces">Hackerspaces.org</a> map.</p>
<p><img src="/img/3d-printed-rascal-bases.jpg" alt="4 handsome pieces of plastic with small fasteners protruding"></p>
<h2 id="drilling-and-tapping-3d-printed-brackets">Drilling and tapping 3D printed brackets</h2>
<p>The holes in the brackets won't have threads in them straight out of the printer. To make  threads in the plastic, you need to drill out the holes to the right diameter and then use a tap to cut the threads.</p>
<p>It would be nice if you didn't need to predrill the holes before tapping. In the model, the holes are set to 2.26 mm in diameter, which theoretically shouldn't need predrilling, but with parts printed on my local Thingomatic, the actual diameter was smaller, so predrilling was required.</p>
<h3 id="m3-fasteners">M3 fasteners</h3>
<p>For M3 fasteners, I use a 0.100" drill (AKA drill size #39). You could certainly use a 2.5 mm drill. I suspect that a 3/32" drill would also work. For mounting the Rascal, a M3 x 6 stainless steel socket head cap screw, such as McMaster part number 91292A111, works great.</p>
<h3 id="4-40-fasteners">#4-40 fasteners</h3>
<p>For #4-40 fasteners, I use a 0.089" drill (AKA drill size #43). I suspect that a 3/32" drill would also work. For mounting the Rascal, a #4-40 x 1/4" stainless steel socket head cap screw, such as McMaster part number 92196A106, works great.</p>]]></content:encoded>
    </item>
    <item>
      <title>Testing the Rascal with the Greenway light blades</title>
      <link>http://rascalmicro.com/blog/2011/12/02/testing-the-rascal-with-the-greenway-light-blades</link>
      <pubDate>Fri, 02 Dec 2011 00:00:00 EST</pubDate>
      <category><![CDATA[rascal]]></category>
      <guid isPermaLink="false">OJywPUOlhJiVgvSpEMEWEMIUw_I=</guid>
      <description>Testing the Rascal with the Greenway light blades</description>
      <content:encoded><![CDATA[<p>Here's a low quality video of a truly excellent event.</p>
<p>I'm working on a project to control the light blades on the Greenway in Boston through text messages. While I was filming the video with my phone, <a href="http://thehinge.net/">Dan</a> was crouched in "The Vault," a concrete bunker under the Greenway plaza. We had a Rascal plugged into the light controller with a serial cable. Dan used a Python script I wrote to generate HTTP POSTs on my laptop. In theory, the POSTs are the same requests that we'll eventually receive from Twilio. (See this <a href="http://rascalmicro.com/docs/basic-tutorial-responding-to-text-messages.html">Rascal-and-Twilio tutorial</a> for the details on how that works.) The Rascal parses the messages Dan sends and decides what show to play. The shows are still a bit of a mess, but the Rascal is working great.</p>
<p>I don't want to say too much more about what we have planned until it's closer to fruition, but I think it will be cool.</p>
<iframe src="http://player.vimeo.com/video/33047579?title=0&amp;byline=0&amp;portrait=0" width="400" height="711" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>

<p>Below is a better still shot from Eric Kilby that gives a better idea of what the light blades look like in person. There are 12 of them in all; they're in the park between Faneuil Hall and the Aquarium.</p>
<p><a href="http://www.flickr.com/photos/ekilby/2600873212/"><img src="/img/eric-kilby-light-blades.jpg" alt="6 green steel blades, 20 feet high, aimed at the sky"></a></p>]]></content:encoded>
    </item>
    <item>
      <title>The first Rascals are up for sale</title>
      <link>http://rascalmicro.com/blog/2011/11/03/the-first-rascals-are-up-for-sale</link>
      <pubDate>Thu, 03 Nov 2011 00:00:00 EDT</pubDate>
      <category><![CDATA[rascal]]></category>
      <category><![CDATA[business]]></category>
      <guid isPermaLink="false">5pWqAzdXEBjpbVgqgYuElllaWfQ=</guid>
      <description>The first Rascals are up for sale</description>
      <content:encoded><![CDATA[<p>Today, I am delighted and terrified to announce that the Rascal is available for sale.</p>
<p>The Rascal beta testers have done their job. As of today, there are 11 <a href="http://store.rascalmicro.com/">Rascals available for sale</a> in the Rascal store. The hardware is the same as the Rascals in the beta test, but the operating system and web interface have been upgraded with all the improvements from the last 6 months of testing and software development.</p>
<p>You're a good candidate to buy a Rascal today if:</p>
<ol>
<li>You want to connect something to the internet, and you'd like my help in doing it. I don't want these things stuck in a drawer!</li>
<li>You're willing to put up with some rough edges. The web interface works, but it's still rudimentary.</li>
<li>You have some technical skills. While not necessary, some vague familiarity with SSH would be helpful if we need to debug stuff.</li>
</ol>
<h2 id="historic-firsts">Historic firsts</h2>
<p>As far as I know, the sale of the Rascal to the general public marks new progress for our species in a few ways.</p>
<ul>
<li>First small hacker board to ship with a modern Python web stack (Flask, uWSGI, and Nginx) pre-installed. This is the original target of the Rascal achieved.</li>
<li>First small hacker board to ship with a web-based editor that you can use to edit web pages on the board.</li>
<li>First Linux hacker board to ship with Arduino shield headers. (The Leaflabs Maple has the headers, but no operating system. I hear there was a beta version of the Chumby Hackerboard that had Arduino headers, but they were removed in the production release.)</li>
</ul>
<h2 id="getting-started-video-tutorial">"Getting started" video tutorial</h2>
<p>Now that the hardware and software have reached a level of basic functionality, I've been working on video tutorials that explain how to use the Rascal. The <a href="/docs/basic-tutorial-getting-started.html">first tutorial</a> covers the web interface.</p>
<p>Detonate the fireworks now,</p>
<p>Brandon</p>]]></content:encoded>
    </item>
    <item>
      <title>I want to connect weird stuff to the internet</title>
      <link>http://rascalmicro.com/blog/2011/08/01/i-want-to-connect-weird-stuff-to-the-internet</link>
      <pubDate>Mon, 01 Aug 2011 00:00:00 EDT</pubDate>
      <category><![CDATA[webinterface]]></category>
      <category><![CDATA[rascal]]></category>
      <category><![CDATA[presentations]]></category>
      <guid isPermaLink="false">p6xbG734P2FnyFVVvjtO2ZNm4wM=</guid>
      <description>I want to connect weird stuff to the internet</description>
      <content:encoded><![CDATA[<p>Through the unseen machinations of social networks, I was invited by LED zealot <a href="http://thingm.com/about-us/team/mike-kuniavsky.html">Mike Kuniavsky</a> to the <a href="http://sketching11.com">Sketching in Hardware</a> conference in Philadelphia last weekend. All 38 attendees were required to give an 18 minute presentation related to the topic of the conference, which is tools for physical computing prototyping. ("Physical computing" is a term used by CS types to describe what the mechanical and electrical engineers call "embedded systems" and the English majors call "Arduinos.")</p>
<p>The talks weren't recorded and my slides (<a href="/files/presentations/2011-07-31-sketching11-weird-stuff-to-the-internet.pdf">1.7 MB PDF</a>) contain only an outline of what I talked about, so I thought it would be useful to summarize what I talked about, while also adding a few links and details that I omitted in the 18-minute spoken format.</p>
<h2 id="what-i-said-at-sketching-in-hardware">What I said at Sketching In Hardware</h2>
<p>Introductory fact: I want to connect weird stuff to the internet.</p>
<p>Because I'm an embedded systems engineer, idle conversation often leads to someone saying this to me:
"Oh, you know about computers? OK, here's what I want to do. I want to somehow take this thing and connect it to the internet."</p>
<p>"This thing" is usually something weird. Recent examples include:</p>
<ul>
<li>A chicken coop</li>
<li>Some kind of sausage factory</li>
<li>Hot tub</li>
<li>Thermostat for the boiler in a box factory</li>
<li>A lighting display that reflects the anger level of the owner, two friends, and a guest</li>
</ul>
<p>I love this kind of project, but I used to have an attitude about the proper hardware for the job.</p>
<p>In grad school, I used to scoff at the <a href="http://www.parallax.com/tabid/295/Default.aspx">BASIC Stamp</a>. Running into a friend buying a BASIC Stamp in Fry's, I'd challenge them: "You know that's just a $3 PIC with a BASIC interpreter on it, right? Why would you pay $50 for that?"</p>
<p>They would have some reasonable response like: "Look, Brandon, I just want to make this valve keep my tomato plants watered. What would you have me do?"</p>
<p>I'd think: "Why, just learn C, PCB layout, and some basic electrical engineering! . . . Er. Um. I guess I'm being unreasonable. But it's a $3 PIC!" I'd say something dumb, and then storm off to the lab.</p>
<p>Now, after a few years working with lots of different microcontrollers and industrial automation systems, I'm on the other side. Yes, I know C, and I can lay out PCBs, but for simple tasks, I want a simple tool.</p>
<p>This is where the <a href="http://arduino.cc">Arduino</a> enters the picture. The Arduino folks have done an incredible job of making a simple microcontroller board that is easy to use for people who are new to programming. As a result, a huge community has developed around the board. The Arduino is not the ultimate solution for all problems, but it does a great job at simple automation tasks.</p>
<h2 id="moving-beyond-the-arduino">Moving beyond the Arduino</h2>
<p>Of course, as you try to do more complex stuff with the Arduino, you start to hit its limits: 16 MHz clock, no file system, no threading, 2 kB RAM, 32 kB of flash, no internet connection, no display. Marginally capable of audio, no hope of video.</p>
<p>You start cobbling together an operating system with different modules. You try to squeeze a webserver, network driver, and threading module into 32 kB.</p>
<p><em>(Note: <a href="http://dam.mellis.org/">Dave Mellis</a> was nodding knowingly and smiling at this point in the talk.)</em></p>
<p>Then you end up in the unfortunate situation where you need to jump up to a more powerful system. There are lots of choices, but probably you end up with something like <a href="http://gumstix.com">Gumstix</a> or the <a href="http://beagleboard.org">Beagleboard</a>-- an embedded Linux system. Suddenly, instead of the friendly Arduino program, you're off in the weeds. The friendly programming environment is gone. The sea of helpful community has <a href="http://en.wikipedia.org/wiki/Black_Sea_deluge_theory">drained back through the Bosphorus</a>, and you're standing in a field of muddy, dying fish. This is not pleasant.</p>
<p>(To speak in defense of the manufacturers of Linux boards for a moment: they're targeting professional engineers who want cheap, reliable hardware. They're deliberately not optimizing for amateur tinkerers, because tinkerers don't place large orders. Makes sense to me.)</p>
<p>This brings us to the point of this presentation (er, blog post). I've come up with 8 barriers to normal people connecting weird stuff to the internet. There are certainly more, but these are what I see as the big ones. I'll list each problem and try to explain what I see as our best solutions are, or at least what direction we should be going. (Throughout this discussion, I'll refer to a "Linux board," but it could be running some other operating system and most or all of the same problems would exist.)</p>
<h2 id="problem-1-i-cant-find-the-damn-things-ip-address">Problem 1: “I can’t find the damn thing’s IP address!”</h2>
<p>You plug a Linux board into your network. It receives an IP address from the DHCP server in your firewall, but you have no idea what it is. If you're a normal person, you probably don't even know that your firewall has a DHCP server, and you definitely don't know how to access its admin interface to check what IPs it has dispensed. You're left in the ridiculous situation where you can see the board sitting on your desk, but you can't find it on your network.</p>
<p>The best solution we have at present is what is called "<a href="http://zeroconf.org/">zero configuration networking</a>" or "zeroconf." Apple calls <a href="http://www.apple.com/support/bonjour/">their implementation</a> "<a href="https://twitter.com/#!/carladiana_/status/97676155359989761">Bonjour</a>," while the Linux people call <a href="http://avahi.org/">theirs</a> "Avahi." Apple has a <a href="http://support.apple.com/kb/DL999">zeroconf implementation for Windows</a>, but it is not installed by default.</p>
<p>I propose that all Linux boards ship with Avahi set to announce its existence on the network. For the board I'm working on, the Rascal, I'd give it the hostname "rascal<serial number>". If you read the serial number 246 on the bottom of the board, you can open a web browser and go to rascal246.local, and the Rascal will respond with a page that gives you basic information about the board (such as the damn IP address).</p>
<h2 id="problem-2-ssh-is-baffling">Problem 2: SSH is baffling.</h2>
<p>The next two problems are connected.</p>
<p>Once you know the board's IP address, you have to log into it using a secure shell (SSH) terminal like <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">Putty</a>. Unfortunately, because SSH traffic is encrypted, and configuring encryption keys is confusing, SSH baffles people. The standard SSH warnings are good, because we want our systems to be secure, but they presume a level of sophistication that is not present in the normal person who is trying to connect a chicken coop to the internet.</p>
<h2 id="problem-3-console-editors-are-weird-alienating-and-ugly">Problem 3: Console editors are weird, alienating, and ugly.</h2>
<p>If you do manage to figure out SSH, you then have to use an ugly console-based text editor like Nano that doesn’t support cut and paste by any conventional means.</p>
<p>I think we can solve the previous two problems together in one stroke. I think we need what I call "self-serve programming tools." (I've written about this in <a href="/blog/2011/07/06/self-serve-programming-tools/">more detail</a> previously.) Since we know these boards can connect to the internet, we should make them serve browser-based editors. On Github, I've started an <a href="https://github.com/rascalmicro/control-freak">open-source project to do this</a>, based around <a href="http://codemirror.net">Codemirror</a> and the <a href="http://abeautifulsite.net/blog/2008/03/jquery-file-tree/">jQuery Filetree plugin</a>. Note that I'm not talking about stuff like the cloud compiler for the <a href="http://mbed.org/">Mbed</a>, though I do think that's cool. I'm talking about hosting the code editor directly on the Linux board.</p>
<h2 id="problem-4-embedded-c-makefiles-and-gcc-are-scary">Problem 4: Embedded C, Makefiles, and gcc are scary.</h2>
<p>I like programming in embedded C as much as the next Linux zealot, but most people prefer to sacrifice some performance in order to use higher-level languages like Python or Ruby. I think we need to have hardware APIs in multiple higher-level languages that can be called through web requests. (In the long run, I think we need server software based around event frameworks like <a href="http://twistedmatrix.com/trac/">Twisted</a>, but I didn't actually say that in the talk.)</p>
<h2 id="problem-5-gui-builders">Problem 5: GUI builders</h2>
<p>Often you need to use a custom GUI builder for a new embedded device with display (e.g. GTK, Qt, …). I actually like GUI builders, but the market has been badly fragmented for so long. As a result, HTML and CSS have won. As Mark Pilgrim has said: “[HTML] is the format of our age.”</p>
<p>There is a large swarm of amateurs who, when faced with HTML and CSS, will say, “I don’t really know how this works, but I can cut and paste it real well...” This pattern of example modification is something that tinkerers thrive on. (TCP handshake with <a href="http://bjoern.org/">Björn Hartmann</a> for the apt phrase, "example modification.") Rather than resisting HTML and CSS, we should embrace them, particularly with the burgeoning acceptance of HTML5 and rapidly improving Javascript libraries like <a href="http://jquery.com/">jQuery</a>.</p>
<h2 id="problem-6-no-users-permissions-sessions">Problem 6: No users, permissions, sessions.</h2>
<p>After you get your weird thing connected to the internet, you often realize that you want to have some features that aren't accessible to everyone, while still letting the general public have some access. This involves writing a bunch of tedious code, and doing it securely is not easy.</p>
<p>Fortunately, these problems were crushed a few years ago by web frameworks like <a href="http://rubyonrails.org/">Ruby on Rails</a> or <a href="https://www.djangoproject.com/">Django</a> (“Python on Rails”).</p>
<h2 id="problem-7-low-fault-tolerance">Problem 7: Low fault tolerance</h2>
<p>“I edited some files, and now it won’t boot.”</p>
<p>Our Linux boards should have removable media so that they can be reset to factory defaults. A normal person can probably handle downloading a default file system from the web onto an SD card and sticking that into the board.</p>
<h2 id="problem-8-dynamic-ip-addresses">Problem 8: Dynamic IP addresses</h2>
<p>In the US, at least, the IP addresses of most home internet connections change periodically, which breaks the domain name system. (I'm told IPs change less in Japan.) If you want your IP address to remain the same, you have to pay around $15 per month to the people selling you the connection.</p>
<p>The only solution I know of to this is to use a dynamic DNS service, and a router running open source firmware like <a href="http://www.polarcloud.com/tomato">Tomato</a> or <a href="http://www.dd-wrt.com/site/index">DD-WRT</a>. After the talk, people suggested a few other possibilities (<a href="https://yaler.net/">Yaler</a>, some VPN service like <a href="https://secure.logmein.com/products/hamachi/">Hamachi</a>, and something involving IPv6), but I don't have any intelligent opinions about them yet.</p>
<p>That's all I talked about during the presentation. If you're interested in making more powerful physical computing devices easier to use, email me at brandon at rascalmicro. If complete sentences aren't your style, try me <a href="https://twitter.com/#!/rascalmicro">@rascalmicro</a>.</p>]]></content:encoded>
    </item>
  </channel>
</rss>

