Sep 06

Building Pulse & Bloom - an interactive biofeedback installation at Burning Man 2014

This was my second year attending Burning Man. Many use Burning Man as a week to detach from their workweek and experience a new life of intense leisure. Not me, I come to Burning Man to build.

Pulse & Bloom is a 2014 honorarium installation. The core team of 6 people — Saba Ghole, Shilo Shiv Suleman, Rohan Dixit, Heather Stewart, Luke Iseman, and myself — built 20 interactive lotus flowers made out of steel and rowlux. Each lotus flower ranges from 8 to 18 feet tall, each of which lights up with your pulse. You and another person can put your hands on a couple of Hamsa hands at the base of the lotus flower and your respective heartbeats will light up the flower.

We've gotten some great press coverage at the BBC, The Guardian, The Atlantic's Big Picture twice, CBS News, NBC News, and MSNBC.

As usual, the complete source code for Pulse & Bloom is on GitHub.

Your heartbeat in light

Here are a couple videos of all twenty lotus flowers in full working order.

Each lotus flower is blue until a person or two sits down at its base and places their hand on the pulse sensor. You can see the Hamsa hand and its embedded pulse sensor in this shot of my girlfriend Brittany and me working on keeping the electronics going.

Photo credit Jim Urquhart / Reuters

When a pulse is read, the lotus flower shoots the heartbeat up the stem and into the petals, where it blooms in a brilliant display of amber. When two people's hands are being measured, both of their heartbeats are shown as two distinct colors.

How the electronics are made

There are five stages to making the electronics:

  1. Making the custom circuit boards
  2. Making the custom pulse sensors
  3. Driving the high current LEDs
  4. Writing the firmware
  5. Powering the lotuses

1. Making the custom circuit boards

The circuit board controls all of the lighting, sensors, timing, and debugging sequences. A reliable circuit board couldn't just be an Arduino and a breadboard. I decided to use OSH Park and OSH Stencils to fabricate inexpensive circuit boards. I ultimately went through seven revisions while we worked out the final design of the lotuses. This included adding additional lights, additional sensors, controls for EL wire, and better power management using an external buck converter.

This board has support for multiple high current petal LEDs driven by digital RGB pins (used for fading colors in and out using PWM) and in multiple voltages. The high current petal LEDs runs on 12V, which comes directly off the battery, the ATmega328p chip and stem LEDs run at 5V, and the pulse sensor runs at 3.3V.

To convert 12V to 5V I use a $3 switching voltage regulator from Electrodragon. This requires a +/- connection for both 12V in and 5V out. To convert 5V to 3.3V I used a linear voltage regulator soldered directly on the board, since the current requirements of the pulse sensor were around 20mA. The heat dissipated was negligible compared to the rest of the circuit.

I also added terminal connections for two 5 meter LEDs that wrapped around the tall lotus stem. We attached two 5 meter LED strips around the stems because when two people put their hands on the two pulse sensors, we need an easy way to show both heartbeats without one winning out over the other. When only one person's hand in being measured, both 5 meter light strips show the same color, which makes it that much brighter for a single person.

Lastly, the two pulse sensors terminate their I2C wires directly on the board. I used two separate I2C channels instead of one to cut down on time. I could easily have put both pulse sensors on the same I2C connections, but that would've required both pull-up resistors on the SDA and SCL data lines as well as a rewrite of the timing functions for the sensor.

All of these terminations are made using 2.5mm and 3.5mm pitch screw terminals. In hindsight I would have used female JST-SM mounted connectors and ordered custom wires with JST-SM male connectors. I assumed the lowest common denomenator would be bare tinned wire, but all of the bare wires could easily have been switched over to polarized, latching connectors. This would have reduced over 90% of the field work I had to perform on boards, as their wire would fall out of the screw terminals due to not being screwed in with enough force.

The board was laid out to be as big as a pack of gum. All of the 12V traces are thickened and isolated on the right side of the board. They are rated for 3 amps although they would end up only driving 1 amp on the playa.

These boards are then stenciled with solder paste and populated with their chips and passive components.

An inexpensive hot plate is used to reflow the solder. The chip is in a TQFP package, which has a 0.5mm pitch between pins. This makes it nearly impossible to hand solder. This stencil and reflow technique works well and my yield stayed high at around 95%.

Finally, the board is ready to be populated with screw terminals.

The final board in a dust-proof enclosure.

2. Making the custom pulse sensors

This was both the riskiest piece of the puzzle and also the most fun to build. In order to show your heartbeat on the lotus, I need to have a clear reading of your pulse. There are a fair number of issues with most off-the-shelf heartbeat sensors, including:

  • Cost: While a $50 pulse sensor is nice, it's way out of our budget. We spent $6 in components to make each of our pulse sensors for a total of 40 sensors (two per lotus).
  • Design affordance: There were a fair number of pulse sensors that required an infrared light on one side of your finger and an infrared detector/receiver on the other. This clamping of your finger wasn't something we could get away with in the desert. We needed a sensor you could just touch and hold on one side. It needed to be a simple interface so we wouldn't have to show any instructions.
  • Reliability: When a sensor gets covered in dust, will it still work? Infrared light, thankfully, passes through a layer of dust and can read the changes in blood flow in your finger. Some options were entirely visual and they would have performed quite poorly out on the playa.

The first prototype I built suffered from the design affordance and reliability issues, although it worked pretty well in ideal conditions.

We ended up finding an IC by Silicon Labs called the Si114x, which uses three LEDs — two infrared and one visible — and a small QFN-10 sized light sensor. The original sensor we used was the Modern Device pulse sensor, which also provided firmware and ideas for a board layout. The folks at Modern Device were kind enough to offer advice on how they built their sensor and about how to fix the infrared LED issues we hit. I owe them beers for saving me from many more excruciating hours of trying to build sensors that don't sense.

I built out a small PCB the size of a fingertip.

This tiny IC is a bit tricky to solder as it has no leads and the pins are extremely close together. My yield dropped to about 80%, but 4 out of every 5 pulse sensors I built worked perfectly the first time. If they failed, I would remount them on the hot plate and try wicking away any solder bridges I could find. This worked only about half the time. After that I gave up and now have a plastic cup full of broken pulse sensors.

Finally the sensor is hooked up and a tiny red light is emitted, letting people know where to put their fingers.

3. Driving the high current LEDs

What turned these lotuses from flowers into gems are the high current LEDs mounted in the petals at the top. There are 9 of these high current LEDs per lotus, split into groups of three, each driven by a constant current driver.

If you were to look at one of these LEDs from a few feet away, you would immediately see spots in your eyes. They are extremely bright pinpoints of light. The fact that they are also full color and need a heatsink due to their brightness means that you won't just find these in an easy package ready for plugging in.

Photo credit Jim Urquhart / Reuters

Normally a single LED is powered by a single constant current driver. This driver can drive up to 1A of current at 12V. Because we were only using a single channel of color (blue) in the rest state, which is where the lotus spent most of its time, we could triple the number of LEDs driven by a single constant current driver.

When in use the petals glow amber, which uses two channels (100% red, 50% green) but only for a moment while at peak current. So while the peak current is above what this constant current driver is rated for, it's only at peak and therefore within our tolerance.

Using a Chinese distributor, we bought these Sparkfun high current LEDs for $0.86 each instead of the full $15. However, we also bought 80 of Sparkfun's PicoBucks to use as our constant current driver. While we could have built this ourselves to save money, buying 80 of something at $15 each is still only $1.2k, while building them ourselves would only have saved a few hundred dollars.

We bought 200 high current LEDs, all of which had to have their 6 anode and cathode connections soldered.

In order to connect 9 high current LEDs to the board, we need to drive them in groups of three. Each group has 6 connections: red, green, blue anodes, and red, green, blue cathodes. The wiring diagram for this setup can get a bit rats nesty, but the end result was fairly easy to work with, as the picobuck groups didn't cross.

Finally, a shot of a complete picobuck with the wire connectors in the background.

4. Writing the firmware

The complete source code for Pulse & Bloom is on GitHub. There you can find the firmware used to program the main circuit board's ATmega328p chip, as well as designs for the laser cut cowl that sits over the pulse sensor's Si1143x IC.

The easiest way to read the firmware is to dive into src/pulse.cpp. It has all of the pulse and rest states and handles the high level logic.

The state machine that runs the entire routine is determined by a couple of critical measurements. The program takes a measurement of both pulse sensors and determines whether a finger is covering either of them and whether or not that finger has an active pulse going.

// Modes
void determinePlayerMode();
void determineFingerMode(int sensor1On, int sensor2On);
void resetStem(PulsePlug *pulse);
uint8_t adjustBpm(PulsePlug *pulse);

When there are no fingers on either of the pulse sensors, the program runs the rest state, which is a blue-topped lotus with a small blue snake running up and down the stem. The program is merely waiting for somebody to put their finger on a sensor.

// State: resting
void runResting();
void runRestStem();
void runRestStem(PulsePlug *pulse, int16_t currentLed);
void clearStemLeds(PulsePlug *pulse);
void beginPetalResting();
bool runPetalResting();

The firmware for the pulse sensor originally came from Modern Device's pulse sensor. Before a heartbeat is shown an accurate measurement of a heartbeat needs to be read. In order to determine whether a heartbeat is found and at what speed, a number of light detection measurements are taken and analyzed.

Modern Device's firmware simply finds the high frequency curve (the heartbeat) and the low frequency curve (the light sensors leveling out) and then use a simple peak and valley hueristic to determine the moment a heartbeat begins. This can take up to two or three seconds at first, so a bit of unwinding animation prepares you when you first put your finger on the sensor. I modified the firmware to account for multiple pulses on the same lotus and to have thresholds that worked better for the desert.

When a finger is detected, the stem snake lights shoot backwards up and down the lotus in prep for a heartbeat. This looks seamless as it clears the stem. This way a heartbeat doesn't interrupt the rest state.

// State: end resting
void beginSplittingStem();
void runSplittingStem();
void runSplittingStem(PulsePlug *pulse, int16_t currentLed);

When a heartbeat is detected, it is first shot up the stem. The color is determined by how many pulse sensors are being used. 1 heartbeat shows amber. 2 heartbeats show in white and light red.

// State: stem rising
bool runStemRising(PulsePlug *pulse, PulsePlug *shadowPulse);

Once the heartbeat reaches the top of the stem, the petals then fill with light.

// State: petal rising
void beginPetalRising();
bool runPetalRising();

After a set delay, the petal slowly lose light while waiting for the next heartbeat.

// State: petal falling
void beginPetalFalling();
bool runPetalFalling();

Lots of debugging messages have been left in the code and are accessible using the Serial pin on the board. Just turn on USE_SERIAL, which is commented out at top. Note that this increases binary code size by about 2.5K. I wrote a lot of logging.

// Debugging
void printHeader();
void blink(int loops, int loopTime, bool half);
int freeRam ();

5. Powering the lotuses

While much of what I built above came out of knowledge I already had, learning how to power this large of an installation off just a battery was all new to me. I'm used to microelectronics that run off a coin cell or AA batteries.

Measuring current and power usage

First, in order to figure out how big of a battery we needed, we had to measure how much power we were taking. I hooked up an ammeter in series with a single lotus to measure the current draw. In rest state, a single lotus drew 0.75A at 12V. In the active pulsing heartbeat state, a single lotus drew 1.5A at 12V. Since a lotus spends 95% of its time at rest, we rounded the average current consumption to 1A.

Twenty lotuses at 1A at 12V meant we needed 240Ah to sustain a 12 hour night. A car battery was recommended, but car batteries can only discharge down to 80% without irreparable harm. However, a marine deep-cycle battery can go down to 20% without harm.

This 150 lb. battery has enough capacity, although we ended up adding a couple 6V batteries in series (to boost them to 12V) and then running them in parallel to offset some of the load.

Dealing with the voltage drop

A big issue we ran into was the voltage drop across the power lines. We placed the batteries on the edge of the installation, which meant some of the lotuses had 20 meters of wire between them and the battery. The voltage drop per 10 meter section is nearly 2V, which means that the voltage reaching the further lotuses was down to 7.5V.

The high current LEDs were not able to be smoothly driven at this low of a voltage, causing them to flicker. We determined that a voltage drop was responsible for the flickering, which got worse the further the lotus sat from the batteries. But when we discovered this the wires had already been trenched 6 inches beneath the playa. A day of work lost, but we sucked it up and ripped out all of the ground wiring to accommodate the battery which had to be moved into the center of the installation.

At the end of each night we had to bike out with a trike and carry all 300 lbs. of batteries back to camp, where they were hooked up to a 1 kW solar array, where they were charged at 48A over 6 hours.

Prototyping the lotuses

Back at American Steel in Oakland, the lotus stems, bases, and petals were ready to be hooked up. These twenty lotus stems were bent by Heather. They range from 6ft to 16ft in length and each weighs 50 lbs.

Such a heavy stem needs a larger base and heavy anchors to stay upright in the wind.

We placed the lily pad over the base to cover it up and then added all of the electronics. Lights, sensors, and circuit boards all had to be mounted.

This is a photo of our first complete lotus flower. Just compare its sheer size to Shilo.

Once we were confident that one lotus would successfully light we left the other 19 lotuses packed away for assembly on the playa.

A dusty scene

We drove out in the biggest rental car I could get my hands on. Our minivan is full of electronics, bicycles, tents, costumes, coolers full of fruit and veggies, dry snacks, and water.

Since we were early arrival, they give you these red bracelets. They say Work hard, don't do stupid shit.

The boards would accumulate dust on them everyday. Our plastic enclosures turned out to be too big for the holes we made in the platform. So we ended up using ziploc bags. These baggies stayed attached, but the only reason they didn't cause any issues is that the boards worked just fine in the dust, as you can see here.

If dust was a real problem for the boards, then I would have spent a whole lot more time making a tight fitting enclosure and a hole for it that protects it both from the elements and from people.

The playa gets covered in dust storms regularly throughout the week. A particularly nasty dust storm is pictured here, eating our poor lotus flowers alive.

Although during the day when its not dust storming the lotuses offer a cozy respite from the heat of the playa.

Photo credit Jim Urquhart / Reuters

The entire process lasted 4 months with 2.5 months of nearly full-time work on my part. I'm thrilled that I get to open-source both the process and the firmware. I hope others who build art installations can use some of my lessons learned here. I'm happy to answer any questions on Twitter.

See you next year on the playa!

Jan 15

Adventures in Wearable Electronics - Making a Light-up Dress

For New Year's Eve 2014, my girlfriend and I went to a dance party where wearable electronics were not only encouraged but also on display from a variety of hobbyists. I decided to use this as an opportunity to combine two of my favorite hobbies: sewing and electronics.

It is my goal to encourage more people to weave wearable electronics into their own clothing. It's the future and we might as well look the part. Plus it's easy to get started and to modify existing code.

The full source code for this dress is available on GitHub.


I attached six addressable LED strands from Sparkfun ($20 each) to the lining of Brittany's dress, and then used a Flora module from Adafruit ($25) to control them. I then used a 3 x AAA battery holder from Adafruit ($2).


I used Adafruit's NeoPixel library to control the LEDs. There were 60 LEDs per 1 meter-long strand. We only needed 40 of the LEDs, but instead of cutting them off, we simply sewed the unused third underneath the strand and cut the software off at 40 LEDs. This way we can repurpose the LED strands when we decide to move them to a new dress.

In order to make the connections between the LED strands and the Flora module, I used 30 AWG wire, which is an extremely thin and light wire. The gauge is 0.01" and is as fine as thread. This allowed me to sew the wire into the fabric. I could have used conductive thread, but this wire wrap has a sheath that prevents it from shorting other wires when they touch. It's also extremely light-weight, so having 18 wires (3 wires per LED strand: power, ground, data) looping around the dress wasn't an issue.

I also want to mention that the code below is hard-coded for six stands. There is a fine line between a hack and a project, and for this, due to my limited time budget, was closer to hack than reusable project. You can easily abstract the code below to account for more or fewer strands, but I was able to ship before midnight on NYE, so I'm considering it a success.

void setup() {
  // To ensure that the first random color in `loop` is never the same.



void loop() {
  for (int i=0; i<2; i++) {
    hulahoop(randomColor(), random(20,60));

  sparkle(randomColor(), random(30,70));

  raindrops(randomColor(), random(20,60));

  spiral(randomColor(), random(15,30));

Above we have the code for setup and loop, the two main Arduino routines. Notice that I am repeating the hula hoop routine, since it's pretty quick and looks good on repeat.

I also want to note that every single routine gets its own random color and random delay. This bit of randomness is something I weave into all of my wearable electronics, since it goes just a bit further than off-the-shelf components and shows that there was some intelligence behind the routine.

By giving a random delay to each routine I am actually changing the speed of the routine. Sometimes the raindrops would fall quickly, sometimes the hula hoop would have a slow fall and rise. It's all part of making mesmerizing patterns.

Hula hoop

For the hula hoop routine, I chose to use cylons at equal positions that move up and down the strand. To make the transition from one LED to the next, I use a cylon, which is a fancy way of saying that the LEDs immediately above and below the active LED are also on, but at a reduced brightness.

In this case the cylon is 5 LEDs wide. 100% brightness for the middle/active LED, 1/18th brightness for the two adjacent LEDs, and 1/36th brightness for the two LEDs further out from there.

So what you see to the left are actually 5 LEDs turned on per-strand, although they get quite dim as you get further from the active LED. You can adjust the dimness of the adjacent LEDs by adjusting the weight parameter.

void hulahoop(unsigned long color, byte wait) {
  // weight determines how much lighter the outer "eye" colors are
  const byte weight = 18;  
  // It'll be easier to decrement each of these colors individually
  // so we'll split them out of the 24-bit color value
  byte red   = (color & 0xFF0000) >> 16;
  byte green = (color & 0x00FF00) >> 8;
  byte blue  = (color & 0x0000FF);

  // Start at closest LED, and move to the outside
  for (int i=0; i<=LED_COUNT-1; i++) {
    led_a.setPixelColor(i, red, green, blue);
    led_b.setPixelColor(i, red, green, blue);
    led_c.setPixelColor(i, red, green, blue);
    led_d.setPixelColor(i, red, green, blue);
    led_e.setPixelColor(i, red, green, blue);
    led_f.setPixelColor(i, red, green, blue);
    // Now set two eyes to each side to get progressively dimmer
    for (int j=1; j<3; j++) {
      byte redWJ = red/(weight*j);
      byte greenWJ = green/(weight*j);
      byte blueWJ = blue/(weight*j);
      if (i-j >= 0) {
        led_a.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_b.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_c.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_d.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_e.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_f.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
      if (i-j <= LED_COUNT) {
        led_a.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_b.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_c.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_d.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_e.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_f.setPixelColor(i+j, redWJ, greenWJ, blueWJ);

  // Now we go back to where we came. Do the same thing.
  for (int i=LED_COUNT-2; i>=1; i--) {
    led_a.setPixelColor(i, red, green, blue);
    led_b.setPixelColor(i, red, green, blue);
    led_c.setPixelColor(i, red, green, blue);
    led_d.setPixelColor(i, red, green, blue);
    led_e.setPixelColor(i, red, green, blue);
    led_f.setPixelColor(i, red, green, blue);
    // Now set two eyes to each side to get progressively dimmer
    for (int j=1; j<3; j++)
      byte redWJ = red/(weight*j);
      byte greenWJ = green/(weight*j);
      byte blueWJ = blue/(weight*j);

      if (i-j >= 0) {
        led_a.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_b.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_c.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_d.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_e.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
        led_f.setPixelColor(i-j, redWJ, greenWJ, blueWJ);
      if (i-j <= LED_COUNT) {
        led_a.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_b.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_c.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_d.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_e.setPixelColor(i+j, redWJ, greenWJ, blueWJ);
        led_f.setPixelColor(i+j, redWJ, greenWJ, blueWJ);


This is by far the easiest routine to program yet the one that brought the most attention. It simply flashes a random LED across all of the LED strips.

void sparkle(unsigned long color, uint8_t wait) {
  for (int i=0; i < LED_COUNT * STRIP_COUNT; i++) {
    int strip = floor(random(STRIP_COUNT));
    int led = floor(random(LED_COUNT));
    switch (strip) {
      case 0:
        led_a.setPixelColor(led, color);;
      case 1:
        led_b.setPixelColor(led, color);;
      case 2:
        led_c.setPixelColor(led, color);;
      case 3:
        led_d.setPixelColor(led, color);;
      case 4:
        led_e.setPixelColor(led, color);;
      case 5:
        led_f.setPixelColor(led, color);;


This is by far the most difficult of the routines. This one sends down cylons (5 LEDs, with the center LED being the brightest and the adjacent LEDs becoming decreasingly bright, so as to give the impression of smoother animation).

But you should notice that the next raindrop starts when the previous raindrop is half-way down the dress. In order to make it seamless, at the beginning of the routine I actually start another LED at the half-way mark, referred to in the below code as e_alt. This means that there is no point at which the dress looks spent and is waiting for the routine to start over.

void raindrops(unsigned long color, byte wait) {
  // weight determines how much lighter the outer "eye" colors are
  const byte weight = 18;  
  // It'll be easier to decrement each of these colors individually
  // so we'll split them out of the 24-bit color value
  byte red = (color & 0xFF0000) >> 16;
  byte green = (color & 0x00FF00) >> 8;
  byte blue = (color & 0x0000FF);
  double sludge = 0.5;
  double a_offset = 0;
  double b_offset = 3;
  double c_offset = 1;
  double d_offset = 2;
  double e_offset = 4;
  double f_offset = 5;

  // Start at closest LED, and move to the outside
  for (int i=0; i<LED_COUNT*(STRIP_COUNT-1)*sludge+LED_COUNT*10; i++) {
    double n = i % (int)(LED_COUNT*(STRIP_COUNT+1)*sludge-LED_COUNT*sludge);
    double led_count = (double)LED_COUNT;

    bool a_on = (sludge*a_offset*led_count) <= n && 
                n <= (sludge*a_offset*led_count+led_count);
    bool b_on = (sludge*b_offset*led_count) <= n && 
                n <= (sludge*b_offset*led_count+led_count);
    bool c_on = (sludge*c_offset*led_count) <= n && 
                n <= (sludge*c_offset*led_count+led_count);
    bool d_on = (sludge*d_offset*led_count) <= n && 
                n <= (sludge*d_offset*led_count+led_count);
    bool e_on = (sludge*e_offset*led_count) <= n && 
                n <= (sludge*e_offset*led_count+led_count);
    bool e_alt= (sludge*a_offset*led_count) <= n && 
                n <= (sludge*a_offset*led_count+led_count*sludge);
    bool f_on = (sludge*f_offset*led_count) <= n && 
                n <= (sludge*f_offset*led_count+led_count);

    if (!a_on && !b_on && !c_on && !d_on && !e_on && !f_on) {

    int a = n-a_offset*LED_COUNT*sludge;
    int b = n-b_offset*LED_COUNT*sludge;
    int c = n-c_offset*LED_COUNT*sludge;
    int d = n-d_offset*LED_COUNT*sludge;
    int e = n-e_offset*LED_COUNT*sludge;
    if (e_alt) {
      e = a+(LED_COUNT/2);
    int f = n-f_offset*LED_COUNT*sludge;

    if (a_on) led_a.setPixelColor(a, red, green, blue);
    if (b_on) led_b.setPixelColor(b, red, green, blue);
    if (c_on) led_c.setPixelColor(c, red, green, blue);
    if (d_on) led_d.setPixelColor(d, red, green, blue);
    if (e_on || e_alt) led_e.setPixelColor(e, red, green, blue);
    if (f_on) led_f.setPixelColor(f, red, green, blue);

    // Now set two eyes to each side to get progressively dimmer
    for (int j=1; j<3; j++) {
      byte redWJ = red/(weight*j);
      byte greenWJ = green/(weight*j);
      byte blueWJ = blue/(weight*j);

      if (a-j >= 0 && a_on) 
        led_a.setPixelColor(a-j, redWJ, greenWJ, blueWJ);
      if (b-j >= 0 && b_on) 
        led_b.setPixelColor(b-j, redWJ, greenWJ, blueWJ);
      if (c-j >= 0 && c_on) 
        led_c.setPixelColor(c-j, redWJ, greenWJ, blueWJ);
      if (d-j >= 0 && d_on) 
        led_d.setPixelColor(d-j, redWJ, greenWJ, blueWJ);
      if (e-j >= 0 && e_on) 
        led_e.setPixelColor(e-j, redWJ, greenWJ, blueWJ);
      if (f-j >= 0 && f_on) 
        led_f.setPixelColor(f-j, redWJ, greenWJ, blueWJ);

      if (a-j <= LED_COUNT && a_on) 
        led_a.setPixelColor(a+j, redWJ, greenWJ, blueWJ);
      if (b-j <= LED_COUNT && b_on) 
        led_b.setPixelColor(b+j, redWJ, greenWJ, blueWJ);
      if (c-j <= LED_COUNT && c_on) 
        led_c.setPixelColor(c+j, redWJ, greenWJ, blueWJ);
      if (d-j <= LED_COUNT && d_on) 
        led_d.setPixelColor(d+j, redWJ, greenWJ, blueWJ);
      if (e-j <= LED_COUNT && e_on) 
        led_e.setPixelColor(e+j, redWJ, greenWJ, blueWJ);
      if (f-j <= LED_COUNT && f_on) 
        led_f.setPixelColor(f+j, redWJ, greenWJ, blueWJ);


This routine is better in theory than in practice. The idea is to have a quick succession of LEDs light up in a spiral pattern. This would work a bit better with more LED strands wrapped around the dress.

In this case, I'm simply looping through the strands and lighting up successive LEDs. But the nice thing about this routine is that it has a dramatic crescendo to the top, at which point the hula hoop routine begins and it looks like the action started at the bottom and quickly worked its way up to the top, only to smoothly fall back down. It's a mesmerizing effect.

void spiral(unsigned long color, byte wait) {
  const byte weight = 18;  
  byte red = (color & 0xFF0000) >> 16;
  byte green = (color & 0x00FF00) >> 8;
  byte blue = (color & 0x0000FF);

  for (int level=LED_COUNT-1; level >= 0; level--) {
    for (int strip=0; strip < STRIP_COUNT; strip++) {

      switch (strip) {
        case 0:
          led_f.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_a.setPixelColor(level, color);
          led_b.setPixelColor(level, red/weight, green/weight, blue/weight);
        case 1:
          led_a.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_b.setPixelColor(level, color);
          led_c.setPixelColor(level, red/weight, green/weight, blue/weight);
        case 2:
          led_b.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_c.setPixelColor(level, color);
          led_d.setPixelColor(level, red/weight, green/weight, blue/weight);
        case 3:
          led_c.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_d.setPixelColor(level, color);
          led_e.setPixelColor(level, red/weight, green/weight, blue/weight);
        case 4:
          led_d.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_e.setPixelColor(level, color);
          led_f.setPixelColor(level, red/weight, green/weight, blue/weight);
        case 5:
          led_e.setPixelColor(level, red/weight, green/weight, blue/weight);
          led_f.setPixelColor(level, color);
          led_a.setPixelColor(level, red/weight, green/weight, blue/weight);

Random Colors

Since randomness is the spice that gives this dress its mesmerizing qualities, it's important to have a good list of colors to use.

unsigned long COLORS[] = {

unsigned long randomColor() {
  return COLORS[random(sizeof(COLORS)/sizeof(unsigned long))];

Dancing to 2014

And what good is a beautiful light-up dress without a well lit dance partner? Here I am decked out in blue EL wire. I spent the better part of three hours sewing this wire into the edges of one of my jackets. But while hand-sewing can take half a day, the result is a great fit and a capable match for Brittany's dress.

The full source code for this dress is available on GitHub.

Jan 02

Building a living photo frame with a Raspberry Pi and a motion detector

Every hardware hacker has a start, and this one is mine. My girlfriend bought me a Raspberry Pi for my birthday, and so I became determined to build something with it for her birthday two months later.

As you can see above, I built a photo frame that has a few interesting parts. For one, the software which runs the photo frame, which I explore below, keeps the photos fresh from Instagram and Flickr. It then displays a random photo for a configurable six seconds. Secondly, there is a motion detector, built using a PIR sensor, which only turns the monitor on when somebody walks by.

This photo frame is easy to build, but it does take a bit of know-how. Mainly, you should feel comfortable soldering wires and mounting the screen and Raspberry Pi to a board or other object. The hard part for me was figuring out how to turn the monitor on and off through the command line.

Everything else is gravy, from configuring wifi and autoboot/auto-login on the device to attaching and setting up the motion detecting PIR sensor. You can also use the eLinux guide to Raspberry Pi and its handy RPi Hardware Basic Setup wiki.


Raspberry Pi

I chose to use a Raspberry Pi for its simple wifi integration so that photos could be automatically updated. I didn't want to have to load photos on to an SD card which could then be read by an Arduino.

Connecting the monitor was also trivial on a Raspberry Pi, where an Arduino, Maple, or Beagle Bone would require sourcing a connection between the monitor's composite input and an output from the device.

Raspberry Pi, $29 on Adafruit.

Make note of the fact that you actually don't see any of my connections on the top of the board (pictured below). In the below photo, where the Raspberry Pi is flipped vertically to show off the electrical connections, the monitor's composite cable and the motion detecting PIR sensor's red wires are soldered underneath.

This way the photo frame looks cleaner. If I had connected the monitor using the yellow composite cable, it would have to be with a male-to-male composite adapter, since both the Raspberry Pi and the monitor have a male RCA connection. This would jut out about 2 inches below the device, resulting in a messy look for the frame.

3.5" LCD Monitor

3.5" LCD Monitor, $45 on Adafruit

Note that if you do not plan to solder the composite cable's two wires, you will need the ugly male-to-male adapter, sold for $1.50 on Adafruit.

There are a number of different sized LCD monitors:

1.5" LCD, $40
2" LCD, $40
2.5" LCD, $45
4.3" LCD, $50
7" LCD, $75
10" LCD, $150

4GB SD Card with Raspbian (Raspberry Pi + Debian)

4GB SD Card, $10 on Adafruit

This tiny SD card comes pre-loaded with Raspbian. If you prefer to use your own SD card and want to bootload it, just follow eLinux's Easy SD Card Setup wiki.

Miniature Wifi on USB

USB Wifi, $11 on Adafruit

Unless you're planning to use an ugly ethernet cable, this tiny wifi USB device works perfectly. It's easy to setup as well. I followed Adafruit's tutorial for setting up wifi on a Raspberry Pi.

Passive Infrared Motion Sensor

PIR sensor, $10 on Adafruit

This is a simple and inexpensive component that is responsible for turning the monitor on and off. The accuracy is great, as it never misses a beat, yet I haven't found it to accidentally trigger in the night unless we walk by. It also has two adjustable dials on the back that allow you to control its sensitivity and delay before firing. Ladyada covers how it works.

Soldering Iron

Aoyue 937+, $60 on Amazon

In order to connect the PIR motion detector and the composite cables, without resorting to the ugly male-to-male adapter, you will need to use a soldering iron. I chose the Aoyue 937+ Digital Soldering Station. Works great and I'm quite happy with it. I should have bought more tips, though.


This is where you get creative. You effectively just need an enclosure, but I found that picture frames offer the greatest aesthetics-to-enclosure ratio. You just need something that can hold a Raspberry Pi and monitor taped to it. I used double-sided mounting tape as an adhesive, although the wires are being held up by the frame itself.


Raspberry Pi setup

You'll want to make sure you're setup with the following:

  • Auto-login, so your Raspberry Pi doesn't sit at a login prompt.
  • Auto-wifi, so you can download images automatically whenever your Raspberry Pi is turned on.
  • Disabled sleep, so your photo frame doesn't shut off when you don't want it to.

Downloading personal photos from Flickr

You'll need to register your Flickr API app, which is a quick process. That way you can get a Flickr API key that you can then use to walk the photos from your account. You will also need your Flickr user id.

There are two Python library dependencies for this code:

pip install flickrapi
pip install requests

Once those are installed, save this script as

#!/usr/bin/env python

import flickrapi
import requests

FLICKR_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
USER_ID = "25704617@N04"

def make_url(photo):
    # url_template = "http://farm{farm-id}
    #                 {server-id}/{id}_{secret}_[mstzb].jpg"
    photo['filename'] = "%(id)s_%(secret)s_z.jpg" % photo
    url = ("http://farm%(farm)" 
           % photo)
    return url, photo['filename']

def main():
    print " ---> Requesting photos..."
    flickr = flickrapi.FlickrAPI(FLICKR_KEY)
    photos = flickr.walk(user_id=USER_ID)
    for photo in photos:
        url, filename = make_url(photo.__dict__['attrib'])
        path = '/home/pi/photoframe/flickr/%s' % filename
            image_file = open(path)
            print " ---> Already have %s" % url
        except IOError:
            print " ---> Downloading %s" % url
            r = requests.get(url)      
            image_file = open(path, 'w')

if __name__ == '__main__':

Downloading extra photos from Flickr by tag name

Part of the fun of this photo frame is that not only do all of my photos get shown randomly, but I introduced a hodgepodge of random photos by downloading photos from a specific Flickr tag. In this case, I added koala photos, which makes for a pleasant randomness.

Save the following command as or whatever you like as a tag.

FLICKR_TAG=koala && \
wget '$FLICKR_TAG' -O- \
| grep -Po 'http://[^.]+\.staticflickr[^"]+(_b.jpg|_z.jpg)' \
| wget -P /home/pi/photoframe/$FLICKR_TAG -nc -i-

Automatic downloading of new photos

In order to have the photos refreshed, you'll need to have them download in the background. Add these two lines to your crontab with crontab -e if you're using both the Flickr photo downloader and the Flickr tag downloader.

0 * * * * python /home/pi/photoframe/
30 * * * * /home/pi/photoframe/


Now that we have the photos downloaded and refreshed at a regular interval, we need to get the slideshow running. We'll use a simple app called the Linux framebuffer imageviewer. Stick this command into a

fbi -noverbose -m 640x480 -a -u -t 6 /home/pi/art/**/*

The option for time is set to 6 seconds, and it uses autozoom to automagically pick a reasonable zoom factor when loading images. The -u option randomizes the order.

Detecting movement

The slideshow is now running at fullscreen with a randomized assortment of Flickr photos, both your own and from favorite tags. But it's running even when you're not there! let's use the PIR (motion) sensor to turn off the monitor after no movement has been detected for 60 seconds.

Save this file as

#!/usr/bin/env python

import sys
import time
import RPi.GPIO as io
import subprocess

SHUTOFF_DELAY = 60 # seconds
PIR_PIN = 25       # 22 on the board
LED_PIN = 16

def main():
    io.setup(PIR_PIN, io.IN)
    io.setup(LED_PIN, io.OUT)
    turned_off = False
    last_motion_time = time.time()

    while True:
        if io.input(PIR_PIN):
            last_motion_time = time.time()
            io.output(LED_PIN, io.LOW)
            print ".",
            if turned_off:
                turned_off = False
            if not turned_off and time.time() > (last_motion_time + 
                turned_off = True
            if not turned_off and time.time() > (last_motion_time + 1):
                io.output(LED_PIN, io.HIGH)

def turn_on():"sh /home/pi/photoframe/", shell=True)

def turn_off():"sh /home/pi/photoframe/", shell=True)

if __name__ == '__main__':
    except KeyboardInterrupt:

Turning the monitor on and off

There are two ways to turn the monitor on and off. Use the tvservice command to turn off the monitor port.

pi@raspberrypi ~/photoframe $ chmod 0744 
pi@raspberrypi ~/photoframe $ cat 
tvservice -o

pi@raspberrypi ~/photoframe $ chmod 0744 
pi@raspberrypi ~/photoframe $ cat 
tvservice -c "PAL 4:3" && fbset -depth 8 && fbset -depth 16

This method actually turns off the port, which works great except when you're connected to an HDMI monitor and it shuts off when the port is turned off. When you walk into the room, the port is turned back on but the monitor is off, so it doesn't come right back up. In this case, simply switch virtual terminals to blank out the screen using the chvt command.

pi@raspberrypi ~/photoframe $ chmod 0744 
pi@raspberrypi ~/photoframe $ cat 
chvt 2

pi@raspberrypi ~/photoframe $ chmod 0744 
pi@raspberrypi ~/photoframe $ cat 
chvt 7

Fixing the monitor edges

By default, the image won't stretch to the edges of your monitor without cajoling.

Here's the before photo:

And here's with margin correction on the monitor:

To fix this, take a look at using RPiconfig. All you need to do is edit /boot/config.txt directly on the Raspberry Pi. The values you need to set are:

overscan_left=-6    # number of pixels to skip on left
overscan_right=-6   # number of pixels to skip on right
overscan_top=24     # number of pixels to skip on top
overscan_bottom=24  # number of pixels to skip on bottom

These are my values, but every monitor is different. In order to figure out the values, I would set the values using a binary search (set high then low then halfway between the two and repeat with the new halfway point being the high/low on the correct side), and then rebooting. Eventually I found optimal values.

Note that the values will be different from the boot screen to the photo viewer. Obviously, I optimized for the photo viewer, but that means the top and bottom of the boot screen is cut off. Not much better you can expect from a tiny $50 LCD monitor.

Also, if you need to rotate or flip the display, it's easy.

display_rotate=0        Normal
display_rotate=1        90 degrees
display_rotate=2        180 degrees
display_rotate=3        270 degrees
display_rotate=0x10000  horizontal flip
display_rotate=0x20000  vertical flip

Automatic start of the photo frame software

You'll want the software to start automatically on boot, so create a new init.d file at /etc/init.d/flickrd, and add the motion sensor and slideshow scripts to that new file:

sudo python /home/pi/photoframe/

Then set the permissions with:

sudo chmod 755 /etc/init.d/flickrd

and finally register the script to be run at startup:

sudo update-rc.d flickrd defaults

Don't forget to run the script as root, since you'll need permissions to turn the monitor on and off.


Everything above should leave you with a photo slideshow that automatically updates your photos, displays them zoomed in and fullscreen in random order, shutting off the monitor when nobody is around.

If you used the code above with no issues, congratulations! You're in a minority that can work with hardware and get everything right on the first try. For everybody else, we have to troubleshoot. Here are the issues that I ran into.

Test your LED

Just getting the Raspberry Pi to respond to my commands was tricky enough, so I wrote this basic program to just blink the onboard LED. This is the Hello, World of the Raspberry Pi.

import RPi.GPIO as GPIO
import time

LED_PIN = 18
def blink(pin):
    print " ---> On"
    print " ---> Off"

# to use Raspberry Pi board pin numbers
# set up GPIO output channel
for _ in range(0,3):

SSH'ing into your Raspberry Pi

You shouldn't have to rely on an external keyboard and a tiny screen to debug your Raspberry Pi. I suggest using Pi Finder to locate the IP address, if it's on your local network.

You can also use arp -a to find it.

Getting additional help

Turn to Stack Exchange's new Raspberry Pi section. It's still in beta as of early 2014, but there's a whole lot of great questions.

Samuel Clay is the founder of NewsBlur, a trainable and social news reader for web, iOS, and Android. He is also the founder of Turn Touch, a startup building hardware automation devices for the home. He lives in San Francisco, CA, but misses Brooklyn terribly. In another life in New York, he worked at the New York Times on DocumentCloud, an open-source repository of primary source documents contributed by journalists.

Apart from NewsBlur, his latest projects are Hacker Smacker, a friend/foe system for Hacker News, and New York Field Guide, a photo-blog documenting New York City's 90 historic districts. You can read about his past and present projects at

Follow @samuelclay on Twitter.

You can email Samuel at He loves receiving email from new people. Who doesn't?