Category Archives: Technology

How to: Forge metal

A couple of years ago now I taught myself how to do rudimentary metal forging using videos from the internet and the occasional digitised book. Here’s the summary of how to do it if anyone else wants to have a go!

Warning: Learning to forge things in metal is dangerous, you should proceed with caution at all times. In particular you risk setting fire to things (including yourself), burns, self inflicted stab wounds and other nasty things if you aren’t sensible. 

Safety items you should have to try forging: A head mounted welding face mask (you will need both hands). Flameproof overalls (I use Nomex ones, also remember to wear natural fibres underneath just in case). Leather welding gloves. Tongs for manipulating very hot things. A face mask to protect you from projecting molten metal is also a good idea. A leather apron can also be useful as it’s comparatively resistant to molten metal. A bucket of water handy is also a very wise precaution.

Step 1: Decide what you want to forge.

20170723_150814

This weekend I decided to forge a moon pendant, based on the above sketch.

Step 2: Carve it in wax. I used a tea light from IKEA, vanilla scent, however you can also buy proper (harder) carving wax from specialists. If you want high detail, this is a must! You can also buy it in pre-formed ring blanks. Be careful when cutting the wax, I’ve previously cut myself quite badly doing this using an Xacto craft knife, but fortunately it’s healed now!

Step 3: Cast the mould. For this you should find a tin can (aluminium or steel) that’s big enough to hold the wax piece. If you’re only detailing on one side then an open mould is fine, stick something on the top of your model to allow it to be rested on top of the can. Otherwise, for more complicated castings such as rings, you should include a sprue and a cone on the top of the mould to allow you to pour in the liquid metal. To make the mould, I used pure plaster of Paris, however you can/should also add some sand to improve the strength of the mould. It’s a good idea to tap the side of the mould vigorously to ensure that any bubbles on the wax model get dislodged. Ideally you should put the mould under a vacuum to remove all air bubbles, but vacuum pumps are hard to come by. I’ve managed without one so far.

Step 4: Wait for the mould to dry. There’s no shortcut for this.

Step 5: Bake out the mould to melt the wax and ensure that the plaster/plaster+sand mixture is fully cured. You might want to build a mini kiln for this, here’s mine. 20170722_195429

It is constructed from a concrete air brick, sawn in half and then drilled to create a cavity and a connection point for a heat gun. It has a top half which is the same, but with a small vent hole instead of the inlet. Here is a picture of the completed kiln.

20170722_195446

Note the small hole on the top for the hot air to come out of. I placed the cured mould, complete with the wax model, upside down in here for about 30 minutes to bake it and melt out all the wax. You could probably just pour in the molten metal, but baking out seems to be more reliable.

Step 6: Whilst the mould is baking, you can set up your furnace. I used an arc welder, since it’s easy to get hold of and runs on easy to handle electricity rather than anything chemical (coal, propane, etc.). To turn the arc welder into a tool for forging, you should remove both the ground clip and the welding rod holder and replace them with large metal mole grips. These can be used to hold the electrodes and/or a crucible. I would recommend using a graphite crucible and graphite rods extracted from 6V ‘lantern’ batteries – be careful not to crack them while extracting them from the 4 zinc housings within the battery. It’s also worth noting that if you obtain them this way, they will be coated in a paraffin type wax which will burn off after the first time you strike an arc.

20170722_195419

Here is my ‘workbench’ you can see the arc welder is the yellow box at the end, with both electrodes replaced with mole grips. I used a small part of the concrete air-brick as a stand for the crucible, here’s a close up also complete with my cracked crucible which I disposed of after this casting and the mole grips holding carbon rods:

20170722_195436

Step 7: Melt the metal. For this step I can highly recommend using some borax as a flux, you can buy it (normally) from your local chemist. It’s not the nicest of chemicals, even though it was used as washing powder in the 19th century, so use sparingly (a light dusting in the crucible is plenty I find) and handle with care. Next add your metal in small chunks that fit in the crucible. For this project I used some silver elements I had left over from another project. Silver is cheap, at least compared to Gold, and melts a lot easier than Copper. Beware of metals containing Zinc as breathing in the vapour can give you the shakes and fever like symptoms. Copper is VERY HARD to melt, and once molten, re-solidifies almost instantly. I started practising with it and was mightily relived when I switched to casting in Silver.

Step 8: Pour into the mould. You should remove the mould from the kiln and place it next to your crucible workstation before attempting this. Pouring the metal in is surprisingly difficult and you really don’t want molten metal splashing or pouring onto anything else (you, clothes, wood, anything that will melt or burn). Once you’ve melted the metal, be sure to lift your welding visor otherwise the mould will be invisible (along with anything else that isn’t an electrical arc or glowing metal).

Step 9: Apply the plunger (carefully!). If you look carefully at the photo of my workbench you’ll see a broken stick of wood attached to the lid of a jam-jar. This is my plunger for steam casting. When you have poured the metal into the mould, you can push the plunger down on top to generate steam and force the metal into unoccupied parts of the mould. You should prime the plunger by stuffing it with newspaper and then wetting it (in your safety bucket of water). However, if you are casting in an open mould, there’s limited benefit to the above, as assuming you used a sensible amount of flux, and it’s hot enough, the metal will naturally fill the mould. In this case, I was overzealous and plunged the plunger down onto my filled mould whilst the Silver was still liquid, creating the following mess:

20170722_191721

You can see the blobs of molten silver that were pushed out by the steam, and the blackened lump in the centre is what I pulled out of the mould itself, which was also looking rather worse for wear. It’s worth noting that metals, generally, can be purified and re-cast even when they look rather messy. The impurities will either burn off or sink to the bottom of the crucible.

20170722_195434

The mould, after use. This type of mould is only intended for a single use. However since I was in a hurry (never cast in a hurry!), I decided to re-use it and modify my original design somewhat. I placed the lumps of silver into the mould and created an arc between the two electrodes in close proximity to the mould (1-2mm max), in order to re-melt the silver into the mould. This worked very well, though changed the nature of the end product.

Step 10: Quench and finish. After re-melting, I was careful to wait for the casting to cool before dropping the whole mould in my handy nearby bucket of water. After a few seconds bubbling, I retrieved the cast using a pair of pliers and tidied it up using a grinding wheel and a wire brush polishing wheel. Since the mould had been abused during the two pours of the casting process, there were some fragments of gypsum (plaster) embedded in the surface of the final cast. These soon came out under the polishing wheel whilst I was improving the overall shape and look of the piece. 20170722_195339

Here is the front of the finished pendant, with a very lunar surface look to it. There’s a 2.4 mm hole drilled into the top for the silver chain, at a slight angle to help it sit ‘moon side up’ when worn as a necklace. I didn’t cast/make the chain, as that’s far too much like hard work, instead buying it from a local jeweller.

20170722_195356

I polished the back side of the pendant to a much smoother finish, with the idea that it would be more comfortable to wear. During the polishing process it got so hot that two tool marks imprinted into the Silver, you can see them towards the bottom. I decided to leave them as they look rather like footprints to me!

Casting is a lot of fun, however it can be extremely hazardous so should only be done with extreme care. It took me about 3 months of occasional evening and weekend practice before I was able to make my first ‘proper’ cast, and I’m still a very, very long way from even a student level of proficiency. But it kind of works, and I’m very happy with the end result. I’m also not going to give up my day job!

P.S. I must give credit to The King of Random for his excellent Arc Furnace video which was my inspiration for using the arc welder to melt metal!

Tagged , , , , , , , ,

Building a distributed cosmic ray detector in a weekend at CERN Webfest

This weekend I made a Android/Arduino based web enabled Muon (Cosmic ray) detector. I have to give a tonne of thanks to the team who did it with me (Ramviyas, Olof, Brad, Justin and Hugo) who deserve full credit for making it happen. I should also thank the ERGO Telescope team for thinking up the whole scheme of a distributed cosmic ray observatory in the first place and sending us the missing elements for our project.

Our Muon Source

What?

One ERGO pixel unit (which I hacked)

One Geiger-Muller tube and amp/PSU board (which we didn’t use in the end)

One Arduino MEGA ADK

Arduino Mega ADK

One Android Phone (with GPS, running 2.3.4 or better) – we used a Samsung Galaxy Mini GT-S5570

CNY17 optocoupler

Some Arduino Code, some Java and some web scripting

Muon Detector (ERGO Pixel)

How:

1) We hooked up the GM tube (in the end I had to hack the LED on the front of the ERGO box) to the Arduino MEGA ADK via a CNY-17 Opto-isolator. The signals out of the Geiger-Muller tube PCB were a bit too noisy to use straight up, and I didn’t manage to build myself a suitable high impedance device/amp to read them directly. We did the whole project in a weekend, so there wasn’t much time for anything!

Writing code…

2)We wrote some Arduino code that will hook up to an android phone and log events with an accuracy of 0.000212s. This is effectively a polling loop which checks a single input pin repeatedly and sends a signal to the Android when it sees a logical high on the input. The code will take any input on pin2 and output a packet with the relative timestamp to the Android. With this method we can resolve to approx 4700 loop cycles within the Arduino, using a counter (declared as a simple int that we add to). The counter is also re-set each 1s by a signal from the Android GPS clock. Counter values at reset are logged to use for a rolling timing calibration, but we didn’t get chance to implement this in the weekend.
3)We wrote an android app that reads NMEA sentences to get the raw time out of the GPS chipset (tested on Samsung phones running Android 2.3.4 and cyanogenmod) and sends a reset to the Arduino every second based on this value. The app also receives signals from the Arduino with the local timestamp (the loop counter in the Arduino) and adds this to the Navstar time (being the correct name for GPS time) We also correct the Arduino timestamp by multiplication with the constant of 0.000212 (our measured resolvable time interval) which bring the Arduino timestamp into seconds. We couldn’t get the date out of the GPS, so the leapsecond (Navstar time is 13 seconds behind UTC at the moment) correction will be necessary to datestamp it correctly – unless we figure out how to get the date from GPS directly.
4) For the moment we’re pushing it via HTTP post to  http://posttestserver.com/data/2012/08/05/populous/  Eventually we will send it to the ERGO database, once we have done some more precise measurements of the timing accuracy.

The Android App in action

We have a few things that would also be nice to add:
The Arduino code could do with some optimisation – we can probably increase the timing accuracy significantly (but this will obviously take more time than we had over the weekend) to go beyond the 212 microsecond resolution. It’s also running as a polling loop without any de-bounce, so duplicate readings are a distinct possibility. Using interrupts caused problems with the Arduino crashing, I’ll put it on my list to figure out when I have time.

Our system timing and architecture drawing

Timing calibration has been worked out on the back of an envelope, with some work the Android could do a rolling calibration on the Arduino (so that the 4700 loop cycles are adjusted based on observed performance).

As for the GM tube interface (which I struggled with), SEEED studio make a geiger shield that at first glance it looks like it would plug straight in fine – the design is open source as well. It can be found here: http://www.seeedstudio.com/depot/grove-geiger-counter-p-867.html?cPath=190

A great team!

That’s everything for the moment –  here are some links for the resources/websites we used/made:
Source code (arduino and android): https://github.com/jussy/cern-webfest
Pirate pads (where we did the working out..) http://piratepad.net/ep/pad/view/ro.-NYTlmpQZIl/latest
Tagged , , , , , , , ,

Arduino + Radiation = ?

In this post I’m going to talk about some preliminary radiation tests I’ve been performing on a couple of Arduino Uno modules and present the story so far…

This shows one of the two test plates, with the Orange LED luminaire, 10 230V direct LEDs, an arduino+ prototype shield and a set of terminals for connection to the main test chassis.

A while ago I attended the awesome Lift’12 conference in Geneva. I met some inspirational people and got inspired to test some arduinos in a radioactive environment. I haven’t found anyone else doing this kind of thing, which isn’t surprising as general access to radioactive environments is fortunately quite limited. However, I’m lucky enough to work at CERN and we have plenty of interesting places to test things!

This is very much a first tentative step into testing the arduino’s performance under the influence of radiation – only two devices were tested, there is no control group and I’m only writing down what I did after the event. I’ve been working on an LED lighting test for about a year now with some colleagues and last time we had access to the test facility I persuaded them to let me add two arduinos (which I named Archie and Bob) to the test bench as cheap signal conditioners to monitor the current flowing in our LED samples. I did also check with my boss (a highly recommended stage of the process for anyone else feeling similarly inspired into testing things at work…).

Beyond the glare of the LED's you can just make out the black ABS enclosure with arduino & shield.

Each arduino (UNO, R2) was mounted in an ABS enclosure with a prototype shield mounted on the top. The shields comprise:

  • Homebrew radiation hard power supply (230V to 16ishV)
  • Screw terminals for the connection of terminals to the outside world
  • Miniature CT + burden resistor to measure current in the LED samples

This shot shows the prototype shield with the power supply and the CT measuring the current in the test LEDs.

The ABS boxes are mounted on steel plates approximately 40cms by 60cms, which also contain a set of terminal blocks (for connection to the main test chassis) and a couple of LED samples under test. I should stress at this point that the arduino isn’t an integral part of the test bench, just a cheap way for us to extract additional information.

The ‘homebrew’ radiation hard power supply is a very basic affaire, composed of a cheap PCB mounted 230V-12V transformer and a GBU8k glass passivated full bridge rectifier with an 800V breakdown voltage. The GBU8K has previously been tested at CERN and found to be a reasonably solid performer when subjected to radiation. This PSU is obviously extremely basic, providing only a wobbly DC voltage at about 14-16V with no load. This set of tests relies on the linear regulator onboard the arduino to step down the voltages to a smooth 3.3/5V level.

The CT is hooked up across a burden resistor to the Ain pins, as this is a test bench and I’m using some components which are sized to a full scale deployment (72 led’s instead of 2) the observed voltage is very low – which is where the signal conditioning of the Arduino comes in. The onboard ADC and DAC are used to sample the voltage across the CT several times, take the maximum measured value (in an effort to measure the peak current for the LEDs running on a 230V 50Hz supply), multiply it by a factor of 10 and then send an analogue output (0-5V) reflecting the multiplied value. The analogue output is sent for 5 minutes, followed by a 0V value for 5 minutes before the whole cycle is repeated and the current is re-sampled. Potentially this helps us check that the arudino can still output a 0 volt signal, that the internal clock is reasonably accurate and from the periodic change in output voltage we can rapidly conclude if it’s broken…  the signal also looks rather like a heartbeat, which is intrinsically pleasing (for me as an Engineer anyway!) to see.

This shows the daily heartbeat of one of the test benches, with operation for 1 hour per day in alternating periods of 5 minutes 'sample' and 5 minutes at 0V.

The justification for this is that it would be very hard to measure the raw CT signal (which is just a few mV, for a current of only a few mA in the LED’s) via the experimental infrastructure we have in place (over a kilometer of copper cables), without adding some sensitive and expensive amplifiers – which more likely than not would be rapidly destroyed by the radiation in the test environment. So in this case the Arduino gives us a cheap (<20 euro) alternative, indicating as a minimum that there is still current flowing to the LEDs, and as an added bonus we can monitor and evaluate the performance of both Archie and Bob as they soak up the rays!

So far (over a month into the ‘test beam’) both test benches are still functional, although some distinctive wobbles can be observed on the outputs of the DAC’s from both Archie and Bob. I was personally quite surprised that they lasted more than 1 day, as a previous test had destroyed a number of SMPS (switch mode power supply) within mere hours once the radiation started.

This is a close up of 1 hour of operation, showing the shape of the DAC output in periods of discrete 5 minute operation, interspersed with periods of a 0V output signal.

So far the conclusion is that the two arduino’s tested are still functional, after a 1 hour per day duty cycle within the radiation test area. As time goes on I’ll update this blog post with some more details about the specific type and levels of radiation experienced, plus a more scientific analysis of the outputs taken from the ADC’s. I feel obliged to point out that this is a very long way short of a formal ‘radiation qualification’ , which would require amongst other things components with a fully controlled provenance, a statistically significant sample pool, source code which tests the operation of (ideally) all the silicon within the arduino and peripherals, and of course a detailed scientific analysis of the results. But every journey starts with the first step and so far Archie and Bob are still marching down their radioactive road…

The source code (sorry it’s rather messy, but it works) running on the arduino’s is below:

/*
arduino radiation test code version 1
current monitoring for led sources within CNGS tunnel, CERN. 8/3/12
100:1 CT with four passes of wire (i.e. 4x amplification on current)

written very quickly and based on a bunch of examples by
David Cuartielles
& Tom Igoe

*/

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 3;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor
int interimValue = 0;

void setup() {
// declare the ledPin as an OUTPUT:
//pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}

void loop() {
// read the value from the sensor:

//init and first value read
sensorValue = 0;
interimValue = analogRead(sensorPin);
sensorValue = interimValue;
//start the acquisition process proper
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(123);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(137);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}  interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(123);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(137);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}  interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(113);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(123);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}
delay(137);
interimValue = analogRead(sensorPin);
if (interimValue > sensorValue)
{
sensorValue = interimValue;
}

//Multiply by 10. Typical measured values pre-start were 15-17 raw (150-170 with multiplication)
//then send this value out over the serial and the pwm ports
sensorValue = sensorValue * 10;
analogWrite(ledPin, sensorValue);
Serial.println(“I am alive and my name is Archie”);
Serial.println(sensorValue, DEC);
//now wait another 5 mins
delay(300000);

//send a zero for 5mins to allow measurement calib.
analogWrite(ledPin, 0);
delay(300000);

}

Tagged , , ,

Robot Drawing Arm

Printer ink is the most expensive commodity in the world (by weight, or volume.. apparently). I’m always running out of it just when I need to print out a boarding pass, or some other essential printed document. So wouldn’t it be great if you could print things out using a biro?

Here is my version 0 attempt at such a device in action at Lift’12. It actually has a lot of similarities to this drawing automaton, although I only realised that after I’d finished and the video blogger Nicolas Charbonnier pointed it out to me! Nicolas did a video interview with me at Lift’12 where I had the chance to show off my creation a little. You can watch the video (which includes a fair bit of discussion about my day job at CERN) here.

Basic idea: A robot arm with two drive servos and one more to move a pen (or pencil) up and down onto standard A5 paper. Plugs into a computer for the power and the drawing data. Draws following the mouse or via a crude black & white filter on a JPEG image.

Ingredients:

Arduino (I used my trusty old duemilanove), USB lead to connect it to a computer, three Futaba S3003 servos (or equivalent), a few bits of wire, and some stationary from Muji (one A5 file box, two aluminium rulers, one wooden ruler and one acryllic one to be precise). A biro (one with four colours if you are feeling fancy!). Software: Processing and some jpg’s (+a bit of patience)!

Building it was fairly straight foreward, with the most complicated part making a cam to lift the pen up/down. I did this by drilling 1/2 of an acryllic ruler so that the pen can pass through it, with the pen attached using a single thin screw to an extremity of a servo horn. Fixing the acrylic ruler to the up/down servo didn’t work very well, hence the blue ‘LIFT’ tape in the photos.

Once assembled it should look like this – obviously you can modify the hardware build as you wish.Image

You can see the coins I added (wrapped in masking tape) as a counterweight on the left. It helped to resolve some issues with the lack of co-planar motion in the two arm segments.

After trying to write my own code I gave up and used the excellent Firmata library for the arduino/processing link (my own code was doing strange things…). The computer communicates serially to the plotter, sending positions for each of the three servos.

When I was writing the initial processing sketch, I controlled the arm directly for the first few passes. This was disasterous as I managed to snap teeth off two out of my three servos (originally they were super-micro lightweight ones… after the damage I decided to upgrade to the S3003’s). This lead me to develop my own ’emulator’ for the arm, so that I could solve the mathematical and physical constraints without breaking anything else. You can see an early demo of the arm here.

Here is the processing source code:

import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int countstart = 0;
int servo1Pin = 9; // Control pin for servo motor
int servo2Pin = 10; // Control pin for servo motor
int servo3Pin = 11; // Control pin for servo motor
int armposn;// = 0;
int digitposn;// = 0;
//int penposn;//= 0;
int penstate = 0;

int xcent = 300;
int ycent = 300;
//int targetX= 400;
//int targetY= 200;
int line1 = 130;
int line2 = 130;
int minimumlength = 40;
color black = color(0);
PImage img;
PImage edgeImg ;

void setup(){
float[][] kernel = { { -1, -1, -1 },
{ -1, 9, -1 },
{ -1, -1, -1 } };

size (600, 600);
background(255);

img = loadImage(“ben.jpg”); // Load the original image

img.loadPixels();
edgeImg = createImage(img.width, img.height, RGB);

// Loop through every pixel in the image.
for (int y = 1; y < img.height-1; y++) { // Skip top and bottom edges
for (int x = 1; x < img.width-1; x++) { // Skip left and right edges
float sum = 0; // Kernel sum for this pixel
for (int ky = -1; ky <= 1; ky++) {
for (int kx = -1; kx <= 1; kx++) {
// Calculate the adjacent pixel for this kernel point
int pos = (y + ky)*img.width + (x + kx);
// Image is grayscale, red/green/blue are identical
float val = red(img.pixels[pos]);
// Multiply adjacent pixels based on the kernel values
sum += kernel[ky+1][kx+1] * val;
}
}
// For this pixel in the new image, set the gray value
// based on the sum from the kernel
edgeImg.pixels[y*img.width + x] = color(sum);
}
}
// State that there are changes to edgeImg.pixels[]
edgeImg.updatePixels();

arduino = new Arduino(this, Arduino.list()[1]);
arduino.pinMode(servo1Pin, Arduino.OUTPUT);
arduino.pinMode(servo2Pin, Arduino.OUTPUT);
arduino.pinMode(servo3Pin, Arduino.OUTPUT);

arduino.analogWrite(servo1Pin, 70);
arduino.analogWrite(servo2Pin, 170);
arduino.analogWrite(servo3Pin, 50); // the servo moves to the horizontal location of the mouse

// note – we are setting a digital pin to output
background(255);

}

void draw()
{
if (countstart == 1){
makepic();
arduino.analogWrite(servo1Pin, 70);
arduino.analogWrite(servo2Pin, 170);
arduino.analogWrite(servo3Pin, 50);
}
countstart = countstart +1;
}

//void draw(){
void makepic(){
background(255);
//fill(50);
stroke(0);
//rect(350+30,320-10,130,130);
image(img, 0, 0, 130, 130); // Displays the image from point (0,0)

image(img, 130, 0, 130, 130); // Draw the new image
filter(POSTERIZE,4);
filter(THRESHOLD);
colorMode(HSB);

for (int xcycle = 130; xcycle < 259; xcycle = xcycle+2)
{
for (int ycycle = 0; ycycle < 129; ycycle++)
{
if (get(xcycle,ycycle)<-2)
{
set(xcycle+350-130+30,ycycle+320-10,black);
markpaper(xcycle+350-130+30,ycycle+320-10,110);//changed pen variable 110
delay(20);
markpaper(xcycle+350-130+30,ycycle+320-10,170);//comment this line and the one further below out to draw lines not dots
//delay(20);
}
else
{
set(xcycle,ycycle,0);
markpaper(xcycle+350-130+30,ycycle+320-10,170);
//delay(50);
}
}
for (int ycycle = 129; ycycle > 0; ycycle–)
{
if (get(xcycle+1,ycycle)<-2)
{
set(xcycle+350-130+1+30,ycycle+320-10,black);
markpaper(xcycle+350-130+1+30,ycycle+320-10,110);
delay(20);
markpaper(xcycle+350-130+1+30,ycycle+320-10,170);//likewise comment this line out for lines not dots on your paper as well as the one further up

}
else
{
set(xcycle+1,ycycle,0);
markpaper(xcycle+350-130+1+30,ycycle+320-10,170);
//delay(50);
}
}
}

}

void markpaper(int targetX, int targetY, int penposn){
//print(“xposn” + targetX);
//println(” yposn” + targetY);
float angle1 = atan2((targetX – xcent), (targetY – ycent));
float sectorlength = sqrt(sq(targetX – xcent)+sq(targetY – ycent));

//if it’s out of reach, shorten the length in the same direction
if (sectorlength > (line1+line2))
{
sectorlength = line1+line2;
targetX = int(xcent + sin(angle1)*sectorlength);
targetY = int(ycent + cos(angle1)*sectorlength);
}

if (sectorlength < minimumlength)
{
sectorlength = minimumlength;
targetX = int(xcent + sin(angle1)*sectorlength);
targetY = int(ycent + cos(angle1)*sectorlength);
}

float internangle = acos((sq(sectorlength)-sq(line2)-sq(line1))/(2*line1*line2));

float sendangle1st = (angle1+(internangle/2));
if (degrees(sendangle1st) < 0 )
{
sendangle1st = radians(0);
}
if (degrees(sendangle1st) > 180 )
{
sendangle1st = radians(180);
}

int line1X = int(xcent+ sin(sendangle1st)*line1);
int line1Y = int(ycent+ cos(sendangle1st)*line1);
int line2X = line1X + int(sin(((angle1+(internangle/2) – internangle)))*line2);
int line2Y = line1Y + int(cos(((angle1+(internangle/2) – internangle)))*line2);
stroke(0,9);
line(xcent, ycent, line1X, line1Y);
line(line1X, line1Y, line2X-1, line2Y-1);
// if (penposn == 150)
// {
// set(line2X,line2Y,black);
// println(“TEXT”);
// }
// set(mouseX,mouseY,black);

//if it’s too close set the minimum threshold in the same direction

int sendangle1 = round(degrees(sendangle1st));
int sendangle2 = round(degrees((radians(180) – internangle)-radians(35)));
//println(“Send1>”+ sendangle1 + ” Send2 >” + sendangle2);
digitposn = sendangle2;
armposn = sendangle1;

arduino.analogWrite(servo1Pin, digitposn);
arduino.analogWrite(servo2Pin, penposn);
arduino.analogWrite(servo3Pin, armposn);
if (penstate != penposn)
{
delay(300);
}
else
{
delay(1);
}// the servo moves to the horizontal location of the mouse
penstate = penposn;
}

//end of source\\

I should add that this code is very rough, and contains hard-coded boundary limits for the drawing area which are specific to the physical configuration of my hardware (and painstakingly obtained by moving the arm and looking at where the pen is). This code is also set to draw dots rather than lines, as people generally indicated a preference for this kind of output.

Performance is ‘interesting’. I’ve set it to draw an approx 160×160 matrix, one pixel at a time. Depending upon the number of dark pixels this can take up to 1.5 hours per image. If you want to draw lines that go between all the connected pixels the time per image comes down to <20 minutes. This is mostly a function of delays added in the code to cope with mechanical oscillations in the two arms and the pen.

Things that could be improved:

  • The code is very ropey! Like my flat, it would benefit from a tidy and the hoovering up of any stray variables.
  • The drawing area is still a bit sub-optimal. The arm can cover almost 100% of the space of an A5 sheet, however I’m only using about 65% for drawing at the moment. The boundary conditions for the angles would need to be carefully adjusted for this.
  • Worst of all the image processing is very crude (simple cut for black and white). This is mostly because I’ve been lazy (it WORKS, right?) and wish to avoid re-inventing the wheel when there are so many excellent image processing suites out there. If I have time it would be great to code something to vectorise JPG’s properly rather than my current ‘quick and dirty’ approach.
  • Colour! My pen has Red, Green, Blue and Black ink.. mostly I use black or blue for clarity, but it would be very interesting to come up with a multi-pass colour image reproduction system.
  • Good projects are never quite finished 😉

Image

A picture of Ben Bashford drawn from a JPG photo, live on the stage of Lift’12.

I hope you liked my creation – please feel free to comment, suggest and contribute. I’d like to thank Amy Shen for being my first drawing subject and for helping me to figure out the maths of converting an XY co-ordinate space into a two polar variables.

Tagged , , , , , , , , , , , , , , , ,

Arduinopower Source Code

So the other day I got a comment about my Ardunipower project. This encouraged me to dig out the source code and post it here. It’s a long way short of finished (and I’ve stopped working on the project.. since early 2010!), but hopefully this will provide at least some kind of insight into how I had commands going back and forth to the ADE7753 power measurement IC.

This code initialises all the various addresses within the ADE7753 from the data sheet. I then wrote (hardest part) a couple of routines to do multi-byte send/receive operations over SPI (Maybe it’s I2C.. I can’t remember anymore!) between the Arduino and the ADE7753. This particular version of the code is a demonstrator that polls some values and sends them back to a PC over serial (great if you have a bluetooth link going on!), slightly less good if you’re on a cable as my PCB design isn’t opto-isolated.

The next stage (that I didn’t do!) was calibration – actually turning the echoed values into something meaningful, and in particular adjusting to the measurement skew introduced between the voltage measures and the current transformer.

 

//registers on ADE7753  
#define WAVEFORM 0x01
#define AENERGY 0x02
#define RAENERGY 0x03
#define LAENERGY 0x04
#define VAENERGY 0x05
#define LVAENERGY 0x06
#define LVARENERGY 0x07
#define MODE 0x09
#define IRQEN 0x0A
#define STATUS 0x0B
#define RSTSTATUS 0x0C
#define CH1OS 0x0D
#define CH2OS 0x0E
#define GAIN 0x0F
#define PHCAL 0x10
#define APOS 0x11
#define WGAIN 0x12
#define WDIV 0x12
#define CFNUM 0x14
#define CFDEN 0x15
#define IRMS 0x16
#define VRMS 0x17
#define IRMSOS 0x18
#define VRMSOS 0x19
#define VAGAIN 0x1A
#define VADIV 0x1B
#define LINECYC 0x1C
#define ZXTOUT 0x1D
#define SAGCYC 0x1E
#define SAGLVL 0x1F
#define IPKLVL 0x20
#define VPKLVL 0x21
#define IPEAK 0x22
#define RSTIPEAK 0x23
#define VPEAK 0x24
#define RSTVPEAK 0x25
#define TEMP 0x26
#define PERIOD 0x27
#define TMODE 0x3D
#define CHKSUM 0x3E
#define DIEREV 0x3F

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

//SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); //set clock rate to 1/16th system

byte eeprom_output_data;
byte multi_byte_data[3];
byte eeprom_input_data=0;
long long_eeprom_data = 0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
  for (int I=0;I<128;I++)
  {
    buffer[I]=I;
  }
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void setup()
{
  Serial.begin(115200);

  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);
  SPSR = (0<<SPI2X);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  Serial.println("init complete");
  delay(1000);

  //testrun starts here

  //utils
  //read_eeprom(address value, how many bytes)
  //write_to_eeprom(target, values, bytes to write)

  //read what is there right now
  //address = LINECYC;
//  Serial.print(address,HEX);
 // eeprom_output_data = read_eeprom(STATUS,2);

  //long TestWrite;
  //TestWrite = 0xABCD;
  //write_to_eeprom(address, TestWrite, 2);
// Serial.println(eeprom_output_data, BIN);
  //eeprom_output_data = read_eeprom(address, 2);
  //Serial.println("Completed basic read write test");

}

void write_to_eeprom(int EEPROM_address, long write_buffer, int bytes_to_write)
{
  //Serial.print("Multiwrite ops to addr>");
  //Serial.println(EEPROM_address, HEX);
  //set write mode
  byte make_write_cmd = B10000000;
  byte this_write = B00000000;
  EEPROM_address = EEPROM_address|make_write_cmd;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer((char)(EEPROM_address));      //send address

  //here there should be a t7 delay, however long that is
  for (int i = 0; i<bytes_to_write; i++){
  //Serial.println(i);
  this_write = byte(write_buffer>>(8*((bytes_to_write-1)-i)));
  //Serial.println(this_write, HEX);
  spi_transfer((char)(this_write));      //send data byte
  }
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
}

long read_eeprom(int EEPROM_address, int bytes_to_read)
{
  //Serial.print("Multi-read to addr>");
  //Serial.print(EEPROM_address, HEX);
  Serial.println(" Data starts:");
  long data = 0;
  byte reader_buf = 0;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  for (int i = 1; i <= bytes_to_read; i++){
    reader_buf = spi_transfer(0xFF); //get data byte
    Serial.println(i);
    Serial.println(reader_buf, BIN);

    data = data|reader_buf;
    if (i< bytes_to_read) {
      data = data<<8;
    }
    }
  Serial.print("completed. data was>");
  Serial.println(data, BIN);
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
  return data;
}

void loop()
{

    eeprom_output_data = read_eeprom(STATUS,2);
   Serial.println("STATUS CHECK");
   Serial.println(eeprom_output_data, BIN);
   Serial.println(eeprom_output_data, HEX);
   delay(1000);
   eeprom_output_data = read_eeprom(LINECYC,2);
   Serial.println("LINECYC CHECK");
   Serial.println(eeprom_output_data, BIN);
   Serial.println(eeprom_output_data, HEX);   

}
Tagged , , , , , , , , , , , , ,

DIY Wedding Photobooth

As if there aren’t enough accounts of how to build your own photobooth on the internet already, here is one more!

Brief: An easy to assemble, relatively drunken person (it is a wedding after all…) proof photobooth that is robust and easy to use by all ages. Basic photo taking capability that produces the authentic Photo-booth experience and encourages silly poses. Cheap-ish to construct with a maximum of re-usable parts afterwards as the remains are going to the bride and groom’s place as shelving units for their shed.

Physical Hardware (mostly from Ikea):

Two sets of GORM shelves, one slim (for the computer enclosure) and one deep for the seating area.

Four height-extenders used to brace the gap between the two shelf units (so 2 packs of 2 bits of wood each)

A curtain rail to cover the door when the booth is in use, hung with an Irma fleece rug that has holes cut into it to go on the rail

One additional large shelf to connect the two shelves together on the side

Four plastic shelf wall mounting brackets (a bargain at about 40p each!)

Covers – 10 x Irma covers (super cheap at 1 pound each) and two of the more expensive Polarvide covers – one black one for the front to cover the computer/electronics and one for the back to make the rear ‘curtain’

Electrical and Electronics:

Again from IKEA 4x Lagra spotlights and compact fluorescent 7W lamps to give it that ‘showbiz’ feel inside. I had problems screwing the bulbs in due to the metal reflectors, so had to cut a couple of them out. After removing the first two, I found that the other two could be persuaded to screw in with a fair bit of force.

One IKEA ‘non’ 11W fluorescent strip light, to go in the top of the booth for ‘house lights’ when the spotlights are off.

A four way power strip from home, plus a two way switch from my dad’s box of household electrical stuff. We also brought along an extension lead to ensure that we could power it all at the venue.

The main component of the electronics was my old laptop – A Highgrade Notino circa 2003, with a 180 degree hinge, so I could slot it in to a space between a shelf mounted vertically with a height extender batten screwed to the back of it. The laptop simply slots in and sits in the gap – excellent for checking the saving of files and making last minute modifications. If you don’t have a laptop that goes flat this will be more complicated! I hooked it up to an old MSI Star Cam Clip (as I bought a couple some time ago) to take the photos, which provided a resolution of 640×480. Not exactly HD, but fine for a photobooth.

Some more sparkle was added by including my girlfriends desk-fan, wired through the second switch on the switch plate, to give that ‘blowing hair’ look.

The booth action was controlled by a single button, mounted in between the slats of the vertical front facing shelf. It was connected to an Arduino running some very simple code which sent a letter over the serial port to the laptop when pressed. Originally I had two buttons, but actually only having one worked fine! The electronics weren’t that well screened, so switching on the fan also had the effect of triggering the booth countdown, which wasn’t all bad for those who couldn’t find the real trigger button.

Software:

The booth software was written in processing, running on Windows XP. To make it work with the webcam I needed to install quicktime and a legacy version of WinVDIG which I found on the web. In the traditional ‘photobooth’ format, I set it up to take 4 consecutive pictures, saving each as a JPEG with a unique time/date/incremented counter filename. On the completion of the fourth picture, they were all re-loaded and put into a 2×2 square format like a print out, displayed back to the user and saved as a composite JPEG. We didn’t attempt to print anything out as the booth was intended (and succeeded in being) able to run ‘stand alone’ without too much human intervention for the evening.

[After all the testing, I actually put my processing source on a corrupt USB key so had to re-write it from the previous version the night before the wedding! Oops.. ]

Source Code:

For the Arduino –

int stbuttonPin = 2;  // change to whatever you want
int tkbuttonPin = 3;
int ledPin = 13; // just using for example
boolean tkoldval = HIGH;
boolean stoldval = HIGH;

void setup()
{
     pinMode(ledPin, OUTPUT);     // LED as output
     pinMode(stbuttonPin, INPUT);    // button as input
     digitalWrite(stbuttonPin, HIGH); // turns on pull-up resistor after input
     pinMode(tkbuttonPin, INPUT);    // button as input
     digitalWrite(tkbuttonPin, HIGH); // turns on pull-up resistor after input
     Serial.begin(9600);
}

void loop()
{
tkoldval = digitalRead(tkbuttonPin);
stoldval = digitalRead(stbuttonPin);
     if( (tkoldval == HIGH) &(digitalRead(tkbuttonPin) == LOW ))   // when pin goes LOW
	   {
	    Serial.println('t');
            digitalWrite(ledPin, HIGH);	     // turn on LED
            delay(10);
	    }
     if( (stoldval == HIGH) & (digitalRead(stbuttonPin) == LOW ))   // when pin goes LOW
	   {
	    Serial.println('s');
            digitalWrite(ledPin, HIGH);	     // turn on LED
            delay(10);
	    }

    digitalWrite(ledPin, LOW);	  // well, turns led off!
    //delay(1000); //one second delay

}

And the code for Processing:

 
  public static void main( String args[] ) {
   PApplet.main( new String[] { "--present", "superbooth8511" } );
 }
//import fullscreen.*;
//import japplemenubar.*;
import processing.serial.*;

/* (made by Tjerk in 10 minutes  ) */

import processing.video.*;
Serial myPort;  // Create object from Serial class
char val;      // Data received from the serial port

Capture myCapture;
int a = 1024; // width of window
int b = 768;  // height of window
int x = 100;  // x- position text
int y = 700; // y- position text
int capnum = 0;
int countdowntimer = 10;
int globalframecount = 0;
PImage aj;
PImage bj;
PImage cj;
PImage dj;
//FullScreen fs;

void setup(){

    //print(Serial.list()[0]);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
  val = 'o';
  frameRate(25);
 size(a,b);
 // fs = new FullScreen(this);

// setFullScreen(true);
 background(0);

 //PFont fontB = loadFont("Ziggurat-HTF-Black-32.vlw");
 //textFont(fontB, 100);
myCapture = new Capture(this, a, b, 30);
}
void captureEvent(Capture myCapture) {
 myCapture.read();
 //fs.enter();
}
void draw(){
 PFont fontA = loadFont("Ziggurat-HTF-Black-32.vlw");
 textFont(fontA);
  //println("start");
if ( myPort.available() > 0) {  // If data is available,
    val = (myPort.readChar());
   //println('1');
//println(val);    // read it and store it in val
 }
 if (mousePressed== true){
   globalframecount = 1;
 }

   //background(255);
   fill(0);

switch(val) {

  case 's':
  globalframecount = 1;
//  background(0);

 break;

  case 't':
//null
    break;
  default:
    //println("Zulu");   // Prints "Zulu"
    break;
}

 if (globalframecount == 25) {
 countdowntimer = 9;
 }
 if (globalframecount == 50) {
 countdowntimer = 8;
 }
 if (globalframecount == 75) {
 countdowntimer = 7;
 }
 if (globalframecount == 100) {
 countdowntimer = 6;
 }
 if (globalframecount == 125) {
 countdowntimer = 5;
 }
 if (globalframecount == 150) {
 countdowntimer = 4;
 }
 if (globalframecount == 175) {
 countdowntimer = 3;
 }
 if (globalframecount == 200) {
 countdowntimer = 2;
 }
 if (globalframecount == 225) {
 countdowntimer = 1;
 } 

 if ((globalframecount < 250) & (globalframecount > 0)) {
       image (myCapture, 0,0);
       textFont(fontA, 30);
       fill(0);
       text ("Preview! Get ready for your photo in "+str(countdowntimer), x+2, y);
       text ("Preview! Get ready for your photo in "+str(countdowntimer), x, y+2);
       text ("Preview! Get ready for your photo in "+str(countdowntimer), x-2, y);
       text ("Preview! Get ready for your photo in "+str(countdowntimer), x, y-2);
       textFont(fontA, 30);
       fill(255);
       text ("Preview! Get ready for your photo in "+str(countdowntimer), x, y);
       //text (countdowntimer, width-250, y);
       globalframecount++;
 }

 if ((globalframecount >= 250) & (globalframecount < 500)) {
      image (myCapture, 0,0);

 if ((globalframecount > 250) & (globalframecount < 311))
 {
 textFont(fontA, 100);
 fill(0);
 text (str(countdowntimer), width/2+2, height/2);

 text (str(countdowntimer), width/2, height/2+2);

 text (str(countdowntimer), width/2-2, height/2);

 text (str(countdowntimer), width/2, height/2-2);

 fill(255);
 text (str(countdowntimer), width/2, height/2-2);
  }
if (globalframecount == 250)
{
  countdowntimer = 3;
}

if (globalframecount == 270)
{
  countdowntimer = 2;
}

if (globalframecount == 290)
{
  countdowntimer = 1;
}

if (globalframecount == 312) {
  background(255);
}
   if (globalframecount == 313){
  saveFrame(capnum+".jpeg");
  aj = loadImage(capnum+".jpeg");
  capnum++;}

  if ((globalframecount > 314) & (globalframecount < 373))
 {
 textFont(fontA, 100);
 fill(0);
 text (str(countdowntimer), width/2+2, height/2);

 text (str(countdowntimer), width/2, height/2+2);

 text (str(countdowntimer), width/2-2, height/2);

 text (str(countdowntimer), width/2, height/2-2);

 fill(255);
 text (str(countdowntimer), width/2, height/2-2);
  }
if (globalframecount == 314)
{
  countdowntimer = 3;
}

if (globalframecount == 335)
{
  countdowntimer = 2;
}

if (globalframecount == 355)
{
  countdowntimer = 1;
}

  if (globalframecount == 374) {
  background(255);
}

  if (globalframecount == 375){
  saveFrame(capnum+".jpeg");
  bj = loadImage(capnum+".jpeg");
  capnum++;
    }

  if ((globalframecount > 375) & (globalframecount < 436))
 {
 textFont(fontA, 100);
 fill(0);
 text (str(countdowntimer), width/2+2, height/2);

 text (str(countdowntimer), width/2, height/2+2);

 text (str(countdowntimer), width/2-2, height/2);

 text (str(countdowntimer), width/2, height/2-2);

 fill(255);
 text (str(countdowntimer), width/2, height/2-2);
  }
if (globalframecount == 376)
{
  countdowntimer = 3;
}

if (globalframecount == 401)
{
  countdowntimer = 2;
}

if (globalframecount == 420)
{
  countdowntimer = 1;
}

  if (globalframecount == 438) {
  background(255);
}

    if (globalframecount == 439){
  saveFrame(capnum+".jpeg");
  cj = loadImage(capnum+".jpeg");
  capnum++;
    }

  if ((globalframecount > 440) & (globalframecount < 497))
 {
 textFont(fontA, 100);
 fill(0);
 text (str(countdowntimer), width/2+2, height/2);

 text (str(countdowntimer), width/2, height/2+2);

 text (str(countdowntimer), width/2-2, height/2);

 text (str(countdowntimer), width/2, height/2-2);

 fill(255);
 text (str(countdowntimer), width/2, height/2-2);
  }
if (globalframecount == 440)
{
  countdowntimer = 3;
}

if (globalframecount == 460)
{
  countdowntimer = 2;
}

if (globalframecount == 480)
{
  countdowntimer = 1;
}

   if (globalframecount == 497) {
  background(255);
}    

     if (globalframecount == 498){
  saveFrame(capnum+".jpeg");
  dj = loadImage(capnum+".jpeg");
  capnum++;
     }

  if (globalframecount == 499) {
 fill(255);
 background(0);
 rect(width/11, height/10, (width-240), (height-100));
 image(aj, width/8, height/8, width/3, height/3);
 image(bj, 4*(width/8), height/8, width/3, height/3);
 image(cj, width/8, 4*(height/8), width/3, height/3);
 image(dj, 4*(width/8), 4*(height/8), width/3, height/3);
 fill(0);
 text ("Press button to take some more!", x, y);
 saveFrame("multipage"+capnum+".jpeg");
 globalframecount = -1;
     }

 //delay(50);
 globalframecount++;}

}

The photobooth output!

The assembly took a few hours with my trusty battery drill and a socket bit to drive the GORM bolts into place. I also used plenty of woodscrews for my ‘non standard’ fixings into the gorm framework, and a couple of different sizes of wood drill bits to pre-drill to prevent splitting in the new mount locations.

Relative to the picture above, the only modifications were the omission of the top and bottom shelves in the middle section – these were replaced with two height extender bars screwed into the tops of each of the other modules, which proved sufficiently rigid to hold it all together. I also added another height extender bar at the back of the computer cabinet, to mount the webcam on. With the installation of the 4 shelf brackets to support the seat, there wasn’t room to install a full depth shelf underneath as a ‘back board’ for peoples feet, so I put a narrow one there instead, and didn’t put any horizontal element in the middle of the computer cabinet section.

Finally, I wrapped the whole thing in the IRMA cloth, using screws as attachment – the original plan called for a staple gun but we couldn’t find one! The curtain rail was mounted above the entrance, screwed to each corner of the booth. The final height extender was screwed to the top using the 90 degree ‘non topple’ brackets, and served as a sign. I had to cut the black polarvide cloth that covered the laptop (apart from the camera and screen of course!), so that I could fit the screen up in the middle of it. Otherwise damage to the cloth was minimal.

A last minute enhancement came from the IKEA bargain bin, where I picked up a large seat cushion cover for £3 and secured this to the seat with some screws underneath. Extra padding would have been nice, but the cover was sufficient to make sure that fancy clothes didn’t get caught on any rough bits of wood.

On the night, the ‘non’ fluorescent tube was useful as I didn’t wire it through the switch, so it remained on all the time – showing people that the booth was ready to use, even if the spotlights inside had been turned off. The booth broke down a couple of times when users accidentally pressed the ‘take picture’ button on the webcam whilst adjusting it, but otherwise it was trouble free.

Disassembly took less than an hour, again using the power drill with a socket to remove the GORM bolts. I was also able to recover 90% of the screws I used, which I can recycle for future projects! I was very happy with how it all worked out, so was my girlfriend. Fingers crossed the bride and groom liked it too.. and will like their new shelves once they get back from honeymoon!

The finished product

Evaluation:

I thought it worked well, building was fast, the construction was solid enough for up to 2 adults and 2 small children to fit inside. The processing sketch performed perfectly, although the resolution wasn’t amazing – if I had a better webcam maybe next time, although there is also a constraint from the size of the laptop screen, as processing actually takes a screendump in my code, rather than a true photo (which would let you go up to 1.3Mp, if I knew how to do it). Overall I went a little over budget (the target was £100, it actually cost about £125) mostly buying extra lights, but everything except a couple of the cloths can be re-used – either somewhere in the house or re-building the photo booth for another happy occasion! I hope this is useful for anyone trying to build a booth.

Original Bill of Materials (we actually bought only some of this and some extra things not listed) –

NON
Countertop lighting,
fluorescent
£15.31
Length: 65.0 cm
Cord length: 1.5 m
Article no:: 001.436.45

IRMA
Throw
£1.01
color: light blue
Length: 170 cm
Width: 130 cm
Article no:: 000.704.89

POLARVIDE
Throw
£2.85
color: green
Length: 170 cm
Width: 130 cm
Article no:: 401.229.43

GORM
Post
£3.06
Height: 174 cm
Package quantity: 2 pack
Article no:: 000.585.24

GORM
Height extension post
£1.53
Height: 59 cm
Package quantity: 2 pack
Article no:: 700.585.06

GORM
Shelving unit
£24.50
Width: 78 cm
Depth: 55 cm
Height: 174 cm
Article no:: 000.585.19
Tagged , , , , , , , , , , , , , , , ,

Kindle Tips and Tricks

Kindle!

As some of you may know I’ve been enjoying my SUPER amazon kindle (the 3G) for two and a bit weeks now. I bought it never having seen one, on the basis that someone took one to London Hackspace (where I’ve never been) and then later tweeted that several people had bought one on the strength of seeing it.. so I decided to as well! Here are some things I’ve learned/figured out (and read elsewhere..) that make it go faster/better. If you want to buy one (As you can gather I think they really are very good!) then you can click here:
Kindle 3G Wireless Reading Device, Free 3G + Wi-Fi, 6″ Display, Graphite, 3G Works Globally – Latest Generation

General impression:

 

Very nice pictures!

Kindle Screensaver

 

It’s thin, it’s light, the screen is excellent (and the pictures that come on like ‘screensavers’ are very cool – though I wish I could put my own up there.. I’m sure I’ll figure that out in the future), speed of page turning and loading is acceptable and the battery life is highly impressive – only managed to flatten it out once by playing MP3’s out loud and surfing the internet for about an hour, after a week of usage and not much charging.  The keyboard occasionally suffers from bounce (i.e. two of the letter you wanted), though given it’s size and compactness it is very usable. The 3G internet access worked first time out of the box and also worked first time off the plane when I arrived in Geneva. Occasionally it has a hiccup, but for the cost of the device and the service it provides I’m extremely satisfied!

I’d give it a 10/10.

Photos:

 

Image display

 

With some searching of the blogosphere I was able to find out how to upload some trusty JPG’s onto the device. I think I created a folder called ‘Pictures’ and then put my photos in there in sub-directories, each of which then appear as individual items on the Kindle home screen. They’re quite hi-res photos (Thanks Justin!) so it doesn’t always display them correctly, probably if I have time I should re-scale to something less megapixeltastic. It would also be nice if the viewer had a slide show mode (and also the books/pdf viewer had an auto page turn mode), but I’m sure this will get added.

Books:

Books are fairly self explanatory. I’m currently reading The Honourable Schoolboy by John Le Carre, which is one of the Smiley series – and apparently the sequel to Tinker, Tailor, Soldier, Spy. I’ve also bought Lustrum, Robert Harris and Smileys People, so I’ll get round to those soon enough!

Web:

 

Renders black and white pages rather nicely!

 

By far the best single feature is the ‘experimental’ web browser. It’s all in black and white and doesn’t open ‘new window’ links. However thanks to the smart deal that Amazon have done with Vodaphone, it works in most parts of the world at no additional cost. Some of my new colleagues don’t actually believe this! I’m not sure how long it will last, though whilst it does it’s definitely a key differentiator for the Kindle in comparison to all the other ebook readers (and of course the iPad). I’ve added/amended some of the default links in the browser bookmarks for an improved experience –

  • http://mobile.twitter.com < Mobile version of twitter, works well but struggles to open links
  • http://mail.google.com/mail/h/ < HTML version of Gmail works a treat. Much faster than the javascript version.
  • http://m.facebook.com < Mobile version of Facebook, though actually I log in via the Touch site (http://touch.facebook.com) and then go back to the mobile site once I have the cookie (which lasts for a while, at least several days!) – downside of the mobile site is that text entry doesn’t seem to work that well. It is of course great for reading stuff and 100x faster than the full site.
  • http://mobile.yahoo.com/mail < Mobile yahoo mail. Works fine.
  • http://facebook.com < Comes on the default list, though crashes occasionally. One of the most impressive features of the Kindle so far is that it runs the Facebook java based chat client very well indeed!
  • Google Maps – the standard Javascript version, switching to HTML doesn’t appear to make a difference. This as my friend Simon has pointed out is potentially another killer app – the Kindle doesn’t have GPS (or that fancy GSM Cell Ident triangulation thing that most phones do these days), but in the case that you already know where you are, finding out where your going with a googlemap is rather useful! I used it with some success to find bike shops in Geneva last weekend, though unfortunately most of them were shut and/or unhelpful – not that I can blame googlemaps or my Kindle for that!

Other stuff:

If you’ve got one already and read the user guide then you may already know that the Alt+Space works at any time to start/stop the MP3 player – the sound quality is impressive for such a flat device that’s basically just a book. When I’m showing people it’s particularly impressive as I’ve filled it up with Jimi Hendrix.

WiFi:

Occasionally it doesn’t seem to like wifi access points that are open/or even secured when you know the password. For example I tried it in the local mall, and got to the last stage on their web log in before it failed. But it isn’t really necessary if you have 3G…

Cases:

I haven’t bought one of these yet – there are some neat (if expensive) ones from Amazon, that include a built in LED light that clips into two slots on the side of the case. I think these power the light, and have some clever connectors in – I saw some folks at the hackspace had done a partial teardown of their new kindles to find out, but as of yet I don’t think there are any third party lights available. £50 is a bit steep for the case, even though it’s very cool – especially as most of the places where I would want to read already have er, lights! I might opt for a slipcase type thing in the near future, hopefully before I have any accidents!

Summary:

Excellent device. Best gadget I’ve bought this year! It is to ebooks (and also tablet/pad/flat pc type devices) what the macbook pro is to laptops. If you don’t already have an ebook/iphone/smartphone/ipad, you should definitely consider it. I think my new boss might even buy one after seeing mine!

Tagged , , , , , ,

Wi-Fi Repeaters for the Developing World?

The other day I was at a meeting about the plan to roll out an IT network at the Druk White Lotus School. It’s a challenging environment – 40 below overnight in the winter, nearly a meter of snow is typical, the ground is mostly dirt/sand/dust and rock, the site is about 3500m above sea level and the UV rays are enough to bleach anything made out of plastic in a couple of months. Electricity is hard to come by, but fortunately the site has a reasonable supply thanks to the PV system installed in 2008 and a trusty diesel back-up generator.

So the challenge is this – how to distribute network access across a 1km long by 500m wide campus with distributed buildings?

My preferred option was a co-ax 10Base2 network, based on an erroneous recollection that co-ax could go a ‘long way’ i.e. about 500 meters. Wikipedia soon put me right – the actual spec limit is between 180 and 200 meters. It’s also prone to total collapse in the event that the cable fails in a single point, or someone steals a terminator from the end! So probably it fails the fault tolerance test by some margin as well.

Another strong contender would be to place Wi-Fi repeaters on the top of each building – they could also be solar powered, so that the whole system would be ‘independent’ of any fixed infrastructure. The theory would be to connect just one to a local broadband connection and then share this across the site. In theory it’s a neat solution, however the availability of an off the shelf solution is limited. I’ve found a couple of attempts to delivery such a system – the closest is Green Wi-Fi but they don’t seem to have anything more up-to-date than a mod to a Linksys WRT54 router.

We thought about fibre, but the termination equipment is currently too expensive to be in the right ball-park.

After some more thinking, I’ve convinced myself that Powerline might be the answer, especially now that adapters are available for 2.5Mbps throughput) on the campus then it would be a significant time/money/effort/maintenance saving in comparison to laying new cable infrastructure.

Subject to the outcome of the powerline experiment, it seems to me that the longer term future is in the development of an ‘internet in a crate’ rooftop Wi-Fi solution – just like the one developed by Green Wifi, but implemented in a way that isn’t subject to manufacturer product cycles. Home routers are subject to repeated product cycling, with the hardware being squeezed smaller and smaller each time – as evidenced by the Linksys WRT54 no longer being capable of supporting OpenWRT. Whilst there are still plenty of OpenWRT-able routers out there, it would be nice to have a solution that’s platform based and sufficiently adaptable to survive product cycles.

A good ‘architecture’ for such a system would be a Linux based SBC (like the Beagleboard) with a USB hub and some wireless USB adapters. The adapters would have to be carefully chosen to provide Linux drivers and an MCX/equivalent connector for a bigger antenna, but in principle there will always be something close enough to this on the market. The system would be composed of:

  • An SBC (such as, but not necessarily the Beagleboard)
  • Linux (with some routing running on top)
  • Solar Panel (ideally something small and cheap)
  • Battery & Charge controller (if overnight operation is required, temperature considerations for the Druk White Lotus School might make this challenging)
  • USB Hub
  • Wireless USB adapters (minimum of 2 No.)
  • Directional Wi-Fi antennae (minimum of 2 No.)
  • Robust box to put everything in.

So in summary I bet you could build a prototype for about £200. The emphasis would be on using modular, off the shelf hardware that can be easily programmed and customised – but most importantly that each component can be potentially swapped for alternatives without the need to radically change the whole design. My main sticking point at present is discovering an SBC that’s sufficiently cheap and basic but capable of running Linux and supporting USB host functionality.

Linux and routing software isn’t my speciality, but I’ve discovered XORP which looks like a rather nice potential solution to the complexity of routing. It’s based on FreeBSD, but they say it compiles on Linux, so I guess that should work.

Next? I’m writing a one pager summary of what I’d like. If anyone wants to take this on as a project then let me know! The idea’s been around for a while, but nobody that I’ve looked at seems to have ‘cracked it’ yet. Hopefully I can persuade a university student somewhere to take it on as a final year project!

Post Script –

The Netgear WNR3500L looks like a good potential alternative to using the beagleboard as an SBC solution. Will need to see if it’s theoretically possible to mount a second Wi-Fi adapter using it’s host USB port.

Tagged , , , , , , , ,