Introduction: Rainbow Lanterns

Get Inspired!
I stumbled across these Chinese-style lanterns while at Michaels (local craft store). I always wanted to purchase white ones when I saw the cool ones at IKEA, but their cost made me feel otherwise.

Luckily the ones at Michaels were only $1USD each, so I picked up one of each color.

Step 1: Acquire Parts

In addition to the lanterns themselves, you will need some other items.

Since I wanted this to be powered off of 120V AC, and planned on using an Arduino, that set the base for a few of the items I needed.

- A 120VAC plug (or whatever you plan to use for your power source)
- Arduino (you only need 6 pins, so nothing fancy is needed)
- A 120VAC to 5VDC converter (I tore apart a cheap iPhone charger)
- Some relays to switch 120VAC using a 5VDC signal
- Light source (I just purchased some small bulbs and bulb fixtures from a local hardware store)

In addition to those main components, you will also need something to mount the lights on; I had a good deal of hardwood floor strips sitting in my garage, so I decided to use one of the pieces. I used a piece of string to hang the lanterns from so I could figure out what I wanted for spacing in order to determine the right piece of wood.

You will also need miscellaneous components and tools, such as wire, solder, solder iron, wire strippers...you get the idea.

Step 2: Design a PCB for the Relays

Since I had 6 lanterns, I needed 6 relays, and since they could easily be laid out on a PCB, I chose that route. You could easily breadboard this, however; I just chose a PCB because I have 2 PCB mills at school that I have access to use.

I made the design in EAGLECAD, exported the appropriate files, imported those into T-Tech ISOPro (the software used to communicate with the mill), and cut away. Once the boards were cut, I soldered some IC sockets into the PCB.

Step 3: Hack Apart Your Power Converter

Since I decided to use a small, cheap iPhone USB charger, I figured it was best to crack it apart so I could solder AC connections directly onto the board.

Now the quality isn't the greatest, you can see there's rust inside; but they tested out alright on a multimeter, so I figured they would suffice.

Since I wanted a quick way to disconnect the power from the Arduino, I made a custom cable that just took the 5VDC from the female usb connector to power the Arduino.

Step 4: Wire and Code

Now is time to wire everything up for testing (always a good idea to use protection, 120VAC is not that friendly).

I had a bench multimeter to verify voltage levels along with me as well, which proved to be useful on a few occasions.

Below is my code, feel free to modify it, its nothing fancy. If you make a new pattern that you think is cool, please share it!

The code cycles randomly through a few patterns defined in the array. I used pins 8-13 for controlling the relays. I also left in debug statements, as they can be useful when testing.

Code:
/*
  Lantern Blink
  Arduino code for Rainbow Lanterns
*/

int timer = 250;           // The higher the number, the slower the timing.

char LIGHTS[6] = {8,9,10,11,12,13};

int PATTERN_COUNT = 5;
int RANDOM_COUNT = 4;

byte ptn[][7] =
{
       // Pattern #0
       {B100000,
        B010000,
        B001000,
        B000100,
        B000010,
        B000001},

       // Pattern #1
       {B101000,
        B010100,
        B001010,
        B000101,
        B001010,
        B010100},

       // Pattern #2
       {B100000,
        B110000,
        B011000,
        B001100,
        B000110,
        B000011,
        B000001},

       // Pattern #3
       {B100001,
        B010010,
        B001100,
        B010010}
};

int randCt = 0;
void setup() {
  Serial.begin(9600);
  // use a for loop to initialize each pin as an output:
  for (int thisPin = 0; thisPin < 6; thisPin++)  {
    pinMode(LIGHTS[thisPin], OUTPUT);     
  }

  //Initilize Random Seed
  // if analog input pin 0 is unconnected, random analog
  // noise will cause the call to randomSeed() to generate
  // different seed numbers each time the sketch runs.
  // randomSeed() will then shuffle the random function.
  randomSeed(analogRead(0));
  //randomSeed(0);
}

void loop() {
  switch(random(PATTERN_COUNT+1)-1)
  {
    case -1:
    {
      Serial.print("Running Pattern #-1 ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");
      pattern_0(randCt,timer);
      Serial.println("Done!");
      break;
    }
    case 0:
    {
      Serial.print("Running Pattern #0 ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");
      defaultPatternLoop(0,randCt,timer);
      Serial.println("Done!");
      break;
    }
    case 1:
    {
      Serial.print("Running Pattern #1 ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");
      defaultPatternLoop(1,randCt,timer);
      Serial.println("Done!");
      break;
    }
    case 2:
    {
      Serial.print("Running Pattern #2 ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");
      defaultPatternLoop(2,randCt,timer);
      Serial.println("Done!");
      break;
    }
    case 3:
    {
      Serial.print("Running Pattern #3 ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");
      defaultPatternLoop(3,randCt,timer);
      Serial.println("Done!");
      break;
    }
    default:
    {
      Serial.print("Running Default Pattern ");
      Serial.print(randCt = (random(RANDOM_COUNT)+5));
      Serial.print(" times...");

      for(;randCt>0;randCt--)
      {
        Serial.print(randCt);
        int arraySize = sizeof(ptn[1]) / sizeof(byte);
        for (int thisPin = 0; thisPin < arraySize; thisPin+=1)
        {
          WritePattern(ptn[1][thisPin]);
          delay(500);
          WritePattern(ptn[1][thisPin]);
        }
      }

      Serial.println("Done!");
    }
  }
}

void WritePattern(byte pattern) {
  for (int i = 5; i >= 0; i--, pattern >>= 1) {
    digitalWrite(LIGHTS[i], pattern & 1 ? HIGH : LOW);
  }
}


void pattern_0(int times, int waitPeriod)
{
  for(;times>0;times--)
  {
    Serial.print(times);
    // loop from the lowest pin to the highest:
    for (int thisPin = 0; thisPin < 6; thisPin++) {
      // turn the pin on:
      digitalWrite(LIGHTS[thisPin], HIGH);  
      delay(waitPeriod);                 
      // turn the pin off:
      digitalWrite(LIGHTS[thisPin], LOW);   
    }

    // loop from the highest pin to the lowest:
    for (int thisPin = 5; thisPin >= 0; thisPin--) {
      // turn the pin on:
      digitalWrite(LIGHTS[thisPin], HIGH);
      delay(waitPeriod);
      // turn the pin off:
      digitalWrite(LIGHTS[thisPin], LOW);
    }
  }
}


void defaultPatternLoop(int pattern, int times, int waitPeriod)
{
  int arraySize = sizeof(ptn[pattern]) / sizeof(byte);
  for(;times>0;times--)
  {
    Serial.print(times);
    for (int thisPin = 0; thisPin < arraySize; thisPin+=1)
    {
      if(ptn[pattern][thisPin] != 0) // if its not blank
      {
        WritePattern(ptn[pattern][thisPin]);
        delay(waitPeriod);
        WritePattern(ptn[pattern][thisPin]);
      }
    }
  }
}

Step 5: Lights Away!

Once you test everything and verify operation, all you need to do is get everything hooked up to whatever you are mounting the lights to, re-connect everything and give it a final test!

I have attached a video below of the lanterns in operation, running just a single pattern in the code given in the previous step.

Lamps & Lighting Contest

Participated in the
Lamps & Lighting Contest