I forget how I discovered HDEV, but now that I’ve found it, I can’t get enough! What can I say, I’m a space geek. HDEV stands for High Definition Earth Viewing. It’s an experiment to test the rate at which the image quality from an HD camera degrades over time while in space. And while it’s up there, they stream that video online for free. But you don’t have to be a NASA-nerd to appreciate HDEV. The views are truly incredible!

Which is why I came up with the idea for this project: a digital picture frame that live streams the video from HDEV, 24/7. I have a Raspberry Pi Zero laying around, it came free with the MagPi Vol 40 (which has an article about my previous project, my Magic Mirror). This sounds like the perfect project to put it to use.

Before I begin, here are some screenshots I took. So I’m gonna need the Raspberry Pi Zero, an LCD screen, a picture frame big enough to fit all of this, and don’t forget the wifi USB and various cords and adapters. Here’s the full parts list that I used in this project:

Adafruit HDMI 4 Pi: 5″ Display (no Touch) w/Mini Driver – 800×480 + USB port power supply – $59.95

Raspberry Pi Zero w/ mini HDMI to HDMI adapter – $7.95

Monoprice Ultra Slim Series High Speed HDMI® Cable, 1ft Black – $5.23

Pictureframes.com SA5 Black Frame (6 1/2″ x 4″) w/ Clear Acrylic & Foamcore Backing – $50.93

Edimax Wifi USB Adapter – $8.99

USB to micro USB adapters – $4.43

Micro USB cord – $4.99

USB extension cord – $5.49

USB Wall Charger – $5.99

Total price – $153.95

This is with all new components. I had some of this laying around already, some had been used in other projects.

Once you have all of your components you can start putting them all together.



Here’s what the picture frame looks like on the inside. It has four metal tabs that are used to keep the foam core backing in place. But luckily enough the foam core is just about the same thickness as the LCD, so you can use those tabs to keep the LCD in place. I used the LCD’s spec sheet from Adafruit to get the measurements of it so I could order the right size frame. As for the depth of the frame, it’s about 1/4″. I just kinda guessed on that part and hoped that all components would fit inside. Don’t forget take all of the stickers and protective film off of the acrylic sheet before you insert the LCD screen.

The LCD driver board comes with the keyboard (control buttons) and power cable already connected, but I removed them to make it easier to work with. I chose the mini driver because it doesn’t have the big VGA connector, only HDMI. I’m not sure there would be room for the VGA connector inside the frame. I also added some spacers to the driver board to keep any of the components from shorting out on the metal back of the LCD. These spacers also keep the LCD ribbon from bending too sharply. I bent the ribbon cable in a sort of ‘S’ shape underneath the driver board, and placed the board at the bottom of the frame. I put some hot glue on the spacers to keep them in place on the LCD.

After I got the LCD driver in place, I started trying to figure out where all of the other components would go. I soon realized that all of the cables and connectors would be too much and wouldn’t be able to fit in this small space. Micro USB to USB cable to power the Pi, USB power cable for the LCD driver, a USB splitter to allow a single USB cable to power the whole thing, USB extension cable that acts as the power cable for the whole thing, and the HDMI cable. There’s just too many cables connecting into each other and too much excess cable, it won’t fit. The only connectors it actually needs are one micro USB, one USB, and the connector to power the LCD driver. I decided the best solution would be to splice a couple cables together to make a single cable that can power both devices.

I had to break out the multimeter because the micro USB cable I got had some sort of reversible connector and used non-standard wire colors, so I couldn’t be sure which wire was which. But I got that figured out and soldered all of the cables together, and added a bit of electrical tape to keep everything separated. Put the cable into the frame, gave it a quick test power up to make sure the cable works. Now with this cable there’s a whole lot more room inside the frame.

That’s probably the toughest part of the build, which isn’t that tough. Now just add the rest of the cables and components, and power it up. I got lucky with this too: with this LCD you need to plug in the keyboard at least once to turn on the LCD. But after that the LCD will revert to its last power state after a power cycle. (meaning it will turn itself back on if it was on when it got unplugged)

To make room for the power cable I cut a small square out of the corner of the foam core, just big enough for the cord to fit. Then I hot glued the cable into the corner to prevent it from moving around and damaging the foam core. I tried to use a staple gun to pin it to the corner, but I couldn’t get a good staple in a 45 degree shot in the corner.





I used the clips that came with the picture frame to keep the foam core in place. It just so happens that all of the components fill up just enough room inside the frame that the foam core can lay directly on top of them and sit flush with the back of the frame. Not that that matters too much, because you won’t be watching it from this side.

That’s it. The hardware is done! Now for the software.

I used the latest version of Raspbian Lite, and then expanded the file system and configured wifi. Then updated everything that’s already on it:

$ sudo apt-get update $ sudo apt-get upgrade

In order to display the HDEV stream I started with a script from Miguel Grinberg’s blog. It uses livestreamer and omxplayer, so I installed those.

$ sudo apt-get install omxplayer $ sudo apt-get install python-pip $ pip install livestreamer

Then the script looks like this:

#!/bin/bash while true do livestreamer http://ustream.tv/channel/iss-hdev-payload mobile_480p --player omxplayer --fifo --player-args "--win \"0 0 800 480\" {filename}" done

Notice that the livestreamer command is inside a while loop. This is because sometimes the video crashes, but the while loop brings it back up once it goes down. But there’s a few seconds in between where it just shows the command line. So I took a screenshot of the ‘Please wait’ screen that is often displayed on the HDEV stream, and displayed that image behind the omxplayer video using fbi. Here’s the screenshot if you want to use it yourself. (For those that are interested, I used raspi2png to take a screenshot of the framebuffer.)

#!/usr/bin/env bash while true do livestreamer http://ustream.tv/channel/iss-hdev-payload mobile_480p --player omxplayer --fifo --player-args "--layer 1000 --win '0 0 800 480' {filename}" done & sudo fbi -T 1 --noverbose --fitwidth --autoup /home/pi/ISS-Display-Loss-of-Signal.png

And we could leave it just like this, add it to rc.local so it starts up at boot. And it would look great! But I wanted a bit more, I wanted a tracker graphic to display where the ISS currently is over earth. I looked online at various ISS trackers, but most of them are JavaScript or some type of webpage and I can’t get that to display live with omxplayer. But then I found Heavens-Above. They have a really awesome image displayed right on their homepage that shows where the ISS is above the earth, all in one single simple image. I also found that you can even change some parameters in the URL and change the size of the image.

Trying to figure out how to display this image in the frame buffer (over the CLI), is a bit tricky though. I can’t use fbi because it displays in full screen and would block out the HDEV stream. Omxplayer would work, it has a layer argument so I can make sure that it stays above the HDEV stream, plus I can adjust where on the screen it’s displayed. But omxplayer can’t display images… But if I convert the image to a video, I could display that. I found this can be done with avconv. I installed avconv with libav-tools:

$ sudo apt-get install libav-tools

Then I created a script where it would download the image, create a one minute video from it, and display that while it repeats the process so that by the end of the one minute there is a fresh video to display. But this didn’t quite work out. It turns out that it takes a little bit longer than one minute to create a one minute video. So instead I decided to create a ten second video and repeat it six times. Here’s what it looks like now:

#!/usr/bin/env bash while true do livestreamer http://ustream.tv/channel/iss-hdev-payload mobile_480p --player omxplayer --fifo --player-args "--layer 1000 --win '0 0 800 480' {filename}" done & sudo fbi -T 1 --noverbose --fitwidth --autoup --autodown /home/pi/ISS-Display-Loss-of-Signal.png & wget -O /tmp/ISS-Display-image1.png "http://www.heavens-above.com/orbitdisplay.aspx?icon=iss&width=150&height=150&satid=25544" avconv -loop 1 -i /tmp/ISS-Display-image1.png -tune stillimage -t 10 -y -r 5 /tmp/ISS-Display-video1.mp4 while true do (wget -O /tmp/ISS-Display-image2.png "http://www.heavens-above.com/orbitdisplay.aspx?icon=iss&width=150&height=150&satid=25544"; avconv -loop 1 -i /tmp/ISS-Display-image2.png -tune stillimage -t 10 -y -r 5 /tmp/ISS-Display-video2.mp4) & (omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video1.mp4 --layer 1100 --win "350 0 450 100" ) & sleep 60 (wget -O /tmp/ISS-Display-image1.png "http://www.heavens-above.com/orbitdisplay.aspx?icon=iss&width=150&height=150&satid=25544"; avconv -loop 1 -i /tmp/ISS-Display-image1.png -tune stillimage -t 10 -y -r 5 /tmp/ISS-Display-video1.mp4) & (omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100" & sleep 9; omxplayer -o hdmi /tmp/ISS-Display-video2.mp4 --layer 1200 --win "350 0 450 100") & sleep 60 done

It looks ugly, really ugly. I know. It’s just what I could come up with. I’m looking into a way to create a video feed that I can pipe the update images into every minute, but I don’t have it yet.

I saved the script as ‘ISS-Display.sh’ in my home directory and made it executable:

sudo chmod +x ./ISS-Display.sh

Then I added this script to rc.local so it starts up at boot. Livestreamer does not like to run as root, so I decided to run the whole script as the user ‘pi’. I did this by using the sudo command, I added this to /etc/rc.local right above the ‘exit 0’ line:

sleep 15 sudo -u pi /home/pi/ISS-Display.sh >/dev/null 2>&1 &

That’s it! Reboot to test the startup script. It starts up pretty quick too because it doesn’t have to wait for X to start.