Tag Archives: diy photobooth arduino

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
Advertisements
Tagged , , , , , , , , , , , , , , , ,