Control Something

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.

THE BASICS

  • 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.

THE NOT-SO-BASICS

Forcing the Pi to Fake PWM

The first step was to get the Raspberry Pi to run some lights. Since the Pi doesn’t have 3 PWM pins, I used this tutorial on using   ServoBlaster for RGB lights.

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.

Parts List

 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[0]['email_address']
   subject = 'Color My Desk: Thank you!'
   body = 'Hey '+data[0]['name']+",<br /><br />"+"Thanks for setting my desk color to <span style='color:"+data[0]['color']+"'>" + data[0]['color'] + "</span> today! <br /><br />"+"You wrote: "+data[0]['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[0]['color'])
   send_email()
else:
   setcolor("#7733F0") # default color if no color is scheduled, aka no one loves me.