Skip navigation
2017

Arduino Projects

July 2017 Previous month Next month

 

It’s no secret that lighting effects have been one of my major focuses in my career as a maker, and I wanted to share a pretty cool concept that I came up with a few years back. In this tutorial I will walk you through the process of creating a pair of accent lights that that utilizes the popular WS2812B LED modules also known as Neopixels, and an open source library called fastLED. Within this tutorial you will learn how to increment a variable with the push of a button, and how to utilize the colorPalette feature within the fastLED library.

 

Hardware

 

To complete this tutorial you will need the following items:

 

Software

 

To complete this tutorial you will need the following software. Click the links to open their download pages in a separate window.

 

Tools

 

You will also need the following tools.

    • Soldering Iron & Solder
    • Hot Glue Gun & Glue Sticks
    • Drill & Drill Bits
    • Scissors or Xacto Knife
    • Needle Nose Pliers

 

The Code

 

If you have used Adafruit’s Neopixels before, you have most likely used the Neopixel library as well. For this tutorial we are going to use a library called FastLED,  the library from which the Neopixel library was born. In reality you could create a very similar lighting effect with the Neopixel library, but the FastLED library comes with a pre-built example that will greatly speed up the code writing portion of this tutorial. Before you get started, make sure you have downloaded and installed the latest version of the Arduino IDE, and the FastLED library. If you are unsure as to how to install a library in Arduino, check out this document on Arduino.org.

 

I am going to explain this code section by section with a comment for each line that is important in hopes that it will make it easier to follow, but if you would like to see the full source code in its entirety, scroll down to the bottom of this section, or visit its repository on my Github. Now let’s get started!

 

Variable Declaration Section

 

In this section we need to include the libraries we will be using, define the variables and integers that our code will need to run properly.  There is also a line of code in this section that will let you reverse the direction in which the strip of NeoPixels will illuminate from. This is handy if your hanging lantern only has room to hide the Arduino in the top of its housing. This will let the LED strips still appear to flicker from the bottom to the top like a real candle would.

 

#include <FastLED.h>

#define LED_PIN     6         // the pin which attaches to the neopixel data pin
#define COLOR_ORDER GRB      // sets the color order in which the LEDs are designed for
#define CHIPSET     WS2812B  // the chipset that the neopixels use
#define NUM_LEDS    8      // how many leds are being adderessed

#define BRIGHTNESS  200         // sets the overall brightness of the leds
#define FRAMES_PER_SECOND 60    // how fast should the led animation render
#define COOLING  55      // defines the level at which the lighting effect fades before a new "flame" generates
#define SPARKING 120    // defines the rate of flicker which we will see from the flame animation

int switchPin = 2;              // switch is connected to pin 2
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed

bool gReverseDirection = false;  // set this to true if you need to invert the animation direction

CRGB leds[NUM_LEDS];     // sets up an array that we can manipulate to set/clear led data.

CRGBPalette16 currentPalette; // sets a variable for CRGBPalette16 which allows us to change this value later

 

Setup Section

 

This section is where we place the code that needs to be ran once before the loop when the arduino first powers up. Here we will initialize the the NeoPixel Strand and inform the library of the variables needed to help the Arduino send commands to the WS2812B chipset on each of the NeoPixel LEDs.

 

void setup() {
  delay(3000); // sets a delay to insure that everything has initialized before proceeding with the setup

  // Informs the library that a strand of NeoPixel's on pin 6 and those leds will use the led array "leds", and there are NUM_PIXELS (aka 8) of them.
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  
  FastLED.setBrightness( BRIGHTNESS );   // sets the brightness to the predetermined levels
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state of the button

 

Loop Section

 

This section is where the code that needs to run in a loop is placed. The code you see below is where much of the magic happens. It takes advantage of the If / Else statement structure, and looks for the number of times the button has been pressed. If that number coincides with one of the numbers in the various if statements, then it will set the color palette being used to whichever color palette has been defined in that if statement. After the if/else statments, there is code that tells the Arduino to count and store the number of times the button was pushed, and once that number reaches 10, it will reset to 0 on the eleventh button push.

 

void loop()
{
  random16_add_entropy( random());  // Add entropy to random number generator; we use a lot of it.

   // The following if statements read the number of times the button has been pressed
   // and then sets the currentPalette variable to the defined CRGBPalette16 color palette.
   // for example: if the button has been pressed 1 time, set the palette to HeatColors. If
   // the button has been pressed 4 times, set the palette to a custom defined palette found in
   // that statement. The else statement at the end helps us return to the top of the if statments.

   if (buttonPresses == 0) {
    currentPalette = CRGBPalette16( CRGB::Black);
    }
  if (buttonPresses == 1) {
    currentPalette = HeatColors_p;
  }
  if (buttonPresses == 2) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Blue, CRGB::Aqua,  CRGB::White);
  }
  if (buttonPresses == 3) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Green, CRGB::GreenYellow,  CRGB::Yellow);
  }
  if (buttonPresses == 4) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Green, CRGB::Purple,  CRGB::Orange);
  }
  if (buttonPresses == 5) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Blue, CRGB::Purple,  CRGB::Red);
  }
  if (buttonPresses == 6) {
    currentPalette = CRGBPalette16( CRGB::White);
  }
  if (buttonPresses == 7) {
    currentPalette = CRGBPalette16( CRGB::Yellow);
  }
  if (buttonPresses == 8) {
    currentPalette = CRGBPalette16( CRGB::Maroon);
  }
  if (buttonPresses == 9) {
    currentPalette = CRGBPalette16( CRGB::DarkBlue);
  }
  if (buttonPresses == 10) {
    static uint8_t hue = 0;
    hue++;
    CRGB darkcolor  = CHSV(hue,255,192); // pure hue, three-quarters brightness
    CRGB lightcolor = CHSV(hue,128,255); // half 'whitened', full brightness
    currentPalette = CRGBPalette16( CRGB::Black, darkcolor, lightcolor, CRGB::White);
  }
  else  {
  }


  Fire2012WithPalette(); // calls the function defined below this loop & runs simulation frames, using palette colors

  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND); // sets a delay using the number 1000 devided by the predetermined frames per second.

  val = digitalRead(switchPin);      // read input value and store it in val
  if (val != buttonState) {          // the button state has changed!
    if (val == LOW) {                // check if the button is pressed
      buttonPresses++;               // increment the buttonPresses variable
      Serial.print("Button has been pressed ");  // prints the statement between "" in the serial terminal
      Serial.print(buttonPresses);              // reads the value stored in the buttonPresses variable.
      Serial.println(" times");                // prints the statement between "" in the serial terminal
    }
  }
  if (buttonPresses > 10){    // reads the number of button presses, and if that number is greater than 10 then
  buttonPresses = 0;         // reset the number of button presses to 0 
  }
  buttonState = val;                 // save the new state in our variable

}

 

Function Section

 

This section is not officially a real section found in the Arduino IDE's documentation, but I like to give it a name to help organize my code for tutorials. The code in this section defines one or more functions that can be called in the setup or loop sections of the code. Here we are defining a function which is the original fire2012 code which has been modified to take advantage of FastLED’s color palette features.

 

void Fire2012WithPalette()   // defines a new function
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }

    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
   
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      // Scale the heat value from 0-255 down to 0-240
      // for best results with color palettes.
      byte colorindex = scale8( heat[j], 248);
      leds[j] = ColorFromPalette( currentPalette, colorindex);
    }
}

 

I have pasted the full code below, but you can also download it from my Github (https://github.com/CharlesJGantt/Neopixel-Realistic-Flickering-Candle-With-Changing-Color-Palette), or even create a fork if you would like to add more functionality on your own.

 

// Fire2012WithPaletteCycle
// Version 0.12 Revision 3


// Portions of this code originated in the FastLED library, and was
// modified & amended by Charles Gantt on 7/1/2017. Visit Charles' website
// at http://www.themakersworkbench.com


// Origial Fire2012 Code by:
// Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY


// This code is the same fire simulation as the original "Fire2012",
// but each heat cell's temperature is translated to color through a FastLED
// programmable color palette, instead of through the "HeatColor(...)" function
// with additional custom defined color palettes.
// The different palettes can be cycled through by a push of a button
// connected to pin 2, and 5V.


#include <FastLED.h>


#define LED_PIN     6          // the pin which attaches to the neopixel data pin
#define COLOR_ORDER GRB       // sets the color order in which the LEDs are designed for
#define CHIPSET     WS2812B  // the chipset that the neopixels use
#define NUM_LEDS    12       // how many leds are being adderessed


#define BRIGHTNESS  200        // sets the overall brightness of the leds
#define FRAMES_PER_SECOND 60   // how fast should the led animation render
#define COOLING  55           // defines the level at which the lighting effect fades before a new "flame" generates
#define SPARKING 120          // defines the rate of flicker which we will see from the flame animation


int switchPin = 2;              // switch is connected to pin 2
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed


bool gReverseDirection = false;  // set this to true if you need to invert the animation direction


CRGB leds[NUM_LEDS];     // sets up an array that we can manipulate to set/clear led data.


CRGBPalette16 currentPalette; // sets a variable for CRGBPalette16 which allows us to change this value later


void setup() {
  delay(3000); // sets a delay to insure that everything has initalized before proceeding with the setup


  // Informs the library that a strand of NEOPIXEL's on pin 6 and those leds will use the led array "leds", and there are NUM_PIXELS (aka 8) of them.
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );


  FastLED.setBrightness( BRIGHTNESS );   // sets the brightness to the predetermined levels
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state of the button
}


void loop()
{
  random16_add_entropy( random());  // Add entropy to random number generator; we use a lot of it.


  // The following if statements read the number of times the button has been pressed
  // and then sets the currentPalette variable to the defined CRGBPalette16 color palette.
  // for example: if the button has been pressed 1 time, set the palette to HeatColors. If
  // the button has been pressed 4 times, set the palette to a custom defined palette found in
  // that statement. The else statement at the end helps us return to the top of the if statments.


  if (buttonPresses == 0) {
    currentPalette = CRGBPalette16( CRGB::Black);
  }
  if (buttonPresses == 1) {
    currentPalette = HeatColors_p;
  }
  if (buttonPresses == 2) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Blue, CRGB::Aqua,  CRGB::White);
  }
  if (buttonPresses == 3) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Green, CRGB::GreenYellow,  CRGB::Yellow);
  }
  if (buttonPresses == 4) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Green, CRGB::Purple,  CRGB::Orange);
  }
  if (buttonPresses == 5) {
    currentPalette = CRGBPalette16( CRGB::Black, CRGB::Blue, CRGB::Purple,  CRGB::Red);
  }
  if (buttonPresses == 6) {
    currentPalette = CRGBPalette16( CRGB::White);
  }
  if (buttonPresses == 7) {
    currentPalette = CRGBPalette16( CRGB::Yellow);
  }
  if (buttonPresses == 8) {
    currentPalette = CRGBPalette16( CRGB::Maroon);
  }
  if (buttonPresses == 9) {
    currentPalette = CRGBPalette16( CRGB::DarkBlue);
  }
  if (buttonPresses == 10) {
    static uint8_t hue = 0;
    hue++;
    CRGB darkcolor  = CHSV(hue, 255, 192); // pure hue, three-quarters brightness
    CRGB lightcolor = CHSV(hue, 128, 255); // half 'whitened', full brightness
    currentPalette = CRGBPalette16( CRGB::Black, darkcolor, lightcolor, CRGB::White);
  }
  else  {
  }




  Fire2012WithPalette(); // calls the function defined below this loop & runs simulation frames, using palette colors


  FastLED.show(); // display this frame
  FastLED.delay(1000 / FRAMES_PER_SECOND); // sets a delay using the number 1000 devided by the predetermined frames per second.


  val = digitalRead(switchPin);      // read input value and store it in val
  if (val != buttonState) {          // the button state has changed!
    if (val == LOW) {                // check if the button is pressed
      buttonPresses++;               // increment the buttonPresses variable
      Serial.print("Button has been pressed ");  // prints the statement between "" in the serial terminal
      Serial.print(buttonPresses);              // reads the value stored in the buttonPresses variable.
      Serial.println(" times");                // prints the statement between "" in the serial terminal
    }
  }
  if (buttonPresses > 10) {   // reads the number of button presses, and if that number is greater than 10 then
    buttonPresses = 0;         // reset the number of button presses to 0
  }
  buttonState = val;                 // save the new state in our variable


}


void Fire2012WithPalette()   // defines a new function
{
  // Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];


  // Step 1.  Cool down every cell a little
  for ( int i = 0; i < NUM_LEDS; i++) {
    heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
  }


  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for ( int k = NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
  }


  // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
  if ( random8() < SPARKING ) {
    int y = random8(7);
    heat[y] = qadd8( heat[y], random8(160, 255) );
  }


  // Step 4.  Map from heat cells to LED colors
  for ( int j = 0; j < NUM_LEDS; j++) {
    // Scale the heat value from 0-255 down to 0-240
    // for best results with color palettes.
    byte colorindex = scale8( heat[j], 248);
    leds[j] = ColorFromPalette( currentPalette, colorindex);
  }
}

 

Assembly

 

The assembly process is not very hard, but it is fairly time consuming. It involves the use of a soldering iron, high speed drill, and a hot glue gun. If you are unsure as to how these tools operate, please read their instruction manuals before continuing along with this tutorial. Additionally, remember to wear safety glasses, and hearing protection when using power tools.

 

IMG_1065.jpg

 

Before we get started let’s take a moment to inventory the parts that we will need to complete this tutorial. You should have the following items:

    • 2X Votive Lantern
    • 2X Arduino Nano
    • 4X Neopixel Sticks
    • 2X Tall Tactile Buttons
    • 2X 10k Resistors
    • 2X USB A - USB Mini Cables
    • Hookup Wire
    • Soldering Iron & Solder
    • Glass Frosting Spray
    • Vellum or Tracing Paper
    • Hot Glue Gun & Glue Sticks
    • Black Craft Foam

 

IMG_1070.jpg

 

For the purposes of this tutorial, I am going to be building one of the lanterns. I will be making a build video with the second lantern. I picked this lantern up at a local home decore store, but I have seen them for sale on Ebay, Amazon, and a lot of other online retailers. You do not have to use this specific lantern, and any votive candle lantern, wall sconce, or even a more traditional hurricane lantern will work.

 

IMG_1073.jpg

 

To get started, we need to remove the glass panes and prep them for the frosting spray. For this particular lantern and most others like it, each glass pane is held on by four small metal tabs, as seen in the image above, that will need to be folded back to allow the pane to be removed. The glass pane’s are usually quite sharp, with their edges chipped from rough handling at the factory, so be careful, and consider wearing gloves when removing and handling these glass panes.

 

IMG_1077.jpg

 

With the glass panes removed, you can see how sharp and jagged their edges are. Now take the panes outside, or somewhere that is very well ventilated as the frosting spray produces noxious fumes when drying.

 

IMG_1078.jpg

 

To ensure that the frosting spray achieves good adhesion the glass needs to be free of any oily residue from handling it. I have found that using 91% isopropyl alcohol is best for cleaning the glass. I just wipe the glass with an alcohol moistened paper towel until the fingerprints disappear, then wait 10 minutes or so to ensure that all of the alcohol has evaporated.

 

IMG_1080.jpg

 

With the glass clean, I held the frosting spray about 10-inches away from the panes and sprayed a nice wet coat onto the glass. The instructions said to wait about 7 minutes and apply another wet coat. Then I waited for about 10 minutes and added another coat, this time about 14-inches from the surface and lighter than the last two. I repeated this step three more times until I was happy with the opacity of the panes.

 

IMG_1146.jpg IMG_1148.jpg

 

With the glass panes dry, I set them aside and started work on the electronics. Here you can see how opaque the frosting spray made the glass. The frosting spray works well, but we will still have to diffuse the light even more and we will discuss that more later. When setting the panes aside, do not stack them, or place anything on top of them as the frosting spray is pretty fragile and will scratch very easily.

 

IMG_1090.jpg

 

For this project I am using some 4-inch strips that I cut from a 5-meter roll of 140 pixel per meter NeoPixels that I had leftover from a previous project. The Neopixel sticks that I link to at the beginning of this tutorial work much better for this type of project, but unfortunately, my order was delayed and I did not receive the sticks in time for this tutorial.

 

IMG_1094.jpg

 

Before we get started wiring things together, the official Arduino Nano V3  comes with its header pins preassembled. I prefer to get the boards unassembled, but that is only possible with the off-brand variants of the nano. Because of this, the SPI header makes the nano a little too tall for our project, so I need to remove the six pin header on top of the board.

 

IMG_1100.jpg

 

To do remove these pins, I clamp the board in my small bench vice, and use my soldering iron to heat each pin’s solder joint while pulling on that pin with a pair of small needle nose pliers. Once the joint reaches molten temperatures, the pins pull right out. When doing this yourself, remember to not clamp the board too tight, as you could cause it to flex and break loose the surface mount connections of the small ICs and passive components.

 

IMG_1101.jpg

 

Here you can see that all of the SPI header pins have been removed, and nothing but small solder balls are left on the pads. I should have done this to the entire board as doing so would have provided me with a cleaner install. When I originally designed this project several years ago, I actually used Arduino Pro Mini boards which come with the header pins unsoldered. Eventually I developed my own purpose built PCB for this project, but that board was proprietary to the company I used to own, so unfortunately, I can not share it here. I could design a new board if there is enough interest though.

 

IMG_1106.jpg IMG_1109.jpg

 

While we are modifying the Arduino Nano to better fit our project, we need to cut some small strips of black craft foam which we will hot glue to the Nano’s surface to insulate it from the metal bottom of the lantern. Since the USB port sits several millimeters proud of the PCB’s surface, I cut a smaller piece of foam to help level things out for the larger piece which will cover the full surface.

 

IMG_1113.jpg IMG_1115.jpg

 

Here you can see how I glue the foam to the Nano to ensure that the final result is nice and flat. It is important to note that you should not cover the Nano’s reset button with hot glue, and make sure to not depress it when pressing the foam into the glue. If you accidentally get glue on the button, just let it dry and remove it with your fingers or the needle nose pliers. Also note that I used two very small drops of glue on each end of the small strip of foam for this very reason. Once the glue has dried, try depressing the button. It should click, which is an indication that it is not stuck with glue.

 

2017-07-12 03_46_23-Start.png

 

Wiring up the hardware is fairly straightforward. Following the Fritzing diagram above make the following connections. It’s important to wire the Neopixel sticks exactly the same so that their animations sync up later on.

 

    1. Arduino Nano Digital Pin 2 to Button Pin  1
    2. Arduino Nano Digital Pin 2 to Resistor Pin 1
    3. Resistor Pin 2 to Arduino Nano GND
    4. Button Pin 3 to Arduino Nano 5V
    5. Neopixel Stick 1 5V to Arduino Nano 5V
    6. Neopixel Stick 1 GND to Arduino Nano GND
    7. Neopixel Stick 1 Data In to Arduino Nano Digital Pin 6
    8. Neopixel Stick 2 5V to Arduino Nano 5V
    9. Neopixel Stick 2 GND to Arduino Nano GND
    10. Neopixel Stick 2 Data In to Arduino Nano Digital Pin 6

 

 

IMG_1122.jpg

 

Let's begin by focusing on the Neopixel sticks / strips. Since I am using flexible strips that have been cut into 4-inch long pieces, I need to add something rigid to them to ensure they stand up nice and proud later in the build. I simply use a popsicle stick that I cut with an x-acto knife to be slightly thinner and shorter than the strips. Typically, the only glue that will bond to the strips is something super tacky like E6000, which just so happens to be my third favorite glue, and something I stock in my workshop by the half dozen. If you are wondering, Cyanoacrylate (CA) and hot glue are my other two favorite types of glue.

 

IMG_1123.jpg IMG_1125.jpg

 

I spread a small thin line of the glue across each strip, and then sandwiched the popsicle stick between the two strips. E6000 is quite the potent glue, and it would be advisable to have a small fan running near your workbench to avoid over inhalation of its fumes.

 

IMG_1127.jpg IMG_1129.jpg

 

To ensure that the strips stayed oriented on the popsicle stick, I used a pair of small zip ties to secure them to the stick. Then I placed the sandwich between two scrap pieces of wood, and used small clamps to apply gentle pressure until the glue cured about an hour later.

 

IMG_1132.jpg

 

Here you can see a closeup of the stick once it had cured and was ready to solder some wires to. I decided to leave the zip ties on for added insurance.

 

IMG_1133.jpg

 

I forgot to mention earlier that you should orient both strips so that their Data In pins are on the same end of the stick. This makes wiring up the Neopixels a little more difficult, but it is necessary to achieve the effect we are going for.

 

IMG_1134.jpg IMG_1135.jpg

IMG_1137.jpg IMG_1142.jpg

 

I pre tinned the hookup wires before soldering them to the Neopixels. In the second photo (click to enlarge) you can see how I hook the strips together. Since the strips are mirrored from each other, I need to cross over the 5V and GND lines, but the Data In pin remains in the middle. This process is much easier with the Neopixel sticks than it is with these high density strips which have very small solder pads.

 

IMG_1143.jpg

 

Before we solder our wires to the Arduino Nano, cut a small passageway into the top of the foam. This will allow us to pass the Neopixel’s wiring under the Arduino when installing the electronics.

 

IMG_1116.jpg

 

In an attempt to make the install even more low profile, I decided to bend over the pins I would be using, which would allow me to lay the wires down instead of having them stick up and possibly create shadows. As I mentioned earlier, this was a mistake, and I should have desoldered all of the pins from the board, and soldered the wiring directly to the pads. This would have resulted in a much cleaner install, but I guess you live and learn, and in reality, no one will see the mess that is to come once the lantern is finished.

 

IMG_1144.jpg

 

With the pins bent over, it's time to solder the Neopixel’s wires to the Arduino Nano. Refer to the diagram above if you forgot which pins each wire connects to. You can see here how messy this looks, but it's functional, and will not be visible in the completed project, so it's not that big of a deal honestly.

 

IMG_1158.jpg

 

Now it’s time to wire up the button. Notice that I hold it in a pair of helping hands. This makes things easier as one alligator clip can hold the button while the other holds the wire in place. If you are worried about mixing up the pinout on the button, as long as you solder one wire to a pin, and then solder the other wire to the opposite corner, the orientation will be correct.

 

IMG_1165.jpg

 

Here you can see the orientation of the wires on the button. I would leave a good three to four inches of wire length to help make installation easier.  You can also see that I added a layer of black foam to the other side of the Arduino Nano as well. I did this to cover up the mess that you will see in the next photo.

 

IMG_1162.jpg

 

With the button soldered in place, I needed to add the resistor Digital Pin 2 and GND on the Arduino. The button press counting code will not function correctly unless  this pull-down resistor is in place. If you wanted a cleaner layout, you could utilize the 5V and GND pins on the SPI header that we removed earlier. With the electronics finished, this is the time to upload the code to the Arduino Nano. I am not covering that part of the project in this tutorial because if you do not know how to do that, you need to head over to the Arduino website, and walk through their getting started guide.

 

  IMG_1145.jpg IMG_1167.jpg

IMG_1168.jpg IMG_1169.jpg

 

Now that the electronics are finished, it's time to reinstall the glass panes in the lantern body. But before we do that, we need to drill a 7/16-inch hole in the top of the lantern as close to its hanger loop as possible. This will allow us to run the USB cable down into the lantern to provide power to the Arduino Nano. You will also need to touch up the paint on the lantern as the drill will cause some minor scratches and the hole’s rim will need paint.

 

IMG_1154.jpg

IMG_1156.jpg IMG_1157.jpg

 

This is also the time to drill the hole in the bottom for the button. In my case a 3/16-inch drill bit was needed. I like to use a small piece of sandpaper to clean the bur from the hole, and to scuff the surface which will make the hot glue we will use to secure the button stick better.

 

IMG_1150.jpg

 

Installing the panes is as simple as reversing the steps you took to remove them. This time you need to be very careful as to not scratch the frosted coating on the lanterns sharp edges. It’s also worth noting that if you have sweaty hands, this would be a good time to wash them and wear gloves, as the oils from your skin will visibly stain the frosted coating.

 

IMG_1152.jpg

 

Here you can see the difference in the frosted glass versus the clear glass. The clear glass is nice when using an actual candle, but since we are using LEDs it must be frosted to hide the electronics. I actually prefer the frosted look myself. This would be a good time to point out that I chose these lanterns because of the one inch tall wall at the bottom. This wall is tall enough to hide the shadow that will be cast by the LEDs when illuminated. Keep this in mind when choosing your lantern. Alternatively you can hide the electronics in the top of the lantern and uncomment the line near the top of the code that will reverse the led animation’s direction of flow, which will allow you to hang the Neopixel sticks from the top, and it still look like the flame is flickering from bottom to top.

 

IMG_1170.jpg IMG_1171.jpg

 

Now let's begin installing the electronics! The first thing we need to attach is the button, and that’s quite simple to do! Place the button in the small hole, and then cover it in a nice thick layer of hot glue, then hold in place using the wiring until the glue solidifies. Try your best to not get any glue between its mandrel and the button body itself as this could prevent it from working.

 

IMG_1173.jpg

 

Now apply a small strip of hot glue to the corner closest to the back of the lantern in relation to the middle of the door. Then press the USB cable into the hot glue making sure to leave just enough room to connect it to the Arduino Nano.

 

IMG_1174.jpg

 

With the USB Cable in place, its time to use two small dabs of hot glue to secure the Arduino nano in place. Plug the USB cable in before doing this. If you are worried about the cable pulling out through the top, you can zip tie a ½-inch steel nut to it in top of the lantern. I have found the hot glue to be sufficient though.

 

IMG_1182.jpg

 

Installing the Neopixel sticks is a little bit tougher than the other components and it requires a steady hand. Once the stick has been placed as close to the center as possible, I use my glue gun to apply hot glue from the first pixel down. I make sure that some of this glue actually coats the first pixel, which gives it a bit more rigidity. Once this first layer of glue is solidified, I add another layer making even more contact with the stick. Note that I did not include a photo of the surface of the lantern under the stick. I scuffed it up with 80-grit sandpaper before applying the glue. After 2 or 3 layers, the stick should be stuck firmly into place, and very rigid. It is important to ensure that no metal from the solder connections are touching the metal surface, and you can add a thin layer of hot glue to the surface before gluing the stick in place if you are worried about this.

 

IMG_1183.jpg

 

Now we need to take the velum paper and create a small cylinder shaped diffuser. This is necessary because the frosting on the glass is not enough to fully diffuse the circular light pattern the LEDs project. Since the stick is about 4-inches tall, I made my diffuser about 5-inches tall, and secured its ends together with a piece of double sided tape. Glue will work fine here as well, but you want the thinnest layer possible to prevent a dark spot in the diffuser.

 

IMG_1186.jpg

 

Since the blob of hot glue holding the Neopixel stick up is so large, I had to cut out some of the diffuser on the bottom to make it fit. I got it as close as possible, and even though a few gaps were showing, I knew that it would be pointed towards the back of the lantern and not visible from the front.

 

IMG_1188.jpg

 

To secure the diffuser in place, I used a few dabs of hot glue. With this in place, we simply need to hook up our USB cable to a power source and things are finished. I did notice that the lantern’s brightness was a bit high, so I plugged the USB cable into my PC and adjusted the brightness to about 125 by changing the code near the beginning of the code.

 

 

Conclusion

 

 

Overall I am quite pleased with the end result, but I am still bothered by how messy the electronics connections to the Arduino were. I decided to desolder all of the pins in the second lantern to make things a bit cleaner. Since I used 10-foot USB cables, I can hang these lanterns almost anywhere and still have enough cable to connect them to a wall outlet, and since they are USB powered, I can use a USB battery pack to power them on excursions like camping trips, over by our fire pit in the backyard, or even in Halloween decorations in our front yard this october.

 

That is going to wrap up this tutorial, and I want to thank you for taking the time to read through it. This project was quite fun, and is something you can accomplish in an afternoon by yourself or with others, and still have a project that is quite impressive when finished and the lights are turned off. I would love to hear everyone’s feedback on this project, so please feel free to leave a comment below.