Build Blog: Digital Photo Frame Powered By 500px, Raspberry Pi, and Ruby That Compliments Your Day

Arjun Bali
7 min readJan 11, 2015

--

After a few days of living in my university dorm, I grew jealous of the girls’ rooms upstairs. They had made Residence their home — polaroids and posters covered every inch of their walls while mine were barren. Eventually, I decided to add some character to my dorm, but instead of investing time and money decorating, I used a little bit of engineering…

Here’s how I made a living photo frame that curates social media photo collections appropriate to the time of day and weather:

What I’m using / what you’ll need:

  • Raspberry Pi Model B — $0 at electronics raffle on campus
  • SD Card — $15
  • Faytech 12.1” IP65 Resistive Touch LCD — $0 scavenged from an office
  • USB keyboard/mouse — $0 scavenged from that same office
  • Mini-USB wifi module or ethernet cable — $10 for wifi, or $0 for ethernet from residence services

Setting Up Your SD Card

You’ll need an SD card to boot the Raspbian Operating System (minimum size of 2GB, but I recommend 4GB or 8GB). I bought a cheap Kingston Class 4 microSDHC 16GB card and adapter for my Pi, but make sure you read this guide on compatible SD cards before using one. We’ll be following the NOOBS setup (New Out Of The Box Software) for beginners.

If you’re willing to spend a little more than my poor student budget can afford, check out this SD card that has NOOBS pre-installed.

This video is absolutely phenomenal at explaining how to format your SD card, download NOOBS, install Raspbian, and get the Pi all set up, so I won’t discuss that here. However, in that process, connecting to a display might be tricky:

Display

If your display operates with HDMI, then setup should be a piece of cake — just plug in an HDMI cable. If your display operates with VGA or composite (as my Faytech LCD does), you may have a problem.

By default, the Raspberry Pi will assume you are using HDMI output mode even if no HDMI monitor is detected. If you haven’t yet started the Pi for the first time, you can hold the ‘3’ key (PAL) or ‘4’ key (NTSC) on your keyboard to force composite output. Otherwise, you can still solve this without reinstalling Raspbian from scratch. Plug your SD card into a computer, open the ‘boot’ directory and then find ‘config.txt’. Scroll down to the line that says

hdmi_force_hotplug=1

in the section NOOBS Auto-generated Settings and comment it out (put a ‘#’ symbol in front of it). This comments that line out so HDMI isn’t the default. If the problem persists, read more solutions here. The config.txt file is a pretty important place, so I encourage you to explore the options it gives you.

If you don’t have a display that you plan on using and would like to purchase one, there are many you can find on Adafruit like this one. They come in varying sizes; however, most will require some soldering and a composite male-to-male adapter.

Connecting to the Internet

I used this wifi module from Adafruit, but I experienced an inconsistent connection. This is a typical problem with this module on Raspberry Pi Model B’s without plugging in a powered USB hub, so I resorted to using an ethernet cable I found in residence.

If you’d like the additional functionality of having a hub, by all means get one. Adafruit has an awesome resource on connecting your Pi to the internet.

500px API

Make an account on 500px as a developer, read through the documentation and then register your application. After registering, you should be able to see something like the following when you click “See application details” under your app. Take note of the consumer key and secret for the next section.

Ruby Script

Your Raspbian OS should already come with Ruby 1.9.3 installed. Just to make sure, check what version it’s running by typing

ruby -v 

in the terminal. Although this is significantly outdated, there is no need to worry. You’ll now want to install the 500px gem (without documentation) by running

sudo gem install —no-rdoc —no-ri f00px

You’re probably not going to want to have documentation installed for any gem given the small SD card space. To do this run

echo ‘gem: —no-ri —no-rdoc’ >> ~/.gemrc

You’re going to want to write a script similar to the following, and you can save it in /home/pi/ or in a specific directory for this project if you made one (safer, as the script deletes certain files). Let’s walk through this code — it’s quite simple:

# 500px.rbrequire ‘f00px’
require ‘rubygems’
require ‘json’
require ‘open-uri’
Dir.glob(“*.jpg”).each do |file|
File.delete(file)
end
# After requiring the appropriate files, we have a loop that
# deletes all files in the format .jpg in the working directory.
F00px.configure do |config|
config.consumer_key = “"
config.consumer_secret = “”
end
# Here we configure our connection to the 500px API. Copy the
# consumer key and secret you took note of in the previous section
# and paste them as strings in the appropriate places.
def save(response)
(JSON.parse(response.body))[“photos”].each do |x|
id = x[‘id’].to_s + ‘.jpg’
open(x[‘image_url’]) do |f|
File.open(id,”wb”) do |file|
file.puts f.read
end
end
end
end
# This method iterates through all the photos in the 500px JSON
# response and saves them to the working directory.
def download(pic_type, num=20)
f00px_terms = [‘popular’, ‘highest_rated’, ‘upcoming’, ‘editors’,
‘fresh_today’, ‘fresh_yesterday’, ‘fresh_week’]
weather_terms = [‘cloud’, ‘snow’, ‘sun’, ‘wind’, ‘haze’, ‘fog’]
search_term = if f00px_terms.include?(pic_type.downcase)
‘?feature=’ + pic_type
elsif index = weather_terms.find_index { |word| pic_type.include?(word)}
‘/search?term=’ + weather_terms[index]
else
‘/search?term=’ + pic_type
end

save(F00px.get(‘photos’ + search_term + ‘&image_size=4&rpp=’ + num.to_s))
end
# This method checks to see what kind of pictures you’d like to
# download and then calls the 500px API with the right query
# string.
def gen_term
case Time.now.strftime(‘%H’)
when “06", “07", “08", “09"
term = “sunrise”
when “10", “11", “12", “13", “14", “15", “16", “17"
term = “productive”
when “18", “19", “20"
term = “sunset”
when “21", “22", “23", “24"
term = “night”
when “00", “01", “02"
term = “sleep”
end
term
end
# This method is very optional and basic way to automate
# what kinds of pictures you’d like to see to compliment the
# time of day. It could be made far more complex but is just a
# fun little way of keeping photos somewhat relevant.
def get_weather(yahoo_id)
response = Weather.lookup(yahoo_id, Weather::Units::CELSIUS)
<<EOT
#{response.condition.text}
EOT
end
# This method calls the the Yahoo Weather API to get the current weather in a given location.
download(“popular”)
download(gen_term, 20)
download(get_weather(23396898), 30)
# To get random pictures that are ‘popular’, pass one of the
# following strings based on which measure of popularity you
# prefer.
# [‘popular’, ‘highest_rated’, ‘upcoming’, ‘editors’,
# ‘fresh_today’, ‘fresh_yesterday’, ‘fresh_week’]
# To search a specific tag, just pass a string as that tag.
# To download photos that reflect your time of day, pass in
# gen_term.
# To download photos that reflect the weather outside, pass in
# get_weather() with the Yahoo ID of your location, easily found at
# http://woeid.rosselliot.co.nz/.
# The second argument is the number of pictures you want returned,
# between 20 and 100.
# If no argument supplied, it defaults to 20.

Slideshow

Thanks to the stellar Ruby community, making a slideshow out of these images is a piece of cake. Install pi-slideshow (you may have to start the installation commands with sudo) and then run the program with pi-slides in the directory with all the images. There are plenty of configurable options like image on-screen time but it runs just fine out of the box.

Automated Retrieval of New Pictures

To have a continuously fresh feed every hour on the hour, we’ll use cron jobs.

Add this to your crontab by running

 crontab -e

Then put this at the bottom of the file, specifying the path to the ruby script if I got it wrong:

0 * * * * ruby /home/pi/<YOUR_FOLDER_NAME>/500px.rb

Make sure you hit ‘enter’/‘return’ after entering your line.

If for some reason the cron job does not work, I highly recommend following this guide, which discusses another way of setting up cron jobs. If the method in the guide works, just paste the cron job we wrote above in the same ‘mycronjob’ file the guide discusses; just put it one line below the one they write, and everything should be okay.

Little Things

Raspberry Pi Resolution

You may have noticed a black border around the main Raspberry Pi output, or low resolution overall.

Follow either of the following two videos:

If those don’t help, then resort to fiddling with the overscan values in /boot/config.txt and rebooting.

Customization

You will also want to disable sleep and enable auto-login.

Troubleshooting

For all other problems reach out to me on Medium or Twitter and I’d be glad to help out. For other problems http://elinux.org/RPi_Hub is a goldmine.

Part 2 — Coming Soon

I was recently inspired by this tutorial, a similar concept except involving Python, Flickr/Instagram, and a PIR Motion Sensor. While I don’t intend on using the former two, the latter I am working on! Expect Part 2 with the motion sensor and more soon!

Note: while I’m not using the touch capability of the display right now, I’m challenging myself to do something cool with it in Part 2.

Unlisted

--

--

Arjun Bali

Thinking about what's next | Prev: Co-founder at Sodatone (music analytics + deep learning, acquired by Warner Music) | @UWaterloo engineering