DIY a Magic Light Box

by maker_studio in Circuits > Art

7465 Views, 62 Favorites, 0 Comments

DIY a Magic Light Box

Magic Light Box
move.JPG
MLB.JPG

Let's see what Magic Light Box (MLB) is!

MLB is a lighting box that can change the color upon the movment. It is based on Arduino Nano, using tri-axial accelerometer ADXL345 to collect the moving information. Besides, it can be charged by way of wireless charging.

Three Lighting Mode:

Shaking in X direction - White Color Mode

Shaking in Y direction - Auto-changing Color Mode

Shaking in Z direction - Changing upon Attitude Mode

Prepare the Materials

adxl345.jpg
arduino nano.jpg
inductive wire.jpg
wireless transcver.jpg
RGBLED.JPG
battery.jpg
voltage booster.JPG

Tools

Iron solder

Hot melt glue gun

Tool for cutting the prototyping board

Materials

1 x Arduino Nano

1 x ADXL345

1 x Wirelss charging module

1 x DC-DC 5V boost module

2 x 3.7V lithium ion battery 952240

20 x Common anode mist RGB led

1 x Resistance of 5 ohms, 100 ohms each one

3 x NPN transistor 8050

N x DuPont line, sewing, fly line

1 x 5.5mm DC Power Interface

1 x 12VDC power adapter

Schmatics

sch.JPG

R1 = 5ohm, R2 = 10ohm, the value depends on the number of RGB LED.

Connects the Modules

IMG_20140907_192657-1024x768.jpg

Connects the modules based on the schematic.

Testing the Circuit

test 2.jpg

Test the circuit to see if the driving part works or not.

Add the Glue to Protect the Circuit and Program

bund.jpg
instalk.jpg

The Arduino Nano is then covered by the glue to avoid the possible short circuit.

Do the same for the other modules.

Then simply tied them with hot melt adhesive. Before that you can cut off some pins on the modules to save space, such as arduino Nano's ICSP pins. Once the work is completed, this Nano is impossible to use again, so, for those unused IO pins, cut them off!

Program to the Nano, and test the functions. Test the charging effect. After doing the above work, this stuff can be put aside.

Installing the RGB LEDs to Acrylic Board

A BOARD.jpg
CONNECT LED.jpg
CONNECT.jpg

The thickness of the acrylic board is 1.7mm. Cut the boards as the attached designs.

Install the RGB LED to the 5 boards with holes.

All 20 RGB LEDs are in prallel connection. Be careful the polarity of each LED.

I don't recommend using the colored line on the photo, as the soldering point is easy to disconnect.

The soft fly line is a good choice, as it is able to adapt to the process of enclosing acrylic to the cubic.

Note, the current of single line only allowed 47mA or less. So the part closer to the power should be connected more lines. The lines connected to anode pins should be more than the cathode pin.

Pay attention to confirm the fly line is not easy to fall off, and using a multimeter to verify before the final installation.

Yes, this step is very complicated.

Downloads

Test With the Electronic Controlling Part

CONNECT BOARD.jpg

Connect the controlling part made above, and test.

Install the Internal Cube

IMG_20141001_183451-768x1024.jpg

Connect the boards with hot melt glue to get the Internal LED cube done.

Install the LED Cube Onto the Acrylic Base Board

IMG_20141003_0208491-1024x768.jpg

Install the LED cube on a white acrylic. Put the wireless charging receiving coil inside the center, self-locking switch to the right position.

Install the External Acrylic Cube Boards

IMG_20141003_020828-1024x768.jpg
chargeposition.jpg
IMG_20141003_0214451-1024x768.jpg

Glue the acrylic boards into a big cube, and install the LED cube into it.

The main body of the MLB is done, and the size is 96x96x96mm

Make the Charging Base

IMG_20141009_175158-1024x768.jpg
IMG_20141009_175302-1024x768.jpg

It's very easy to make the charging base.

Put the DC connecter and the wireless charging module to the acrylic board.

Plug in the power adapter, and put the MLB onto the charging base, the work is finally done.

Thanks!

Made by Xie Linhong

Arduino Code Attached

MLB.JPG

#include //use timer lib

#include

#define Register_ID 0

#define Register_2D 0x2D

#define Register_X0 0x32

#define Register_X1 0x33

#define Register_Y0 0x34

#define Register_Y1 0x35

#define Register_Z0 0x36

#define Register_Z1 0x37

int ADXAddress = 0xA7 >> 1;

//variable to keep the info of accelerometer

int X0, X1, Xg;

int Y0, Y1, Yg;

int Z1, Z0, Zg;

//pins for three color

int ledx = 9;

int ledy = 5;

int ledz = 6;

//declare 7 counters

int counterX, counterY, counterZ, counterT, counterx, countery, counterz;

//3 variable to keep the state

int stateX, stateY, stateZ;

//breathing value

int valx = 60;

int valy = 130;

int valz = 195;

//breathing speed

int fadeAmount1 = 3;

int fadeAmount2 = 6;

int fadeAmount3 = 9;

void setup() {

// Serial.begin(9600); //use the serial port to debug

// initial

Wire.begin();

delay(10);

Wire.beginTransmission(ADXAddress);

Wire.write(Register_2D);

Wire.write(8);

Wire.endTransmission();

pinMode(ledx, OUTPUT);

pinMode(ledy, OUTPUT);

pinMode(ledz, OUTPUT);

counterY = 0;

counterX = 0;

counterT = 0;

//set the state of X,Y,Z in off state

stateX = 0;

stateY = 0;

stateZ = 0;

}

void loop() {

//all off

digitalWrite(ledx, 0);

digitalWrite(ledy, 0);

digitalWrite(ledz, 0);

//read the acc info of X,Y,Z

Wire.beginTransmission(ADXAddress);

Wire.write(Register_X0);

Wire.write(Register_X1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

X0 = Wire.read();

X1 = Wire.read();

X1 = X1 << 8;

Xg = X0 + X1;

}

Wire.beginTransmission(ADXAddress);

Wire.write(Register_Y0);

Wire.write(Register_Y1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

Y0 = Wire.read();

Y1 = Wire.read();

Y1 = Y1 << 8;

Yg = Y0 + Y1;

}

Wire.beginTransmission(ADXAddress);

Wire.write(Register_Z0);

Wire.write(Register_Z1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

Z0 = Wire.read();

Z1 = Wire.read();

Z1 = Z1 << 8;

Zg = Z0 + Z1;

}

//judge if acc value of X arrives the threshold, add the counter

if (Xg >= 500 || Xg <= -500) {

counterX++;

//when counter X starts, timer will start, and enter clear function after 0.5s

if (counterX == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

//if the counterX is more than 16 before clearing, open X trig state(auto-changing color)

if (counterX >= 16) { //16 can be changed to other number, the smaller the more sensitive

stateX = !stateX;

while (stateX == 1) {

fading();

}

}

if (Yg >= 500 || Yg <= -500) {

// checking Y

counterY++;

if (counterY == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

if (counterY >= 16) {

stateY = !stateY;

while (stateY == 1) {

following();

}

}

if (Zg >= 500 || Zg <= -500) {

// checking Z

counterZ++;

if (counterZ == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

if (counterZ >= 14) {

stateZ = !stateZ;

while (stateZ == 1) {

white();

}

}

delay(6);

// Serial.print("X=");

// Serial.print(Xg);

// Serial.print(" Y=");

// Serial.print(Yg);

// Serial.print(" Z=");

// Serial.print(Zg);

// Serial.print(" CX=");

// Serial.print(counterX);

// Serial.print(" CY=");

// Serial.print(counterY);

// Serial.print(" CZ=");

// Serial.println(counterZ);

}

void Clear() {

//clear all counters

counterX = 0;

counterx = 0;

counterY = 0;

countery = 0;

counterZ = 0;

counterz = 0;

}

void white() {

//white color

digitalWrite(ledx, 1);

digitalWrite(ledy, 1);

digitalWrite(ledz, 1);

//read the acc of Z

Wire.beginTransmission(ADXAddress);

Wire.write(Register_Z0);

Wire.write(Register_Z1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

Z0 = Wire.read();

Z1 = Wire.read();

Z1 = Z1 << 8;

Zg = Z0 + Z1;

}

if (Zg >= 500 || Zg <= -500) {

counterz++;

if (counterz == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

//if counterZ is more than 140, close the trig state of Z and go back to the main function

if (counterz >= 140) {

stateZ = !stateZ;

return;

}

// Serial.print("Z=");

// Serial.print(Zg);

// Serial.print(" CZ=");

// Serial.println(counterz);

}

void following() {

//跟随姿态变色的程序

int xfollow, yfollow, zfollow;

Wire.beginTransmission(ADXAddress);

Wire.write(Register_X0);

Wire.write(Register_X1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

X0 = Wire.read();

X1 = Wire.read();

X1 = X1 << 8;

Xg = X0 + X1;

}

Wire.beginTransmission(ADXAddress);

Wire.write(Register_Y0);

Wire.write(Register_Y1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

Y0 = Wire.read();

Y1 = Wire.read();

Y1 = Y1 << 8;

Yg = Y0 + Y1;

}

Wire.beginTransmission(ADXAddress);

Wire.write(Register_Z0);

Wire.write(Register_Z1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

Z0 = Wire.read();

Z1 = Wire.read();

Z1 = Z1 << 8;

Zg = Z0 + Z1;

}

//keep the color steady by contraining the value of X,Z. Y is used to exit

Xg = constrain(Xg, -272, 272);

// Yg = constrain(Yg, -272, 272);

Zg = constrain(Zg, -272, 272);

xfollow = map(Xg, -272, 272, 5, 250);

analogWrite(ledx, xfollow);

yfollow = map(Yg, -290, 290, 5, 250);

analogWrite(ledy, yfollow);

zfollow = map(Zg, -272, 272, 5, 250);

analogWrite(ledz, zfollow);

//keep the color steady by contraining the value

xfollow = constrain(xfollow, 1, 255);

yfollow = constrain(yfollow, 1, 255);

zfollow = constrain(zfollow, 1, 255);

if (Yg >= 500 || Yg <= -500) {

countery++;

if (countery == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

if (countery >= 40 ) {

stateY = !stateY;

return;

}

// Serial.print("Y=");

// Serial.print(Yg);

// Serial.print(" CY=");

// Serial.println(countery);

}

void fading() {

//auto-chaning color

analogWrite(ledx, valx);

analogWrite(ledy, valy);

analogWrite(ledz, valz);

valx = valx + fadeAmount1;

valy = valy + fadeAmount2;

valz = valz + fadeAmount3;

if (valx <= 4 || valx >= 252) {

fadeAmount1 = -fadeAmount1 ;

}

if (valy <= 7 || valy >= 249) {

fadeAmount2 = -fadeAmount2 ;

}

if (valz <= 10 || valz >= 246) {

fadeAmount3 = -fadeAmount3 ;

}

delay(90);

Wire.beginTransmission(ADXAddress);

Wire.write(Register_X0);

Wire.write(Register_X1);

Wire.endTransmission();

Wire.requestFrom(ADXAddress, 2);

if (Wire.available() <= 2);

{

X0 = Wire.read();

X1 = Wire.read();

X1 = X1 << 8;

Xg = X0 + X1;

}

if (Xg >= 500 || Xg <= -500) {

counterx++;

if (counterx == 1) {

MsTimer2::set(500, Clear);

MsTimer2::start();

}

}

if (counterx >= 2) {

stateX = !stateX;

return;

}

// Serial.print("X=");

// Serial.print(Xg);

// Serial.print(" CX=");

// Serial.println(counterx);