<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml showalllink="/?x=&amp;n=all"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <title>birthday cake 5</title>
  <date>7 Jan 2012</date>
  <p>
  Multi-coloured birthday cake!
  </p>
  <image src="/posts.assets/birthdaycake5a.jpg"/>
  <p>
  And some pics from the build:
  </p>
  <image src="/posts.assets/birthdaycake5b.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/birthdaycake5c.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/birthdaycake5d.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/birthdaycake5e.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/birthdaycake5f.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/birthdaycake5g.jpg"/>
  <p>
  </p>
</post><post>
  <title>autozen ttl update</title>
  <date>
  1 Oct 2011
  </date>
  <p>
  I've updated my <a href="/posts.xml/zen_dyndns_(the_VIEWSTATE_problem).xml">Zen DNS script</a> to be able to set the TTL. This is really handy as Zen reset the TTL back to 86400 seconds 24 hours after you change it. It uses the same XSLT method as used to set the IP and is triggered by passing 'force' as the first parameter to the script - this also forces a IP update even if it's currently correct.
  </p>
  <p>
  I currently have a cronjob set to run it in standard mode (i.e. check if it's wrong before updating) every two minutes and once every six hours with force set. This means normally I'm only hitting Zen's boxes four times a day which I don't think is too much of an extra load - although there will of course be extra load on their name servers as I'm setting my TTLs lower than the default.
  </p>
  <p>
  Code can be found <a href="https://github.com/sodnpoo/autozen">here</a>.
  </p>
</post><post>
  <title>arduino double horse 9053 board</title>
  <date>
  13 Sep 2011
  </date>
  <p>
  </p>
  <image src="/posts.assets/heliboard_3b.jpg"/>
  <p>
  For quite a while now I've been working on converting a <a href="http://youtu.be/Eesrn_mczv0">Double Horse 9053</a> from radio to arduino controlled so it can be used as an experimental platform for guidance control.
  </p>
  <p>
  After a couple of attempts I've designed a drop in replacement board (although mine is much larger than the stock one) that can just be plugged into the existing motor and battery connectors.
  </p>
  <p>
  Via two PWM pins connected to a couple of IRL3704 MOSFET's I can control the two main rotor blades, which when used together can adjust the height (by increasing/decreasing the speed of both motors) and provide left or right rotation (when one rotors's speed in increased and the other decreased).
  </p>
  <p>
  Using two digital pins connected to the input lines on an L293D motor driver, the tail rotor can be made to move in either direction, tilting the main rotors and making it move forwards/backwards. An increase in speed of the main rotors is required to maintain level flight. PWM on a third pin connected to the L293D enable line can control the tail rotor's speed.
  </p>
  <p>
  The 7.2v supply from the battery is converted both to 3.3v and 5v via an LV33 and 7805 respectively. The 5v supply is used by most of the components including the arduino, L293D (excluding the motor supply which is 7.2v), serial and i2c. The 3.3v also used for i2c after the SDA/SCL level has been converted using a sparkfun level converter. A 3.3v pin is also broken out next to the standard 6 pin serial so that a <a href="/posts.xml/homemade_btm182_breakout.xml">btm182 bluetooth module</a> can be used for wireless control instead of a FTDI cable - again with the levels converted.
  </p>
  <p>
  Below is the first version, it was built organically and so is a bit of a mess. It became unworkable when I needed to add 3.3v i2c support for the <a href="/posts.xml/arduino_with_bma180_and_itg3200.xml">accelerometer and gyroscope</a>. (The ATmega328 should be in the left socket the L293D in the right one.)
  </p>
  <image src="/posts.assets/heliboard_1.jpg"/>
  <p>
  The second version was based on the <a href="/posts.xml/stripboard_arduino_clone.xml">stripboard arduino</a> but the modular design proved to be far too heavy.
  </p>
  <p>
  This time I laid everything out using <a href="http://www.cadsoftusa.com/eagle-pcb-design-software/?language=en">Eagle</a> to get it as tight as possible. The space in the bottom right has been left to later include logging to SD card via the SPI bus. The gold lines are the copper tracks on the underside of the stripboard, the red lines are jumper wires on the top.
  </p>
  <image src="/posts.assets/heliboard_3.jpg"/>
  <p>
  <a href="/posts.assets/heliboard_3.brd">eagle .brd</a> | <a href="/posts.assets/heliboard_3_large.png">larger version</a>
  </p>
  <image src="/posts.assets/heliboard_3d.jpg"/>
  <p>
  The original stock board next to version three - the motor connectors have been removed; the grey and yellow wires were attached to key points during early experiments.
  </p>
  <image src="/posts.assets/heliboard_3c.jpg"/>
  <p>
  Here's the board installed in the chassic of the 9053, on the left you can see the btm182 bluetooth module.
  </p>
  <image src="/posts.assets/heliboard_3e.jpg"/>
  <p>
  With the board complete I can now use <a href="https://market.android.com/details?id=es.pymasde.blueterm">blueterm</a> to perform basic remote control from my phone.
  </p>
</post><post>
  <title>stripboard arduino update</title>
  <date>
  4 Sep 2011
  </date>
  <p>
  After a long wait, I've finally added a eagle schematic to the following pages:
  <ul>
  <li><a href="http://sodnpoo.com/posts.xml/stripboard_arduino_clone.xml">stripboard arduino clone</a></li>
  <li><a href="http://sodnpoo.com/posts.xml/stripboard_arduino_shield_1.xml">stripboard arduino shield 1</a></li>
  </ul>
  </p>
  <p>
  </p>
</post><post>
  <title>zen dyndns (the VIEWSTATE problem)</title>
  <date>
  28 Aug 2011
  </date>
  <p>
  Due to the complete failure of my previous name host provider (freeparking.co.uk - not only did they fail to renew my domain for the second year in a row but also didn't respond to any of my support tickets leaving my domain unavailable for 3 days. The situation was only resolved when I contacted their upstream registrar..&lt;sigh&gt;) I moved my name hosting to <a href="http://www.zen.co.uk">Zen Internet</a>. Zen's support is excellent - highly recommended.
  </p>
  <p>
  The only downside is that I can no longer set the @ record to a CNAME (seems to work fine for the subdomains however). Previously I'd been pointing sodnpoo.com to sodnpoo.ath.cx, this is in turn updated from the dyndns client on my router.
  </p>
  <p>
  I thought the easy way to solve this would be to just use curl to form post to Zen's customer portal. Login was easy but when I tried to post to the DNS management form it failed with an error, upon closer examination I noticed a huge (several K) parameter being passed called VIEWSTATE.
  </p>
  <p>
  After doing some research I discovered that VIEWSTATE is an opaque data blob produced by ASP.NET forms to hold the persistent state of the page. I pulled the page with curl and used some simple sed to extract the VIEWSTATE value and posted it back. It still didn't work so I started to add more parameters and soon hit the "html isn't regular so you can't parse it with a regex" problem, so I looked for another solution.
  </p>
  <p>
  I decided I should parse the html properly and thought that XSLT was really the best solution - I just needed to generate post data as expected by curl (i.e. uri encoded name=values pairs). I tried to run it through <a href="http://xmlsoft.org/XSLT/xsltproc2.html">xlstproc</a> but the html was too dirty, so I ran it through <a href="http://tidy.sourceforge.net/">tidy</a> which cleaned it up enough to not trip up xsltproc. The following XSLT was matched against all input tags to build the post data.
  </p>
  <pre>
  &lt;xsl:template match="xhtml:input"&gt;
    &lt;xsl:value-of select="@name"/&gt;=&lt;xsl:value-of select="str:encode-uri(@value ,true())"/&gt;&amp;#38;
  &lt;/xsl:template&gt;
  </pre>
  <p>
  Extracting the form data and posting it back still failed though. I looked again at what the browser was doing and saw that some of the parameters were being modified, some dropped and some added by the javascript in the page. I also notice one parameter didn't exist at all in the form when using curl's default user agent - setting it to Firefox's made the parameter appear.
  </p>
  <p>
  I fixed up XLST to modify what was needed to match what the browser was sending and posted the results again - this time there were no errors and a html page was returned. I modified the XSLT to change the IP it was sending and ran through it again - I refreshed the page in my browser and the IP had been changed - success!
  </p>
  <p>
  The code is implemented as a shell script, a template for the login part and a couple of XSLT's. It requires that the zen friendly name is set to the domains name e.g. 'sodnpoo.com'.
  </p>
  <p>
  Autozen.sh is the main script - don't forget to set the USERNAME/PASSWORD/DOMAINS and probably the method of getting the latest IP (IPADDR). (You might need to change the DOMLISTURL - this is the page in the Zen portal where you select the domain to modify).
  </p>
  <p>
  Zen.login.post is a quick and dirty static template - we just poke the USERNAME/PASSWORD values in there with sed.
  </p>
  <p>
  Getdomains.xml is an XSLT to extract the POST URLs of all domains with their friendly name set.
  </p>
  <p>
  Zenasp.xsl is another XSLT that takes the four octets of the desired IP and pokes them into the form data to be sent to the POST URLs.
  </p>
  <p>
  Code can be found on <a href="https://github.com/sodnpoo/autozen">github</a>.
  </p>
</post><post>
  <title>sudoku solver</title>
  <date>
  02 Jul 2011
  </date>
  <p>
  This is a python script to solve sudoku puzzles - in particular a 16x16 board but with some small modifications it should be able to solve 9x9 boards too. It walks through the board evaluating each cell against six tests - first it removes any proven negatives from the cells list of possible values in it's row, column and square neighbours - then it checks against the same neighbours to see if the cell has any unique possibilities amongst them.
  </p>
  <p>
  The code's a bit messier than I would like and I suspect could be optimised some what but as it completes on my desktop in 0.38 seconds I don't really thinks its worth the effort. It take 21 iterations of the board, running a total of 9247 individual tests.
  </p>
  <pre>
### GC2RBNM

import time

#The board is defined as an two dimensional array of ints with -1 representing a blank cell.

#      0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
game = {
  'board' : [
    [  7, -1, 14, 10, -1, -1, -1, 12, -1, 13, -1, -1, -1,  8,  6,  1 ], # F
    [  6, -1, -1, -1, -1, -1, -1, -1, 16,  4, -1,  8, -1,  7,  3, 12 ], # E
    [ 16, -1, -1,  8, -1, -1,  6, -1,  3, -1, -1,  7, -1,  4, -1, 14 ], # D
    [ -1,  4, -1,  9,  8, -1, -1, -1, -1,  6, -1, -1, -1,  5, -1, -1 ], # C
    [ -1, -1, -1, -1, -1, -1, -1,  6, -1, -1,  8, 16, -1, -1, 13, -1 ], # B
    [  9, -1, 12,  4,  2, 11, -1, 16,  7,  5,  6, -1,  8, -1, -1, -1 ], # A
    [ -1, -1,  3,  6, -1, -1, 13,  8, -1, -1, -1, 12, -1, 11, -1, -1 ], # 9
    [ -1, -1,  8, 11, -1, -1, -1,  7,  1, -1, -1,  3,  6, 12, -1,  2 ], # 8
    [ 15, -1, 11, -1, 16,  6,  7, -1, -1, -1, -1, -1, -1, -1, -1,  8 ], # 7
    [  1, -1,  6,  7, -1,  5,  2, -1, -1,  8, -1, -1,  3,  9, -1,  4 ], # 6
    [ 14, -1, -1, -1, 15,  8, 12, 11, -1, 10, -1, -1,  7,  6, -1, -1 ], # 5
    [  8, -1, -1, 16, -1, -1,  3,  9, -1, -1, -1,  6,  5, -1, 14, -1 ], # 4
    [ -1, -1, -1,  5,  6, -1,  1, 14, 15, -1, -1, 11,  4, -1,  8,  3 ], # 3
    [ -1, -1, -1, -1, 13, -1,  8, -1,  6, -1, -1,  1, -1,  2,  7, -1 ], # 2
    [ -1,  6, 15, -1, -1,  2, -1, -1,  8,  3, -1,  9,  1, -1, -1, 10 ], # 1
    [ -1,  8, -1,  2, -1, -1, -1,  3, -1, 16, 14, 10, -1, -1,  9,  6 ]  # 0
  ],
  'possible' : [[]], # list of possibilities - one for each cell
  'changed' : [[]]   # changed flag - one for each cell
}

#init the arrays
for x in range(16): # add a row
  game['possible'].append([])
  game['changed'].append([])
  for y in range(16):
    game['possible'][x].append(range(1,16+1))
    game['changed'][x].append(False)

#print the board - uses ansi colours to show updated
def printgame():
  CSI="\x1B["

  for x in range(16): 
    for y in range(16):
      cell = game['board'][x][y]

      if cell == -1:
        cell = ''

      cell = str(cell)

      if game['changed'][x][y] == True:
        #color it
        cell = '\033[93m' + cell.rjust(4) + '\033[0m'
        game['changed'][x][y] = False #clear it

      else:
        cell = cell.rjust(4)
  
      print cell,
    print

#walk the column removing possibilities that have been proven
def checkcellx(x, y):
  for i in range(0,16):
    if game['board'][x][i] != -1:
      if game['board'][x][i] in game['possible'][x][y]:
        game['possible'][x][y].remove(game['board'][x][i])

#walk the row removing possibilities that have been proven
def checkcelly(x, y):
  for i in range(0,16):
    if game['board'][i][y] != -1:
      if game['board'][i][y] in game['possible'][x][y]:
        game['possible'][x][y].remove(game['board'][i][y])

#walk the square removing possibilities that have been proven
def checksquare(x, y):
  minx = x-(x-(4*(x/4)))
  maxx = minx+4
  miny = y-(y-(4*(y/4)))
  maxy = miny+4
  for xi in range(minx, maxx):
    for yi in range(miny, maxy):
      #print xi, yi
      if game['board'][xi][yi] != -1:
        if game['board'][xi][yi] in game['possible'][x][y]:
          game['possible'][x][y].remove(game['board'][xi][yi])

#walk the col checking if we have any unique possibities
def checkcellx2(x, y):
  c = { }
  for i in range(0,16):

    for possible in game['possible'][x][i]:
      for poss in game['possible'][x][y]:

        if poss == possible:
          c[str(possible)] = c.get(str(possible), 0) + 1
          if c[str(possible)] &gt; 1:
            break

  for a in c:
    if c[a] == 1:
      game['possible'][x][y] = [int(a)]

#walk the row checking if we have any unique possibities
def checkcelly2(x, y):
  c = { }
  for i in range(0,16):

    for possible in game['possible'][i][y]:
      for poss in game['possible'][x][y]:

        if poss == possible:
          c[str(possible)] = c.get(str(possible), 0) + 1
          if c[str(possible)] &gt; 1: #optimisation - break out early if we're not the only one
            break

  for a in c:
    if c[a] == 1: #if we are the only one then update the game board
      game['possible'][x][y] = [int(a)]

#walk the square checking if we have any unique possibities
def checksquare2(x, y):
  c = { }
  minx = x-(x-(4*(x/4)))
  maxx = minx+4
  miny = y-(y-(4*(y/4)))
  maxy = miny+4
  for xi in range(minx, maxx):
    for yi in range(miny, maxy):
      for possible in game['possible'][xi][yi]:
        for poss in game['possible'][x][y]:

          if poss == possible:
            c[str(possible)] = c.get(str(possible), 0) + 1
            if c[str(possible)] &gt; 1:
              break

  for a in c:
    if c[a] == 1:
      game['possible'][x][y] = [int(a)]


printgame()
print
print

start = time.time()

testsrun = 0
runnum = 0
update = True
while update:
  #print runnum
  update = False
  for x in range(16):
    for y in range(16):
      if game['board'][x][y] == -1:
        #print "x:",x," y:",y,
        #possible optimisation - dont run more tests if already proven in previous test 
        #(probably not worth it as it only saves ~350 tests and duration is approx the same)

        if len(game['possible'][x][y]) != 1:
          checkcellx(x,y)
          testsrun = testsrun + 1
        
        if len(game['possible'][x][y]) != 1:
          checkcelly(x,y)
          testsrun = testsrun + 1

        if len(game['possible'][x][y]) != 1:
          checksquare(x,y)
          testsrun = testsrun + 1

        if len(game['possible'][x][y]) != 1:
          checkcellx2(x,y)
          testsrun = testsrun + 1

        if len(game['possible'][x][y]) != 1:
          checkcelly2(x,y)
          testsrun = testsrun + 1

        if len(game['possible'][x][y]) != 1:
          checksquare2(x,y)
          testsrun = testsrun + 1

        if len(game['possible'][x][y]) == 1: #only one possibility left so its now proven
          #print "x:",x," y:",y, "update:", game['possible'][x][y]
          game['board'][x][y] = game['possible'][x][y][0]
          update = True
          game['changed'][x][y] = True

      else:
        game['possible'][x][y] = [game['board'][x][y]]

  runnum = runnum + 1
        

elapsed = (time.time() - start)

print
printgame()
print "runs#".ljust(10),runnum
print "tests#".ljust(10),testsrun
print "elapsed".ljust(10),elapsed
  </pre>
  <p/>
</post><post>
  <title>n95 remote cam</title>
  <date>
  21 May 2011
  </date>
  <p>
  I wanted to do some time lapse photography of the peppers and tomatoes I have on my windowsill so I could see how they're growing. I'd done this before using a webcam and a shell script. Although you could see the plants growing, due to the low resolution of the webcam you couldn't really see much more.
  </p>
  <p>
  I started thinking about hacking an old digital camera with an arduino but while digging around for the best one found my old n95. The n95 has a 5 mega pixel camera on it which is better than the 3 mega pixel camera I've got. I also realised as I'd written code for it before (<a href="http://sodnpoo.com/posts.xml/cola_lace.xml">here (c++)</a> and <a href="http://sodnpoo.com/posts.xml/volume_control.xml">here (pys60)</a>) that I could probably use the camera on it without having to make any modifications to the hardware.
  </p>
  <p>
  The pys60 camera api makes taking the picture easy with the only sticking point being the need to first wake the screen up and then change the orientation to landscape otherwise we won't get the full 5 mega pixel image. All that was left was to code some method of retrieving the picture - I decided to use a TCP server over wifi, simply pushing the JPEG back to the client. I can then use netcat to pull the picture from anywhere I can connect to it from.
  </p>
  <pre>
import appuifw, e32, SocketServer, camera, time

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):    
        e32.reset_inactivity() # wake screen up
        time.sleep(1)
        appuifw.app.orientation = 'landscape' #Switch to landscape mode
        time.sleep(1)
        img = camera.take_photo("JPEG_Exif",(2592, 1944),0)
        self.request.send(img)

if __name__ == "__main__":
    HOST, PORT = "0.0.0.0", 9999
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()  
  </pre>
  <p/>
</post><post>
  <title>homemade btm182 breakout</title>
  <date>
  25 Apr 2011
  </date>
  <p>
  This is my homemade btm182 bluetooth module breakout board. Although the module is a SMD part - due to the pads being 'c' shaped and their pitch being the same as the ribbon cable I was using (see <a href="http://dlnmh9ip6v2uc.cloudfront.net/images/products/09913-01.jpg">here</a>) - I was able to break it out to a small piece of stripboard.
  </p>
  <image src="/posts.assets/btm182_stripboard_breakout.jpg"/>
  <p>
  Although I took the time to breakout all of the module's pins to the stripboard, in the end I only ended up putting headers on seven of them and even then only four (rx, tx, +3.3v, GND) of them are used. The three LEDs are power, data and link. Many thanks to Atomsoft who kindly published the <a href="http://atomsoft.wordpress.com/2011/02/03/bt-up-and-running/">relevant pin outs</a>.
  </p>
  <p>
  As the btm182 is a 3.3v device I used a level shifter to interface it with my 5v arduino. I built this into a 'shield' for my <a href="http://sodnpoo.com/posts.xml/stripboard_arduino_clone.xml">stripboard arduino clone</a>.
  </p>
  <image src="/posts.assets/btm182_stripboard_level_shifter.jpg"/>
  <p>
  And finally - an Eagle board diagram of the shield - this if my first go at one but hopefully it's readable. The horizontal yellow lines are the copper stripboard tracks (only the used tracks are shown) and the red lines are top side jumper wires, the dashed ones are the four connections to the ribbon cable.
  </p>
  <image src="/posts.assets/btm182_stripboard_level_shifter_diagram.jpg"/>
  <p>
  </p>
</post><post>
  <title>stripboard arduino shield 1</title>
  <date>
  6 Feb 2011
  </date>
  <p>
  So my <a href="http://sodnpoo.com/posts.xml/stripboard_arduino_clone.xml">stripboard arduino clone</a> can do something useful I've built some shields for it. This one is a dual function board handling i2c (both 3.3 &amp; 5 volt) and access to a microSD card via the SPI bus.
  </p>
  <image src="/posts.assets/i2c_sd_1.jpg"/>
  <p>
  The i2c bus is physically accessed by the pins at the bottom of the picture above. On the left is the 5 volt pins (the 4x4 block) and on the right is the 3.3 volt ones (I've run out of pin headers so only one column is populated). Each column on both sides provides v+, SDA, SCL and ground.
  </p>
  <image src="/posts.assets/i2c_sd_2.jpg"/>
  <p>
  The red sub-board is a <a href="http://www.sparkfun.com/products/8745">sparkfun logic level converter</a> that handles the conversion for the 3.3 volt part of the i2c bus. Unlike i2c, the lines on the SPI bus are unidirectional so I could use voltage dividers to perform the level conversion instead of the larger footprint sparkfun board.
  </p>
  <p>
  I've used an old SD to microSD adapter as a card socket which was easy to work with as the contact spacing is the same as standard pin headers (see the top of the first picture).
  </p>
  <image src="/posts.assets/i2c_sd_3.jpg"/>
  <p>
  The underside of the board is a bit less neat than I would like although I'm quite pleased with how the vertical solder tracks for the SD card came out.
  </p>
  <p>
  Right now I'm using the 5v i2c bus to read from an SRF08 ranger mounted on the bottom of my prototype UAV, and the SD card to dump the values of the sensors and internal state of relevant program parameters for post test analysis. I'm going to use the 3.3v i2c bus to read from the <a href="http://sodnpoo.com/posts.xml/arduino_with_bma180_and_itg3200.xml">bma180 and itg3200</a> once I've mounted both of them on to the UAV chassis.
  </p>
  <p>
  Arduino code <a href="https://github.com/sodnpoo/arduino">here</a>.
  </p>  
  <p>
  04/Sep/11 - Updated with eagle schematic below - yellow horizontal lines are the copper tracks on the underside of the stripboard, red lines are jumper wires on the top.
  </p>
  <image src="/posts.assets/i2c_sd_eagle.jpg"/>
  <p>
  </p>  
</post><post>
  <title>stripboard arduino clone</title>
  <date>
  22 Jan 2011
  </date>
  <p>
  I needed a small arduino for a UAV project, I could of just bought a mini but I wanted to see how small and cheap I could actually build one without requiring etching equipment. The final size of the board got down to 45 x 25 mm although by using a resonator instead of a crystal + two capacitors it may be possible to make it slightly thinner.
  </p>
  <p>
  The board includes only the bare minimal - just regulated power (both 5v and 3.3v), the Atmel 328, the crystal and four capacitors (two for the power lines and two for the crystal).
  </p>
  <image src="/posts.assets/stripboard_arduino_a.jpg"/>
  <p>
  On the underside you can see where the tracks have been cut. The power section is a bit of a mess as the first attempt had the regulators mounted vertically but the layout was too tight and had to changed. Even then I still had a problem when I first powered it up because the heat sinks were touching - the sink on the 7805 is grounded but the one on the LD33 is +3.3v.
  </p>
  <image src="/posts.assets/stripboard_arduino_b.jpg"/>
  <p>
  The first 'shield' I made has the basic extra features - a reset button, a general purpose LED and a serial programming header compatible with the standard FTDI cable or breakout board. This board is not required in normal use and only really needs to be installed during programming.
  </p>
  <image src="/posts.assets/stripboard_arduino_c.jpg"/>
  <p>
  And the underside - the pin on the right hand side does nothing electrically and is just there to help hold the shield.
  </p>
  <image src="/posts.assets/stripboard_arduino_d.jpg"/>
  <p>
  The programming shield needs to be at the top of the stack as it only has eight of the stackable headers mounted on it. The main board has a full set of them and so can be anywhere in the stack, not necessarily at the bottom.
  </p>
  <image src="/posts.assets/stripboard_arduino_e.jpg"/>
  <p>
  The two pins near the power capacitors on the main board are power in - I'm using a standard 9v battery but anything above 7v should work.
  </p>
  <p>
  I've also built two more shields - one handles the interface to the UAV hardware and the other deals with the I2C bus (both 5v and 3.3v) and SD card via SPI. I'll document these in a future post.
  </p>
  <p>
  04/Sep/11 - Updated with eagle schematic below - yellow horizontal lines are the copper tracks on the underside of the stripboard, red lines are jumper wires on the top. Notice on the photos the orientation of the 7805 and the LD33.
  </p>
  <image src="/posts.assets/stripboard_arduino_eagle.jpg"/>
  <p>
  </p>
</post></xml>

