Tuesday, December 04, 2007

Installing Ubuntu was easy!

I just got myself a new computer and started running Ubuntu on it, I'm astonished at how easy the whole process of installation was. Over the years I've installed Windows countless times, always a painful process, though I haven't installed Vista so maybe they finally figured it out.

So, I built the computer, burnt an Ubuntu live CD, put it in and the first suprise was that I hadn't stuffed anything up putting the machine together. The live CD is really functional, and I was able to start up Pidgin, browse the web and most usefully, remote desktop into my old PC.

I only have one keyboard/mouse and monitor and two machines, both of which I want to continue to use for a while as I'm expecting that transitioning from my old system to the new one will take some time as the machine is used for development, as a full media center as well as web browsing etc. and I don't know how long it will take to learn how to do all that under Linux. Being able to remote desktop back to the old machine solves the problem nicely.

After playing with Ubuntu a bit and chatting with friends for a while I clicked "Install". A bit of deliberation was required to determine the partition layout I want, as in the future I expect I will install XP and dual boot. Finding an article on installing XP after Linux set my mind at ease so I figured I'd be able to repartition as necessary later. So I chose all the default install options and that plugged away in the background for a little while.

The truly impressive bit was that while this was happening, I was able to continue chatting with friends to get advice on installation options, search the web for answers and so on. It only required a quick restart and I was all done, and I didn't really stop "working" the whole time.

I did hit two small snags:

  • During the restart I realized I'd "boxed" in the CD drive so had to hastily hit the power switch, pull of the front bezel and open a slot so it could eject... my bad :)
  • Installing Opera didn't go very smoothly, I tried using Add/Remove programs but it failed mysteriously with the following error:
    Downloading the .deb file from the Opera website failed the first time too, but when I ran it again it worked, so there may be something broken with the way the dependencies went on and once they'd be put on by previous attempts it succeeded.

I guess I probably won't have to reinstall Ubuntu as often as I did Windows, but at least I won't dread the process.

Monday, November 19, 2007

Now Playing Album Cover Art Desktop Wallpaper

A little Python program I wrote to update my Windows desktop wallpaper with the album cover art of each album I play. The idea is to represent a stack of CDs with the latest played one on top. This concept could easily be extended to other images, a random photo each day springs to mind.

The details of how this script is run when an album is played and where the album cover art comes from aren't really relevant, and aren't going to work outside my system anyway, but the concept can be used easily enough.

Windows requires a little messing about to change the wallpaper dynamically, and this will only work with BMP files:

def setWallpaper( bmp ):
   import win32api, win32con, win32gui
   k = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER,"Control
Panel\\Desktop",0,win32con.KEY_SET_VALUE)
   win32api.RegSetValueEx(k, "WallpaperStyle", 0, win32con.REG_SZ, "0")
   win32api.RegSetValueEx(k, "TileWallpaper", 0, win32con.REG_SZ, "0")
   win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, bmp, 1+2)

The following functions generate the wallpaper. The main function takes the filename of the wallpaper file, and the name of the new cover image, which will be pasted over the top of the existing wallpaper.

# read bmp in old_filename, "paste" current_filename over the top 
# and write out to new_filename (usually the same as old_filename)
import sys, os, urllib, math, Image, random
def makeBackgroundCollage(old_filename, current_filename, new_filename):
   if os.path.exists( old_filename ):
      new = Image.open( old_filename )
   else:
      new = Image.new( "RGB", (1280, 1024), (58, 110, 165) )
   if os.path.exists( current_filename ):
      current = Image.open( current_filename)
      if max(current.size) < 300:
         current = current.resize( (current.size[0]*2, current.size[1]*2) )
      if max(current.size) > 600:
         current = current.resize( (600, 600 * current.size[1]/current.size[0]) )
      border = Image.new("RGB", (current.size[0]+10, current.size[1]+10), 0xffffff)
      shadow = Image.new("RGB", border.size, 0x000000)
      angle = int(random.betavariate(2,2) * 50 - 25)
      (shadow, shadow_mask) = rotate2(shadow, border.size, angle, 128)
      (current, current_mask) = rotate2(current, border.size, angle)
      (border, border_mask) = rotate2(border, border.size, angle)
      pos = (int(random.betavariate(2,2) * (new.size[0] - border.size[0])),
             int(random.betavariate(2,2) * (new.size[1] - border.size[1])))
      new.paste(shadow, (pos[0]+5, pos[1]+5), shadow_mask)
      new.paste(border, pos, border_mask)
      new.paste(current, pos, current_mask)
   new.save( new_filename )

def rotate2(img, box, angle, alpha=255):
   img2 = Image.new(img.mode, boundingBox(box, angle * math.pi/180.0), 0)
   img2.paste(img, ( img2.size[0]/2 - img.size[0]/2,
                     img2.size[1]/2 - img.size[1]/2 ) )
   mask2 = Image.new("L", img2.size, 0)
   mask2.paste(Image.new("L", img.size, alpha), ( img2.size[0]/2 - img.size[0]/2,
                                                  img2.size[1]/2 - img.size[1]/2 ) )
   return (img2.rotate( angle, Image.BICUBIC ),
           mask2.rotate( angle, Image.BICUBIC ))

def boundingBox(box, angle):
   (x,y) = (box[0]/2.0, box[1]/2.0)
   (r, a) = (math.sqrt(x*x+y*y), math.atan2(y, x))
   (x1, y1) = (r * math.cos( a+angle ), r * math.sin( a+angle ) )
   (x2, y2) = (r * math.cos( -a+angle ), r * math.sin( -a+angle ) )
   return (int(math.ceil(max(abs(x1),abs(x2))*2)),
           int(math.ceil(max(abs(y1),abs(y2))*2)))

The position and rotation of the album is chosen using a beta distribution. This gives a nice distribution weighted towards the center of the screen, borders and a "drop shadow" are added to enhance the "stack" effect.

Tuesday, July 31, 2007

Picaxe breadboard adapter

A quick project to simplify Picaxe prototyping on my breadboard. The idea is to house the Picaxe chip (either an 08M or 14M) and "standard" serial interfacing circuit on a "breakout" board that can be easily plugged into the breadboard while providing easy access to the chip's pins.

  1. power input, about 5V, will be regulated by LM7805
  2. 3.5mm stereo serial socket
  3. serial mode selector, switches serial in between "pin 5" (program mode) and "pin 3" (control mode)
  4. power switch
  5. jumpers to allow isolating standard serial circuit to "override" via breadboard
  6. 14 pin socket
  7. header pins to provide 5V and 0V to "power rails" of breadboard
  8. header pins to connect Picaxe to breadboard


serial schematic


power schematic

For some unknown reason, I had to add an extra 10k resistor between leg 2 and ground (soldered on the underside of the pcb, not shown on schematic.)

The board works pretty much as I'd hoped. Unfortunately it is quite difficult to insert/remove from the breadboard so a future version would only have a single row of header pins. Another addition would be a DC socket to allow powering from a "wall wart" and I'd improve the layout a little to allow easier access to the switches.

Tuesday, July 24, 2007

Handlebar "Remote" for LED Bike Light

Changing modes and using the high-beam was awkward using the switches mounted on the original LED bikelight box, so I added a "remote" within easy reach of my thumb. This will make the high-beam more useful when approaching treacherous areas of paths that require more light but are exactly the places where you don't want to take your hands off the handlebars.

This uses a "rocker" navigation switch to change modes, pushing it switches on the high beam. The mode-up and down buttons are simply wired in in parallel with the existing mode rocker switch, however the high-beam was a bit trickier and uses a BD681 darlington pair transitor to "pull" the control signal to the BuckPuck to ground. This has the same effect as the existing NC push-button switch.

This was necessary because all three switches on the navigation switch share a common wire, the Picaxe software and circuit is expecting the switches to provide +5v, so it was easier to make the high-beam use a transistor to cut-out the control signal than rework the remainder of the circuit to pull the Picaxe pins to ground when the switches are pushed. If I was building this again, using ground as the common wire would be much simpler.

There was enough room on the existing pcb to solder in the transistor, resistor and wires from the navigation switch. That's one advantage of using proto-board over a printed pcb.

One further mod would be to have a capacitor attached to the BD681 some how so that a single push holds the high-beam on for say 5 seconds, but I couldn't figure out how to get that to work. Alternatively, putting in a flip-flop to toggle the high-beam on/off would work too, but there was definitely not enough space on the pcb for that option.

Friday, July 06, 2007

Ambient Email Notifier

Small project to provide email notification via an RGB LED hooked up to the USB port.

Uses a 4d-micro-USB module to provide power and RS232 to a Picaxe 08M controlling an RGB LED. Can control colour (seven colours: work email in red, newsletters in green, other in blue) and brightness by sending characters to the COM port, this is done by a Python script run every 10 minutes by Task Scheduler with an accompanying system tray icon to allow LED to be turned off again (see python gmail check in four lines of code, pySerial and pySystray).

The schematic is as simple as possible:

The relevant code (python and picaxe basic) is pretty self-evident, I will provide it if anyone is interested. Update: Another post has some code.

Wednesday, May 30, 2007

CCTV Filmmaking

BBC article about a film, Faceless, made entirely using CCTV footage. Pretty neat, the manifesto states you can't take your own camera or lighting and the protaganist must appear in every shot to allow them to obtain the footage via freedom of information/privacy legislation.

Sunday, May 27, 2007

Wow, fixed already...

Interesting article about the reconstruction of the freeway in San Francisco that collapsed after a truck fire. No, really.

Saturday, May 19, 2007

LED bike light project

Design

The goal was to create a high power LED bike light (some similar projects: a 3 LED mountain bike light, a whole series of evolving light designs or this simple and neat 3 LED light).

After discovering the BuckPuck LED driver has a 5V output and a dimmer control circuit, I decided to control it with a Picaxe microcontroller. The primary purpose of the microcontroller was to provide a battery level indicator of some sort. Secondary features would be to allow multiple brightness modes etc.

I couldn't find a simple battery level circuit or simple way to calculate the remaining capacity of a battery so decided instead to simply use the Picaxe to time the amount of time the light has been switched on and use this to determine when a recharge is required.

The aim is to discharge the batteries about 30% between each recharge. The circuit should draw a maximum of about 1A for the LED, and say 0.2A for the Picaxe and bargraph LEDs. Using 2400mAH batteries, and 100% efficiency, would give 2 hrs at 100% discharge. However the light will rarely be on at full power; assuming it's on at 30% power, a 30% discharge will therefore take about 2 hours... or so I'm guessing, it's much more complicated than that, but that'll do for now.

The controller will require two buttons to change up and down through the brightness modes, and one to test the battery level (i.e. display the timer value.) Two buttons are required to avoid having to cycle through all the modes to get back to the start, like all the stupid flashing LED tail lights require...

The pins for the buttons plus one output for the LED controller and one to drive the LED bargraph uses all 5 input/output pins on the Picaxe 08M.

One further feature was added, which is a "high beam" button. This will override the current mode from the Picaxe and put the LED on full power. This will be used to briefly illuminate dark parts of paths and to flash at cars that might not have seen me or have cut in front of me or something like that. Fortunately, this button does not need to be connected to the Picaxe, as there are no free pins.

Schematic

The Picaxe usese 3 standard input circuits. For the outputs, Pin2 is used for PWM output in the background to drive the LED controller. This will allow different brightnesses to be set by varying the duty cycle.

To drive the LED bargraph, the basic reference circuit from the LM3914 datasheet is used to measure the voltage over a resistor/capacitor circuit. The capacitor is charged via a PWM output from the picaxe. Varying the duty cycle allows the capacitor to charge to different levels which is reflected in the bargraph.

I added a fuse between the battery and the BuckPuck too, just in case. No idea if it's really needed...

Parts list

Components
1Cree XR-E 3W LED + 8° Lens + BuckPuck 3023-D-E-1000 Driver (datasheet)(Cutter Electronics)
1Picaxe 08M microcontroller(Microzed)
1LM3914 LED bargraph driver (datasheet)(DSE)
110 seg LED bargraph(DSE)
31k resistors
410k resistors
11k2 resistors
13k6 resistors
10k2 resistors
110uF 25V electrolitic capacitor
Hardware
1Plastic "Jiffy" box (30x54x83mm)(DSE)
1Veroboard (24 tracks x 18 holes)(DSE)
1Heatsink(Jaycar)
13.5mm mono plug + socket(Jaycar)
1SPDT rocker switch (on-off-on)(Jaycar)
1Push button (N/O)(DSE)
1Push button (N/C)(DSE)
1Fuse + Holder (M205 2A)(Radioparts)
18 Pin DIL socket(DSE)
118 Pin DIL socket(DSE)
120 Pin DIL socket (machine pin strip)(DSE)
24 AA battery holder(Jaycar)
29v Battery snaps(DSE)
8AA NiMH batteries (2400mAH)(Jaycar)
2velcro straps 12.5cm of hook + 12.5cm fuzz(Spotlight)
1inner tube rubber
Materials
1Arctic Silver Thermal Adhesive(Mittoni)

Note: The above suppliers are not necessarily where I got the part, just the first link I could find...

Software

The above circuit was first layed out on a breadboard with a regular LED in place of the 3W Cree LED and using 4 AA batteries directly rather than via the BuckPuck.

Note that when I got the BuckPuck and LED, the 4 AA batteries were not sufficient to provide enough voltage from the Ref pin to switch the LED off. This was fixed by using all 8 AA batteries.

LED bargraph output calibration

After realising I had no real idea how to get the LM3914 input range to match the output from the Picaxe, or how to choose the right resistor/capacitor combination, it occurred to me that it didn't matter and the picaxe could be calibrated to output voltages that lit up the bargraph LEDs the right amount. Hooray for software!

The values output by the following program when each of the 10 LEDs lit up were written down and used in the final program.

symbol x = b0
symbol y = b1
symbol dot = b2

main: 
 for x = 0 to 10
  dot = x
  gosub display_dot
 next x
 for x = 10 to 0 step -1
  dot = x
  gosub display_dot
 next x
 goto main


display_dot:
 lookup dot, (0, 89, 134, 156, 169, 177, 184, 190, 198, 207, 214), y
 
 pwm 1, y, 100
 
' pause 500
 
 return

Controller program

' 252 bytes program + 2 bytes data

' pins
symbol led_pin = 2
symbol dot_pin = 0
symbol test_btn = pin3
symbol modeUp_btn = pin4
symbol modeDn_btn = pin1

' variables
symbol mode = b0
symbol time = w4
symbol time_counter = w6

symbol dot = b1
symbol dot_duty = b2
symbol dot_cycles = b3

symbol led_period = b4
symbol led_duty = w5


' constants
symbol minMode = 0
symbol maxMode = 10
symbol flashMode = 9
symbol maxTime = 1200 ' minutes * 10
symbol dotTime = maxTime / 10
symbol time_interval = 1122 ' roughly 11215 ticks per minute

' data
eeprom 0, (0, 0) ' time as a word

' initialize
high led_pin

mode = 0
read 0, word time

' wakeup
gosub strobe

main:
 dot_cycles = 50

 time_counter = time_counter + 1
 if time_counter > time_interval then
  ' clock tick (4 bytes)
  high dot_pin
  high dot_pin
  low dot_pin

  time = time + 1
  goto write_time ' return to main
 endif

 if modeUp_btn = 1 and mode < maxMode then
  mode = mode + 1
  goto show_mode ' return to main
 endif
 if modeDn_btn = 1 and mode > minMode then
  mode = mode - 1
  goto show_mode ' return to main
 endif
 
 if test_btn = 1 then
  dot = time / dotTime max 10
  dot_cycles = 100
  gosub do_dot
  ' hold to reset (8 bytes per delay loop)
  if test_btn = 1 then
   gosub do_dot
   if test_btn = 1 then
    gosub strobe

    time = 0
    goto write_time ' return to main
   endif
  endif
 endif

 if mode >= flashMode then
  gosub do_mode
 endif

 goto main

write_time:
 write 0, word time
 time_counter = 0
 goto main

show_mode:
 gosub do_mode
 dot = mode
 gosub do_dot
 goto main

do_mode: ' high - led off, low - led on
 led_period = 255
 'led_duty = 4 - mode * 250
 lookup mode, (0, 1010, 980, 950, 900, 800, 600), led_duty
 select mode
  case 0 ' off
   led_period = 0
   high led_pin
'  case 1 ' dim 1
'   led_duty = 750
'  case 2 ' dim 2
'   led_duty = 500
'  case 3 ' dim 3
'   led_duty = 250
  case 8 ' full
   led_period = 0
   low led_pin
  case 9 ' dim short flash
   led_period = 0
   'low led_pin
   'pause 50
   pwm led_pin, 150, 10
   high led_pin
   pause 350
  case 10 ' long flash (17 bytes)
   led_period = 0
   low led_pin
   pause 100
   high led_pin
   pause 300
 endselect

 pwmout led_pin, led_period, led_duty
 
 return

do_dot:
 lookup dot, (0, 89, 134, 156, 169, 177, 184, 190, 198, 207, 214), dot_duty
 
 pwm dot_pin, dot_duty, dot_cycles
 low dot_pin
 
 return

strobe:
 dot_cycles = 10
 for dot = 1 to 10
  gosub do_dot
 next dot
 return

Some points to note:

  • The time the light has been running in "minutes" is stored in the EEPROM memory of the Picaxe.
  • Pressing the "test" button will display the current time on the bargraph using 1 LED for each 12 minutes (120 minutes total).
  • Holding the "test" button for a few seconds will reset the timer. This will be used when freshly charged batteries are inserted.
  • There are 8 brightness modes (plus "off") and two flash modes.

Timer calibration

The above controller flashes the bargraph briefly each 6 seconds or so. A few minutes worth of these flashes were counted and timed and the program adjusted so that the bargraph will reach 10 after approximately 120 minutes.

Construction

First, all the required holes were drilled in the box, and the aluminium lid was bent into shape to hold the LED and heatsink. The box lid was also shaped to fit the aluminium lid sticking out the side.

The spacers inside the box were cut down to lower the circuit board so there was enough room for the LED bargraph to stick out the top and the switches and BuckPuck to fit underneath.

The wires from the BuckPuck were soldered to the LED (with an extra wire joined to LED -ve output to become the ground for the circuit board.)

The LED was glued to the heatsink using the Arctic Silver epoxy, and when it was dry the heatsink and LED were glued to the aluminium lid.

The first version of the battery pack was put together at this stage too. This failed as the battery holders were made of Delrin which is ungluable... So, I drilled tiny holes in the two cases and "sewed" them together with fine jewellery or tie wire. An on/off switch was soldered to the battery wires and the socket assembled.

The circuit board layout was sketched out, the board cut to size and the tracks between the IC sockets cut. The sockets were then soldered in and the the resistors and capacitor soldered in too. The chopped off legs from the resistors were used as bridges between the +ve LED bargraph pins and the ground 10k resistor line. Some legs were also used to form some jumpers, with soldered in for others.

Next, I measured out the wire and soldered to the switches etc. and soldered in the BuckPuck and circuit board.

At this point, the circuit was tested and found to work (incredibly!) so the bottom of the circuit board was insulated with some electrical tape and the whole lot squeezed into the box.

A thin strip of inner tube rubber was added as a gasket on top of the aluminium lid to seal it in case of rain (which wasn't really considered in the design...)

For the first test ride, the whole lot was attached to my bike with rubber bands and the batteries were lashed to the frame with an inner tube! I was very happy with the results so started working out a more permanent mounting mechanism.

I removed the socket from my old Cateye light and bolted/Araldyted it to the box, which took care of mounting the light itself. It is adjustable/tiltable too which is a nice bonus.

Initially the batteries were mounted using an elastic strap, but this proved to be a little difficult to attach/remove with less than 3 hands and I dropped it breaking the damn thing. Because the battery holder can't be glued I had to start again with a different construction method.

This time, the battery holders were "sewn" together using jewellery wire again and the whole lot held in a cradle made from inner tube rubber (helpfully sewn by Alison) that is velcroed to the bike.

This looks quite professional and is a lot easier to take on and off!

Results

I'm extremly happy with the results, the LED is way too bright to look at and lights the road extremely well when on "full". Under normal conditions "mode 3" was quite sufficient to see the road.

The following image was taken by shining the light onto my door from about 3m away and photographing at 1/15 sec, f2.8, ISO100. The door has a slightly gloss paint, so the middle of the beam is being reflected back.

Some minor changes I would make:

  • The "high beam" button really neads to be accessible without moving your hand to the light. I'm not sure how best to achieve this.
  • A switch on the battery box would be useful (this was initially planned but died with the first battery box.)
  • A "console light" to light up my speedo.
  • Waterproof design!
  • A future version may well use a proper battery capacity meter (such as this one for lead acid batteries or this one for R/C cars.)

Monday, April 30, 2007

What if It's All Been a Big Fat Lie?

New York Times piece from 2002 questioning the received "fat is bad, mkay?" wisdom.  The first 8 pages are good, then it starts promoting the Atkins diet a little too specifically, which given that the main message I take out of the whole article is "there's no silver bullet" seems a little short sighted...

Wednesday, April 25, 2007

You Are What You Grow

Michael Pollan in the New York Times with a glimmer of hope that the US farm bill could get a run for it's money this time around...

Humans hot, sweaty, natural-born runners

Interesting article on the evolution of long distance running as a hunting strategy for early hominids.

Tuesday, February 13, 2007

Recovering Accidentally Deleted Files with Undelete Plus

After accidentally deleting about 100gb of recorded TV programs, 
I spent a bit of time looking around for a utility that would 
let me recover them easily (God knows why this isn't built into Windows...)

After trying a lot of utilities, I eventually found Undelete PLUS. This scanned and found all the deleted files very quickly and I was able to copy them to another drive.

The program's UI is not particularly intuitive, and a general flaw with all these programs is that you must copy the recovered files to a separate disk to avoid destroying other yet-to-be recovered files (which is a pain with 100gb of files...)

However, it's free, and it works! Download or bookmark it in case you need it one day.

(I'm using Windows XP SP2 with NTFS formatted drives.)

Monday, January 15, 2007

Restaurant reviewer with an ethical stance

From now on, if a restaurant does not offer me tap water, politely, unsarcastically, and before they offer mineral water, then they will be penalised.