This hack was featured on Hackaday.com on 01/08/2014
This hack was featured on Adafruit.com on 01/10/2014
At the 2013 Open Hardware Summit that I attended a few months ago, all attendees were given a “BADGEr,” a unique ePaper badge that displayed our credentials, showed the conference schedule, etc. Of course, since this was the OPEN Hardware Summit, the BADGEr (designed by the awesome folks at Wyolum) was completely open source. Not only is the BADGEr hackable, it was designed to be hacked. So, of course, I immediately started hacking on it as soon as I returned home from the summit at MIT. It didn’t take me long to write new firmware for the device, connect it to a web-connected Rapsberry Pi computer, and hang it on my wall with some custom 3D-printed brackets. I’ve been using it for the last several months as a handy weather station that I can glance at before I leave my apartment each morning. A supplementary LED beacon warns me of extreme conditions (hot, cold, or rainy). On the weekends, it shows the weather report for San Francisco (where I live), and on the weekdays, it shows the weather report for Mountain View (where I work). The display checks for new weather data and updates once every 10 minutes.
What to see it in action? Want to learn how to make it yourself? Read on!
Weather Station in Action:
Here’s a quick Instagram video (Don’t you follow me on Instagram!?) that shows the data updating, the warning light coming on, and the ePaper display refreshing. In this example, I’ve chosen to display data for New York City. Since there is a 90% chance of rain, the warning light glows a pleasant blue. Ordinarily, you wouldn’t actually see the terminal program spitting out debug data, since it runs automatically on the headless Raspberry Pi (I’m SSH‘ed into the Pi to show you what the updating process looks like).
Are animated GIF’s more your speed? Here’s a looping GIF showing the display switching back and forth between New York and San Francisco weather reports (my previous and current places of residence):
Here’s how the Weather Station works:
- Once every 10 minutes, a cronjob triggers on the Raspberry Pi. This cronjob launches a python script that uses weather.com and yahoo.com APIs to fetch the following data:
- Yahoo weather code: This corresponds to an image ID that will load on the ePaper display. Different codes represent different conditions like, “sunny”, “cloudy”, etc.
- City name: You provide the script with your zip code, and it will automatically get the name of the city.
- Current Date
- Sunrise Time
- Sunset Time
- Forecast (Sunny, cloudy, etc)
- Chance of Precipitation
- Temperature (high)
- Temperature (low)
- Once the script has grabbed all this info, it parses out the relevant data, and formats it to be sent over USB-serial to the attached BADGEr device. An identifying character is appended to the start of each serial string, which allows the BADGEr to determine which piece of data it is receiving.
- Once the Pi has finished sending data (it sends a termination character to tell the BADGEr it is done), the BADGEr parses through the data.
- The BADGEr identifies and loads the appropriate weather condition image from the loaded SD card (it contains a specially converted and formatted image for each possible weather condition).
- The BADGEr loads the remainder of the data into a buffer and sends it all to the ePaper display.
- Steps 1-5 repeat once every 10 minutes.
Want to Make This? Here are the Steps:
- Visit the GitHub Repository that I link to at the bottom of this post. Either clone it to your computer with git command line tools, or download the entire ZIP by clicking “Download ZIP” on the right side of the GitHub repo page.
- Remove the MicroSD card from your BADGEr and insert it into a card reader on your computer. You may need a microSD to SD adapter. Format the card.
- Copy the contents of the “BADGEr SD Card” folder in my GitHub repo to the SD card. Once you’ve done this, the root of the SD card should contain three files and an IMAGES folder. The Wyolum ePaper library utilizes a special image format (.WIF). I’ve taken the liberty of already converting the weather glyphs to this format, and have included the original .gif files as well. If you’d like to experiment with making your own .WIF files, you can do so by using the Wyolum python-based .WIF image conversion tool.
- Next, you’ll need to flash the BADGEr with my custom firmware. The BADGEr uses a standard FTDI 5-pin connector for this purpose, but NOT all FTDI cables will work. I was only able to flash the device by using the sparkfun FTDI breakout. Connect BADGEr to your computer using one of these cables.
- Follow the instructions from Wyolum to download and install the EReader Arduino Library. Make sure you do this with the Arduino IDE closed.
- Open up the “BADGEr_Display.ino” Arduino sketch contained in the GitHub repo linked from the end of this post. One you have it open in the Arduino IDE, select your USB-Serial port in Tools>Serial Port, and select “Arduino Pro Mini 3v3 8MHz” in Tools>Board.
- Press the upload button to upload my firmware to your BADGEr.
- You can now unplug the BADGEr from your computer, and plug it into the one of the USB ports on your Raspberry Pi. The BADGEr is now ready to accept serial commands that can control its screen. This tutorial assumes you already have Raspberry Pi up and running with internet connectivity. If you don’t, follow the introductory Raspberry Pi tutorials from Adafruit first. I am also assuming that you are connected to your Raspberry Pi over SSH, and that are you comfortable transferring files to it via FTP. The remainder of the steps should be performed on your Raspberry Pi (either directly, or via SSH) unless otherwise noted.
- By default, Arduinos (including the BADGEr) will restart whenever a serial connection is initiated with them. We don’t want the BADGEr to do that while it is plugged into the Pi. Figure out what device your BADGEr is listed as on the Raspberry Pi:
[email protected] ~ $ cd /dev[email protected] ~ $ ls -l
That will print out an exhaustive list of all hardware devices connected to your Pi. Your USB-Serial converter (the BADGEr) will likely be called something like ttyUSB* where * is some number. Scroll through the list and find those entries. If there is just one, that is your BADGEr. If there are multiple, unplug the BADGEr, re-run ls-l, and see which one disappears – that is your BADGEr. Note down the device name. With the directory appended, it will look something like “/dev/ttyUSB1”. Use your favorite editor to modify your Pi boot file so that it disables Serial resets for that device on boot:[email protected] ~ $ sudo nano /etc/rc.local
Append “stty -F /dev/ttyUSB* -hupcl” (without the quotes) to the end of that file. Be sure to replace the “*” with the number for your device! Save the file.
- Now, you’ll need to install the Weather and Serial python libraries. Navigate to your home directory:
[email protected] ~ $ cd /home/pi
Download, unzip, and install the Python Weather API Library:[email protected] ~ $ wget https://launchpad.net/python-weather-api/trunk/0.3.8/+download/pywapi-0.3.8.tar.gz[email protected] ~ $ tar -zxvf pywapi-0.3.8.tar.gz[email protected] ~ $ rm pywapi-0.3.8.tar.gz[email protected] ~ $ cd pywapi-0.3.8[email protected] ~ $ python setup.py build[email protected] ~ $ sudo python setup.py install
Now, install PySerial using PIP:[email protected] ~ $ sudo apt-get install python-dev python-pip[email protected] ~ $ sudo pip install pyserial
- Now, on your main computer, edit my weather.py script to match your needs (you can use any text editor). When you open the file, you’ll see that there is a configuration section at the top. Right off the bat, you’ll probably want to set the “use_SUNN” variable to “False”. SUNN is a custom piece of LED lighting hardware that I’m using to act as the warning light (it’s not open source yet, but may be in the future). Make sure you set “BADGEr_dev” to match the device name that you determined earlier! Save the python script when you are done.
- Next up, you need to copy my weather.py script to your Pi home directory. Since you already have my entire GitHub repo for this project downloaded on your main computer, I recommend sending the file over to your Pi via FTP. The python file is located in the “Weather Checker” directory of the GitHub repo, and should placed in your Pi’s home directory (/home/pi/weather.py). Once you’ve copied it over, make sure you make it executable:
[email protected] ~ $ cd /home/pi[email protected] ~ $ chmod 755 weather.py
- At this point, you should now be able to manually run this file, and see the BADGEr display update accordingly. Assuming you are still in the home directory, manually run the script like this:
[email protected] ~ $ ./weather.py 10001
The program accepts a zipcode as its one argument. 10001 is a zip code for New York City. When you run it, replace it with the zipcode for wherever you want to see the weather report. When you run the script, you should see an output on the terminal that looks like this animated GIF:
When you run it, you will see different text because you will presumably have the SUNN functionality disabled, and you will be using a different zipcode.
- As the final step, you’ll setup a cronjob to handle automatically running this script once every 10 minutes. Open up the crontab editor:
[email protected] ~ $ crontab -e
At the end of this file, add two lines:
*/10 * * * 1-5 /home/pi/weather.py 94043
*/10 * * * 0,6 /home/pi/weather.py 94117
The first line triggers the script once every 10 minutes on weekdays. Replace “94043” with the zipcode of where you work. The second line triggers the script one every 10 minutes on weekends. Replace “94117” with the zipcode of where you live. Save and close the crontab.
- You’re done! You can now log out of your SSH session to the Pi. It will continue to run, and will update the display every 10 minutes with the latest weather report. Hooray!
Supporting Documentation and Code
This project is licensed under an Apache v2 Open Source License. Please Attribute and Share-Alike. You can download the source files directly from the GitHub Repository linked below:
I can’t work out from the links whether the BADGEr is available for sale to us mere mortals from anywhere, or whether it was a ‘one off’ for the event – do you know?
I’m shortly going to be involved with a data collection project in Peru and this could be an ideal method for displaying data as I move amongst the sensors (linked to a small RF pack).
Yet another Blum masterpiece – I remain in awe…!!!
You can find the badger at this link http://www.seeedstudio.com/depot/badgerv4-p-1587.html?cPath=70_72 .its $50 with free shipping. enjoy hacking it. Thanks jeremy for great hack.
Love this! I was at the OHS and received the badge, too. It’s awesome, and in fact, I’m working on a Pi project now that uses an epaper display because I really fell in love with it. Your weather station is a great idea and I’m glad you posted directions. Hope to see you this year!
My hack is more text oriented and less graphical. Showing sensor readings etc..
The font support seems to be lacking a bit. Is there a way to get larger text or bold?
Not that I know of. You should talk to Wyolum about that, since they developed the library.
I’ve been trying to think of something like this since I also got one of the BADGr’s at OSHS ’13 and this is absolutely spot on perfect! I got almost all the way through to the end until ./weather.py returned the following error code-
Getting weather for zipcode 04101… Got weather for Portland, ME!
Skipping SUNN Light warning generation.
Generating BADGEr command strings… Done!
Skipping SUNN Light control.
Connecting to BADGEr…
Traceback (most recent call last):
File “./weather.py”, line 121, in
File “/usr/local/lib/python2.7/dist-packages/serial/serialposix.py”, line 491, in write
d = to_bytes(data)
File “/usr/local/lib/python2.7/dist-packages/serial/serialutil.py”, line 76, in to_bytes
b.append(item) # this one handles int and str for our emulation and ints for Python 3.x
TypeError: an integer or string of size 1 is required
Could be a few things:
-Make sure you’re using Python 2.7. I didn’t attempt to make this compatible with Python 3.0+
-Make sure the BADGEr_dev variable is set correctly. You can do this by plugging in your FTDI cable and running “dmesg” to see what device was just plugged in
-Make sure pySerial is installed
dmesg detects FTDI interface registered on ttyUSB0 as it should (I think?)
Python 2.7 is running
PySerial is installed
Its pretty much a fresh install of Raspbian too so there shouldnt be any funny stuff going on with the GPIOs etc… One thing that does raise my eyebrows is this discussion on StackOverFlow-
The only answer was that it was related to “encoding issues”
Either way its more of a puzzle-type challenge than a do or die kind of thing… I’ve been dreaming up different ways of using the BADGr since I got it so its nice to see somebody got it to work doing something.
One thing I’ve been wondering… I wonder how hard it would be to make it run something similar to the Pebble Watch? Perhaps using a BLE breakout to receive push notifications from Android? Obviously it would be far more limited than a Pebble Watch, but I wonder how much we could get away with?
Hmmm… Looks like the image variable might be empty? can you add “print image” after image is created to see what the string looks like? You could also try unicode encoding it by putting a “u” before the opening quotes of the strings.
I acquired Yun board recently and now wondering how difficult would it be to do the same on it, what do you think?
little elaboration, Yun + BADGEr of cause
You should certainly by able to make that work. As long as the Yun is sending out serial data in the same format that the Pi was, the BADGEr wouldn’t even know the difference.
Thanks for responding…
Actually I have an issue with serial… :(
Initially, when I connected FTDI to my Yun, /dev/ttyUSB0 hasn’t been listed in devlist. That’s fixed by setting up kmod-usb-serial-ftdi package;
But in Python script the following line
call([“stty”, “-F”, “/dev/ttyUSB0”, “-hupcl”])
throws an error:
Traceback (most recent call last):
File “test.py”, line 45, in
call([“stty”, “-F”, “/dev/ttyUSB0”, “-hupcl”])
File “/usr/lib/python2.7/subprocess.py”, line 493, in call
return Popen(*popenargs, **kwargs).wait()
File “/usr/lib/python2.7/subprocess.py”, line 679, in __init__
File “/usr/lib/python2.7/subprocess.py”, line 1249, in _execute_child
OSError: [Errno 2] No such file or directory
Don’t mean to bother you too much but may be you have an idea of what could be wrong?
I assume you are supplying power via the FTDI connector?