Building 16 Sites in 2 Hours

Our program (Boulder Digital Works) recently hosted the Making Digital Work conference in Boulder. Jesse Weaver and I were requested to help with the conference. The idea was to split the conference attendees into teams and develop an idea. They would come up with two variations of that idea and create some copy/keyword combinations to test between. Then Jesse and I code all the variations for each team into web pages that we could test with Google’s web optimizer. Tim Malbon developed the logos and Jesse and I coded. It turned out well and the teams had some great ideas! I have  a few takeaways:

Simple Works….

The template, the process and the testing platform were all immediately understandable and easy to work with.

Start with a Clear Explanation…

Start with a clear explanation of the intended outcome. Tim explained the idea in one short email. The concept wasn’t hard to grasp because it was clearly explained and thus we were able to put most of our energy into building it.

Don’t Agonize…

When you’re rapidly prototyping an idea it doesn’t need to be perfectly polished, the key word here is “rapid.” I noticed several small errors while were presenting the websites, but it didn’t matter because the groups understood that this was an exercise in speed not quality. Most importantly they got the overall gist.

Make Backups…

About 4AM on the day of our presentation, I had the thought to make backups. Like an idiot, I thought “nah, my server hasn’t gone down in 8 months…what are the chances?” Famous last words. About 7:30AM I woke up to a text message telling me my server had gone down. I checked several ports including SSH and found confirmed my server was unavailable. I contacted my hosting provider who informed me their whole network was out due a (d)Dos attack from LA, California. I assumed it would only take an hour to clear up, but three hours later we getting a little worried. I had an encrypted backup, but couldn’t open it because I didn’t have my encryption key. It’s been a while since I’ve used those backups and forgot to get the key when I left my last job. A couple hours before the presentation the network came back online. We got lucky. Had my server been out during that time, we would have been screwed! Always make a backup, test the backup works and have  a backup plan to easily switch to another server just in case.

Designate a Zero Hour…

Decide collectively on a time when all production must be finished and changes cannot be made after that point. There is always an urge to “tweak” things to make you project just a little bit better. This is dangerous territory, in programming there are always unforeseen consequences to changes and they may not be immediately apparent. The reason I was up at 4AM (day of) was because I was “tweaking” things. However, when you’re tired you make mistakes and I failed to realize that some other tweaks I was made obfuscated some of the text on the pages. This made things difficult to read and became pejorative rather than helping.

All in all I think the project was successful, things could have gone smoother but considering we built 16 websites in a day, things went as well as they probably could have. Thank again to Jesse Weaver and Tim Malbon for making this a success.

Make Your Own Instavision

Recently I built the backend for the Instavision TV and wanted to give a quick tutorial on how to build one yourself. Brian Fouhy, George Tong, Jesse Weaver and Pedro Sorrentino actually made this TV a reality.


  • Retro looking TV
  • VGA to Coaxial adapter
  • Old Laptop
  • Instagram account
  • Instagram API Client ID, Client Secret and an Access Token
  • Node.js
  • Shell access to your server

Getting Started…

The first step is to get the backend working. Register a new client on the Instagram API, just register for the url you’ll be using to setup your feed.

Next you need to store an access token to use later on in our node.js file. Once you have your Client registered with Instagram, simply input the following into your browser’s url (replacing with your newly registered client ID and your specific redirect URI):

Once you visit this page, simply login with your instagram account credentials and you should be redirected. You don’t necessarily need to have your redirect URI do anything when you land on it, what your interested in is the access token.

Copy this access token and save it for later, we’ll use it to gain access to Instagram and pull information for our TV to display.


Lets get our code up and running. The basic idea is to have a client side page calling our server about every 5 seconds to get an update on the most recent photo. We’ll then also need something on our server to go out and get the most recent photos from Instagram, this script will also run about every 5 seconds. It would be hard to do this with PHP, sleep() and a chron job…so we’ll turn to node.js. Copy the following script and put it in the root of your public_html folder (make sure you replace your access token with the access token you got in the previous step also, you’ll need to make sure and replace all paths and urls with your own custom paths and domains).


	shell: cd /home/instavis/public_html/
	shell: node instavision.js
	shell: kill ##### (process number)

	call the url:

			find out rate limit with instagram = 5000 requests per hour
var sys = require("sys"),
    http = require("http"),
    https = require("https"),
    url = require("url"),
    path = require("path"),
    fs = require("fs"),
    util = require("util"),
    events = require("events");  

function load_static_file(uri, response) {
    var filename = path.join(process.cwd(), uri);
    path.exists(filename, function(exists) {
        if(!exists) {
            response.writeHead(404, {"Content-Type": "text/plain"});
            response.write("404 Not Foundn" + " filename: " + filename);

        fs.readFile(filename, "binary", function(err, file) {
            if(err) {
                response.writeHead(500, {"Content-Type": "text/plain"});
                response.write(err + "n");

            response.write(file, "binary");

//var twitter_client = http.createClient(80, "");  

var tweet_emitter = new events.EventEmitter();  

function get_tweets() {
    //var request = twitter_client.request("GET", "/v1/tags/bdwinstavision/media/recent?access_token=3036112.f59def8.4708bbe9fe9e43639c8d9fe93c5c41df", {"host": ""}); 

    var options = {
    // public search - unauthenticated
	//host: '',
	//path: '/v1/tags/bdwinstavision/media/recent?access_token=3036112.f59def8.4708bbe9fe9e43639c8d9fe93c5c41df',

	// authenticated feed -

	// instavisionTV access token
	// access_token = 3036112.c90c34d.411d18988857490c9032a2bac30e6943

	// instavision access token
	// access_token = 3060511.0b03a1e.fff65e339b694cf0844306131ab82b97
	host: '',
	path: '/v1/users/self/feed?access_token=3060511.0b03a1e.fff65e339b694cf0844306131ab82b97',

    https.get(options, function (res) {
		var raw = "";
		res.on('data', function (chunk) {
		    raw += chunk;
		res.on('end', function () {
		    var response = JSON.parse(raw);


		    if(raw.length > 0) {
	/*         	sys.puts("tweets:" + response);  */
	            tweet_emitter.emit("tweets", response);
	        //res.removeListener('connection', callback);
    }).on('error', function(e) {

    /*request.addListener("response", function(response) {
        var body = "";
        response.addListener("data", function(data) {
            body += data;
            sys.puts("tweets:" + data);

        response.addListener("end", function() {
            var tweets = JSON.parse(body);
            if(tweets.length > 0) {
            	//sys.puts("tweets:" + tweets);
                tweet_emitter.emit("tweets", tweets);
    }); */ 


setInterval(get_tweets, 5000);

http.createServer(function(request, response) {
    var uri = url.parse(request.url).pathname;
    //var uri = request.url;

    var callback = function(stream) {
	  sys.puts('listener removed!');

    if(uri === "/stream") {  

        //var listener = tweet_emitter.addListener("tweets", function(tweets) {
        var listener = tweet_emitter.on("tweets", function(tweets) {
            response.writeHead(200, { "Content-Type" : "text/plain" });


            //sys.puts("stringify tweets:" + JSON.stringify(tweets));


            //var listenersForTeets = tweet_emitter.listeners(listener);







        //sys.puts(util.inspect(tweet_emitter.listeners(listener), true, null));

        var timeout = setTimeout(function() {
            response.writeHead(200, { "Content-Type" : "text/plain" });


        }, 10000); 

    else {
        load_static_file(uri, response);

sys.puts("Server running at");

Note: I am pulling a user feed in this case, you can also do a search for specific photos and other users’ feeds if you call different urls. For more information read the Instagram API.

Once you have this copied and named instavision.js in your root, you need to make an html page with a special script to call instavision.js and get the most recent photos. Copy the following and save this into a file named feed.html, also in the root of your public_html folder:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link href="css/styleDark.css" rel="stylesheet" type="text/css">
<title>Instavision TV</title>

<body style="">
    <div id="wrap">

    	<div id="tweets"></div>

	<script type="text/javascript" src=""></script>
	<script type="text/javascript">
	    var tweet_list = $("#tweets");
	    var tweet_caption = $("#caption"); 

	    function load_tweets() {
	        $.getJSON("/stream", function(tweets) {
	            var imageurl =[0].images.standard_resolution.url;
	            var imageUser =[0].user.username;
	            var imageCaption = '';
	            if ([0].caption != null){
	            var imageCaption =[0].caption.text;

	            imageurl = "<img id='tweet' src='"+imageurl+"' /><br/>";
	            imageCaption = "<div id='caption'><img id='captionImage' src='/images/ColorBars.png' height='18px' width='29px'/><h1>"+imageUser+"</h1><h3>"+imageCaption+"</h3></div>";
	            $(tweet_list).html(imageurl + imageCaption);

	    setTimeout(load_tweets, 5000); 

	    $(document).ready(function() {


Once you have feed.html saved, you can try it out! You have to run the instavision.js script as a process on your server, simply run these commands to get it running:

cd /home/instavis/public_html
node instavision.js&

Make sure you have node installed. If you find that you want this process to stop, look at its process ID and kill it by:

kill 76234

Once you have the process running, visit the feed.html page at port 8080 (place the url with your custom url):

If it worked, then you’re good to go! If it didn’t, leave a comment below and I’ll try to help out!

Once you have it up and running, its simply a matter of plugging the TV in and formatting the image, which is totally a case by case situation and thus beyond the scope of this tutorial.

Bubble Sorting Algorithm

Recently, I had the need to re-order posts in wordpress according to a specifically numbered tag. Unfortunately, WordPress doesn’t let you order post output by tag since that’s usually what categories are used for. So I decided to capture all the output into a multidimensional array. However, I still needed some way to sort the array and asort(); wasn’t the answer. Instead I used something called a Bubble sort algorithm to do the heavy lifting.

The code…

for($x = 0; $x < $array_size; $x++) {
  for($y = 0; $y < $array_size; $y++) {
    if($ran[$x] < $ran[$y]) {
      $hold = $ran[$x];
      $ran[$x] = $ran[$y];
      $ran[$y] = $hold;

It works by running through the entire array, comparing each element to every element in the array. If it encounters a situation where the item’s value is less than the next item it stores it in a temporary variable and sets the variable to the larger version. Then replaces the previously larger version with the smaller amount. If you don’t get it, here’s a great video to explain it!

Netbeans, XDebug and Xampp on Mac

I recently had some confusion about x-debug on a mac. I read online when I googled it that it’s not possible to debug with netbeans on a mac using x-debug. Not true, so I wanted to clarify and release some instructions on how to do this.


Make sure you have netbeans and xampp installed on your local machine. This environment is great for debugging but not ready for production so please don’t try to install the xampp environment on any production ready server. Once you have everything installed we can alter the installation in to allow xdebug to work.


  1. Find out what PHP version your running. If you don’t know, simply put “phpinfo()” in a file, save it and visit the file in a browser (with xampp running of course).
  2. Download the x-debug binaries. You can find there at:
  3. Open the gzipped file and search for a subfolder that corresponds with your php version. In that folder you’ll find a file called “”
  4. Copy this file and navigate to your php extensions folder. I will look something like: /Applications/XAMPP/xamppfiles/lib/php/php-5.3.1/extensions/no-debug-non-zts-20090626. Note the file path, you will use this later.
  5. Paste the “” file into this directory.
  6. Now edit your php.ini file. It’s probably located in /Applications/XAMPP/xamppfiles/etc/php.ini.
  7. Open this file in your favorite text editor and scroll to the bottom. Paste the following in making sure to tweak the file paths to your specific setup:
  8. [xdebug]
    xdebug.remote_enable = On
    xdebug.remote_autostart = 1
  9. Restart Apache with the xampp controls and your good to go! Open netbeans and happy debugging!


As of now, the newer XAMPP ships with the latest xdebug pre-installed so no need to worry about the above. Just install a fresh copy of xampp and edit the php.ini file to the following:

zend_extension = /Applications/XAMPP/xamppfiles/lib/php/extensions/no-debug-non-zts-20121212/

This should have everything you need to get this up and running immediately and should work with an update copy of netbeans as well!

Blobify Yourself with Kinect and Bubble Boy

UPDATE (4/3/12): I’ve fixed the “marchingCubes” error. Please click the link below to get an updated script. I’m leaving this page up for reference only.


Here’s a simple modification to a sketch that renders polygonal meshes from point clouds. All I did was strap a kinect to it. Most of the credit goes to Daniel Schiffman and Rui Madeira.


  • You’ll need Schiffman Open Kinect library, as posted here.
  • The ToxicLibs Library
  • Marching Cubes example sketch here.

Getting started…

Download and install the libraries above. Once you have the libraries installed, download the sample sketch listed above. Run the sample sketch to make sure everything is working.

Modify the sketch…

I won’t go into too much detail since it would just be easier to copy what I have and play around with it in order to find out how it works. Basically, we’ll import the openkinect library to begin using the kinect. We’ll modify the setup function to prepare some new classes and set the screen correctly. After that we’ll change the “mousepressed” if statement to update metaBalls with points from the kinect instead of points from a mouse. We’ll do some not-so-scientific math in order to get the screen to center and call it good.

Below is the working example, if you have any suggestions let me know! Also, if anyone out there knows of a more efficient meshing library from point clouds I’m all ears, I’d like to be able to render poly in real time and at high resolution, but so far I haven’t been able to find an efficient way of doing this!

The sketch…

import toxi.geom.Vec3D;
import processing.opengl.*;
import rui.marchingCubes.*;

// kinect
import org.openkinect.*;
import org.openkinect.processing.*;

MarchingCubes mc;
Vec3D rotationAxis;

Boolean bUseFill;

// kinect
Kinect kinect;
float a = 0;
// Size of kinect image
int w = 640;
int h = 480;
int kWidth  = 640;
int kHeight = 480;
// depth mapping and tilt
boolean depth = true;
boolean rgb = false;
boolean ir = false;
float deg = 8; // Start at 15 degrees
PImage depthImg;
int minDepth =  40;
int maxDepth = 860;
// set initial record to false
boolean record = false;
int counter = 0;
// print custom file
boolean printFile = false;
ArrayList points;
PrintWriter output;
// We'll use a lookup table so that we don't have to repeat the math over and over
float[] depthLookUp = new float[2048];

void setup(){
  size(1024, 600, OPENGL);
  Vec3D aabbMin = new Vec3D(-width/2, -height/2, -250);
  Vec3D aabbMax = new Vec3D(width/2, height/2, 250);
  Vec3D numPoints = new Vec3D(50,50,50);
  float isoLevel = 1;
  mc = new MarchingCubes(this, aabbMin, aabbMax, numPoints, isoLevel);

  rotationAxis = new Vec3D();

  bUseFill = false;

  // kinect
  kinect = new Kinect(this);
  // We don't need the grayscale image in this example
  // so this makes it more efficient
  // get depthImg to constrain
  depthImg = new PImage(kWidth, kHeight);
  // Lookup table for all possible depth values (0 - 2047)
  for (int i = 0; i < depthLookUp.length; i++) {
    depthLookUp[i] = rawDepthToMeters(i);
  points = new ArrayList();
  output = createWriter("points.txt");


void draw(){

  // kinect
  int[] depth = kinect.getRawDepth();
  int skip = 50;

    // original for loop
    println("entering loop");
    int nBalls = 0;
    for(int x=0; x<w; x+=skip) {
      for(int y=0; y<h; y+=skip) {
        int offset = x+y*w;
        int rawDepth = depth[offset];

        if(rawDepth >= minDepth && rawDepth <= maxDepth) {
          PVector v = depthToWorld(x,y,rawDepth);
          Vec3D metaBallPos = new Vec3D(v.x * 500, v.y * 300, v.z*300);
          mc.addMetaBall(metaBallPos, 100, 1);

    println("done with loop, " + nBalls + " balls");
    // end original for loop

  else {

  translate(width/2, height/2, 0);

PVector depthToWorld(int x, int y, int depthValue) {

  final double fx_d = 1.0 / 5.9421434211923247e+02;
  final double fy_d = 1.0 / 5.9104053696870778e+02;
  final double cx_d = 3.3930780975300314e+02;
  final double cy_d = 2.4273913761751615e+02;

  PVector result = new PVector();
  double depth =  depthLookUp[depthValue];//rawDepthToMeters(depthValue);
  result.x = (float)((x - cx_d) * depth * fx_d);
  result.y = (float)((y - cy_d) * depth * fy_d);
  result.z = (float)(depth);
  return result;

float rawDepthToMeters(int depthValue) {
  if (depthValue < 2047) {
    return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161));
  return 0.0f;

void keyPressed(){
  if(key == CODED){
    if(keyCode == LEFT) rotationAxis.y += 0.05;
    if(keyCode == RIGHT) rotationAxis.y -= 0.05;
    if(keyCode == UP) rotationAxis.x -= 0.05;
    if(keyCode == DOWN) rotationAxis.x += 0.05;
  else {
    if(key == ' '){
      bUseFill = !bUseFill;
    if(key == 'r' || key == 'R'){

void stop() {

Watch the video below to get a better understanding of the installation process (see it in action around 02:13):

That’s it! You should be able to copy this code, paste it over the original example sketch and away you go or just download the example below!

Download Bubble Boy


I’ve added a new git repo here, please let me know if you wish to contribute!


I’ve been getting a lot of responses saying they are getting a rui.marchingcubes error. I’m looking into this, but for now I believe it has to do with the differences between processing 1.2.1 and 1.5.1 – if you have a newer version of processing (1.5.1) it will break with an error:

No library found for rui.marchingCubes

I still haven’t found a solve for this, since the marching cubes library is contained within the sketch folder itself, labeled “”

If anyone has any suggestions other than to install an older version of processing (1.2.1), I’m all ears…

How to Install Node.js on Your Server

A quick guide for getting up and running with node js on your personal server.

Getting started…

If you don’t already have git installed on your server I suggest you refer to my earlier post on installation. We’ll be using git to grab node.js in this tutorial. You also must have root or shell exec access in order to execute an installation, if you don’t have ssh or command line access to your server, check with your hosting provider.


Change to your temporary directory…

cd /var/tmp

Tell git to grab the latest installation of node js…

git clone git://

Now change to the new directory of node…

cd node

Configure the installation…


Make the makefile…


Install node…

make install

Double check node was installed correctly by typing this command…

node --version

If everything was set up correctly you should get a return in the command line with the latest version of node installed on your server.

Running the server…

Now that you have node installed, let’s get a quick hello world up so we can make sure everything is configured properly and start experiementing with node!

Let’s assume you want to run a server available from Change to your domain’s home directory…

cd /home/mydomain/public_html

Now create a file in here that will be our node server. When run from the command line, this file will tell node to listen on whatever port you designate. When it gets a hit, it will send an output that we specify.

Create a file named node_test.js…

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World!n');
console.log('Server running at');

Save this file in your domain’s directory.

Then run it in the command line…

node /home/mydomain/public_html/node_test.js

You can also set the process to run indefinetely on your server by running the command with an “&” symbol at the end…

node /home/mydomain/public_html/node_test.js&

You should get a response that looks like this…

In your browser type in “” and you should see the response from node that we entered in above! If everything is configured properly, your node process should be running in the command line and listening on port 8080 for any connections, when it gets hit, it will output our message!

How to Install Git on your server

A quick tutorial on installing Git on your server in order to download packages directly from github like Node.js.

First make sure you don’t have Git already installed.

git --help

If something other than an error pops up in the command line, then you already have it installed! Otherwise read on…


(Keep in mind, I’m writing this tutorial for people using CentOS distros and other red hat based operating systems. This means I have no package installer like yum or apt-get)

Change to the temporary directory on your server where you wish to install something. Log in as root and…

cd /var/tmp

Now download the file…


Now unpack it…

tar -zxf git-

Change to the new directory…

cd git-

Configure for installation…


Make the install…


Install Git…

make install

Now test to make sure it installed properly…

git --help

If everything goes according to plan, you should now see something like the screenshot below appear.

Kinect Hacking with Schiffman – Part 1

In this tutorial you’ll find out how to:

  1. Install processing on your mac.
  2. Install a library to use with our X-Box Kinect.
  3. Run some example programs to start playing with the Kinect’s output.

The goal is to keep this tutorial as simple as possible.


You’ll need:

  • Microsoft XBox kinect with a wall unit power adapter with usb connection.
  • Unix based operating system (if your running windows, then you’ll have to run a virtual machine – try a live cd with your favorite linux distro)
  • Processing Language Installation (don’t worry if you don’t have it yet, well get to that)
  • Schiffman Kinect Library (Again, if you don’t have it, read on)

Getting Started…

First we’ll need the processing language. Go to and click on the install for your operating system. Install it like a regular application. Once installed processing works by running a custom editor where you can write new scripts or run example scripts. If you’re on a mac running apple’s OS then you can expect processing to automatically create a folder called “Processing” in your user’s “Documents” folder. Inside the “Processing” folder there should be two other folder labeled “sketches” and “library.” The “sketches” folder is where you’ll store all of your custom projects. The “library” folder is where you’ll store all the libraries you download and subsequently where we’ll store our schiffman library for the Kinect.

Getting Schiffman…

Now that you have processing installed it’s time to get the schiffman library. Let’s grab the latest distribution here:

Once you’ve downloaded the master branch, unzip it and navigate to “wrappers” -> “java” -> “processing” -> “distribution” -> “openkinect”. Grab “openkinect” and drag it into your “Documents” -> “Processing” -> “libraries” folder. That’s it! Processing automatically knows where to look when it looks for libraries so you just need to include it with your scripts in order to make it run!

Connecting the Kinect…

Now that we have processing and our library it’s time to hook up the kinect and get started hacking! Simply plug in your kinect to any USB port and navigate to “Documents” -> “Processing” -> “libraries” -> “openkinect” -> “examples”, inside this directory are 4 (at the current schiffman library version) examples to chooose from. Simply click into one of the example folders and double click the “filename.pde” to run it in processing. You can also right click and “open with” then choose processing.

Running a script…

Processing interprets code at run time so as soon as you press the “play” button at the top left hand of the processing environment it will either compile the script or let you know you have an error. When you run the script you should see a small window appear. If you run one of the example scripts, you should see a window with live data from the Kinect. I chose to run the “Point Cloud” script.

You can see that it’s working and a point cloud of depth data is appearing on the screen. From here we can copy and paste this code into a new script. Rename and save your new script in “Documents” -> “Processing” -> “sketches” and your free to start making changes to the script itself. Don’t be afraid to mess things up, you can simply copy from the examples and start over if you do!

Up next…

In the second part of this series we’ll talk about modifying some of these scripts to do certain things. In the end we’ll end up using our XBox Kinect as a 3D scanner that can output an .stl file made for a 3D printer. This will allow us to scan things and print them in 3D! Stay tuned.

How to SSH to Your Server

Getting started…

You must have shell access available on your server. If you don’t know, you can always check the administration panel of your hosting to find out. Many hosting providers use something called “cPanel” to manage their backends, they will often change styles but the icons will look the same. Look for something that looks like this:

If you have shell access enabled on your account you should be either able to view the access credentials by clicking on this icon, or set them up.

Things you should know…

Having shell access available is sometimes dangerous, especially if your don’t use authentication keys. I have set up ssh keys on my server and only allow ssh keyed connections, this way you can’t just try to guess a password…you must have a keyed pair in order to make a connection. However, for the scope of this tutorial, I’ll simply explain how SSH to your server using the password credentials you set up in the last section.


Now that you have shell access set up, it’s time to connect. If you don’t know your server’s IP address you can look up your domain at: which will provide information about your hosting provider and should present your server’s IP address if it’s available. If it’s not listed here, you must log into your hosting account and find it there.

If your on a mac the ssh connection command looks like this:

ssh username@111.222.333.444 -p1234

Just replace the username with your ssh login credential, the IP address numbers with your server’s IP and “-p1234” with the port number your ssh access is allowed on (usually this is run out of port 22, you should change this if you can as everyone knows that’s the standard port for ssh access).

If your on a windows machine, the process is a little harder. First you need to download an ssh client like PuTTY.

How to use PuTTY.

I’ve found in the long run, using PuTTY on Windows is actually faster and more convenient than using a mac to connect via SSH.

DIY – Smart Home: Part 1

I’ll be doing a series on smartifying your house. What better way to start this series that with the most important device in man’s modern history, the toilet? Then we’ll take a look generally at the bathroom and see what else we can wire up in order to provide ourselves with some interesting albeit funny data. After conquering the bathroom, we’ll move on to something a little more complex, the kitchen. Finally, we’ll cap the series off with something that everyone with a smartphone should be able to do…check the garage door! We’ll also get into a little iphone development and program an app that will allow us to close the garage door remotely! But first, the toilet…

The idea…

Back when twitter was still learning to fly, I thought it would be funny to make a toilet tweet. I also thought it would be interesting to know how many times a day I use the toilet and how many gallons of water I was using. So I build a simple device to keep track. However, it wasn’t very useful or reliable and with Twitter’s adoption of oAuth Authentication, my feed went the way of the buffalo. Let’s revisit the idea and make some modest improvements in order to get some more information about our bathroom habits and have some fun tweeting about it in the process.

Getting started…

First off, we’ll need to know the basics. We’ll be using an ultrasonic range finder hooked up to an ethernet enabled arduino. We’ll also do some serverside programming in order to monitor out toilet and ultimately tweet every time we use our toilet. The rangefinder will act as a detection sensor and also provide us some useful information about the person’s position when they use the toilet, without the privacy invasion of a camera.


  • ultrasonic rangefinder from parallax (available at radio shack)
  • Arduino
  • Ethernet shield
  • copper wire
  • led
  • bread board
  • server hosting / LAMP enabled


The first step is to hook everything up and begin running a test program to make sure everything is set up properly. We’ll start by attaching the range finder to our toilet:

Next, we’ll run the wires from the range finder to the arduino/ethernet module hooked up wherever it’s conventient:

Finally, we’ll run power to the arduino and upload the example program for range finders provided with the arduino software package:

Once we’re able to output some serial data that shows we are taking accurate measurements, it’s time to modify code…


We need to modify this example program a bit to include the ethernet shield and to notify an address on our server as soon as we’ve tripped our sensor. We’ll start by importing some libraries and getting our setup function working:


// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  0x99, 0xA9, 0xDA, 0x00, 0x99, 0x99 };
byte ip[] = { 192,168,1,177 };
//byte server[] = { 173,194,33,104 }; // Google
byte server[] = { 11,222,33,44 }; // your server IP address

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
Client client(server, 80);

long inches = 11;

void setup() {

// sonar pins
//pinMode(13, OUTPUT); // blue
//pinMode(12, OUTPUT); // green

// reset pin
pinMode(9, OUTPUT); // resest
pinMode(7, OUTPUT); // ping pin

// start the Ethernet connection:
  Ethernet.begin(mac, ip);
  // start the serial library:
  //digitalWrite(9, LOW);


void loop()
  // send a sonar ping

Next we’ll add some custom functions:

void pingSonar() {
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;
  const int pingPin = 7;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  digitalWrite(pingPin, HIGH);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  inches = microsecondsToInches(duration);
  String inchesStr = inches;
  Serial.println("ping returned: "+ inchesStr +"...");
  // show LED colors
  if(inches < 30 ) {
    // then the person is sitting
     callServer(inchesStr, "sonar");
  } else {
    // do nothing...
  //cm = microsecondsToCentimeters(duration);
  //Serial.print("in, ");

void responseLoop () {
  for(int i = 0; i < 1200; i++) {
       // delay the timer
                        // BEGIN IF STATEMENTS FROM LOOP
                        // if there are incoming bytes available 
                        // from the server, read them and print them:
                        if (client.available()) {
                          //while(client.available()) {
                            char c =;
   } // end for loop
    // if the server's disconnected, stop the client:
    if (!client.connected()) {
      //i = 120000;
      //digitalWrite(9, LOW);
      // do nothing forevermore:

void callServer (String inchesStr, String type) {
  // reset pin nine
  /*digitalWrite(9, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(9, HIGH);*/
  // define some vars
  String str = ""+ inchesStr +"&type=" + type;
  // give the Ethernet shield a second to initialize:

  // if you get a connection, report back via serial:
  if (client.connect()) {
    Serial.println("Calling: "+ str);
    // Make a HTTP request:
    client.println("GET "+ str +" HTTP/1.0");
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed:" + str);
    //digitalWrite(9, LOW);
    //callServer(inchesStr, type);

long microsecondsToInches(long microseconds)
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See:
  return microseconds / 74 / 2;

long microsecondsToCentimeters(long microseconds)
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;

After we're done with our arduino, we'll need to create a script that will collect information about our toilet usages and also notify twitter when we're using it. We'll also need to set up a database where we can store this information. Let's create the database now:

  `id` int(11) NOT NULL auto_increment,
  `measurement` varchar(255) NOT NULL,
  `sensor_type` varchar(255) NOT NULL,
  `time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`)

Now let's create a script that will search for a $_GET request and update the database and twitter when it receives the proper information:

	Written By: Mike Newell
	No license - Feel free to copy!
if(isset($_GET['measurement'])) {
	$inches = intval($_GET['measurement']);
	if($inches < 16) {
		$activity = "sitting";
		$searchStr = "sitting+on+toilet";
	} else {
		$activity = "standing";
		$searchStr = "standing+at+urinal";
    if ($handle = opendir('./toilets')) {
	    echo "Directory handle: $handlen";
	    echo "Files:n";
		$images = array();
	    /* This is the correct way to loop over the directory. */
	    while (false !== ($file = readdir($handle))) {
	        //echo "$filen";
	        $images[] = $file;
	// select a random image
	$count = count($images);
	for($i = 0; $i < $count; $i++) {
		$imageNum = mt_rand(1, $count);
		$selectedImageSrc = $images[$imageNum];
	echo 'toilets/'.$selectedImageSrc;
	 * All of this info is needed only for API calls that
	 * require authentication. However, if the API call doesn't
	 * require authentication and you provide the information anyways,
	 * it won't make a difference.
	$api_key = ""; // your TwitPic API key (
	$consumer_key = ""; // your Twitter application consumer key
	$consumer_secret = ""; // your Twitter application consumer secret
	$oauth_token = ""; // the user's OAuth token (retrieved after they log into Twitter and auth there)
	$oauth_secret = ""; // the user's OAuth secret (also from Twitter login)
	 * The TwitPic() constructor can be left blank if only
	 * doing non-auth'd API calls
	$twitpic = new TwitPic($api_key, $consumer_key, $consumer_secret, $oauth_token, $oauth_secret);
	try {
	  * Uploads an image to TwitPic AND posts a tweet
	  * to Twitter.
	  * NOTE: this still uses v2 of the TwitPic API. This means that the code makes 2 separate
	  * requests: one to TwitPic for the image, and one to Twitter for the tweet. Because of this,
	  * understand this call may take a bit longer than simply uploading the image.
	  $resp = $twitpic->uploadAndPost(array('media'=>'toilets/'.$selectedImageSrc, 'message'=>"Someone is ".$activity." at Mike's toilet right now!"));
	} catch(TwitPicAPIException $e) {
		echo $e->getMessage();
	//$connection->post('statuses/update', array('status' => "Guess the activity! Someone is using Mike's toilet "));
	// set the values to variables
	$measurement = $_GET['measurement'];
	$type = $_GET['type'];
	// store the value in a database
	$db = new DBconnect("localhost", "user_name", "password", "database_name");
	$result = $db->query("INSERT INTO readings (measurement, sensor_type) VALUES ('$measurement', '$type')");
	if($result) {
		echo "successful.";
	} else {
		echo "unsuccessful input.";
} else {
	echo "get request with measurement not present";

We also need a twitter class that will handle pictures. I chose to use twitpic, you can download the library here.

We'll also need a small database class to manage input and output from our database. Download the demo at the bottom of the page to get it.

Once we've properly initialized everything, it's just a matter of getting the proper api keys from twit pic and twitter. Make sure to enter your database connection information into the new class, modify the arduino code with your server's specific IP address and path to the process.php file wherever you decide to store it on your server. You'll also need to make sure and have HTTP_OAuth and HTTP_Request2 installed on your server.

Download the demo!