Build a Photobooth with an Arduino Yun, a Webcam and Dropbox

The Arduino Yun is an Arduino with built-in WiFi and Linux. With the Yun, not only can you do all the hardware hacking that you’d expect from an Arduino, but you can also connect it to the Internet and run programs in your favorite scripting language.

In this tutorial, we’ll build a proof-of-concept for an Arduino powered photo booth to serve as the foundation for teaching my dog to send me selfies using Twilio MMS. The goal is to:

  • take a picture with a webcam plugged into the Arduino Yun
  • upload the image to dropbox using Python
  • trigger these actions via the press of a button

The end result is going to look something like this:

Getting Started

This tutorial builds on our Getting Started with the Arduino Yun tutorial, which covers:

  • How to format your SD card for use in the Yun
  • How to upgrade to the latest version of OpenWRT-Yun
  • How to install the Arduino IDE
  • How to run your first sketch on the Yun

Assuming you’ve completed those steps, this photo booth tutorial will take you about 30 minutes. The ingredients you’ll need are:

Webcam and the Arduino Yun

It’s surprisingly easy to use a webcam with an Arduino Yun. Any webcam that uses the UVC protocol (most of them do) will work. If you don’t have a webcam lying around, check out the Logitech C270 ($23 on Amazon).

To start:

  • plug the webcam into your Arduino Yun’s USB slot
  • insert your microSD card into the Yun
  • SSH into your Arduino Yun

If you can’t SSH into your Yun or haven’t formatted the microSD card to work in your Yun, check out our getting started with the Yun guide.

Once connected to your Yun, you’ll need to

  • upgrade the OpenWRT package manager
  • install drivers for the webcam
  • install fswebcam, “a neat and simple webcam app.”

From the command line:

Then cd into the root of your SD card:

We’ll run the fswebcam utility with two parameters:

  • where to save the file
  • the resolution at which to shoot

You’ll see a bunch of text, some of which looks like an error message. Disregard it. So long as you see Writing JPEG image to pic.jpg , you’re fine.

take-a-picture

If you want to verify that that file really is a picture, you can pop the SD card out of your Yun, plug it into your computer and view it there.

Dropbox and Arduinos

You might be saying, “But Greg, what good is a picture on the Yun if I have to pop out the SD card just to look at it?” I hear ya. Let’s get those pictures off the Yun and into the cloud.

To interact with the Dropbox API, we need to create a new Dropbox app. Sign up for a Dropbox account if you haven’t already, then visit the create apps page on the developer console. Then:

  • Select Dropbox API app
  • Select “Files and datastores only”
  • Select “Yes – My app only needs access to files it creates.”
  • Give your app a name (it has to be unique to the Dropbox world)
  • Click Create

dropbox

Once you create your app, you’ll need to generate an access token

dropbox-access-key

Keep that tab open. We’re going to need that access token in a few minutes.

Install pip on the Arduino Yun

Let’s write some code to interact with the Dropbox API. This is when the power of the Yun shines. Instead of working with APIs in the Arduino programming language, you can write programs in a scripting language with which you’re more familiar. Here we’ll do it in Python since that’s what comes preinstalled on the Yun, but you could install Ruby or Node if that’s your jam.

Dropbox has an easy to use Python SDK. Before we install that though, we’ll need to install pip, a Python package manager.

From the command line:

And that’s it.

By default, pip  would install Python packages to the Yun’s onboard memory. However, the Arduino Yun docs carry an ominous warning that says, “You’re discouraged from using the Yún’s built-in non-volatile memory, because it has a limited number of writes.” Let’s install the Dropbox SDK to the SD card instead.

That requires three steps:

  • Create a new directory on the SD card for our Python packages
  • Tell Python to look for packages there
  • Force pip to install the Dropbox SDK there

Plug your SD card back into your Yun if you haven’t already. Then create a directory:

Now let’s edit our /etc/profile  and set a  PYTHONPATH environment variable so that Python knows to look here.

You’ll see several lines that start with export. Move the cursor down below those lines, then press i to enter insert mode. Then paste this:

Press  esc to go back to command mode. Type :wq  to save the file and quit vim. Then, from the command line, reload your environment by typing:

source /etc/profile

Finally, install the Dropbox SDK with a flag to install to our newly created directory:

python-path

Upload a file to Dropbox from the Arduino Yun in Python

Your Arduino Yun expects code to live in a directory on the SD card called  arduino. Let’s create that directory and navigate there:

Now let’s create a new file and edit it in vim:

Then press i  to enter insert mode.

The code we’re about to copy and paste will:

  • import the dropbox and datetime libraries
  • use datetime to create a unique filename for each picture
  • initialize a Dropbox client with our access token
  • open the picture taken by our webcam
  • save the file to Dropbox with our unique filename
  • print the response from the dropbox API

Make sure you replace YOURACCESSTOKENGOESHERE  with the access token you generated on the Dropbox dashboard. Then hit  esc  and type :wq  to save the file and quit.

(If you’d like more detail on what’s happening in those last four lines, check out Dropbox’s excellent documentation on using Dropbox Core API in Python.)

Let’s see if it works. Open your apps folder in Dropbox and click into the folder for your newly created app. It should be empty. Now run your Python script from the terminal:

Now check that Dropbox folder again.

upload-to-dropbox

Upload a file with an Arduino Sketch

If all you wanted to do was take a picture with a webcam and upload it to Dropbox, you wouldn’t need an Arduino. The reason we’re doing this on the Yun is so that we can do some hardware hacking along with our software writing.

To interact with the pins on the board, we are going to have to write some code in the Arduino programming language (oddly, it has no official name other than that). So let’s first write a sketch that will trigger the shell command to take a picture and the Python script to upload a picture, then we’ll deal with the button.

Open the Arduino IDE and create a new sketch. At the top of the sketch, include the bridge and process libraries:

The Arduino Yun has two processors: the “Arduino chip” which controls the pins and interfaces with the hardware and runs, and the “Linux and WiFi Chip.” These two chips communicate with one another via the Bridge library. The  Process  library is how we execute Linux commands from Arduino code.

Your sketch comes pre-populated with setup()  and loop()  functions. We’ll come back to those in a minute.

First, let’s write the function to take a picture:

Then a function to upload the file from the Arduino to Dropbox:

Pretty simple, huh?

Now back to our setup()  and loop() . The setup() runs one time after you upload the sketch to your Arduino.

Our setup()  will simply initialize the bridge:

Once  setup()  is finished,   loop() runs continuously. Ours will take a picture, upload a picture, then do it again. The   loop() can run thousands of times per second, but our synchronous Linux processes will slow it down considerably (if you ever need to slow it down more, you can introduce a  delay()).

That’s it. Click the upload button in the top left of the Arduino IDE to push your sketch to the Arduino. Then open your Dropbox folder, smile for the camera, and you should see something like this:

lots-of-pics

Photos at the push of a button

Now that our functions work, lets trigger them with a button instead of running an infinite loop. For our circuit we’re going to need:

  • Breadboard
  • Three jumper cables
  • 10K Ohm resistor
  • Momentary tactile pushbutton switch

The general idea is that we have a circuit running from the 5V pin, through a button, and back into GND. When the circuit is completed — i.e. the button is pressed — we send a signal to PIN 7.

This circuit is based on an example from Massimo Banzi’s excellent introductory book called Getting Started with Arduino. Here’s what it looks like:

arduino-circuit-front arduino-circuit-toparduino-circuit-close-up

Once you’ve built your circuit, we’ll update the sketch with an additional flourish — instead of having the button press take a picture immediately, we’ll have it flash the onboard LED three times to tell us to get ready, then take a picture.

The first two lines of your sketch currently are includes . Below those, add two constants to identify the LED and the pin telling us if the button has been pressed:

In the setup() , add these two lines to prepare those pins for output and input, respectively:

Then create a new function at the end of your sketch to blink the LED — turn it on for half a second, then off for a tenth of a second — and do this three times:

Finally, replace your loop()  with code that will read from the pin we’ve identified as BUTTON . If it’s HIGH (i.e., current is running through it) then:

  • blink the LED
  • take a picture
  • upload that picture to Dropbox.

Upload this new sketch to your Arduino, press your button and watch that Dropbox fill up.

Next Steps

Full disclosure — I started working on this series of Arduino Yun tutorials because I wanted to teach my dog to send selfies. So far we’ve managed to set up an Arduino Yun, take pictures at the push of a button, and ship those pictures to the cloud. In our next tutorial, we’ll learn how to send SMS and MMS from the Arduino Yun.

What about you? Maybe you could:

  • Stream video from the webcam
  • Trigger the camera with a motion sensor instead of a button
  • Store data from other input devices, such as environmental sensors or a keypad
  • Build a real-deal photo booth

When Arduinos first came out, the possibilities seemed pretty wide open. Now that you can run scripts from your favorite programming language and connect to the Internet, the possibilities seem limitless. I’d love to hear what you’ve built with your Yun and I’d be happy to help if you run into any problems. You can leave a comment below or drop me an email at gb@twilio.com. And if you’ve enjoyed this post, you may want to follow me on Twitter.

Happy hacking.

Resources

These resources were incredibly helpful as I wrote this tutorial:

  • Markus

    Thank you so much, helped me a lot!

  • Itisnotgolden

    This is super intriguing to me. Do you think it would be possible to snap a series of 3-5 photos in succession? I want to use this in a haunted house that we do for the cub scouts. But I want it to snap a few photos in a row so we get the “best” one and the clientele may make a donation to get the photo.

  • Rachel

    Could I take a camera out of a phone and use that instead of a webcam?

  • Alex Mattson

    great post, but would using this (https://www.arduino.cc/en/Tutorial/ExpandingYunDiskSpace) be easier for leveraging space on an SD card?

  • bobbyperu

    Thank you very much for sharing this. I appreciated it a lot.. coudnt make sense of the dropbox API tutorial but this helped to get me starting :)

    • bobbyperu

      I do have one question, hope you can help: can you tell me how to make
      it possible in your code to send multiple .jpg files ? I cannot get it
      done ..

  • Wazqar

    Hello, Thanks for your post. it helped me a lot. But i have a question when write this line of code “opkg install kmod-video-uvc” in the terminal of my macbook it says “* opkg_install_cmd: Cannot install package kmod-video-uvc.” so could you help me with fixing that problem. Thanks a lot.

  • Simon Schvartzman

    Many thanks for this excellent tutorial.
    I’ve hit the wall though when running:

    root@Yun28:~# opkg install distribute

    I get:

    Unknown package ‘distribute’.
    Collected errors:
    * opkg_install_cmd: Cannot install package distribute.

    What am I doing wrong? Help please, I’m have no LInux knowledge…

    Thanks in advance

    • Simon Schvartzman

      Solved: was just a matter up updating the Yun with the latest LInux image.

      • Glad to hear that. Thanks for following up here.

        • Simon Schvartzman

          Greg, I hit another wall, any hints as what could be wrong:

          root@Yun28:/mnt/sda1/arduino# python upload-to-dropbox.py
          Traceback (most recent call last):
          File “upload-to-dropbox.py”, line 2, in
          import dropbox
          ImportError: No module named dropbox
          root@Yun28:/mnt/sda1/arduino# pip install –target /mnt/sda1/python-packages dropbox
          Collecting dropbox
          /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#snimissingwarning.
          SNIMissingWarning
          /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
          InsecurePlatformWarning
          Using cached dropbox-7.3.1-py2-none-any.whl
          Collecting six>=1.3.0 (from dropbox)
          Using cached six-1.10.0-py2.py3-none-any.whl
          Collecting urllib3 (from dropbox)
          Using cached urllib3-1.21.1-py2.py3-none-any.whl
          Collecting requests!=2.6.1,>=2.5.1 (from dropbox)
          Using cached requests-2.17.3-py2.py3-none-any.whl
          Collecting idna=2.5 (from requests!=2.6.1,>=2.5.1->dropbox)
          Using cached idna-2.5-py2.py3-none-any.whl
          Collecting certifi>=2017.4.17 (from requests!=2.6.1,>=2.5.1->dropbox)
          Using cached certifi-2017.4.17-py2.py3-none-any.whl
          Collecting chardet=3.0.2 (from requests!=2.6.1,>=2.5.1->dropbox)
          Using cached chardet-3.0.3-py2.py3-none-any.whl
          Installing collected packages: six, urllib3, idna, certifi, chardet, requests, dropbox
          Killed
          root@Yun28:/mnt/sda1/arduino#

          • Simon Schvartzman

            Greg, sorry for bothering you but as I said before I am Linux Illiterate…I guess the hint should be on the following but I don’t know what to do:

            root@Yun28:~# pip install –target /mnt/sda1/python-packages dropbox
            Collecting dropbox
            /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#snimissingwarning.
            SNIMissingWarning
            /usr/lib/python2.7/site-packages/pip-9.0.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
            InsecurePlatformWarning
            Using cached dropbox-7.3.1-py2-none-any.whl
            Collecting six>=1.3.0 (from dropbox)
            Using cached six-1.10.0-py2.py3-none-any.whl
            Collecting urllib3 (from dropbox)
            Using cached urllib3-1.21.1-py2.py3-none-any.whl
            Collecting requests!=2.6.1,>=2.5.1 (from dropbox)
            Using cached requests-2.17.3-py2.py3-none-any.whl
            Collecting idna=2.5 (from requests!=2.6.1,>=2.5.1->dropbox)
            Using cached idna-2.5-py2.py3-none-any.whl
            Collecting certifi>=2017.4.17 (from requests!=2.6.1,>=2.5.1->dropbox)
            Using cached certifi-2017.4.17-py2.py3-none-any.whl
            Collecting chardet=3.0.2 (from requests!=2.6.1,>=2.5.1->dropbox)
            Using cached chardet-3.0.3-py2.py3-none-any.whl
            Installing collected packages: six, urllib3, idna, certifi, chardet, requests, dropbox
            Killed
            root@Yun28:~#

        • Dennis Carcamo

          hey, I want to do this project but I´m afraid to have some dificulties and not able to have some support, could you please help me?

  • Simon Schvartzman

    Really disappointing. this is a great tutorial but it doesn’t work. As described on a previous post I can’t install the Dropbox SDK. The command

    pip install –target /mnt/sda1/python-packages dropbox

    returns several errors that i wasn’t able to overcame. I’ve poste here, at Arduino forum and also at Dropbox forum and got no answer from any of those.

    Really frustrating experience!

    • Hey Simon, so sorry for the frustrating experience. Want to drop me an email at gb@twilio.com and we’ll see if we can get it sorted?

  • Pablo Sanchez Egido

    Hi! I’d like to know where have you bought those cables… because the ones I have are different and more difficult to catch and use. I’d also like to know where have you bought the base where arduino yun and breadboard lay.
    Thanks!

  • vish

    How many frames per second?