Do you need to exercise some control over the physical world, but don’t want to leave your computer? Well then, take a minute to set the color of my desk on a day of your choosing at http://colormydesk.com/
Yes, I backlit my desk and connected the lights to a server that anyone can control.
- I used a Raspberry Pi, a small Linux server.
- I built a circuit that allows me to power RGB lights with 12-volt power without frying the Raspberry Pi.
- I developed the website, http://colormydesk.com/, on CakePHP that handles requests from the general public. I ran this on my web server.
- I wrote some software in Python on the Raspberry Pi that pulls the information daily from the web server using JSON.
If this is already too much for you, consider just going to the site and setting a color: http://colormydesk.com/. If you’re really interested in that how / why, read on.
Forcing the Pi to Fake PWM
I ran into some issues and had to use Wheezy instead of Occidentalis because its kernel version, 3.2.7 was more up-to-date. Then I used the older version of ServoBlaster, instead of the one built for the newest 3.6.11 mainly because I didn’t want to figure out how to upgrade the kernel. I used this thread to figure out kernel versions: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=15011&p=278566
Building the Shield
Once that was working, I soldered the basic circuit onto some proto board. I then realized I should’ve used my Raspberry Pi proto board instead of the regular Radio Shack one. But no worries, I hooked up some headers and a custom shield was born.
CakePHP and a Web Server
I built the CakePHP site on a separate web server because I didn’t want the Pi to get overloaded. Besides, I’m a web developer and have plenty of server resources at my disposal. I then wrote some Python code on the Pi to pull the data from the site’s JSON feed with some simple authentication to protect email addresses from the public. A crontab runs every day at 6pm ET to pull the data and turn the lights on. Another one runs at 11pm ET to turn them off.
Translating Hex to ServoBlaster
ServoBlaster allows you to set a ‘servo position’ from 0 – 249. Since a color value for each red, green, or blue, can only be between 0 – 255, I decided to simply clip the last 6 values (250, 251, etc…) down to a servo position of 249. What this really means is that anything above the hex value of F9, just looks like F9. #FFFFFF, is just #F9F9F9, a dimmer white.
The Python Code
#!/usr/bin/env python import os import requests import json import datetime import time import smtplib # FUNCTIONS def pwm(pin, angle): angle = checkmax(angle) print "servo[" + str(pin) + "][" + str(angle) + "]" cmd = "echo " + str(pin) + "=" + str(angle) + " > /dev/servoblaster" os.system(cmd) def checkmax(angle): #PWM can only handle 249 units, so we're simply cutting the hex values 250-255 down to 249 if angle > 249: angle = 249 return angle def setcolor(hex): pwm(5, int(hex[1:3],16)) pwm(2, int(hex[3:5],16)) pwm(0, int(hex[5:7],16)) # Define a Thank You Email def send_email(): SMTP_SERVER = 'smtp.gmail.com' SMTP_PORT = 587 sender = '' password = '' recipient = data['email_address'] subject = 'Color My Desk: Thank you!' body = 'Hey '+data['name']+",<br /><br />"+"Thanks for setting my desk color to <span style='color:"+data['color']+"'>" + data['color'] + "</span> today! <br /><br />"+"You wrote: "+data['details']+"<br /><br />"+"Will Wnekowicz" headers = ["From: " + sender, "Subject: " + subject, "To: " + recipient, "MIME-Version: 1.0", "Content-Type: text/html"] headers = "\r\n".join(headers) session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT) session.ehlo() session.starttls() session.ehlo session.login(sender, password) session.sendmail(sender, recipient, headers + "\r\n\r\n" + body) session.quit() # Getting the JSON Feed os.environ['TZ'] = 'America/New_York' time.tzset() r = requests.get('http://colormydesk.com/full_calendar/events/feed?start='+str(datetime.date.today())+'&api_secret=thesecret') data = r.json() # Setting the Color of the Strip if data: setcolor(data['color']) send_email() else: setcolor("#7733F0") # default color if no color is scheduled, aka no one loves me.