Controlling an RGB LED with the power of the Internet and Electric Imp
17 January 2014

Lately I’ve been playing with an Electric Imp, using it to control a single 3-color LED. My goal is to develop a product out of it, but I’m skeptical that I’ll ever get it off the ground, so I’m sharing my findings here. (Also, if and when I do start selling this, all hardware and software will be open anyway).

Components

First thing is to get the Imp set up with a breakout board and talking to the Internet. Adafruit sells both Imps and April breakout boards, and the Electric Imp “Getting Started” guide will walk you through setting up the Imp for the first time.

April breakout board and Imp

April breakout board and Imp

The LED I want to control is one of Adafruit’s 12mm Diffused Flat Digital RGB LED Pixels. Note that this LED wants 5V, which the Imp is not equipped to provide, so using an external 5V power supply is necessary. So far I’ve been using a power adapter and 5V 2A supply to great effect.

Wiring

Either using a breadboard, or if you’re like me and soldered female headers onto the April, connect the input wires of the LED to the April (the LED I’m using has a handy arrow printed on the silicone to show directionality of clock/data). Connect the blue wire to Ground, yellow wire to Pin7 and blue wire to Pin5. On the output side of the LED, insert the red wire into the + end of the power adapter, and the blue wire to the – end. You’ll also have to power the April separately. For now I’m using a USB cable–note the jumper on the board, and make sure it’s in the correct position for your situation (“BAT” or “USB”).

LED wired

LED wired

Code

Fire up the Electric Imp IDE and set up the Imp with a Model (codebase). Note that the “device” will be associated with the April board, not the Imp itself. I named my model Agent RGB.

Insert the following as Device code:

function staticRGB(rgb) {
    server.log("Static RGB: "+rgb);
    hardware.spi257.write(rgb);
}

server.log("spi config start");
hardware.spi257.configure(SIMPLEX_TX, 15000); // Datasheet says max 25MHz
hardware.pin5.configure(DIGITAL_OUT);
hardware.pin5.write(0);    
imp.sleep(0.01);
hardware.pin5.write(1);
hardware.configure(SPI_257);
server.log("spi config end");

agent.on("rgb", staticRGB);

In this section we are defining the code that runs on the Imp itself. The staticRGB(...) function sets the SPI to our desired RGB value (which is 3 bytes large). The next several lines set up pin5 as digital out and configures SPI (I have little idea what this means…). The last line (agent.on(...)) registers a trigger to the staticRGB(...) function when the Agent communicates with the key “rgb”.

Insert the following as Agent code:

function requestHandler(request, response) {
  try {
    // check if the user sent "red" as a query parameter
    if ("red" in request.query) {
        local rgb = blob(3);
        rgb.writen(request.query.red.tointeger(), 'b');
        rgb.writen(request.query.green.tointeger(), 'b');
        rgb.writen(request.query.blue.tointeger(), 'b');
        device.send("rgb", rgb);
    }
    // send a response back saying everything was OK.
    response.send(200, "OK");
  } catch (ex) {
    response.send(500, "Internal Server Error: " + ex);
  }
}
 
// register the HTTP handler
http.onrequest(requestHandler);

The requestHandler(...) function processes the request made to the Agent URL. In the above example it returns either 200 or 500, depending on the GET parameters. So, if you hit http://agent.electricimp.com/<YOUR AGENT ID HERE>/?red=255&green=255&blue=255 in your browser, the Agent will send those RGB values to the device as a 3-byte blob.

Next Steps

I really wanted to control this thing without having to enter some hard-to-remember URL and parameters, so how can we achieve that? Well, at first I thought about IFTTT and all the awesome it represents. After implementing it I realized it was not an ideal solution, but I’ll outline my steps anyway.

After doing some digging I found a Github repository written by Abhay Rana aka @capt_n3m0. It basically operates as a fake WordPress installation, and in the current version it will take any WordPress Post and reroute it to a desired URL. Here’s how it works:

  1. I quickly spun up an instance of Abhay’s code on a Heroku app.
  2. I added a WordPress channel to my IFTTT profile with “Blog URL” containing the Heroku app’s URL, and “spilliams” as my username. I left the password field blank, but you don’t have to: these values will get passed through to the Imp Agent, so you could do some basic auth with them if you wanted to.
  3. I created a new IFTTT recipe that states if: “any new Tweets from [my developer Twitter account] with the hashtag #impled” then: “create a wordpress post with {{UserName}} as the Title, http://agent.electricimp.com/<AGENT ID>?{{TextNoHashtag}} as the Body, and ignored as the Tags”. Oh, and it might behoove you to “publish immediately”.
  4. Simply Tweet something like “red=255&green=255&blue=255 #impled”! IFTTT will pick up on the Tweet (within 15 minutes, see below) and call out to the Heroku app with the crafted response. The Heroku app will hot-potato it over to the Imp Agent and your LED turns on!.

So why did I abandon IFTTT? 15 minutes is too long. My potential applications for this are things like “you got an iMessage/email/other urgent communique” or “it’s 10 minutes before your next meeting!”. Sure, IFTTT allows you to forcibly run the recipe, but I prefer to use that solely for debugging. What, should I write a cron job to hit https://ifttt.com/myrecipes/personal/<ID>/force_run every 30 seconds? There’s probably a throttle on requests per hour. And anyway that feels pretty wrong to me, on a high level. The tech should work without kludge like that.

So what’s next for ImpLED? I’m going to try modifying the Agent code thusly (pseudocode):

if (request is POST) {
    process parameters
}
redirect to Heroku instance, passing LED and program states as GET params

The Heroku instance will have a cute little form on it, with whatever options are required to drive the Imp. My plan is to include commands like “blink”, “ombre”, “hsb wheel” in addition to the “static” command I’ve described above. Tune in again soon for more Imp Ventures!

Tags: , . Posted in impled