Learn how to build a tiny self-contained picture frame that syncs images with your choice of supported cloud storage providers. The frame self-updates for any new PiFrame code and supports tapping on the screen for navigating forward and back through your photos.
We had a kid and my extended family wants to stay updated with the latest and greatest kid pictures. I wanted to give them something that would always stay up-to-date as I added or removed pictures and required zero setup (other than WiFi info) from family members who might not be as tech-savvy as I am. Ideally, they plug in the device and it just works. On my side, I wanted to be able to drop some photos somewhere and have them picked up automatically by the photo frame. While there are many frames that do allow for this type of behavior, I decided not to take a chance on them because they all probably talk to some foreign server about my photos and frame usage as well as leaking PII. Furthermore, once I saw I could get a tiny screen, I loved the idea of having a little picture frame that rotated through a bunch of gifs on my desk.
- Materials
- Which Pi?
- The screen
- How-to
- Installing and configuring all required software
- Configure the desktop to be a kiosk
- Optional: Optimizing power usage and reducing heat
Specific details about each material is below, but hereâs a quick reference list.
- Pi 3B or 3B+
- Micro sd card with the latest and greatest Raspbian installed. I use a 32gb card. Any size is fine, just make sure it doesn't fill up.
- 3.5 inch touch screen with case.
- You can use the official 7â screen, in-fact I use that for one frame. It also means you get to skip the LCD driver setup section of this guide.
Note: There are a ton of tutorials online that show how to get your downloaded Raspbian image onto an sd card, so Iâll be skipping the details on that. Personally, I use a mac, so I downloaded from https://www.raspberrypi.org/downloads/raspbian/ and then used Etcher (https://www.balena.io/etcher/) to image it to an sd card.
The 3B is great- it uses less power and doesnât seem to get as warm, but it lacks the dual-band 820.11ac WiFi that the 3B+ has. Iâve used both for this, so really, itâs whatever you want. Also, in an attempt to reduce heat and power usage, we will be adjusting the CPU speed as part of this guide. Overall, the 3B is my personal preference since it runs cooler, I donât need a fast internet connection, and seems to draw less power. These folks have done some comparative tests between the 3B and 3B+ that confirm lower power draw. That being said, in order to maximize compatibility for my family, Iâm choosing to send them 3B+âs.
The screen is an interesting beast. There are a number of 3.5 inch screens that connect in a couple different ways. The preferred screen connects directly to the Pi as a hat (uses SPI). You donât need to connect anything else, and touch also JustWorks(â˘). There are other 3.5 screens that require you connect the screen to the Pi with a special small HDMI part. While those are probably better (less screen lag), I havenât been able to find a case that looks clean and professional-ish for my family that has room for the weird HDMI part. if you want to design a 3d-printed one, Iâd happily print one out and test for you đ. The particular touchscreen I chose is sold together with a stylus, 3 heat sinks, a terrible screwdriver, and an equally terrible pair of tweezers. The quality of the LCD is meh, but it works.
Before you go and power it on, youâll want to enable SSH. Plug the SD card into your computer and navigate to the volume labeled âbootâ. Create a file named âsshâ. If youâre using a Mac, you can also do this in the terminal:
touch /Volumes/boot/ssh
Now eject the media.
Put your sd card with Raspbian on it into the Pi. You can also go ahead and put the heat sinks on that were included and then place the Pi in the case. You'll want to screw it in with the 4 included screws. After, put the LCD hat on the Pi and close it all up.
If you have ethernet available, plug it in.
If you have an HDMI monitor, a USB keyboard, and mouse available, plug them in. If you donât, you will need to plug the Pi into your router using an ethernet cable so that you can use SSH to continue the setup. If you have a screen and keyboard plugged in, go ahead and power on the Pi.
If you connected by ethernet and donât have a keyboard, you canât easily find out your IP address to SSH into. If you have access to your router, you can check the DHCP clients. Look for a MAC address that starts with B8:27:EB
this is likely the pi on your network.
You can login using:
ssh pi@<ip address>
Note: the password is raspbian
Go ahead and open open up a terminal, there should be an icon in the menu bar for that.
There are a few things youâll want to do right away:
- Change the password:
passwd pi
- Use ssh public key auth so you donât have to use the password anymore. A good how-to, but make sure you do this locally, not on your pi.
- While they suggest you use a password on your private key, I donât, that way itâs easier for me to login (no password required at all)
Once youâve created your keys, you can use
ssh-copy-id pi@<Pi address>
To copy over the key from your local machine to your Pi. From here on out, you won't need to enter the password for the frame if you SSH into it đđ
Caveat: If youâre using a USB keyboard, mouse, and HDMI monitor, I would skip this step and come back to it after everything else is done. I donât think you can use an HDMI monitor with your LCD screen at the same time, and it's much nicer to use an external monitor to finish setup than it is to use SSH, but that's my two cents.
Grab the drivers for your LCD hat.
cd ~
git clone https://github.com/goodtft/LCD-show.git
Enable the scripts to be executable
chmod -R 755 LCD-show
I just chmod
the whole directory recursively, it's not best practice and you can be more picky about this if youâd like, but in practice this wonât matter so #YOLO đ¤.
Run the install script, reminder: I donât think you can use your HDMI monitor at the same time.
sudo ./LCD-show/MHS35-show
At this point, the device will reboot and youâll see the Raspbian boot screen on the LCD đ
If the screen is rotated in a direction you donât like (I prefer my frame to be in portrait), you can change that, but warning: it reboots after you run it, so be sure you thatâs ok before you run the command:
. ~/LCD-show/rotate.sh 270 (or 90/180)
Youâll probably want to get rid of the mouse cursor when itâs not in use, the menu bars, the splash screen as the desktop manager loads, the screensaver, and disable power-saving features that turn off the screen. This way the Pi boots directly into a super clean desktop that doesnât obviously allow you to do anything (other than loading up your picture frame).
Install unclutter, this makes the mouse pointer disappear when not in use.
sudo apt install -y unclutter
Install chromium, this will be what displays your pictures in borderless mode.
sudo apt install -y chromium-browser
Create configuration folder.
mkdir -p ~/.config/lxsession/LXDE-pi
Create autostart file- this gets run every time your desktop manager boots up.
nano ~/.config/lxsession/LXDE-pi/autostart
Add the following to the autostart file:
@unclutter -idle 0
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@xset s off
@xset -dpms
@xset s noblank
@chromium-browser --disable-infobars --incognito --kiosk http://localhost/
Save the autostart file.
In order to hide the đď¸(Trash) icon or any mounted filesystem icons, youâll need to:
nano ~/.config/pcmanfm/LXDE-pi/desktop-items-0.conf
And set the following values
show_trash=0
show_mounts=0
For wireless networking, youâll want to add your own networks as well as those of your family.
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
And add the following:
network={
ssid="My WiFi Name"
scan_ssid=1
key_mgmt=<encryption type (e.g., WPA-PSK)>
psk="<my network password>"
}
If you want to add multiple networks, duplicate this block, including the ânetwork=â
portion and edit it. Thereâs no need for commas between the networks, just literally copy/paste the block. The order of WiFi searching is top-down. If you want to test this, reboot the Pi and unplug your ethernet. Youâll need to then go back to your router and find your IP address again. From here on out, you can SSH into the PI using its WiFi.
I use rclone to sync images from BackBlaze down to my Pi. It supports a bunch of providers including s3 and Google Drive. I was already using BackBlaze. If I werenât, Iâd probably suggest s3.
sudo apt install -y rclone
This will configure rclone for BackBlaze, the steps are very similar for other providers. The rclone website provides a bunch of help if you need it. Hereâs what I did:
rclone config
This command presents you with a setup flow asking the following questions (for BackBlaze, in my case)
Name:
This is the name of your rclone configuration. I chose GifsTallConfig
because my screen will be tall, and I want to use the tall gif bucket I set up.
Choose a number from below, or type in your own value:
I picked 5
(for BackBlaze, there's a list that displays and you can pick from it).
Application Key ID:
This came from my BackBlaze Bucket configuration.
Application Key:
This also came from my BackBlaze Bucket configuration.
hard_delete:
true
(so when I update the bucket, it deletes the old files from my pi.
Edit advanced config?:
no
Is this OK?:
Yes
To test this setup, you need to know the specifics of the buckets you set up on BackBlaze. I created one on BackBlaze called GifsTall
. So Iâll tell rclone to use the config GifsTallConfig
that I just setup above, with the new remote bucket named GifsTall
to pull down the contents of that bucket to where apache will be serving images from /var/www/html/img/sync
, but first I must create this directory on my Pi:
mkdir -p /var/www/html/img/sync
Now I can initiate the first sync:
rclone sync "GifsTallConfig":GifsTall /var/www/html/img/sync
This should complete successfully if you used the correct rclone config and BackBlaze bucket.
sudo apt install -y apache2
Once that completes, youâll need to link the apache cgi mod so we can run some code that generates a list of images to display when the webpage loads.
sudo ln -s /etc/apache2/mods-available/cgi.load /etc/apache2/mods-enabled/
Copy over the available configuration into the enabled folder.
sudo cp /etc/apache2/conf-available/serve-cgi-bin.conf /etc/apache2/conf-enabled/
Since weâre only going to serve one webpage and one cgi script, we can simplify the config by editing:
sudo nano /etc/apache2/conf-enabled/serve-cgi-bin.conf
Find the the following:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
Change that so it references the path where the frame cgi script will exist:
ScriptAlias /cgi-bin/ /var/www/html/cgi-bin/
<Directory "/var/www/html/cgi-bin">
Double check you updated the above two /usr/lib/cgi-bin/
entries to /var/www/html/cgi-bin/
.
Change the owner of your website to the user pi
so you donât need to sudo all the things all the time.
sudo chown -R pi /var/www/html
Delete the preinstalled index.html test website
rm /var/www/html/index.html
Now that weâve configure Apache and mod_cgi, weâre going to be using that with Ruby. The best way Iâve found to install Ruby is with rbenv. There are a lot of benefits to using rbenv.
Install rbenv
sudo apt install rbenv -y
rbenv init
echo 'eval "$(rbenv init -)"'>> ~/.bashrc
source ~/.bashrc
rbenv works best with the ruby-build
plugin, so let's make a directory for it and then install the plugin:
mkdir -p "$(rbenv root)"/plugins
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
Install a recent Ruby version, I use 2.5.5, this takes a while so put some tea đľ on.
rbenv install 2.5.5
When finished installing ruby 2.5.5, set it as global:
rbenv global 2.5.5
git clone https://github.com/taquitos/PiFrame.git /var/www/html/.
If you are SSHâd into the Pi, you can attach to the display and launch chromium to test it all out:
export DISPLAY=:0
chromium-browser --disable-infobars --incognito --kiosk http://localhost/
This should load up your images that you synced in the rclone steps above! If it doesn't you might have missed a step.
Once everything is all set up and working, you can use cron to sync your images and your code. Specify that you want to use nano
as your crontab editor (optional), and then launch the editor:
export VISUAL=nano; crontab -e
Add the following
15 * * * * rclone sync "GifsTallConfig":GifsTall /var/www/html/img/sync >/dev/null 2>&1
0 */12 * * * cd /var/www/html; git pull origin master >/dev/null 2>&1
The first line syncs your images every 15 minutes, and the second syncs the PiFrame
code with GitHub every 12 hours.
Want to change the default desktop background from the pre-installed one? Get yourself an image that is 480x320px, and then copy it over to the Pi using SCP:
scp <folder-with-background>/background.jpg pi@<Pi IP address>:/home/pi/
In my case, this was:
scp ~/background.jpg pi@10.0.1.38:/home/pi/
Next, SSH into the pi and run:
export DISPLAY=:0
pcmanfm --set-wallpaper="/home/pi/background.jpg"
Note: The desktop is only shown for a few seconds while the device is finishing loading up chromium-browser. Itâs a nice touch to do this, but really doesnât matter.
There are a few things you can do to attempt to reduce the amount of power you use and heat generated. By editing/adding some values in the /boot/config.txt file, we can configure our Pi to reduce the max speed, and also decrease the minimum speed. In this example, I'm using a pi3 B and decreasing the maximum clock speed by 200mhz (1200mhz to 1000mhz), and decreasing the minimum clock speed on pi3 B from 600mhz to 400mhz.
Add in the following lines to /boot/config.txt
(make sure no duplicate lines exist):
arm_freq_min=400
arm_freq=1000
Now reboot the pi (sudo reboot
) and youâre done đš!