Introduction: Mt. Everest Lamp

The idea of the Everest Lamp came from a close friend. I've traveled in the Himalayas and have seen some of the highest peaks from far. I visualized a lamp that would imitate the feeling of an icy terrain with translucent light reflecting off its surface. We created an early prototype (which is quite far from the ambitious floating Everest peak). I will also be sharing media of the early prototype to give an idea of the baby steps that lead to the final project.

The final version of the lamp was designed by me and a colleague.

Supplies

Clearly, I dreamed this up pretty ambitious. But thankfully, the materials used are commonly available.

    1. WS2812B LED strip (Example)
    2. Soldering equipment(Example)
    3. Arduino Nano (Example)
    4. 5V 1A power supply with female connector or 4 AA cells(Example)
    5. 3D printed mountain
    6. 2 Meters of 12.5 mm stainless steel hollow square section (Example)
    7. M3 screw fasteners(Example)
    8. M3 dome nuts(Example)
    9. Magnet wire(Example)
    10. Hot glue (Example)
    11. Access to a metal shop for fabrication

    Step 1: Design

    The lamp was designed to simulate the feeling of a floating mountain whose reflection (often seen in pristine lakes) creates an illusion between the real and the reflected mountain. The iconic Everest terrain was irresistible to replicate. The ends of the lamp could not flatten out because I wanted the lamp to remain true to the geographic landscape. Hence I decided to end it off as a cross-section of the lower peaks surrounding Everest which form the four sides of the design.

    Since the final mountain was to "float" the metal stand had to complement this. It was important to frame the mountain, yet remove all contact from the frame. This is the concept behind the design of the metal stand. With a minimal top and bottom square frame and a single vertical connecting piece it worked perfectly well.

    The final part of the design was the lighting bit. We found an existing library that nicely programmed RGB LEDs to replicate a shifting hue of colours. This was the desired effect we wanted and went ahead with it.

    To summarize the work for this project can be broadly divided into 3 areas:

    1. The mountain 3d printing
    2. The metal stand fabrication
    3. The electronics for the lighting
    4. The assembly

    Step 2: First Prototype

    The first prototype was done with a smaller 3d print of Mt. Everest and a cardboard base concealing the electronics. The motivation to do a more ambitious 'floating' lamp came after building the first prototype.

    Step 3: Mountain [3D Printing]

    A bit of searching & I managed to find a 3D model of Mt.Everest here which I modified and adapted for use in my lamp (Final model STL files attached).

    The 3d printing settings used by me are 200 micron, 20% infill, Shell/top/bottom thickness 0.8, printing speed inner walls at 30 mm/sec, outer wall at 50 mm/s. The spool has to be a translucent one. Around 100 meters of spool will get used to print both the mountains.

    You might notice the final lamp design is suspended from 4 posts inside the mountain terrain. These platforms are subtly concealed in the terrain (numbered in red in the image). At the time of assembly small holes can be punched into these platforms for the wiring to pass through.

    The total 3d printing time will be around 18 hours for both the mountains.

    Step 4: Metal Stand

    The stand is largely made of 12.5 mm square stainless steel tubes welded together, buffed & polished to a glossy mirror perfection. The drawing indicates the dimension & features of the stand for easy fabrication. Mitre joints were cut at the corners and used for welding off to get perfect squares.

    The location of the holes in the various parts of the stand is very important. The final stand image shows the holes numbered. Holes 1-6 are drilled and 7,8,9 are tapped holes. The addition of dome nuts at the bottom of the stand is optional and if you chose to omit this part holes 7-9 need not be tapped.

    1-4 holes are from which the enameled wiring (magnet wires) powering up the arduino and LEDs pass through. Interesting part of the design is that these wires conduct power as well as carry the weight of the mountain. Hole number 5 was used to make the assembly process easier, giving an entry point to pass the wiring through. Holes number 6 (out of view) is from which the wires meet the cabling of the 5V adapter.

    Step 5: Electronics

    We started playing around with regular RGB LEDs hooked up to an Arduino Uno and quickly realized it needed a lot of those LEDs to get the lamp up to the kind of brightness & hue transition we were hoping for. We came across the DS2812B addressable RGB LEDs that seemed to be much brighter and were available as strips.
    The nicest part of the DS2812B turned out that it works with the Adafruit neopixel library for Arduino. This is the same code used in the early prototype. We got the simple example of code from the internet that uses a single digital PWM pin to drive the LEDs, wired up everything to a power supply & it works! For the final version, we decided to use the Arduino Nano because of its small board footprint.
    The electronics are powered using a 5V 1A AC adapter. The wiring of components is illustrated in the schematics.

    Step 6: Arduino Code

    #include 
    #ifdef __AVR__
    #include <avr power.h="" style="background-color: initial;">
    #endif
    #define PIN A5
    #define NUM_LEDS 100
    #define BRIGHTNESS 250
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRBW + NEO_KHZ800);
    int gamma[] = {
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
      1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
      2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
      5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
      10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
      17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
      25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
      37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
      51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
      69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
      90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
      115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
      144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
      177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
      215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255
    };
    void setup() {
      Serial.begin(115200);
      // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
    #if defined (__AVR_ATtiny85__)
      if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
    #endif
      // End of trinket special code
      strip.setBrightness(BRIGHTNESS);
      strip.begin();
      strip.show(); // Initialize all pixels to 'off'
    }
    void loop() {
      // Some example procedures showing how to display to the pixels:
      colorWipe(strip.Color(255, 0, 0), 50); // Red
      colorWipe(strip.Color(0, 255, 0), 50); // Green
      colorWipe(strip.Color(0, 0, 255), 50); // Blue
      colorWipe(strip.Color(0, 0, 0, 255), 50); // White
      whiteOverRainbow(20, 75, 5);
      pulseWhite(5);
      // fullWhite();
      // delay(2000);
      rainbowFade2White(3, 3, 1);
    }
    // Fill the dots one after the other with a color
    void colorWipe(uint32_t c, uint8_t wait) {
      for (uint16_t i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, c);
        strip.show();
        delay(wait);
      }
    }
    void pulseWhite(uint8_t wait) {
      for (int j = 0; j < 256 ; j++) {
        for (uint16_t i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, strip.Color(0, 0, 0, gamma[j] ) );
        }
        delay(wait);
        strip.show();
      }
      for (int j = 255; j >= 0 ; j--) {
        for (uint16_t i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, strip.Color(0, 0, 0, gamma[j] ) );
        }
        delay(wait);
        strip.show();
      }
    }
    void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
      float fadeMax = 100.0;
      int fadeVal = 0;
      uint32_t wheelVal;
      int redVal, greenVal, blueVal;
      for (int k = 0 ; k < rainbowLoops ; k ++) {
        for (int j = 0; j < 256; j++) { // 5 cycles of all colors on wheel
          for (int i = 0; i < strip.numPixels(); i++) {
            wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);
            redVal = red(wheelVal) * float(fadeVal / fadeMax);
            greenVal = green(wheelVal) * float(fadeVal / fadeMax);
            blueVal = blue(wheelVal) * float(fadeVal / fadeMax);
            strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );
          }
          //First loop, fade in!
          if (k == 0 && fadeVal < fadeMax - 1) {
            fadeVal++;
          }
          //Last loop, fade out!
          else if (k == rainbowLoops - 1 && j > 255 - fadeMax ) {
            fadeVal--;
          }
          strip.show();
          delay(wait);
        }
      }
      delay(500);
      for (int k = 0 ; k < whiteLoops ; k ++) {
        for (int j = 0; j < 256 ; j++) {
          for (uint16_t i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(0, 0, 0, gamma[j] ) );
          }
          strip.show();
        }
        delay(2000);
        for (int j = 255; j >= 0 ; j--) {
          for (uint16_t i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, strip.Color(0, 0, 0, gamma[j] ) );
          }
          strip.show();
        }
      }
      delay(500);
    }
    void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) {
      if (whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;
      int head = whiteLength - 1;
      int tail = 0;
      int loops = 3;
      int loopNum = 0;
      static unsigned long lastTime = 0;
      while (true) {
        for (int j = 0; j < 256; j++) {
          for (uint16_t i = 0; i < strip.numPixels(); i++) {
            if ((i >= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ) {
              strip.setPixelColor(i, strip.Color(0, 0, 0, 255 ) );
            }
            else {
              strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
            }
          }
          if (millis() - lastTime > whiteSpeed) {
            head++;
            tail++;
            if (head == strip.numPixels()) {
              loopNum++;
            }
            lastTime = millis();
          }
          if (loopNum == loops) return;
          head %= strip.numPixels();
          tail %= strip.numPixels();
          strip.show();
          delay(wait);
        }
      }
    }
    void fullWhite() {
      for (uint16_t i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, strip.Color(0, 0, 0, 255 ) );
      }
      strip.show();
    }
    // Slightly different, this makes the rainbow equally distributed throughout
    void rainbowCycle(uint8_t wait) {
      uint16_t i, j;
      for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
        for (i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
        }
        strip.show();
        delay(wait);
      }
    }
    void rainbow(uint8_t wait) {
      uint16_t i, j;
      for (j = 0; j < 256; j++) {
        for (i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i + j) & 255));
        }
        strip.show();
        delay(wait);
      }
    }
    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos) {
      WheelPos = 255 - WheelPos;
      if (WheelPos < 85) {
        return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3, 0);
      }
      if (WheelPos < 170) {
        WheelPos -= 85;
        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3, 0);
      }
      WheelPos -= 170;
      return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0, 0);
    }
    uint8_t red(uint32_t c) {
      return (c >> 8);
    }
    uint8_t green(uint32_t c) {
      return (c >> 16);
    }
    uint8_t blue(uint32_t c) {
      return (c);
    }</avr>

    Step 7: Assembly

    After prepping all the individual bits, I started assembling the parts together with appropriate joining processes.

    The power wires for the electronics is snaked thorough the metal frame using magnets and thread which is a bit tricky, but that extra bit of effort offers a satisfying concealment.

    The LED strips were hot glued in the shape of an 'X' on both mountains. The arduino should already be programmed and then can be hot glued to a secure surface of the mountain. Once the wiring is soldered based on the schematic it can be taken out of the back hole of the vertical piece to be soldered with the female connector of the 5V adapter.

    The trickiest part is leveling the mountain such that it doesn't float at an angle. Easy way to do this is once the electronics is complete suspend the top mountain. Remember as mentioned in step 3 the wiring gets pulled out of the tiny holes punched in the four platforms concealed within the terrain of the mountain (refer mountain 3d print section). This makes it easy to level the mountain. After that the lower mountain can be fixed using screw fasteners at the corners.The dome nuts can be screwed to the bottom with 3mm threaded studs which give the entire stand a finishing touch.

    A major design flaw in this version is the lower piece is not actually a mirrored piece of the upper mountain. But this has been corrected in the 3d printed files attached in this instructable. Also this mountain works really well as a corner mood lamp, in dim settings. It definitely has given me a soothing effect.

    Step 8: Finished Lamp

    Some more images and a short time lapse....