Arduino Project Hub
Project tutorial

Kaleidoscope Infinity Mirror © GPL3+

Build a beautiful “infinity mirror” Illusion that you can control by changing this mirrors' orientation. Rotate for changing colors!

  • 8,404 views
  • 1 comment
  • 45 respects

Components and supplies

Ardgen 101
Arduino 101 & Genuino 101
×1
1m Adressable unsealed LEDs (60)
This Sparkfun version is conveniently wired for this project, but you can use Adafruit's NeoPixels or similar.
×1
Short section of solid-core wire or jumper pins
This is to make stranded wire Arduino pin-compatible.
×1
heat shrink tubing
Optional if you are feeling fancy.
×1
barrel jack female connector w/screw terminals
×1
barrel jack male connector w/screw terminals
×1
3x AA battery holder with switch
×1
Pololu Valtage Step-Up Regulator
This $4 regulator allows the whole project to be powered from one battery pack with 3 AA batteries. Alternatively, you can skip this part and use a 9v battery to power the Arduino 101. If you go that route, you'll still need the 3 AA pack to power the lights. https://learn.adafruit.com/adafruit-neopixel-uberguide/power
×1
61vhxtmzbyl
AA Batteries
×1
12” square “shadow box” picture frame
The depth and size of this frame is perfect!
×1
12" square mirror
This will fit in the back of the picture frame.
×1
11" photo easel
To display the finished product
×1
Mirrored privacy tinting
(optional – greatly improves the effect, but not 100% required)
×1
FoamCore
Standard 3/16" or 1/4" FoamCore. I used white but black might look nice too. You need enough to make one 12" x 12" piece, plus enough to piece together a strip 1m long, 05” wide.
×1

Necessary tools and machines

09507 01
Soldering iron (generic)
box cutter with fresh blade
Hy gluegun
Hot glue gun (generic)
wire strippers

Apps and online services

Ide web
Arduino IDE
You need the Adafruit NeoPixel library for this project. https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-installation Also, if you're new to the Arduino 101, you'll need to install the Curie Core to access the positional sensors. https://www.arduino.cc/en/Guide/Arduino101

About this project

A cross between a Kaleidoscope and an Infinity Mirror! As you change the rotation of the mirror, the lights change in response. This project is built with an off-the-shelf mirror and picture frame, and a few other components. The Arduino 101 development board has a built-in positional sensing that we can use to sense the angle, and control the light display.

Note: This project uses the same electronics set-up as the Holiday Shadow Theater, basically just an Arduino101, an LED strip, and a battery pack. I use a $4 voltage regulator so that the same battery pack can power both the LEDs and the Arduino 101. Alternatively you could use a 9v battery to power the Arduino and skip the regulator.

Part One: Build the Mirror

Step 1:

Using a sharp box-cutter or hobby knife, cut a 12” x 12” square of Foamcore and mark the center with a pencil. You can use the back cardboard from the picture frame as a reference.

Step 2:

Using a circle drawing tool or a string and pencil, draw a perfect circle with a radius of 5.25” centered in the 12 x 12. You can use a ruler to put a mark 0.75" from the edge of the 12x12 and use that as a starting reference point.

Step 3:

Using a box-cutter or hobby knife with a new blade, carefully cut out the circle. This cut will be visible in the final product so cut as cleanly as you can.

Step 4:

Once the hole is cut, choose the best-looking side, and place it good-side down on a clean work surface.

Step 5:

Cut a separate ½ inch strip of Foamcore, about 36" long. This can be pieced together from shorter segments with tape if needed. Use a ruler and keep the size as close to a uniform 0.5” as you can.

Step 6:

Lay the completed strip horizontally on a table, and cut even vertical scores through the top sheet of paper every 2” along the total length.

Step 7:

Flip the strip over, and using hot glue, attach the LED string along the length of the Foamcore strip.

Step 8:

Bend the completed strip into a rough circle using the scores you cut in the back of the Foamcore as bend points.

Step 9:

Lay the LED strip in a ring over the hole in your 12x12" foamcore square. The full LED strip will be too long. Size your LED circle to be just larger than the hole, and cut off the extra LEDs (about 6 LEDs.) You can still use these spare LEDs for a different project later.

Step 10:

Place the LED strip in a ring on the top surface (bad side) of your 12x12" square, and hot-glue in place just at the edge of the circle hole. Make sure the back of the LED ring is at least 0.25” in from the edge of the 12 x 12” square. (Otherwise, the black plastic spacers from the frame won't fit around it.

Step 11:

If using the semi-mirror film, take the glass out for your shadowbox frame and apply the film to the glass following the manufacturer’s instructions. I found this to be the most fiddly step. Make sure to clean the glass first and use water (or soap solution) to make the air bubbles easier to remove. Using the mirror film creates a much stronger illusion and hides the LEDs, but it is not 100% necessary (and you can added it later if desired!) If using film, place the glass back in the frame with the film side facing up/into the frame.

Step 12:

With the frame facing down and the glass clean, position the foam on top of the glass, with the good side down and the LED ring up. Add two of the spacers that came in the frame, then add your 12x12” mirror face down. The LED wires should come out the back of the frame past the mirror. If the mirror fit is too tight for the wires, you may need to carefully carve a notch for the wires in the frame edge using a box-cutter or hobby knife.

If there’s space, add the cardboard frame backer, or if not just hold the mirror in place with the frame’s tabs. That’s done! Now for the magic of electronics.

Part Two: Setting up the Electronics

Step 1

Find the extra 6-LEDs you cut off the end earlier. Collect the harness from the end, cutting about 1 cm from the lights. Strip the wire ends.

Step 2

Break apart the bent header pins that came with your voltage regulator, and solder two of them to the ends of the green and yellow wires. This will let you easily plug them into the pins of the Arduino 101.

Step 3

Next solder the red wire to the VIN terminal on the Voltage Regulator, and solder two straight headers into the GND and VOUT pins as shown.

Step 4

Now connect the barrel jack adapters. First strip the ends of the wires coming from your battery case, then mount them in the terminals of the male barrel jack and tighten with a screwdriver. RED goes to the (+) terminal, BLACK goes to the (-) terminal.

Next connect the female barrel jack adapter onto to the loose wires coming from the beginning of the LED strip (coming from the back of your mirror.) On this strip, YELLOW goes to the (-) terminal, and RED goes to the (+).

Step 5

Now connect your harness to the Arduino 101. The GREEN wire goes to PIN 6, the YELLOW wire goes to the GND pin near #13.

With the two header pins on the voltage regulator, GND goes to GND and VOUT goes to the "Vin" pin on the Arduino 101. Don't get this wrong! Plugging in backwards leads to smells and burns. I know this.

Step 6: Connect the wire harnesses on the Arduino 101 and the LED strip together, then connect the battery-pack barrel jack to the LED strip's barrel jack and you're all wired up!

Step 7:

Now that your electronics are done, position the Arduino 101 on the back of the mirror with its orientation parallel to any side of the mirror. Attach it with Velcro, double-sided tape or hot glue. Mount the battery pack nearby and secure any loose wires with tape or glue.

Upload the sample code using a computer, a USB cable and the Arduino IDE.

Alternatively, you can access, edit and upload the example code using the Arduino web-based IDE.

Try it out!

The example code changes the colors of the LEDs based on the angle of the mirror, as read from the accelerometer on the Intel Cure Compute Module. Currently, one position turns all the lights off, and one angle creates a chasing light effect with the last color used. Feel free to dive into the code and make some crazy lighting effects! The excellent Adafruit NeoPixel Uberguide is a great place to start.

IMPORTANT! If you want to permanently install this mirror, you can use a plug-in power supply instead of the battery pack, but make sure it's outputting 3.5v - 5v! Any higher voltage (such as a 9v square battery) may overload the LED strip.

Code

Arduino 101 Infinity Mirror SketchArduino
Simple sketch that reads the angle of the Arduino 101 from the internal accelerometer, and uses the angle to control colors of a NeoPixel LED strip.
/*
   Copyright (c) 2016 Intel Corporation.  All rights reserved.
   See license notice at end of file.

  Arduino 101 "Infinity Mirror." The rotation angle of the Arduino 101 changes the lights in a Neopixel strip.
  This code uses the Adafruit Neopixel library. Library installation instructions here: https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-installation
  If using the desktop version of the Arduino IDE, make sure you have the latest Intel Curie Core installed. For more info, visit https://www.arduino.cc/en/Guide/Arduino101
*/



#include "CurieIMU.h"
#include <Adafruit_NeoPixel.h>
#define PIN 6  //// what pin are the NeoPixels connected to?
Adafruit_NeoPixel strip = Adafruit_NeoPixel(54, PIN, NEO_GRB + NEO_KHZ800);  /// the strip is 15 pixels long.  You can change this for the number of pixels in your individual strip.

int tr = 0;  //Some variables to hold "color-target" and "color-current" for smoothing...
int tg = 0;
int tb = 0;
int r = 0;
int g = 0;
int b = 0;

int rawX = 0;  /////  to hold values from the Curie's accelerometer
int rawY = 0;
//int rawZ = 0;
float angle = 0.0;


void setup() {
  // put your setup code here, to run once:

  //Serial.begin(9600);  //for debug.
  CurieIMU.begin();
  CurieIMU.setAccelerometerRange(2);  // Set the acceleromiter range to 2g.

  strip.begin();  //  intialize neopixel strip
  strip.show();   // Initialize all pixels to 'off'
}

void loop() {
  // put your main code here, to run repeatedly:

  // read accelerometer:
  int rawX = CurieIMU.readAccelerometer(X_AXIS);
  int rawY = CurieIMU.readAccelerometer(Y_AXIS);
  int rawZ = CurieIMU.readAccelerometer(Z_AXIS);


  angle = atan2(rawX, rawY); // the funtion atan2() converts x and y forces into an angle in radians.  cool!  Output is -3.14 to 3.14

  if (abs(angle) > 2.5) { //  digital pins are down
    ///  turn lights off in this position
    tr = 0;
    tg = 0;
    tb = 0;
    runlights();
  }

  if ((angle > 1.5) && (angle < 2.5)) {
    //make lights white in this position (equal r, g and b.)  Color values can go up to 255, but I find it's bright enough at 100.
    tr = 100;
    tg = 100;
    tb = 100;
    runlights();
  }
  
  else if ((angle < 1.5) && (angle > 0.5)) {
    //make lights red in this position
    tr = 100;
    tg = 0;
    tb = 0;
    runlights();
  }
  
  else if ((angle < 0.5) && (angle > -0.5)) {
    //make lights green in this position
    tr = 0;
    tg = 100;
    tb = 0;
    runlights();
  }
  

  else if ((angle < -1.5) && (angle > -2.5)) {
    //make lights blue in this position
    tr = 0;
    tg = 0;
    tb = 100;
    runlights();
  }

    else if ((angle < -0.5) && (angle > -1.5)) { ////  picking one corner angle for something fun!

theaterChase();  /// these functions are written out at the bottom of the sketch.  
//rainbowCycle(2);

  }
  
  else {
    ////  in case of some unexpected angle, turn lights off.
    tr = 0;
    tg = 0;
    tb = 0;
    runlights();
  }
}

void runlights() {
  /// color smoothing.  Current color moves toward target color...  If target is more than curent, move up, if less, move down.
  if (tr > r + 1) {
    r++;
  }
  if (tg > g + 1) {
    g++;
  }
  if (tb > b + 1) {
    b++;
  }
  if (tr < r) {
    r--;
  }
  if (tg < g) {
    g--;
  }
  if (tb < b) {
    b--;
  }

  //turn all the LEDS to the current r, g, b values.
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, r, g, b);
  }
  strip.show();
  delay(10); //  time delay for simple fade timing.
}

///////////////Special light functions from Adafruit Strandtest Example Code

// Rainbow!  Note- this function blocks new position inputs until it's finished.
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);
  }
}

    //////Theater Chase lights from Adafruit strandtest example code.  This takes whatever the curent RGB value is, and does a "theatre chase" effect with it.
  void theaterChase(){  for (int j = 0; j < 3; j++) { //3cycles of chasing
      for (int q = 0; q < 3; q++) {
        for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
          strip.setPixelColor(i + q, r, g, b); //turn every third pixel on
        }
        strip.show();

        delay(50);

        for (uint16_t i = 0; i < strip.numPixels(); i = i + 3) {
          strip.setPixelColor(i + q, 0);      //turn every third pixel off
        }
      }
    }
  }

// Input a value 0 to 255 to get a color value.  Used for rainbow effect above.
// 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);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}



////////////////////////////////////////////////////////////////////////////////////////////
/*
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

Comments

Similar projects you might like

Arduino morse code machine

Project tutorial by Vlada Krsmanovic

  • 441 views
  • 0 comments
  • 7 respects

Arduino 101 - Intel Curie Pattern Matching Dress

Project tutorial by Kitty Yeung

  • 1,483 views
  • 2 comments
  • 13 respects

Arduino Laser Tripwire

Project tutorial by Ian Cumming

  • 1,996 views
  • 1 comment
  • 15 respects

Smart Home Sensor Node

Project tutorial by vincent wong

  • 509 views
  • 0 comments
  • 5 respects

Magnetic Stirrer

Project showcase by jdale18

  • 594 views
  • 7 comments
  • 4 respects

ESP8266 + L298N Motor Drive + Smartphone

by luciorocha

  • 1,400 views
  • 2 comments
  • 5 respects
Add projectSign up / Login