Introduction: Dance Notification Network

About: I tend to have too much energy, so I try to do everything so I can sleep at night.
Ever since finishing school I regularly hear friends saying "I'm sad I didn't take more electronics / programming / web dev classes and really learn how to use it." In the 3 years I've been out of school, I feel I've learned more practical design skills in new domains than I learned in all 6 years of college / grad school combined. After thinking about why some of my friends and I have had different experiences, I realized the hardest part of learning new domains is figuring out where to even begin. Electronics and web development are saturated with a million different development platforms, each with their own particular programming language, programming environment, pros/cons, and weird name. Each set of tools and architectures come with their own learning curves and abstractions. Ideally I'd come up with a witty analogy here, but nothing comes to mind so maybe later :)

I wanted to do a project that someone who wanted to broaden their domain exposure could use as a starting point with a lower barrier to entry. By crafting a project that demonstrates several of the powerful prototyping tools in different fields, then showing how they can be interfaced together to create a working multi-dimensional project, the idea is to inspire people to craft their own projects that utilize their particular depths and interests yet push them out of their comfort zone into new domains in a controlled way using properly-selected tools. Enough talk.


Backstory

I like to dance. A lot. The second-most common text I get is "are you dancing tonight?", probably right after "when are you gonna get here?" (I'm chronically late, but acknowledgment is one of the steps on the way to recovery). There's a very well-used website in San Francisco for acquiring important and simple information, http://isthereagiantsgametoday.com/. Extremely straightforward, just tells you whether or not there's a game so you can plan your miserable commute accordingly. Inspired me to create a Dance Button that when pressed updates a website www.istripdancing.com (yes I realize that can be is trip dancing or i strip dancing) and communicates to friends that you're dancing.

In order to do this, you need a local device that can detect when a button is pressed, a module that enables the device to communicate the information to the internet, a website that can display the button status, and a web server that can mediate between the device, the website, and any social platforms.

Wanted to use platforms and tools that are extremely flexible (can be used in many different ways), well-documented (so bending them to your will is easier when you run into bugs), and abstract away as many of the technical concepts that contribute to steep learning curves as possible (but allow you to dive into the details if you'd like).

The last diagram shows an outline of all the components needed for this system and the interfaces between them.

Step 1: The Electrical

Generally when doing projects without strong form-driving requirements (it's just a silly button, so weight size, how it fits into your hand, how people feel about the form aren't critical to it being successful), before I do any of the physical/form design, I pick the electrical components and architecture that are going to make my life the easiest. There's a huge variety of options for controllers, batteries, connectors and wiring, but options are normally very different physically, so choose the ones you like the best, then fit them to your box. See the sketch schematic for a general overview of the final system.


Choice of microcontroller wireless module

Arduino is the obvious choice for most people. Provides an electrical platforms that provides most basic functionality makers need, has a relatively intuitive language, cheap, and has TONS of online documentation. Partnering it with a well-documented Wifi module with a powerful online API like the Electric Imp seems like a natural choice (Spark Core is another option that will be released soon). However, what I'm trying to accomplish here is so simple that rather than using the Arduino to do all logic and using the Imp solely as a communication channel, I decided to take advantage of the Imp's onboard processor (which few people realize can do many things the Arduino can do) to eliminate the need for an Arduino from the system. You could just as easily use both together (which might be easier for beginners). The advantage of skipping the Arduino is fewer parts, longer battery life, lower cost. The main disadvantage is that the Imp uses Squirrel, a language that uses a slightly different flow and syntax from the Arduino, and might be harder to learn and slightly less useful (based on the frequency you might use it).


The strategy:

- We're decided on using the Electric Imp, which runs at 3.3V and can consume on the order of 5mA in sleep mode. LiPo batteries come in multiples of 3.7V nominal, and I happened to have some small, lightweight 2000 mAh LiPo batteries from SparkFun lying around that would work perfect, lasting approximately 16ish days. If you're ever looking for a source for cheap, reliable LiPo batteries, go to www.all-battery.com. I love them.

- Next we need to make sure the Imp can control our LEDs that light the button. I'm using the common cathode diffused RGB LED from Sparkfun, which needs to pull 20 mAs for each color. Unfortunately while going through the Electric Imp documentation, I found the Imp's GPIOs can only source/sink up to 4 mAs, which means we can't power the LEDs directly from the Imp. To address this, a common strategy is to use transistors to turn on the LEDs. A great explanation of transistors can be found HERE. Effectively the transistors take a smaller current input from the Imp to close an internal switch that allows the LEDs to be powered from the battery, so our Imp isn't trying to provide more current than it can. The 2N2222 transistor is very common in low-power amplification applications. Because we're using a common cathode LED (meaning positive terminal for each LED is shared) and each LED needs a different applied voltage to work (and therefore a different current-limiting resistor), I setup all of the transistors to share their emitters with ground. See the notebook work for how to size the resistors for the transistors to work.

- After selecting all the auxiliary (non-Electric Imp) components, I like to lay them out nicely and attach them to a protoboard (printed circuit board with through holes you solder components to) that will connect to the Electric Imp with breakaway headers (this way I can easily remove the protoboard from the Imp if I want to use the Imp in another project). Protoboards come with a huge variety of routings between the through holes: the one I chose from Amazon has no routing between holes, giving me more freedom with component layout but more work doing my own routing. I included connectors for the battery (2-pin JST), LED (4-pin breakaway), and button (2-pin JST) so the system could be easily disassembled. The final step is to add a jumper to the Imp to easily switch between battery or USB power.


Now that we have a hold on the electrical side, time to move onto the box that'll bring everything together.

Step 2: The Physical

Pick the button!
I LOVE buttons. I've been pushing buttons all my life. Dancing is a huge outlet of energy for me, and I wanted a button that would begin it with a bang. These big buttons from Sparkfun are great and have a satisfying click when you smack 'em. They include an LED wired to run at 12V that we'll swap out, and an electrical switch with Normally-Open (NO) and Normally-Closed (NC) terminals. I replaced the stock LED with my own RGB LED with a plug, check the pictures to see how. The plan is to use the LED as a feedback mechanism. Initially the color and lighting sequences will be able to show when the button is in dance mode (with some pizzazz). Eventually I aim to integrate multiple buttons into www.isanyonedancing.com with a few more social features, then the light will show when other people are in dance mode, and maybe notify you when other people think you should be dancing.

While the button was dismantled, I figured it was worth it to add a little extra flair. The Objet Connex 500 printers can print transparent materials, as well as print with 2 different materials simultaneously. To try out this functionality, I decided to replace the yellow button dome with a clear one to better work with my RGB LED and enable me to print into the dome some text. Also replaced the stock diffuser with a piece of paper with the dancing man.


Get the dimensions straight
Now that all the electrical components are chosen, I laid things out in various configurations (just on a table) to figure out the smallest, most convenient packaging envelope I could achieve. Then CAD it all up so you can design a 3D printed box around it. I designed in features to the box to make assembly easy: hex nuts are first inserted into the top, the button is then attached using the stock mounting ring, then electronics inserted, and finally closed using 8-32 screws from local hardware store.


3D print the form
There are a huge variety of printers, each with their own pros/cons. Here's an Instructable with a good lay of the land on 3D printing. Pick the one for you that's a proper balance of resolution, materials, accessibility, and cost, then lookup what's necessary to learn it. There are lots of good Instructables on how to use 3D printers. Or just send your STL file to an online 3D printing company like Shapeways.


Elbow grease for finish
A good bit of patience is needed to make a printed piece really shine or be nearly transparent. The Objet manual recommended a progression of 150, 300, 600, 1000, 1500 sandpaper, finishing with a plastic buffing compound and a rotary tool. I used 3M Plastic Cleaner followed by 3M Polish and Protector, each with a Dremel felt polishing wheel. I could find a particularly good tutorial on exactly how to do this, so maybe later I'll make a quick Instructable outlining the nuances and pitfalls to avoid.


Everything physical that needs to be done for for the button (electrical and mechanical) is done, time to make the button more than a pile of plastic and metal with some programming magic.

Step 3: The Embedded Work

(NOTE: Electric Imp performed a major overhaul on their IDE after I finished this project. The planner no longer exists, and is instead replaced by Agents, which are analogous to the functional output blocks in the planner.)

First order of business in bringing the button to life is getting the Imp to interface properly with the button and LEDs, then getting it to talk to the Internet.

If you have any experience with Arduino or other microcontrollers, this step would normally be:

  • firing up your preferred IDE (integrated development environment, or software that you write code in an provides additional features like checking your syntax, coloring your code to read easier, and others)
  • writing a program that sets up pins on your microcontroller as inputs for the button and outputs for the LEDs, then logic the controller uses to take sequences of event (button pushes) to drive its actuators (light colors and sequences, sending messages to the internet)
  • loading that program onto your microcontroller with some sort of communication cable (oftentimes USB)


However, the Electric Imp uses an online IDE. This means you write your program in a web browser on the Imp's site, then hit a button that automagically pushes the program to the Imp over Wifi. Has the advantage of not needing to install an IDE on any computers you want to program from, as well as keeping your code safe in the Imp's cloud.

Electric Imp's developer wiki has lots of examples on how to program in Squirrel to get the Imp to do what you want.

If you're familiar with Arduino, Squirrel's syntax is relatively similar (similar to C and Java), but is more dynamic like Python. The major differences you need to wrap your head around:

  • There's not a loop function in Squirrel. Instead the code runs from beginning to end, running functions as it runs into them. Recurring functional code run (like a loop function) can be created as follows. If you have a function testFunction, you use imp.wakeup(X, testFunction) at the end of the definition of testFunction. Imp.wakeup tells the Imp to call testFunction again in X seconds. So every time testFunction is called, it will be run again in X seconds. Like a loop where instead of running as fast as possible, you can set the time between runs.
  • If your code is run by events that don't need a loop (such as inputs from the web), you define INPUT classes for the Imp, which tell it which functions to call when that particular input is detected.
  • Finally there are OUTPUT classes, which are used to send particular data to the output ports in the Electric Imp planner.
  • Defining INPUT and OUTPUT ports allows you to hook up functional blocks (like HTTP requests) in the Planner to make your devices interact with the internet


What logical flow do we want? Really simple.

  1. Hardware interrupt checks when the button is pressed.
  2. When the button is pressed, actuate the impServerOut OUTPUT class (which we will hookup to an HTTP request to tell our server the button is pressed)
  3. Additionally, there's a simple state machine that keeps track of whether or not the button is in Dance Mode, and animates the light when it is.


The attached code danceButtonSimple.txt, along with the Planner configuration, is all we need on the microcontroller side. When the button is pressed, the Planner sends an HTTP POST request to the server, which will keep track of the times of the requests so it can update its webpages accordingly. Now on to the server!

Step 4: The Web Server

Choice of server website
A common tool for web prototyping is Heroku, which is a service that allows you to easily launch a web application. It supports a variety of web application frameworks (standardized ways to structure programs that run websites) in a variety of languages, with great documentation on how to do it. It eliminates the need for you to spin up your own Linux server (which it beautifully hides under the hood) to host your web application. If you don't know what that means or have any idea how to do it, praise the heavens Heroku exists. And for most things you'll need to do for prototypes, it's free.

Within Heroku there are many web application frameworks you could go with. I've been loving the simplicity of Python and the huge variety of modules created for it, so I decided to go with Python running Flask and Bottle. Flask is a simple Python web framework that handles the addressing of your pages, and executes logic structures and accesses databases as necessary. Flask then uses the Python module Bottle as a template engine: Bottle takes mostly pre-populated HTML templates I created and feed in dynamic information from my databases whenever the website is accessed. (technically Bottle can do everything Flask can I think, but it was recommended to me to use Flask for routing with Heroku and Bottle for templating).

Get an application online
You can launch a working web application on Heroku for the first time in an hour just by following tutorials. The major steps are:
Use your own web address
Heroku assigns your application an address (usually APPNAME.herokuapp.com). If you want to use your own domain for your application (for example I wanted www.istripdancing.com instead of dancebutton.herokuapp.com), you'll need to purchase your own domain and redirect it to the Heroku address. I used Hover to purchase my domain for $10 for a year. I've heard you can get domains cheaper through other services, but I haven't looked into it yet. After you've purchased the domain, it's incredibly simple to forward requests to your domain to the Heroku app (see snapshot).


Heroku details
Once you have everything up and running, if you haven't done stuff like this before there's several tools you'll be learning as you morph your first Heroku app to do your bidding. Here's a brief overview to get your head in the right place.

Heroku's basic application running process
To run an application in Heroku with Python and Flask, Heroku looks for the app.py file, which needs to be structured according to the nuances of Flask. Before running the file, Heroku looks at the requirements.txt file to determine what Python modules are required to run the server. There are a million Python modules and each application usually only needs a few modules installed to run. Heroku installs those modules, then spins up an instance of Python running your app. It's important that as you develop your application you understand the Python Virtualenv (virtual environment) and how to update requirements.txt properly (described below). App.py tells Heroku what to do whenever a request is made to certain addresses/routes within your site (a function for the web server to run is associated with each route). These routing functions return the raw code to be displayed in the browser. The simplest example is demonstrated in the Heroku Getting Started tutorial: the default application route returns simply the text "Hello World", which will be displayed in the browser when someone goes to that address.

Creating dynamic webpages with Heroku
If you wanted to return something more interesting to the browser, you might return HTML that's determined based on the state of your server. To do this, I used the Python module Bottle. I create an HTML template with all the formatting and static text I want on my page, and then specify dynamic information containers within the template with {{variable}} (a particular of Bottle). To populate that space with information from my server, I use the template function within bottle in the return line of my Flask function (bottle.template(...)).

Changing and redeploying your web application with Heroku
With Heroku, you work on local files on your computer, then when you want to update your server, you "push" the changes to Heroku with Git. Git is a can of worms inside a can of worms itself, but essentially it is a revision control system for code - a fancy way of saying it keeps track of your changes for you. You write your code, and every time you want Git to store your current code, you "commit" your changes, and can restore your code to any previously committed state whenever you want. Git can be setup to have main revision database online (a free example is GitHub). In our case, the main repository is Heroku, and whenever we want to update the server, we simply "push" our most recent version to it. You can find the specifics how to use Git with Heroku here. If you want to learn more on Git:
Working locally
Dependencies can be a huge source of headaches for people using Python on different machines if you're not careful. Imagine I made my own Python module that lets me call myModule.myFunction(), and I use that in my Python program. If I simply give you my Python file without the module, your computer will have no idea what myModule is referring to. To address this, we use a virtual environment with Virtualenv, or an isolated instance of Python where we have direct control over what is installed, as well as a well-designed workflow for running our programs on different machines. A simpler way to visualize this: you have two computers, one that has Adobe Photoshop and Microsoft Office, the other with no software. The Excel files and images you create on the first computer can't be opened on the second because the computer doesn't have the programs (or modules) that know how to read the files. A virtualenv would be akin to having an account on each computer that you can log into that has identical programs. Any time you start using a new program on one account, you'd want a way for the same account on the other computer to have it too, so you can open all your files. Virtualenv is this for Python.


The workflow for the virtual environment with Heroku is:

- setup Virtualenv

- activate virtualenv
source venv/bin/activate

- install new modules using pip or easy_install (installation managers for Python)

- update requirements.txt by "freezing" the Virtualenv dependencies into the file (requirements.txt keeps track of what modules are installed in the virtualenv)
pip freeze > requirements.txt


Alternative explanation of Virtualenv for those whom I confused (sorry!).


After you have Heroku, Git, and Virtualenv setup, and you've written some code into your app.py file, you can run a test server locally before pushing the code to Heroku, to check to make sure it works first. To run a local server, while in the virtualenv in console run:

foreman start


This will run a local server at 0.0.0.0:5000 in your web browser. Go there, test the functionality of your server. If errors pop up, the browser will show them, and you can check your console for debug messages.

Once your happy with the functionality of your server, in console run:

Add any new files to the local Git copy
git add .

Save any changes to your local Git copy
git commit -m "Add your commit message that describes the changes you made since last time."

Copy you local copy to the Heroku copy, or repository
git push heroku master


And viola! Your code is now running on Heroku and can be accessed by the Internets! I still need to describe how to record button pressed events in the server using a database, but I will do this later. Now on to talking with Facebook.

Step 5: Social Integration

What good is it for a website to show that you're dancing if no one thinks to look at it? Obviously it needs to tell everyone on Facebook whenever you're dancing, so that they may join you and be merry.

There are several different ways to make your website interact with Facebook. You can read about various SDKs here. There are tons of examples on the Facebook site of code you can copy and paste to get basic functionality.
The Facebook Graph API provides low-level HTTP access to Facebook. This means that our server can make simple HTTP requests (like the ones you put into your web browser) to sign in to Facebook, post on your wall, etc.

Setup a "login" for your web application
In order to allow the server secure access so not just anyone can login, we need to setup a Facebook application. Go here, sign up as a developer, and create your own Facebook app. The Facebook app will only work as our login to Facebook: we won't actually be programming any application on Facebook itself. All you need to do is:
  • enter the App Domain of your Heroku server (you can find this in the Heroku dashboard through a web browser)
  • disable "Sandbox Mode" to allow anyone to use the app
  • checkmark website with Facebook login, and enter the server address (this is going to allow people who are already logged into Facebook to give our Facebook app permission to post on their walls when the button is pushed)
Now that we have that setup, note your APP ID and APP SECRET. These will serve as our server's username and password for logging into Facebook.

"Login" to Facebook with the web application with Python
Since the server runs in Python, we need to go through the motions with HTTP requests to gain access to Facebook. Basically we program the APP_ID and APP_SECRET into the Python code, "login" to Facebook with these to get our authorization token. Then every time we post to Facebook, we make the post request and include our authorization token. See the attached facebook.py for my Python functions for logging into Facebook and posting on a wall (note that I removed my APP_SECRET and APP_ID).

Authorize Dance Button to post on Facebook walls
We now have a server that can log into Facebook and post whatever we please on the wall's of those poor souls that give us permission. How do we get this permission? The social strategy is up to you, but technically speaking we'll use Javascript. The Facebook Javascript SDK has lots of great examples you can copy and paste into your HTML templates to make your website interface with Facebook. To load the SDK on your page look here, and to login with the SDK look here. Check out register.tpl for my Bottle template with the Javascript code for authorizing the Dance Button Facebook app (note that I removed my APP_ID).

Step 6: Time to Dance!


More action media to come...