Final – ☆ Photo Roulette ☆

Concept and Inspiration

My concept and inspiration for the final project came from a wish to make something related to cameras/photo-taking/film. Initially, I wanted to make a “camera on wheels”, but then I realized the camera lens would be on my laptop and therefore couldn’t add wheels to it, haha. So, I changed my idea but stuck with the camera concept.

I really enjoy taking photo booth pictures. In fact, I will always push my friends to take them with me if I see a photo booth anywhere. I have collected these grid images from all around the world – Beirut, Abu Dhabi, Paris, New York, Madrid, London, Dubai… And I still have them all saved. They are, to me, a beautiful way of keeping memories in a non-digital fashion, which we tend to towards these days with our phones. I also enjoy the photo booth app on the phone, but the grid layout that results is not the same as a typical, “retro” photo booth.

So, I decided to create a photo booth, which generates four images as a vertical grid!

How to use it

This project is composed of two parts: my laptop with a p5 sketch, and a “camera” I built out of cardboard, inside which there is the Arduino and breadboard. The p5 sketch begins with a start page, that states “photo booth”. There are also instructions: the first step is to click on the screen (when the images are downloaded, the user needs to press on the screen to return to the chrome page); the second step is to press record on the camera to start taking the images.

Once the record button on the camera is pressed, a message is sent from Arduino to p5 to start the photo booth session. Simultaneously, a LED turns on for 20 seconds (which is the length of each session). The four images are taken at five second intervals, with a countdown starting at three seconds. After the twenty seconds have passed, the images are downloaded as a grid, and the user can airdrop it to their phone. Moreover, when the images are done, the start page is displayed again.

Codes

 

To achieve this, I created a short code on Arduino and a longer one on p5.

Arduino code & circuit

const int BUTTON_PIN = 2;
const int LED_PIN = 13;

bool ledState = false;
int lastButtonState = LOW;
unsigned long startTime = 0; // variable to store the time the button was pressed
const unsigned long interval = 20000; // interval of 20 seconds to indicate when the LED must turn off

void setup() {
  pinMode(BUTTON_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int reading = digitalRead(BUTTON_PIN);

  // checking if the button was pressed
  if (reading != lastButtonState) {
    lastButtonState = reading;
    if (reading == HIGH) {
  
      ledState = true; // turn LED on
      digitalWrite(LED_PIN, HIGH);
      Serial.println("START"); // send "START" to p5
      startTime = millis(); // start recording the time of button press
    }
  }

  // checking if 20 seconds have passed since the button was pressed
  if (ledState && (millis() - startTime >= interval)) {
    ledState = false; // turn LED off
    digitalWrite(LED_PIN, LOW);
    Serial.println("STOP"); // when 20 seconds have passed, send "STOP" to p5
  }
}

p5 code snippets

→ a function to start the countdown between each image.

function startCountdown() {
  countdownValue = 4; // start the countdown with "nothing"
  clearInterval(countdownTimer); // clear the existing timer, necessary after the first image is taken after the sketch is played
  countdownTimer = setInterval(() => {
    countdownValue--;
    if (countdownValue === 0) {
      // when count is down to 0
      clearInterval(countdownTimer); // stopping the timer
      captureImage(); // capturing an image after the countdown
      countdownValue = 4; // resetting the countdown value back to 4
      setTimeout(startCountdown, interval); // 1-second delay before restarting the countdown
    }
  }, interval); // repeat the function at 1-second intervals
}

→ a function to capture and save the images, with a sound that plays when each image is taken.

function captureImage() {
  if (recording) {
    sound1.play(); // playing the sound when an image is captured

    images[captureIndex] = videos[captureIndex].get(); // capturing the image from each of the four video feeds
    captureIndex++;

    // when the four images are taken, recording is stopped and images are saved as a grid
    if (captureIndex >= 4) {
      stopRecording();
      saveImages();
    }
  }
}

→ determining the countdown value which is then displayed (3, 2, 1 only).

if (recording && countdownValue <= 3 && countdownValue > 0) {
  fill(255);
  textSize(200);
  textAlign(CENTER, CENTER);
  text(countdownValue, width / 2, height / 2);
}

→ function to start recording, which is later activated when the button of the camera is pressed, in a “START” state.

function startRecording() {
  if (!recording) {
    recording = true;
    captureIndex = 0;
    images = [null, null, null, null]; // reset the images array to clear previous session
    clearInterval(countdownTimer); // clear the timer from the previous session

    // clearing the video feeds
    for (let i = 0; i < 4; i++) {
      videos[i].hide(); // hide the video to clear the old feed
      videos[i] = createCapture(VIDEO); // create a new video capture
      videos[i].size(width / 3, height / 3); // set size for each video feed
      videos[i].hide(); // hide the video feed
    }

    startCountdown(); // start the countdown before the first image is captured
  }
}

→ function to stop recording, which is activated by the “STOP” message received by Arduino after the twenty seconds have passed.

// function to stop recording
function stopRecording() {
  print("Recording ended");
  if (recording) {
    recording = false;
    clearInterval(countdownTimer); // clear the countdown timer completely
  }
}

→ function to read the serial data from Arduino.

// read serial data from arduino
function readSerial(data) {
  if (data != null) {
    if (data == "START") { // when data from arduino is "START"
      displayStartPage = false; // switch to the photo booth page
      startRecording(); // start recording
    } else if (data == "STOP") { // when data from arduino is "STOP"
      displayStartPage = true; // display start page
      stopRecording(); // stop recording
    }
  }
}

 

Sketch

 

And here is a link to the full screen sketch:

https://editor.p5js.org/alexnajm/full/LVOvvvioq

What I am proud of

I am particularly proud of finally being able to understand how serial communication works. For me, I had a hard time processing it in practice, although in theory it did make sense. Applying it for this project which I made from scratch, as compared to the exercises we did in class, enabled me to better grasp the concept of serial communication.

Additionally, I am proud of how this project has evolved. I had a few ideas in between which truly were not challenging enough. I am not saying that this project is super complex, but it definitely took time and effort to try and understand how everything works in order to achieve this final result.

 

Challenges

I encountered multiple challenges, first, creating serial communication from scratch. Again, it was a bit hard for me to apply the concepts.

Another challenge was getting the feeds and countdown to reset after each session. At first, the images from the previous session remained on the feeds, which means the user couldn’t see a live version but only the images taken. Gladly, I was able to figure it out – same for the countdown.

 

Areas for future improvement

Eventually, I would like to create a better design for the p5 sketch. As of now, I feel like it’s a bit… bland.

I would also like to try to incorporate filters, which the user can choose from before taking the images. This was a bit hard as the images cannot be downloaded with the filter, and I did not want the grid to look different than the images displayed on the sketch.

 

References

https://p5js.org/reference/#/p5/createCapture

https://learn.digitalharbor.org/courses/creative-programming/lessons/using-timers-in-p5-js/

 

IM Showcase Documentation

Leave a Reply